From c72b5469cfac10daab30de036bd92cdcfcce76b7 Mon Sep 17 00:00:00 2001 From: KoiosSG Date: Thu, 28 May 2026 09:34:05 +0200 Subject: [PATCH 01/12] Add repository external reference pin guard --- .../.gitignore | 4 + .../README.md | 29 +++ .../acceptance-notes.md | 25 +++ .../demo.js | 51 +++++ .../index.js | 200 ++++++++++++++++++ .../make-demo-video.py | 76 +++++++ .../package.json | 12 ++ .../reports/blocked-packet.json | 74 +++++++ .../reports/clean-packet.json | 29 +++ .../reports/demo.mp4 | Bin 0 -> 52531 bytes .../reports/external-reference-report.md | 9 + .../reports/summary.svg | 24 +++ .../reports/warning-packet.json | 44 ++++ .../requirements-map.md | 15 ++ .../sample-data.js | 100 +++++++++ .../test.js | 150 +++++++++++++ 16 files changed, 842 insertions(+) create mode 100644 repository-external-reference-pin-guard/.gitignore create mode 100644 repository-external-reference-pin-guard/README.md create mode 100644 repository-external-reference-pin-guard/acceptance-notes.md create mode 100644 repository-external-reference-pin-guard/demo.js create mode 100644 repository-external-reference-pin-guard/index.js create mode 100644 repository-external-reference-pin-guard/make-demo-video.py create mode 100644 repository-external-reference-pin-guard/package.json create mode 100644 repository-external-reference-pin-guard/reports/blocked-packet.json create mode 100644 repository-external-reference-pin-guard/reports/clean-packet.json create mode 100644 repository-external-reference-pin-guard/reports/demo.mp4 create mode 100644 repository-external-reference-pin-guard/reports/external-reference-report.md create mode 100644 repository-external-reference-pin-guard/reports/summary.svg create mode 100644 repository-external-reference-pin-guard/reports/warning-packet.json create mode 100644 repository-external-reference-pin-guard/requirements-map.md create mode 100644 repository-external-reference-pin-guard/sample-data.js create mode 100644 repository-external-reference-pin-guard/test.js diff --git a/repository-external-reference-pin-guard/.gitignore b/repository-external-reference-pin-guard/.gitignore new file mode 100644 index 00000000..eddc6484 --- /dev/null +++ b/repository-external-reference-pin-guard/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +reports/demo-frame.png +__pycache__/ +*.tmp diff --git a/repository-external-reference-pin-guard/README.md b/repository-external-reference-pin-guard/README.md new file mode 100644 index 00000000..1b05e6a1 --- /dev/null +++ b/repository-external-reference-pin-guard/README.md @@ -0,0 +1,29 @@ +# Repository External Reference Pin Guard + +Self-contained Project Repository & Version Control slice for issue #10. + +This module checks whether a scientific repository can safely publish a DOI, citation badge, API view, or export bundle when it depends on external references such as Git submodules, linked datasets, API snapshots, model weights, or external code/data pointers. + +## What It Checks + +- Git submodules and external code are pinned to immutable commit SHAs. +- Linked datasets and model weights have checksum, DOI, or immutable version evidence. +- API sources use dated snapshots with checksum evidence instead of floating "latest" endpoints. +- Export bundles do not require authenticated external references. +- License and attribution metadata are present before DOI publication. +- Reference verification evidence is fresh enough for release. + +## Commands + +```powershell +npm test +npm run demo +npm run video +npm run check +``` + +The demo writes deterministic JSON, Markdown, SVG, and MP4 reviewer artifacts under `reports/`. + +## Safety + +All records are synthetic. The module does not call external repositories, APIs, DOI registries, identity providers, storage systems, payment systems, or private research databases. diff --git a/repository-external-reference-pin-guard/acceptance-notes.md b/repository-external-reference-pin-guard/acceptance-notes.md new file mode 100644 index 00000000..018aa1ef --- /dev/null +++ b/repository-external-reference-pin-guard/acceptance-notes.md @@ -0,0 +1,25 @@ +# Acceptance Notes + +## Local Validation + +Run from `repository-external-reference-pin-guard/`: + +```powershell +npm test +npm run demo +npm run video +npm run check +``` + +Expected evidence: + +- `reports/blocked-packet.json` blocks repository release when external references are floating, authenticated only, stale, or missing durable identifiers. +- `reports/warning-packet.json` stages pinned references that still need license and attribution metadata. +- `reports/clean-packet.json` releases a repository with immutable external pins, fresh verification evidence, and exportable metadata. +- `reports/external-reference-report.md` summarizes lanes and finding codes. +- `reports/summary.svg` provides a visual reviewer packet. +- `reports/demo.mp4` is a short H.264 walkthrough generated from synthetic frames. + +## Safety Boundaries + +All records are synthetic. No external repositories, live APIs, DOI registries, object stores, credentials, private research data, identity providers, or payment systems are contacted. diff --git a/repository-external-reference-pin-guard/demo.js b/repository-external-reference-pin-guard/demo.js new file mode 100644 index 00000000..74f01815 --- /dev/null +++ b/repository-external-reference-pin-guard/demo.js @@ -0,0 +1,51 @@ +const fs = require('fs'); +const path = require('path'); + +const { assessExternalReferences } = require('./index'); +const { riskyRepository, cleanRepository, warningRepository } = require('./sample-data'); + +const reportsDir = path.join(__dirname, 'reports'); +fs.mkdirSync(reportsDir, { recursive: true }); + +const packets = [ + ['blocked-packet.json', assessExternalReferences(riskyRepository)], + ['clean-packet.json', assessExternalReferences(cleanRepository)], + ['warning-packet.json', assessExternalReferences(warningRepository)] +]; + +for (const [fileName, packet] of packets) { + fs.writeFileSync(path.join(reportsDir, fileName), `${JSON.stringify(packet, null, 2)}\n`); + console.log(`${fileName}: ${packet.status}; findings=${packet.findings.length}; digest=${packet.auditDigest.slice(0, 12)}`); +} + +const markdown = [ + '# Repository External Reference Pin Guard Report', + '', + '| Packet | Status | DOI publication | Export bundle | API access | Findings |', + '| --- | --- | --- | --- | --- | --- |', + ...packets.map(([fileName, packet]) => `| ${fileName} | ${packet.status} | ${packet.releaseLanes.doiPublication} | ${packet.releaseLanes.exportBundle} | ${packet.releaseLanes.apiAccess} | ${packet.findings.map((finding) => finding.code).join(', ') || 'none'} |`), + '', + 'Synthetic data only. No external repositories, APIs, DOI registries, or private data sources are contacted.' +].join('\n'); +fs.writeFileSync(path.join(reportsDir, 'external-reference-report.md'), `${markdown}\n`); + +const rows = packets.map(([fileName, packet], index) => { + const y = 94 + index * 68; + const color = packet.status === 'hold_repository_release' ? '#b91c1c' : packet.status === 'stage_reference_metadata_revision' ? '#a16207' : '#047857'; + return ` + + + + ${packet.repositoryId} + ${fileName} | findings ${packet.findings.length} | digest ${packet.auditDigest.slice(0, 16)} + `; +}).join(''); + +const svg = ` + + Repository External Reference Pin Guard + Issue #10 release/export gate for submodules, linked datasets, API sources, and model references +${rows} + +`; +fs.writeFileSync(path.join(reportsDir, 'summary.svg'), svg); diff --git a/repository-external-reference-pin-guard/index.js b/repository-external-reference-pin-guard/index.js new file mode 100644 index 00000000..155804e9 --- /dev/null +++ b/repository-external-reference-pin-guard/index.js @@ -0,0 +1,200 @@ +const crypto = require('crypto'); + +const DEFAULT_POLICY = { + maxReferenceAgeDays: 180 +}; + +function assessExternalReferences(repository) { + const policy = { ...DEFAULT_POLICY, ...(repository.policy || {}) }; + const findings = repository.references + .flatMap((reference) => assessReference(reference, repository.assessedAt, policy)) + .sort(compareFindings); + + const blockerCount = findings.filter((finding) => finding.severity === 'blocker').length; + const warningCount = findings.filter((finding) => finding.severity === 'warning').length; + + const packet = { + repositoryId: repository.repositoryId, + status: chooseStatus(blockerCount, warningCount), + releaseLanes: chooseReleaseLanes(blockerCount, warningCount), + findings, + actions: buildActions(repository, findings), + referenceSignals: buildSignals(findings), + referenceSummary: summarizeReferences(repository.references), + assessedAt: repository.assessedAt + }; + + packet.auditDigest = digestPacket(packet); + return packet; +} + +function assessReference(reference, assessedAt, policy) { + const findings = []; + + if (isGitReference(reference) && !hasPinnedCommit(reference)) { + findings.push(finding(reference, 'FLOATING_GIT_REFERENCE', 'blocker', 'Git reference must be pinned to an immutable commit SHA before release.')); + } + + if (reference.kind === 'api_source' && !hasSnapshotEvidence(reference)) { + findings.push(finding(reference, 'FLOATING_API_REFERENCE', 'blocker', 'API source must reference a dated snapshot with checksum evidence.')); + } + + if (needsDurableIdentifier(reference) && !hasDurableIdentifier(reference)) { + findings.push(finding(reference, 'MISSING_DURABLE_IDENTIFIER', 'blocker', 'External data or model reference needs a checksum, DOI, or immutable version.')); + } + + if (reference.authRequired) { + findings.push(finding(reference, 'AUTH_REQUIRED_REFERENCE', 'blocker', 'Export bundles cannot depend on authenticated external references.')); + } + + if (!hasText(reference.license)) { + findings.push(finding(reference, 'MISSING_LICENSE', 'warning', 'External reference needs license metadata before DOI publication.')); + } + + if (!hasText(reference.attribution)) { + findings.push(finding(reference, 'MISSING_ATTRIBUTION', 'warning', 'External reference needs attribution metadata before DOI publication.')); + } + + if (isStale(reference.lastVerifiedAt, assessedAt, policy.maxReferenceAgeDays)) { + findings.push(finding(reference, 'STALE_REFERENCE_EVIDENCE', 'blocker', 'External reference verification is older than policy allows.')); + } + + return findings; +} + +function isGitReference(reference) { + return reference.kind === 'git_submodule' || reference.kind === 'external_code'; +} + +function hasPinnedCommit(reference) { + return /^[a-f0-9]{40}$/i.test(reference.commitSha || ''); +} + +function hasSnapshotEvidence(reference) { + return hasText(reference.snapshotDate) && hasText(reference.checksum); +} + +function needsDurableIdentifier(reference) { + return ['linked_dataset', 'model_weights', 'external_data'].includes(reference.kind); +} + +function hasDurableIdentifier(reference) { + return hasText(reference.checksum) || hasText(reference.doi) || hasText(reference.version); +} + +function isStale(lastVerifiedAt, assessedAt, maxAgeDays) { + if (!lastVerifiedAt || !assessedAt) return false; + const verified = Date.parse(lastVerifiedAt); + const assessed = Date.parse(assessedAt); + if (Number.isNaN(verified) || Number.isNaN(assessed)) return true; + const ageDays = Math.max(0, (assessed - verified) / (24 * 60 * 60 * 1000)); + return ageDays > maxAgeDays; +} + +function chooseStatus(blockerCount, warningCount) { + if (blockerCount > 0) return 'hold_repository_release'; + if (warningCount > 0) return 'stage_reference_metadata_revision'; + return 'release_repository_references'; +} + +function chooseReleaseLanes(blockerCount, warningCount) { + if (blockerCount > 0) { + return { + doiPublication: 'blocked', + exportBundle: 'blocked', + apiAccess: 'metadata_only' + }; + } + + if (warningCount > 0) { + return { + doiPublication: 'metadata_revision', + exportBundle: 'draft_only', + apiAccess: 'allowed' + }; + } + + return { + doiPublication: 'allowed', + exportBundle: 'allowed', + apiAccess: 'allowed' + }; +} + +function buildActions(repository, findings) { + if (!findings.length) return [`release_with_reference_pin_monitoring:${repository.repositoryId}`]; + + const byReference = new Map(); + for (const item of findings) { + if (!byReference.has(item.referenceId)) byReference.set(item.referenceId, new Set()); + byReference.get(item.referenceId).add(item.code); + } + + const actions = new Set(); + for (const [referenceId, codes] of byReference.entries()) { + if (codes.has('AUTH_REQUIRED_REFERENCE')) actions.add(`replace_or_snapshot_auth_reference:${referenceId}`); + if (codes.has('FLOATING_GIT_REFERENCE') || codes.has('FLOATING_API_REFERENCE')) actions.add(`pin_external_reference:${referenceId}`); + if (codes.has('MISSING_DURABLE_IDENTIFIER')) actions.add(`add_checksum_or_doi:${referenceId}`); + if (codes.has('STALE_REFERENCE_EVIDENCE')) actions.add(`refresh_reference_verification:${referenceId}`); + if (codes.has('MISSING_LICENSE') || codes.has('MISSING_ATTRIBUTION')) actions.add(`complete_license_attribution:${referenceId}`); + } + + return [...actions].sort(); +} + +function buildSignals(findings) { + const codes = new Set(findings.map((finding) => finding.code)); + return { + immutablePins: !codes.has('FLOATING_GIT_REFERENCE') && !codes.has('FLOATING_API_REFERENCE'), + exportable: !codes.has('AUTH_REQUIRED_REFERENCE') && !codes.has('MISSING_DURABLE_IDENTIFIER'), + attributionComplete: !codes.has('MISSING_LICENSE') && !codes.has('MISSING_ATTRIBUTION'), + verificationFresh: !codes.has('STALE_REFERENCE_EVIDENCE') + }; +} + +function summarizeReferences(references = []) { + return references.reduce((summary, reference) => { + summary.total += 1; + summary.byKind[reference.kind] = (summary.byKind[reference.kind] || 0) + 1; + return summary; + }, { total: 0, byKind: {} }); +} + +function finding(reference, code, severity, message) { + return { + referenceId: reference.id, + kind: reference.kind, + target: reference.target, + code, + severity, + message + }; +} + +function compareFindings(left, right) { + return `${left.referenceId}:${left.code}`.localeCompare(`${right.referenceId}:${right.code}`); +} + +function hasText(value) { + return typeof value === 'string' && value.trim().length > 0; +} + +function digestPacket(packet) { + return crypto.createHash('sha256').update(stableStringify(packet)).digest('hex'); +} + +function stableStringify(value) { + if (Array.isArray(value)) return `[${value.map(stableStringify).join(',')}]`; + if (value && typeof value === 'object') { + return `{${Object.keys(value) + .filter((key) => value[key] !== undefined) + .sort() + .map((key) => `${JSON.stringify(key)}:${stableStringify(value[key])}`) + .join(',')}}`; + } + return JSON.stringify(value); +} + +module.exports = { + assessExternalReferences +}; diff --git a/repository-external-reference-pin-guard/make-demo-video.py b/repository-external-reference-pin-guard/make-demo-video.py new file mode 100644 index 00000000..74cc6a06 --- /dev/null +++ b/repository-external-reference-pin-guard/make-demo-video.py @@ -0,0 +1,76 @@ +from pathlib import Path +import subprocess +import textwrap + +from PIL import Image, ImageDraw, ImageFont + + +ROOT = Path(__file__).resolve().parent +REPORTS = ROOT / "reports" +REPORTS.mkdir(exist_ok=True) +FRAME = REPORTS / "demo-frame.png" +VIDEO = REPORTS / "demo.mp4" + + +def font(size, bold=False): + candidates = [ + "C:/Windows/Fonts/arialbd.ttf" if bold else "C:/Windows/Fonts/arial.ttf", + "C:/Windows/Fonts/segoeuib.ttf" if bold else "C:/Windows/Fonts/segoeui.ttf", + ] + for candidate in candidates: + if Path(candidate).exists(): + return ImageFont.truetype(candidate, size) + return ImageFont.load_default() + + +img = Image.new("RGB", (1280, 720), "#ffffff") +draw = ImageDraw.Draw(img) +title_font = font(44, True) +body_font = font(25) +small_font = font(21) + +draw.rectangle((0, 0, 1280, 92), fill="#0f172a") +draw.text((48, 26), "Repository External Reference Pin Guard", fill="#ffffff", font=title_font) + +cards = [ + ("hold_repository_release", "#991b1b", "Blocks floating git refs, auth-only APIs, stale dataset evidence"), + ("stage_reference_metadata_revision", "#a16207", "Stages pinned references that still need license or attribution"), + ("release_repository_references", "#047857", "Allows DOI/export release only with immutable pins and checksums"), +] + +for index, (status, color, description) in enumerate(cards): + y = 138 + index * 134 + draw.rounded_rectangle((58, y, 1222, y + 96), radius=8, outline="#cbd5e1", width=2, fill="#f8fafc") + draw.ellipse((88, y + 29, 126, y + 67), fill=color) + draw.text((150, y + 22), status, fill="#111827", font=body_font) + for line_index, line in enumerate(textwrap.wrap(description, width=78)): + draw.text((150, y + 55 + line_index * 26), line, fill="#475569", font=small_font) + +draw.text((58, 596), "Synthetic evidence only. No external repositories, APIs, DOI registries, or private data sources are contacted.", fill="#334155", font=small_font) +img.save(FRAME) + +subprocess.run( + [ + "ffmpeg", + "-y", + "-loop", + "1", + "-i", + str(FRAME), + "-t", + "7.5", + "-r", + "24", + "-vf", + "format=yuv420p", + "-movflags", + "+faststart", + str(VIDEO), + ], + check=True, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, +) + +FRAME.unlink(missing_ok=True) +print(f"wrote {VIDEO}") diff --git a/repository-external-reference-pin-guard/package.json b/repository-external-reference-pin-guard/package.json new file mode 100644 index 00000000..fd485f57 --- /dev/null +++ b/repository-external-reference-pin-guard/package.json @@ -0,0 +1,12 @@ +{ + "name": "repository-external-reference-pin-guard", + "version": "1.0.0", + "private": true, + "type": "commonjs", + "scripts": { + "test": "node test.js", + "demo": "node demo.js", + "video": "python make-demo-video.py", + "check": "node --check index.js && node --check sample-data.js && node --check test.js && node --check demo.js && python -m py_compile make-demo-video.py" + } +} diff --git a/repository-external-reference-pin-guard/reports/blocked-packet.json b/repository-external-reference-pin-guard/reports/blocked-packet.json new file mode 100644 index 00000000..ee8723e6 --- /dev/null +++ b/repository-external-reference-pin-guard/reports/blocked-packet.json @@ -0,0 +1,74 @@ +{ + "repositoryId": "repo-reference-risk", + "status": "hold_repository_release", + "releaseLanes": { + "doiPublication": "blocked", + "exportBundle": "blocked", + "apiAccess": "metadata_only" + }, + "findings": [ + { + "referenceId": "api-weather-source", + "kind": "api_source", + "target": "https://api.example.invalid/weather/latest", + "code": "AUTH_REQUIRED_REFERENCE", + "severity": "blocker", + "message": "Export bundles cannot depend on authenticated external references." + }, + { + "referenceId": "api-weather-source", + "kind": "api_source", + "target": "https://api.example.invalid/weather/latest", + "code": "FLOATING_API_REFERENCE", + "severity": "blocker", + "message": "API source must reference a dated snapshot with checksum evidence." + }, + { + "referenceId": "dataset-lab-export", + "kind": "linked_dataset", + "target": "https://data.example.invalid/lab-export.csv", + "code": "MISSING_DURABLE_IDENTIFIER", + "severity": "blocker", + "message": "External data or model reference needs a checksum, DOI, or immutable version." + }, + { + "referenceId": "dataset-lab-export", + "kind": "linked_dataset", + "target": "https://data.example.invalid/lab-export.csv", + "code": "STALE_REFERENCE_EVIDENCE", + "severity": "blocker", + "message": "External reference verification is older than policy allows." + }, + { + "referenceId": "submodule-analysis-tools", + "kind": "git_submodule", + "target": "https://github.com/example/analysis-tools", + "code": "FLOATING_GIT_REFERENCE", + "severity": "blocker", + "message": "Git reference must be pinned to an immutable commit SHA before release." + } + ], + "actions": [ + "add_checksum_or_doi:dataset-lab-export", + "pin_external_reference:api-weather-source", + "pin_external_reference:submodule-analysis-tools", + "refresh_reference_verification:dataset-lab-export", + "replace_or_snapshot_auth_reference:api-weather-source" + ], + "referenceSignals": { + "immutablePins": false, + "exportable": false, + "attributionComplete": true, + "verificationFresh": false + }, + "referenceSummary": { + "total": 3, + "byKind": { + "git_submodule": 1, + "linked_dataset": 1, + "api_source": 1 + } + }, + "assessedAt": "2026-05-28T12:00:00Z", + "auditDigest": "845fc5612c82a4a307ac3b4d65af240e262d5e164c709f43462cc2b9586c30c6" +} diff --git a/repository-external-reference-pin-guard/reports/clean-packet.json b/repository-external-reference-pin-guard/reports/clean-packet.json new file mode 100644 index 00000000..452c118b --- /dev/null +++ b/repository-external-reference-pin-guard/reports/clean-packet.json @@ -0,0 +1,29 @@ +{ + "repositoryId": "repo-reference-clean", + "status": "release_repository_references", + "releaseLanes": { + "doiPublication": "allowed", + "exportBundle": "allowed", + "apiAccess": "allowed" + }, + "findings": [], + "actions": [ + "release_with_reference_pin_monitoring:repo-reference-clean" + ], + "referenceSignals": { + "immutablePins": true, + "exportable": true, + "attributionComplete": true, + "verificationFresh": true + }, + "referenceSummary": { + "total": 3, + "byKind": { + "git_submodule": 1, + "linked_dataset": 1, + "api_source": 1 + } + }, + "assessedAt": "2026-05-28T12:00:00Z", + "auditDigest": "5b1ede709bdfe56bb066cce64315055c0e3e87678a2bc86d7d8846ab17ae48a1" +} diff --git a/repository-external-reference-pin-guard/reports/demo.mp4 b/repository-external-reference-pin-guard/reports/demo.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..881f51c5b2b366acd9c4da620eef51f71d707b40 GIT binary patch literal 52531 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
6KOXpX^6UMrRMY2iJUX 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 upy2>GgfbO>MdXbg>|-balXY6 + + Repository External Reference Pin Guard + Issue #10 release/export gate for submodules, linked datasets, API sources, and model references + + + + + repo-reference-risk + blocked-packet.json | findings 5 | digest 845fc5612c82a4a3 + + + + + repo-reference-clean + clean-packet.json | findings 0 | digest 5b1ede709bdfe56b + + + + + repo-reference-warning + warning-packet.json | findings 2 | digest 2bcec8202016cc03 + + diff --git a/repository-external-reference-pin-guard/reports/warning-packet.json b/repository-external-reference-pin-guard/reports/warning-packet.json new file mode 100644 index 00000000..a707e1c7 --- /dev/null +++ b/repository-external-reference-pin-guard/reports/warning-packet.json @@ -0,0 +1,44 @@ +{ + "repositoryId": "repo-reference-warning", + "status": "stage_reference_metadata_revision", + "releaseLanes": { + "doiPublication": "metadata_revision", + "exportBundle": "draft_only", + "apiAccess": "allowed" + }, + "findings": [ + { + "referenceId": "model-weights", + "kind": "model_weights", + "target": "https://models.example.invalid/model-v3.bin", + "code": "MISSING_ATTRIBUTION", + "severity": "warning", + "message": "External reference needs attribution metadata before DOI publication." + }, + { + "referenceId": "model-weights", + "kind": "model_weights", + "target": "https://models.example.invalid/model-v3.bin", + "code": "MISSING_LICENSE", + "severity": "warning", + "message": "External reference needs license metadata before DOI publication." + } + ], + "actions": [ + "complete_license_attribution:model-weights" + ], + "referenceSignals": { + "immutablePins": true, + "exportable": true, + "attributionComplete": false, + "verificationFresh": true + }, + "referenceSummary": { + "total": 1, + "byKind": { + "model_weights": 1 + } + }, + "assessedAt": "2026-05-28T12:00:00Z", + "auditDigest": "2bcec8202016cc03a70f2a1bd751d8f07518e31cd76900ca9f428e638a168afc" +} diff --git a/repository-external-reference-pin-guard/requirements-map.md b/repository-external-reference-pin-guard/requirements-map.md new file mode 100644 index 00000000..11b3230e --- /dev/null +++ b/repository-external-reference-pin-guard/requirements-map.md @@ -0,0 +1,15 @@ +# Requirements Map + +Issue #10 asks for robust project repositories with versioned files, collaboration, reproducibility, identifiers, citations, programmatic access, and export bundles. + +| Issue #10 area | Coverage in this slice | +| --- | --- | +| File and metadata versioning | Holds releases when Git submodules or external code are not pinned to immutable commits. | +| Hash-based integrity | Requires checksums, DOI evidence, or immutable versions for external datasets and model weights. | +| Computation-aware reproducibility | Blocks reproducibility/export lanes when API data sources are floating or authenticated only. | +| Repository identifiers and citation | Prevents DOI publication when external references are stale or lack license/attribution metadata. | +| Programmatic access and export | Separates API metadata-only access from export-bundle and DOI publication release lanes. | + +## Non-Overlap + +This contribution is distinct from broad repository ledgers, release engines, structured diffs, provenance attestations, release embargo controls, notebook replay, schema migration, citation impact, API/export contract verification, merge queue governance, environment drift, access review, DOI tombstone handling, metadata readiness, branch hypothesis lineage, sensitive-artifact scanning, dependency-license checks, legal hold, component-owner approval, restore rehearsal, compute sandbox policy, and semantic version-tag governance. It focuses specifically on immutable external reference pins and exportable citation evidence for submodules, linked datasets, API sources, model weights, and external code/data pointers. diff --git a/repository-external-reference-pin-guard/sample-data.js b/repository-external-reference-pin-guard/sample-data.js new file mode 100644 index 00000000..def458cd --- /dev/null +++ b/repository-external-reference-pin-guard/sample-data.js @@ -0,0 +1,100 @@ +const riskyRepository = { + repositoryId: 'repo-reference-risk', + assessedAt: '2026-05-28T12:00:00Z', + policy: { + maxReferenceAgeDays: 180 + }, + references: [ + { + id: 'submodule-analysis-tools', + kind: 'git_submodule', + target: 'https://github.com/example/analysis-tools', + branch: 'main', + commitSha: '', + license: 'MIT', + attribution: 'Example Analysis Tools', + lastVerifiedAt: '2026-05-20T08:00:00Z' + }, + { + id: 'dataset-lab-export', + kind: 'linked_dataset', + target: 'https://data.example.invalid/lab-export.csv', + checksum: '', + doi: '', + license: 'CC-BY-4.0', + attribution: 'Example Lab', + lastVerifiedAt: '2025-01-15T08:00:00Z' + }, + { + id: 'api-weather-source', + kind: 'api_source', + target: 'https://api.example.invalid/weather/latest', + snapshotDate: '', + checksum: 'sha256:abcdef', + authRequired: true, + license: 'CC0-1.0', + attribution: 'Example Weather API', + lastVerifiedAt: '2026-05-20T08:00:00Z' + } + ] +}; + +const cleanRepository = { + repositoryId: 'repo-reference-clean', + assessedAt: '2026-05-28T12:00:00Z', + references: [ + { + id: 'submodule-analysis-tools', + kind: 'git_submodule', + target: 'https://github.com/example/analysis-tools', + commitSha: '7f9c2d6c8e0f4b1a2d3c5e6f708192a3b4c5d6e7', + license: 'MIT', + attribution: 'Example Analysis Tools', + lastVerifiedAt: '2026-05-20T08:00:00Z' + }, + { + id: 'dataset-lab-export', + kind: 'linked_dataset', + target: 'https://doi.org/10.5281/zenodo.1234567', + checksum: 'sha256:1234567890abcdef', + doi: '10.5281/zenodo.1234567', + license: 'CC-BY-4.0', + attribution: 'Example Lab', + lastVerifiedAt: '2026-05-20T08:00:00Z' + }, + { + id: 'api-weather-source', + kind: 'api_source', + target: 'https://api.example.invalid/weather/snapshots/2026-05-01.json', + snapshotDate: '2026-05-01', + checksum: 'sha256:abcdef', + authRequired: false, + license: 'CC0-1.0', + attribution: 'Example Weather API', + lastVerifiedAt: '2026-05-20T08:00:00Z' + } + ] +}; + +const warningRepository = { + repositoryId: 'repo-reference-warning', + assessedAt: '2026-05-28T12:00:00Z', + references: [ + { + id: 'model-weights', + kind: 'model_weights', + target: 'https://models.example.invalid/model-v3.bin', + checksum: 'sha256:feedface', + version: 'v3.0.1', + license: '', + attribution: '', + lastVerifiedAt: '2026-05-20T08:00:00Z' + } + ] +}; + +module.exports = { + riskyRepository, + cleanRepository, + warningRepository +}; diff --git a/repository-external-reference-pin-guard/test.js b/repository-external-reference-pin-guard/test.js new file mode 100644 index 00000000..67dcce4e --- /dev/null +++ b/repository-external-reference-pin-guard/test.js @@ -0,0 +1,150 @@ +const assert = require('assert'); + +const { assessExternalReferences } = require('./index'); + +function findingCodes(packet) { + return packet.findings.map((finding) => finding.code).sort(); +} + +function testBlocksFloatingAndNonExportableExternalReferences() { + const packet = assessExternalReferences({ + repositoryId: 'repo-reference-risk', + assessedAt: '2026-05-28T12:00:00Z', + policy: { + maxReferenceAgeDays: 180 + }, + references: [ + { + id: 'submodule-analysis-tools', + kind: 'git_submodule', + target: 'https://github.com/example/analysis-tools', + branch: 'main', + commitSha: '', + license: 'MIT', + attribution: 'Example Analysis Tools' + }, + { + id: 'dataset-lab-export', + kind: 'linked_dataset', + target: 'https://data.example.invalid/lab-export.csv', + checksum: '', + doi: '', + license: 'CC-BY-4.0', + attribution: 'Example Lab', + lastVerifiedAt: '2025-01-15T08:00:00Z' + }, + { + id: 'api-weather-source', + kind: 'api_source', + target: 'https://api.example.invalid/weather/latest', + snapshotDate: '', + checksum: 'sha256:abcdef', + authRequired: true, + license: 'CC0-1.0', + attribution: 'Example Weather API' + } + ] + }); + + assert.equal(packet.status, 'hold_repository_release'); + assert.equal(packet.releaseLanes.doiPublication, 'blocked'); + assert.equal(packet.releaseLanes.exportBundle, 'blocked'); + assert.deepEqual(findingCodes(packet), [ + 'AUTH_REQUIRED_REFERENCE', + 'FLOATING_API_REFERENCE', + 'FLOATING_GIT_REFERENCE', + 'MISSING_DURABLE_IDENTIFIER', + 'STALE_REFERENCE_EVIDENCE' + ]); + assert.ok(packet.actions.includes('pin_external_reference:submodule-analysis-tools')); + assert.ok(packet.actions.includes('add_checksum_or_doi:dataset-lab-export')); + assert.ok(packet.actions.includes('replace_or_snapshot_auth_reference:api-weather-source')); + assert.match(packet.auditDigest, /^[a-f0-9]{64}$/); +} + +function testAllowsPinnedExportableReferences() { + const packet = assessExternalReferences({ + repositoryId: 'repo-reference-clean', + assessedAt: '2026-05-28T12:00:00Z', + references: [ + { + id: 'submodule-analysis-tools', + kind: 'git_submodule', + target: 'https://github.com/example/analysis-tools', + commitSha: '7f9c2d6c8e0f4b1a2d3c5e6f708192a3b4c5d6e7', + license: 'MIT', + attribution: 'Example Analysis Tools', + lastVerifiedAt: '2026-05-20T08:00:00Z' + }, + { + id: 'dataset-lab-export', + kind: 'linked_dataset', + target: 'https://doi.org/10.5281/zenodo.1234567', + checksum: 'sha256:1234567890abcdef', + doi: '10.5281/zenodo.1234567', + license: 'CC-BY-4.0', + attribution: 'Example Lab', + lastVerifiedAt: '2026-05-20T08:00:00Z' + }, + { + id: 'api-weather-source', + kind: 'api_source', + target: 'https://api.example.invalid/weather/snapshots/2026-05-01.json', + snapshotDate: '2026-05-01', + checksum: 'sha256:abcdef', + authRequired: false, + license: 'CC0-1.0', + attribution: 'Example Weather API', + lastVerifiedAt: '2026-05-20T08:00:00Z' + } + ] + }); + + assert.equal(packet.status, 'release_repository_references'); + assert.equal(packet.releaseLanes.doiPublication, 'allowed'); + assert.equal(packet.releaseLanes.exportBundle, 'allowed'); + assert.deepEqual(packet.findings, []); + assert.deepEqual(packet.actions, ['release_with_reference_pin_monitoring:repo-reference-clean']); + assert.equal(packet.referenceSignals.immutablePins, true); + assert.equal(packet.referenceSignals.exportable, true); +} + +function testStagesReferencesMissingLicenseAttributionOnly() { + const packet = assessExternalReferences({ + repositoryId: 'repo-reference-warning', + assessedAt: '2026-05-28T12:00:00Z', + references: [ + { + id: 'model-weights', + kind: 'model_weights', + target: 'https://models.example.invalid/model-v3.bin', + checksum: 'sha256:feedface', + version: 'v3.0.1', + license: '', + attribution: '', + lastVerifiedAt: '2026-05-20T08:00:00Z' + } + ] + }); + + assert.equal(packet.status, 'stage_reference_metadata_revision'); + assert.equal(packet.releaseLanes.doiPublication, 'metadata_revision'); + assert.equal(packet.releaseLanes.exportBundle, 'draft_only'); + assert.deepEqual(findingCodes(packet), [ + 'MISSING_ATTRIBUTION', + 'MISSING_LICENSE' + ]); + assert.deepEqual(packet.actions, ['complete_license_attribution:model-weights']); +} + +const tests = [ + testBlocksFloatingAndNonExportableExternalReferences, + testAllowsPinnedExportableReferences, + testStagesReferencesMissingLicenseAttributionOnly +]; + +for (const test of tests) { + test(); +} + +console.log(`repository-external-reference-pin-guard tests passed (${tests.length})`); From 0445f373945ba87669872c7c71b125b3cd09ed9b Mon Sep 17 00:00:00 2001 From: KoiosSG Date: Thu, 28 May 2026 17:38:13 +0200 Subject: [PATCH 02/12] Harden external reference version pins --- .../README.md | 2 +- .../acceptance-notes.md | 1 + .../index.js | 7 ++++- .../requirements-map.md | 2 +- .../test.js | 28 ++++++++++++++++++- 5 files changed, 36 insertions(+), 4 deletions(-) diff --git a/repository-external-reference-pin-guard/README.md b/repository-external-reference-pin-guard/README.md index 1b05e6a1..8750edef 100644 --- a/repository-external-reference-pin-guard/README.md +++ b/repository-external-reference-pin-guard/README.md @@ -7,7 +7,7 @@ This module checks whether a scientific repository can safely publish a DOI, cit ## What It Checks - Git submodules and external code are pinned to immutable commit SHAs. -- Linked datasets and model weights have checksum, DOI, or immutable version evidence. +- Linked datasets and model weights have checksum, DOI, or immutable version evidence; floating aliases such as `latest` do not count. - API sources use dated snapshots with checksum evidence instead of floating "latest" endpoints. - Export bundles do not require authenticated external references. - License and attribution metadata are present before DOI publication. diff --git a/repository-external-reference-pin-guard/acceptance-notes.md b/repository-external-reference-pin-guard/acceptance-notes.md index 018aa1ef..ce5b31bb 100644 --- a/repository-external-reference-pin-guard/acceptance-notes.md +++ b/repository-external-reference-pin-guard/acceptance-notes.md @@ -14,6 +14,7 @@ npm run check Expected evidence: - `reports/blocked-packet.json` blocks repository release when external references are floating, authenticated only, stale, or missing durable identifiers. +- Floating version aliases such as `latest` are blocked unless the reference also has checksum or DOI evidence. - `reports/warning-packet.json` stages pinned references that still need license and attribution metadata. - `reports/clean-packet.json` releases a repository with immutable external pins, fresh verification evidence, and exportable metadata. - `reports/external-reference-report.md` summarizes lanes and finding codes. diff --git a/repository-external-reference-pin-guard/index.js b/repository-external-reference-pin-guard/index.js index 155804e9..b180bf08 100644 --- a/repository-external-reference-pin-guard/index.js +++ b/repository-external-reference-pin-guard/index.js @@ -79,7 +79,12 @@ function needsDurableIdentifier(reference) { } function hasDurableIdentifier(reference) { - return hasText(reference.checksum) || hasText(reference.doi) || hasText(reference.version); + return hasText(reference.checksum) || hasText(reference.doi) || hasImmutableVersion(reference.version); +} + +function hasImmutableVersion(version) { + if (!hasText(version)) return false; + return !/^(latest|main|master|head|current|stable|dev|nightly)$/i.test(version.trim()); } function isStale(lastVerifiedAt, assessedAt, maxAgeDays) { diff --git a/repository-external-reference-pin-guard/requirements-map.md b/repository-external-reference-pin-guard/requirements-map.md index 11b3230e..ceb73f9c 100644 --- a/repository-external-reference-pin-guard/requirements-map.md +++ b/repository-external-reference-pin-guard/requirements-map.md @@ -5,7 +5,7 @@ Issue #10 asks for robust project repositories with versioned files, collaborati | Issue #10 area | Coverage in this slice | | --- | --- | | File and metadata versioning | Holds releases when Git submodules or external code are not pinned to immutable commits. | -| Hash-based integrity | Requires checksums, DOI evidence, or immutable versions for external datasets and model weights. | +| Hash-based integrity | Requires checksums, DOI evidence, or non-floating immutable versions for external datasets and model weights. | | Computation-aware reproducibility | Blocks reproducibility/export lanes when API data sources are floating or authenticated only. | | Repository identifiers and citation | Prevents DOI publication when external references are stale or lack license/attribution metadata. | | Programmatic access and export | Separates API metadata-only access from export-bundle and DOI publication release lanes. | diff --git a/repository-external-reference-pin-guard/test.js b/repository-external-reference-pin-guard/test.js index 67dcce4e..8c08428c 100644 --- a/repository-external-reference-pin-guard/test.js +++ b/repository-external-reference-pin-guard/test.js @@ -137,10 +137,36 @@ function testStagesReferencesMissingLicenseAttributionOnly() { assert.deepEqual(packet.actions, ['complete_license_attribution:model-weights']); } +function testFloatingVersionAliasDoesNotCountAsDurableIdentifier() { + const packet = assessExternalReferences({ + repositoryId: 'repo-reference-floating-version', + assessedAt: '2026-05-28T12:00:00Z', + references: [ + { + id: 'model-weights-latest', + kind: 'model_weights', + target: 'https://models.example.invalid/model.bin', + version: 'latest', + checksum: '', + doi: '', + license: 'Apache-2.0', + attribution: 'Example Model Lab', + lastVerifiedAt: '2026-05-20T08:00:00Z' + } + ] + }); + + assert.equal(packet.status, 'hold_repository_release'); + assert.deepEqual(findingCodes(packet), ['MISSING_DURABLE_IDENTIFIER']); + assert.ok(packet.actions.includes('add_checksum_or_doi:model-weights-latest')); + assert.equal(packet.referenceSignals.exportable, false); +} + const tests = [ testBlocksFloatingAndNonExportableExternalReferences, testAllowsPinnedExportableReferences, - testStagesReferencesMissingLicenseAttributionOnly + testStagesReferencesMissingLicenseAttributionOnly, + testFloatingVersionAliasDoesNotCountAsDurableIdentifier ]; for (const test of tests) { From 59492e3dc0ef2eae2b61cada1ed893cd32237bb3 Mon Sep 17 00:00:00 2001 From: KoiosSG Date: Fri, 29 May 2026 17:29:34 +0200 Subject: [PATCH 03/12] Reject future-dated reference verification --- .../README.md | 2 +- .../index.js | 1 + .../requirements-map.md | 2 +- .../test.js | 27 ++++++++++++++++++- 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/repository-external-reference-pin-guard/README.md b/repository-external-reference-pin-guard/README.md index 8750edef..8223bce6 100644 --- a/repository-external-reference-pin-guard/README.md +++ b/repository-external-reference-pin-guard/README.md @@ -11,7 +11,7 @@ This module checks whether a scientific repository can safely publish a DOI, cit - API sources use dated snapshots with checksum evidence instead of floating "latest" endpoints. - Export bundles do not require authenticated external references. - License and attribution metadata are present before DOI publication. -- Reference verification evidence is fresh enough for release. +- Reference verification evidence is fresh enough for release and is not future-dated. ## Commands diff --git a/repository-external-reference-pin-guard/index.js b/repository-external-reference-pin-guard/index.js index b180bf08..08206c72 100644 --- a/repository-external-reference-pin-guard/index.js +++ b/repository-external-reference-pin-guard/index.js @@ -92,6 +92,7 @@ function isStale(lastVerifiedAt, assessedAt, maxAgeDays) { const verified = Date.parse(lastVerifiedAt); const assessed = Date.parse(assessedAt); if (Number.isNaN(verified) || Number.isNaN(assessed)) return true; + if (verified > assessed) return true; const ageDays = Math.max(0, (assessed - verified) / (24 * 60 * 60 * 1000)); return ageDays > maxAgeDays; } diff --git a/repository-external-reference-pin-guard/requirements-map.md b/repository-external-reference-pin-guard/requirements-map.md index ceb73f9c..41df3101 100644 --- a/repository-external-reference-pin-guard/requirements-map.md +++ b/repository-external-reference-pin-guard/requirements-map.md @@ -7,7 +7,7 @@ Issue #10 asks for robust project repositories with versioned files, collaborati | File and metadata versioning | Holds releases when Git submodules or external code are not pinned to immutable commits. | | Hash-based integrity | Requires checksums, DOI evidence, or non-floating immutable versions for external datasets and model weights. | | Computation-aware reproducibility | Blocks reproducibility/export lanes when API data sources are floating or authenticated only. | -| Repository identifiers and citation | Prevents DOI publication when external references are stale or lack license/attribution metadata. | +| Repository identifiers and citation | Prevents DOI publication when external references are stale, future-dated, or lack license/attribution metadata. | | Programmatic access and export | Separates API metadata-only access from export-bundle and DOI publication release lanes. | ## Non-Overlap diff --git a/repository-external-reference-pin-guard/test.js b/repository-external-reference-pin-guard/test.js index 8c08428c..36d9c3f8 100644 --- a/repository-external-reference-pin-guard/test.js +++ b/repository-external-reference-pin-guard/test.js @@ -162,11 +162,36 @@ function testFloatingVersionAliasDoesNotCountAsDurableIdentifier() { assert.equal(packet.referenceSignals.exportable, false); } +function testFutureDatedVerificationEvidenceIsNotFresh() { + const packet = assessExternalReferences({ + repositoryId: 'repo-reference-future-verification', + assessedAt: '2026-05-28T12:00:00Z', + references: [ + { + id: 'dataset-future-verified', + kind: 'linked_dataset', + target: 'https://doi.org/10.5281/zenodo.7654321', + checksum: 'sha256:feedface', + doi: '10.5281/zenodo.7654321', + license: 'CC-BY-4.0', + attribution: 'Example Lab', + lastVerifiedAt: '2026-05-29T12:00:00Z' + } + ] + }); + + assert.equal(packet.status, 'hold_repository_release'); + assert.deepEqual(findingCodes(packet), ['STALE_REFERENCE_EVIDENCE']); + assert.ok(packet.actions.includes('refresh_reference_verification:dataset-future-verified')); + assert.equal(packet.referenceSignals.verificationFresh, false); +} + const tests = [ testBlocksFloatingAndNonExportableExternalReferences, testAllowsPinnedExportableReferences, testStagesReferencesMissingLicenseAttributionOnly, - testFloatingVersionAliasDoesNotCountAsDurableIdentifier + testFloatingVersionAliasDoesNotCountAsDurableIdentifier, + testFutureDatedVerificationEvidenceIsNotFresh ]; for (const test of tests) { From 0026dde41e2807e59d61ec6f4e22e4a569c30a4e Mon Sep 17 00:00:00 2001 From: KoiosSG Date: Fri, 29 May 2026 18:32:31 +0200 Subject: [PATCH 04/12] Validate API snapshot dates for references --- .../README.md | 2 +- .../acceptance-notes.md | 1 + .../index.js | 10 +++++-- .../requirements-map.md | 2 +- .../test.js | 28 ++++++++++++++++++- 5 files changed, 37 insertions(+), 6 deletions(-) diff --git a/repository-external-reference-pin-guard/README.md b/repository-external-reference-pin-guard/README.md index 8223bce6..692806dd 100644 --- a/repository-external-reference-pin-guard/README.md +++ b/repository-external-reference-pin-guard/README.md @@ -8,7 +8,7 @@ This module checks whether a scientific repository can safely publish a DOI, cit - Git submodules and external code are pinned to immutable commit SHAs. - Linked datasets and model weights have checksum, DOI, or immutable version evidence; floating aliases such as `latest` do not count. -- API sources use dated snapshots with checksum evidence instead of floating "latest" endpoints. +- API sources use parseable, non-future dated snapshots with checksum evidence instead of floating "latest" endpoints. - Export bundles do not require authenticated external references. - License and attribution metadata are present before DOI publication. - Reference verification evidence is fresh enough for release and is not future-dated. diff --git a/repository-external-reference-pin-guard/acceptance-notes.md b/repository-external-reference-pin-guard/acceptance-notes.md index ce5b31bb..22529222 100644 --- a/repository-external-reference-pin-guard/acceptance-notes.md +++ b/repository-external-reference-pin-guard/acceptance-notes.md @@ -15,6 +15,7 @@ Expected evidence: - `reports/blocked-packet.json` blocks repository release when external references are floating, authenticated only, stale, or missing durable identifiers. - Floating version aliases such as `latest` are blocked unless the reference also has checksum or DOI evidence. +- Future-dated API snapshots do not count as pinned snapshot evidence for DOI/export release. - `reports/warning-packet.json` stages pinned references that still need license and attribution metadata. - `reports/clean-packet.json` releases a repository with immutable external pins, fresh verification evidence, and exportable metadata. - `reports/external-reference-report.md` summarizes lanes and finding codes. diff --git a/repository-external-reference-pin-guard/index.js b/repository-external-reference-pin-guard/index.js index 08206c72..0cb7aa32 100644 --- a/repository-external-reference-pin-guard/index.js +++ b/repository-external-reference-pin-guard/index.js @@ -35,7 +35,7 @@ function assessReference(reference, assessedAt, policy) { findings.push(finding(reference, 'FLOATING_GIT_REFERENCE', 'blocker', 'Git reference must be pinned to an immutable commit SHA before release.')); } - if (reference.kind === 'api_source' && !hasSnapshotEvidence(reference)) { + if (reference.kind === 'api_source' && !hasSnapshotEvidence(reference, assessedAt)) { findings.push(finding(reference, 'FLOATING_API_REFERENCE', 'blocker', 'API source must reference a dated snapshot with checksum evidence.')); } @@ -70,8 +70,12 @@ function hasPinnedCommit(reference) { return /^[a-f0-9]{40}$/i.test(reference.commitSha || ''); } -function hasSnapshotEvidence(reference) { - return hasText(reference.snapshotDate) && hasText(reference.checksum); +function hasSnapshotEvidence(reference, assessedAt) { + if (!hasText(reference.snapshotDate) || !hasText(reference.checksum)) return false; + const snapshot = Date.parse(reference.snapshotDate); + const assessed = Date.parse(assessedAt); + if (Number.isNaN(snapshot) || Number.isNaN(assessed)) return false; + return snapshot <= assessed; } function needsDurableIdentifier(reference) { diff --git a/repository-external-reference-pin-guard/requirements-map.md b/repository-external-reference-pin-guard/requirements-map.md index 41df3101..524e7a5f 100644 --- a/repository-external-reference-pin-guard/requirements-map.md +++ b/repository-external-reference-pin-guard/requirements-map.md @@ -6,7 +6,7 @@ Issue #10 asks for robust project repositories with versioned files, collaborati | --- | --- | | File and metadata versioning | Holds releases when Git submodules or external code are not pinned to immutable commits. | | Hash-based integrity | Requires checksums, DOI evidence, or non-floating immutable versions for external datasets and model weights. | -| Computation-aware reproducibility | Blocks reproducibility/export lanes when API data sources are floating or authenticated only. | +| Computation-aware reproducibility | Blocks reproducibility/export lanes when API data sources are floating, authenticated only, or backed by malformed/future snapshot dates. | | Repository identifiers and citation | Prevents DOI publication when external references are stale, future-dated, or lack license/attribution metadata. | | Programmatic access and export | Separates API metadata-only access from export-bundle and DOI publication release lanes. | diff --git a/repository-external-reference-pin-guard/test.js b/repository-external-reference-pin-guard/test.js index 36d9c3f8..3df9768e 100644 --- a/repository-external-reference-pin-guard/test.js +++ b/repository-external-reference-pin-guard/test.js @@ -186,12 +186,38 @@ function testFutureDatedVerificationEvidenceIsNotFresh() { assert.equal(packet.referenceSignals.verificationFresh, false); } +function testFutureDatedApiSnapshotDoesNotCountAsPinnedEvidence() { + const packet = assessExternalReferences({ + repositoryId: 'repo-reference-future-api-snapshot', + assessedAt: '2026-05-28T12:00:00Z', + references: [ + { + id: 'api-future-snapshot', + kind: 'api_source', + target: 'https://api.example.invalid/weather/snapshots/2026-06-01.json', + snapshotDate: '2026-06-01', + checksum: 'sha256:abcdef', + authRequired: false, + license: 'CC0-1.0', + attribution: 'Example Weather API', + lastVerifiedAt: '2026-05-20T08:00:00Z' + } + ] + }); + + assert.equal(packet.status, 'hold_repository_release'); + assert.deepEqual(findingCodes(packet), ['FLOATING_API_REFERENCE']); + assert.ok(packet.actions.includes('pin_external_reference:api-future-snapshot')); + assert.equal(packet.referenceSignals.immutablePins, false); +} + const tests = [ testBlocksFloatingAndNonExportableExternalReferences, testAllowsPinnedExportableReferences, testStagesReferencesMissingLicenseAttributionOnly, testFloatingVersionAliasDoesNotCountAsDurableIdentifier, - testFutureDatedVerificationEvidenceIsNotFresh + testFutureDatedVerificationEvidenceIsNotFresh, + testFutureDatedApiSnapshotDoesNotCountAsPinnedEvidence ]; for (const test of tests) { From 3c09dce61d0ffd6433ea301e8c2217cdfcaef1bb Mon Sep 17 00:00:00 2001 From: KoiosSG Date: Fri, 29 May 2026 20:41:45 +0200 Subject: [PATCH 05/12] Require reference verification evidence --- .../README.md | 2 +- .../acceptance-notes.md | 1 + .../index.js | 9 ++++++- .../requirements-map.md | 2 +- .../test.js | 26 ++++++++++++++++++- 5 files changed, 36 insertions(+), 4 deletions(-) diff --git a/repository-external-reference-pin-guard/README.md b/repository-external-reference-pin-guard/README.md index 692806dd..0407493d 100644 --- a/repository-external-reference-pin-guard/README.md +++ b/repository-external-reference-pin-guard/README.md @@ -11,7 +11,7 @@ This module checks whether a scientific repository can safely publish a DOI, cit - API sources use parseable, non-future dated snapshots with checksum evidence instead of floating "latest" endpoints. - Export bundles do not require authenticated external references. - License and attribution metadata are present before DOI publication. -- Reference verification evidence is fresh enough for release and is not future-dated. +- Reference verification evidence is present, fresh enough for release, and not future-dated. ## Commands diff --git a/repository-external-reference-pin-guard/acceptance-notes.md b/repository-external-reference-pin-guard/acceptance-notes.md index 22529222..5fb6537e 100644 --- a/repository-external-reference-pin-guard/acceptance-notes.md +++ b/repository-external-reference-pin-guard/acceptance-notes.md @@ -16,6 +16,7 @@ Expected evidence: - `reports/blocked-packet.json` blocks repository release when external references are floating, authenticated only, stale, or missing durable identifiers. - Floating version aliases such as `latest` are blocked unless the reference also has checksum or DOI evidence. - Future-dated API snapshots do not count as pinned snapshot evidence for DOI/export release. +- Otherwise pinned references without verification timestamps are blocked until verification evidence is refreshed. - `reports/warning-packet.json` stages pinned references that still need license and attribution metadata. - `reports/clean-packet.json` releases a repository with immutable external pins, fresh verification evidence, and exportable metadata. - `reports/external-reference-report.md` summarizes lanes and finding codes. diff --git a/repository-external-reference-pin-guard/index.js b/repository-external-reference-pin-guard/index.js index 0cb7aa32..8fd939ae 100644 --- a/repository-external-reference-pin-guard/index.js +++ b/repository-external-reference-pin-guard/index.js @@ -55,7 +55,9 @@ function assessReference(reference, assessedAt, policy) { findings.push(finding(reference, 'MISSING_ATTRIBUTION', 'warning', 'External reference needs attribution metadata before DOI publication.')); } - if (isStale(reference.lastVerifiedAt, assessedAt, policy.maxReferenceAgeDays)) { + if (hasMissingVerificationEvidence(reference, findings)) { + findings.push(finding(reference, 'STALE_REFERENCE_EVIDENCE', 'blocker', 'External reference needs verification evidence before release.')); + } else if (isStale(reference.lastVerifiedAt, assessedAt, policy.maxReferenceAgeDays)) { findings.push(finding(reference, 'STALE_REFERENCE_EVIDENCE', 'blocker', 'External reference verification is older than policy allows.')); } @@ -91,6 +93,11 @@ function hasImmutableVersion(version) { return !/^(latest|main|master|head|current|stable|dev|nightly)$/i.test(version.trim()); } +function hasMissingVerificationEvidence(reference, findings) { + return !hasText(reference.lastVerifiedAt) + && !findings.some((item) => item.severity === 'blocker'); +} + function isStale(lastVerifiedAt, assessedAt, maxAgeDays) { if (!lastVerifiedAt || !assessedAt) return false; const verified = Date.parse(lastVerifiedAt); diff --git a/repository-external-reference-pin-guard/requirements-map.md b/repository-external-reference-pin-guard/requirements-map.md index 524e7a5f..8735fed2 100644 --- a/repository-external-reference-pin-guard/requirements-map.md +++ b/repository-external-reference-pin-guard/requirements-map.md @@ -7,7 +7,7 @@ Issue #10 asks for robust project repositories with versioned files, collaborati | File and metadata versioning | Holds releases when Git submodules or external code are not pinned to immutable commits. | | Hash-based integrity | Requires checksums, DOI evidence, or non-floating immutable versions for external datasets and model weights. | | Computation-aware reproducibility | Blocks reproducibility/export lanes when API data sources are floating, authenticated only, or backed by malformed/future snapshot dates. | -| Repository identifiers and citation | Prevents DOI publication when external references are stale, future-dated, or lack license/attribution metadata. | +| Repository identifiers and citation | Prevents DOI publication when external references lack verification timestamps, are stale, future-dated, or lack license/attribution metadata. | | Programmatic access and export | Separates API metadata-only access from export-bundle and DOI publication release lanes. | ## Non-Overlap diff --git a/repository-external-reference-pin-guard/test.js b/repository-external-reference-pin-guard/test.js index 3df9768e..525ffc1d 100644 --- a/repository-external-reference-pin-guard/test.js +++ b/repository-external-reference-pin-guard/test.js @@ -211,13 +211,37 @@ function testFutureDatedApiSnapshotDoesNotCountAsPinnedEvidence() { assert.equal(packet.referenceSignals.immutablePins, false); } +function testMissingVerificationEvidenceBlocksOtherwisePinnedReference() { + const packet = assessExternalReferences({ + repositoryId: 'repo-reference-missing-verification', + assessedAt: '2026-05-28T12:00:00Z', + references: [ + { + id: 'dataset-needs-verification', + kind: 'linked_dataset', + target: 'https://doi.org/10.5281/zenodo.2345678', + checksum: 'sha256:abcdef123456', + doi: '10.5281/zenodo.2345678', + license: 'CC-BY-4.0', + attribution: 'Example Lab' + } + ] + }); + + assert.equal(packet.status, 'hold_repository_release'); + assert.deepEqual(findingCodes(packet), ['STALE_REFERENCE_EVIDENCE']); + assert.ok(packet.actions.includes('refresh_reference_verification:dataset-needs-verification')); + assert.equal(packet.referenceSignals.verificationFresh, false); +} + const tests = [ testBlocksFloatingAndNonExportableExternalReferences, testAllowsPinnedExportableReferences, testStagesReferencesMissingLicenseAttributionOnly, testFloatingVersionAliasDoesNotCountAsDurableIdentifier, testFutureDatedVerificationEvidenceIsNotFresh, - testFutureDatedApiSnapshotDoesNotCountAsPinnedEvidence + testFutureDatedApiSnapshotDoesNotCountAsPinnedEvidence, + testMissingVerificationEvidenceBlocksOtherwisePinnedReference ]; for (const test of tests) { From 99ff7a80f9cd56ee42e002af7d88dd2142924a8c Mon Sep 17 00:00:00 2001 From: KoiosSG Date: Fri, 29 May 2026 23:36:48 +0200 Subject: [PATCH 06/12] Reject null git reference pins --- .../README.md | 2 +- .../acceptance-notes.md | 1 + .../index.js | 3 ++- .../requirements-map.md | 2 +- .../test.js | 24 +++++++++++++++++++ 5 files changed, 29 insertions(+), 3 deletions(-) diff --git a/repository-external-reference-pin-guard/README.md b/repository-external-reference-pin-guard/README.md index 0407493d..b3de656b 100644 --- a/repository-external-reference-pin-guard/README.md +++ b/repository-external-reference-pin-guard/README.md @@ -6,7 +6,7 @@ This module checks whether a scientific repository can safely publish a DOI, cit ## What It Checks -- Git submodules and external code are pinned to immutable commit SHAs. +- Git submodules and external code are pinned to immutable commit SHAs, rejecting null all-zero placeholders. - Linked datasets and model weights have checksum, DOI, or immutable version evidence; floating aliases such as `latest` do not count. - API sources use parseable, non-future dated snapshots with checksum evidence instead of floating "latest" endpoints. - Export bundles do not require authenticated external references. diff --git a/repository-external-reference-pin-guard/acceptance-notes.md b/repository-external-reference-pin-guard/acceptance-notes.md index 5fb6537e..22e41ac5 100644 --- a/repository-external-reference-pin-guard/acceptance-notes.md +++ b/repository-external-reference-pin-guard/acceptance-notes.md @@ -14,6 +14,7 @@ npm run check Expected evidence: - `reports/blocked-packet.json` blocks repository release when external references are floating, authenticated only, stale, or missing durable identifiers. +- All-zero Git commit placeholders are treated as unpinned references rather than immutable release evidence. - Floating version aliases such as `latest` are blocked unless the reference also has checksum or DOI evidence. - Future-dated API snapshots do not count as pinned snapshot evidence for DOI/export release. - Otherwise pinned references without verification timestamps are blocked until verification evidence is refreshed. diff --git a/repository-external-reference-pin-guard/index.js b/repository-external-reference-pin-guard/index.js index 8fd939ae..7cec50d7 100644 --- a/repository-external-reference-pin-guard/index.js +++ b/repository-external-reference-pin-guard/index.js @@ -69,7 +69,8 @@ function isGitReference(reference) { } function hasPinnedCommit(reference) { - return /^[a-f0-9]{40}$/i.test(reference.commitSha || ''); + const commitSha = reference.commitSha || ''; + return /^[a-f0-9]{40}$/i.test(commitSha) && !/^0{40}$/.test(commitSha); } function hasSnapshotEvidence(reference, assessedAt) { diff --git a/repository-external-reference-pin-guard/requirements-map.md b/repository-external-reference-pin-guard/requirements-map.md index 8735fed2..edb1b184 100644 --- a/repository-external-reference-pin-guard/requirements-map.md +++ b/repository-external-reference-pin-guard/requirements-map.md @@ -4,7 +4,7 @@ Issue #10 asks for robust project repositories with versioned files, collaborati | Issue #10 area | Coverage in this slice | | --- | --- | -| File and metadata versioning | Holds releases when Git submodules or external code are not pinned to immutable commits. | +| File and metadata versioning | Holds releases when Git submodules or external code are not pinned to immutable commits, including null all-zero commit placeholders. | | Hash-based integrity | Requires checksums, DOI evidence, or non-floating immutable versions for external datasets and model weights. | | Computation-aware reproducibility | Blocks reproducibility/export lanes when API data sources are floating, authenticated only, or backed by malformed/future snapshot dates. | | Repository identifiers and citation | Prevents DOI publication when external references lack verification timestamps, are stale, future-dated, or lack license/attribution metadata. | diff --git a/repository-external-reference-pin-guard/test.js b/repository-external-reference-pin-guard/test.js index 525ffc1d..d78cfbf3 100644 --- a/repository-external-reference-pin-guard/test.js +++ b/repository-external-reference-pin-guard/test.js @@ -211,6 +211,29 @@ function testFutureDatedApiSnapshotDoesNotCountAsPinnedEvidence() { assert.equal(packet.referenceSignals.immutablePins, false); } +function testNullGitCommitShaDoesNotCountAsImmutablePin() { + const packet = assessExternalReferences({ + repositoryId: 'repo-reference-null-git-pin', + assessedAt: '2026-05-28T12:00:00Z', + references: [ + { + id: 'submodule-null-sha', + kind: 'git_submodule', + target: 'https://github.com/example/analysis-tools', + commitSha: '0000000000000000000000000000000000000000', + license: 'MIT', + attribution: 'Example Analysis Tools', + lastVerifiedAt: '2026-05-20T08:00:00Z' + } + ] + }); + + assert.equal(packet.status, 'hold_repository_release'); + assert.deepEqual(findingCodes(packet), ['FLOATING_GIT_REFERENCE']); + assert.ok(packet.actions.includes('pin_external_reference:submodule-null-sha')); + assert.equal(packet.referenceSignals.immutablePins, false); +} + function testMissingVerificationEvidenceBlocksOtherwisePinnedReference() { const packet = assessExternalReferences({ repositoryId: 'repo-reference-missing-verification', @@ -241,6 +264,7 @@ const tests = [ testFloatingVersionAliasDoesNotCountAsDurableIdentifier, testFutureDatedVerificationEvidenceIsNotFresh, testFutureDatedApiSnapshotDoesNotCountAsPinnedEvidence, + testNullGitCommitShaDoesNotCountAsImmutablePin, testMissingVerificationEvidenceBlocksOtherwisePinnedReference ]; From c3d3811190d26be0f00267a0208549adb4840179 Mon Sep 17 00:00:00 2001 From: KoiosSG Date: Sat, 30 May 2026 01:01:19 +0200 Subject: [PATCH 07/12] Validate external reference checksums --- .../README.md | 4 +- .../acceptance-notes.md | 1 + .../index.js | 9 +++- .../requirements-map.md | 4 +- .../sample-data.js | 2 +- .../test.js | 52 +++++++++++++++++++ 6 files changed, 65 insertions(+), 7 deletions(-) diff --git a/repository-external-reference-pin-guard/README.md b/repository-external-reference-pin-guard/README.md index b3de656b..37f31dff 100644 --- a/repository-external-reference-pin-guard/README.md +++ b/repository-external-reference-pin-guard/README.md @@ -7,8 +7,8 @@ This module checks whether a scientific repository can safely publish a DOI, cit ## What It Checks - Git submodules and external code are pinned to immutable commit SHAs, rejecting null all-zero placeholders. -- Linked datasets and model weights have checksum, DOI, or immutable version evidence; floating aliases such as `latest` do not count. -- API sources use parseable, non-future dated snapshots with checksum evidence instead of floating "latest" endpoints. +- Linked datasets and model weights have parseable checksum, DOI, or immutable version evidence; floating aliases such as `latest` do not count. +- API sources use parseable, non-future dated snapshots with parseable checksum evidence instead of floating "latest" endpoints. - Export bundles do not require authenticated external references. - License and attribution metadata are present before DOI publication. - Reference verification evidence is present, fresh enough for release, and not future-dated. diff --git a/repository-external-reference-pin-guard/acceptance-notes.md b/repository-external-reference-pin-guard/acceptance-notes.md index 22e41ac5..22458390 100644 --- a/repository-external-reference-pin-guard/acceptance-notes.md +++ b/repository-external-reference-pin-guard/acceptance-notes.md @@ -16,6 +16,7 @@ Expected evidence: - `reports/blocked-packet.json` blocks repository release when external references are floating, authenticated only, stale, or missing durable identifiers. - All-zero Git commit placeholders are treated as unpinned references rather than immutable release evidence. - Floating version aliases such as `latest` are blocked unless the reference also has checksum or DOI evidence. +- Invalid checksum placeholders such as `pending` do not count as durable identifier or API snapshot evidence. - Future-dated API snapshots do not count as pinned snapshot evidence for DOI/export release. - Otherwise pinned references without verification timestamps are blocked until verification evidence is refreshed. - `reports/warning-packet.json` stages pinned references that still need license and attribution metadata. diff --git a/repository-external-reference-pin-guard/index.js b/repository-external-reference-pin-guard/index.js index 7cec50d7..57f62157 100644 --- a/repository-external-reference-pin-guard/index.js +++ b/repository-external-reference-pin-guard/index.js @@ -74,7 +74,7 @@ function hasPinnedCommit(reference) { } function hasSnapshotEvidence(reference, assessedAt) { - if (!hasText(reference.snapshotDate) || !hasText(reference.checksum)) return false; + if (!hasText(reference.snapshotDate) || !hasValidChecksum(reference.checksum)) return false; const snapshot = Date.parse(reference.snapshotDate); const assessed = Date.parse(assessedAt); if (Number.isNaN(snapshot) || Number.isNaN(assessed)) return false; @@ -86,7 +86,12 @@ function needsDurableIdentifier(reference) { } function hasDurableIdentifier(reference) { - return hasText(reference.checksum) || hasText(reference.doi) || hasImmutableVersion(reference.version); + return hasValidChecksum(reference.checksum) || hasText(reference.doi) || hasImmutableVersion(reference.version); +} + +function hasValidChecksum(checksum) { + return typeof checksum === 'string' + && /^(sha256|sha384|sha512):[a-f0-9]{6,}$/i.test(checksum.trim()); } function hasImmutableVersion(version) { diff --git a/repository-external-reference-pin-guard/requirements-map.md b/repository-external-reference-pin-guard/requirements-map.md index edb1b184..3b08d88e 100644 --- a/repository-external-reference-pin-guard/requirements-map.md +++ b/repository-external-reference-pin-guard/requirements-map.md @@ -5,8 +5,8 @@ Issue #10 asks for robust project repositories with versioned files, collaborati | Issue #10 area | Coverage in this slice | | --- | --- | | File and metadata versioning | Holds releases when Git submodules or external code are not pinned to immutable commits, including null all-zero commit placeholders. | -| Hash-based integrity | Requires checksums, DOI evidence, or non-floating immutable versions for external datasets and model weights. | -| Computation-aware reproducibility | Blocks reproducibility/export lanes when API data sources are floating, authenticated only, or backed by malformed/future snapshot dates. | +| Hash-based integrity | Requires parseable checksums, DOI evidence, or non-floating immutable versions for external datasets and model weights. | +| Computation-aware reproducibility | Blocks reproducibility/export lanes when API data sources are floating, authenticated only, or backed by malformed/future snapshot dates or invalid checksum evidence. | | Repository identifiers and citation | Prevents DOI publication when external references lack verification timestamps, are stale, future-dated, or lack license/attribution metadata. | | Programmatic access and export | Separates API metadata-only access from export-bundle and DOI publication release lanes. | diff --git a/repository-external-reference-pin-guard/sample-data.js b/repository-external-reference-pin-guard/sample-data.js index def458cd..ede87d36 100644 --- a/repository-external-reference-pin-guard/sample-data.js +++ b/repository-external-reference-pin-guard/sample-data.js @@ -19,7 +19,7 @@ const riskyRepository = { id: 'dataset-lab-export', kind: 'linked_dataset', target: 'https://data.example.invalid/lab-export.csv', - checksum: '', + checksum: 'pending', doi: '', license: 'CC-BY-4.0', attribution: 'Example Lab', diff --git a/repository-external-reference-pin-guard/test.js b/repository-external-reference-pin-guard/test.js index d78cfbf3..be89aa87 100644 --- a/repository-external-reference-pin-guard/test.js +++ b/repository-external-reference-pin-guard/test.js @@ -162,6 +162,31 @@ function testFloatingVersionAliasDoesNotCountAsDurableIdentifier() { assert.equal(packet.referenceSignals.exportable, false); } +function testInvalidChecksumDoesNotCountAsDurableIdentifier() { + const packet = assessExternalReferences({ + repositoryId: 'repo-reference-invalid-checksum', + assessedAt: '2026-05-28T12:00:00Z', + references: [ + { + id: 'dataset-invalid-checksum', + kind: 'linked_dataset', + target: 'https://data.example.invalid/lab-export.csv', + checksum: 'pending', + doi: '', + version: '', + license: 'CC-BY-4.0', + attribution: 'Example Lab', + lastVerifiedAt: '2026-05-20T08:00:00Z' + } + ] + }); + + assert.equal(packet.status, 'hold_repository_release'); + assert.deepEqual(findingCodes(packet), ['MISSING_DURABLE_IDENTIFIER']); + assert.ok(packet.actions.includes('add_checksum_or_doi:dataset-invalid-checksum')); + assert.equal(packet.referenceSignals.exportable, false); +} + function testFutureDatedVerificationEvidenceIsNotFresh() { const packet = assessExternalReferences({ repositoryId: 'repo-reference-future-verification', @@ -211,6 +236,31 @@ function testFutureDatedApiSnapshotDoesNotCountAsPinnedEvidence() { assert.equal(packet.referenceSignals.immutablePins, false); } +function testInvalidApiSnapshotChecksumDoesNotCountAsPinnedEvidence() { + const packet = assessExternalReferences({ + repositoryId: 'repo-reference-invalid-api-checksum', + assessedAt: '2026-05-28T12:00:00Z', + references: [ + { + id: 'api-invalid-checksum', + kind: 'api_source', + target: 'https://api.example.invalid/weather/snapshots/2026-05-01.json', + snapshotDate: '2026-05-01', + checksum: 'pending', + authRequired: false, + license: 'CC0-1.0', + attribution: 'Example Weather API', + lastVerifiedAt: '2026-05-20T08:00:00Z' + } + ] + }); + + assert.equal(packet.status, 'hold_repository_release'); + assert.deepEqual(findingCodes(packet), ['FLOATING_API_REFERENCE']); + assert.ok(packet.actions.includes('pin_external_reference:api-invalid-checksum')); + assert.equal(packet.referenceSignals.immutablePins, false); +} + function testNullGitCommitShaDoesNotCountAsImmutablePin() { const packet = assessExternalReferences({ repositoryId: 'repo-reference-null-git-pin', @@ -262,8 +312,10 @@ const tests = [ testAllowsPinnedExportableReferences, testStagesReferencesMissingLicenseAttributionOnly, testFloatingVersionAliasDoesNotCountAsDurableIdentifier, + testInvalidChecksumDoesNotCountAsDurableIdentifier, testFutureDatedVerificationEvidenceIsNotFresh, testFutureDatedApiSnapshotDoesNotCountAsPinnedEvidence, + testInvalidApiSnapshotChecksumDoesNotCountAsPinnedEvidence, testNullGitCommitShaDoesNotCountAsImmutablePin, testMissingVerificationEvidenceBlocksOtherwisePinnedReference ]; From 5e54fa4db49d6d6f9abf516a83a220ffe2a73f65 Mon Sep 17 00:00:00 2001 From: KoiosSG Date: Sat, 30 May 2026 09:19:55 +0200 Subject: [PATCH 08/12] Require full-length external reference checksums --- .../README.md | 4 +- .../acceptance-notes.md | 1 + .../index.js | 14 ++++++- .../requirements-map.md | 4 +- .../sample-data.js | 8 ++-- .../test.js | 40 +++++++++++++++---- 6 files changed, 54 insertions(+), 17 deletions(-) diff --git a/repository-external-reference-pin-guard/README.md b/repository-external-reference-pin-guard/README.md index 37f31dff..38de92ba 100644 --- a/repository-external-reference-pin-guard/README.md +++ b/repository-external-reference-pin-guard/README.md @@ -7,8 +7,8 @@ This module checks whether a scientific repository can safely publish a DOI, cit ## What It Checks - Git submodules and external code are pinned to immutable commit SHAs, rejecting null all-zero placeholders. -- Linked datasets and model weights have parseable checksum, DOI, or immutable version evidence; floating aliases such as `latest` do not count. -- API sources use parseable, non-future dated snapshots with parseable checksum evidence instead of floating "latest" endpoints. +- Linked datasets and model weights have full-length SHA checksum, DOI, or immutable version evidence; floating aliases such as `latest` do not count. +- API sources use parseable, non-future dated snapshots with full-length SHA checksum evidence instead of floating "latest" endpoints. - Export bundles do not require authenticated external references. - License and attribution metadata are present before DOI publication. - Reference verification evidence is present, fresh enough for release, and not future-dated. diff --git a/repository-external-reference-pin-guard/acceptance-notes.md b/repository-external-reference-pin-guard/acceptance-notes.md index 22458390..53613984 100644 --- a/repository-external-reference-pin-guard/acceptance-notes.md +++ b/repository-external-reference-pin-guard/acceptance-notes.md @@ -17,6 +17,7 @@ Expected evidence: - All-zero Git commit placeholders are treated as unpinned references rather than immutable release evidence. - Floating version aliases such as `latest` are blocked unless the reference also has checksum or DOI evidence. - Invalid checksum placeholders such as `pending` do not count as durable identifier or API snapshot evidence. +- Truncated checksum values such as `sha256:abcdef` do not count as API snapshot evidence. - Future-dated API snapshots do not count as pinned snapshot evidence for DOI/export release. - Otherwise pinned references without verification timestamps are blocked until verification evidence is refreshed. - `reports/warning-packet.json` stages pinned references that still need license and attribution metadata. diff --git a/repository-external-reference-pin-guard/index.js b/repository-external-reference-pin-guard/index.js index 57f62157..d229ade2 100644 --- a/repository-external-reference-pin-guard/index.js +++ b/repository-external-reference-pin-guard/index.js @@ -4,6 +4,12 @@ const DEFAULT_POLICY = { maxReferenceAgeDays: 180 }; +const CHECKSUM_HEX_LENGTHS = { + sha256: 64, + sha384: 96, + sha512: 128 +}; + function assessExternalReferences(repository) { const policy = { ...DEFAULT_POLICY, ...(repository.policy || {}) }; const findings = repository.references @@ -90,8 +96,12 @@ function hasDurableIdentifier(reference) { } function hasValidChecksum(checksum) { - return typeof checksum === 'string' - && /^(sha256|sha384|sha512):[a-f0-9]{6,}$/i.test(checksum.trim()); + if (typeof checksum !== 'string') return false; + const match = checksum.trim().match(/^(sha256|sha384|sha512):([a-f0-9]+)$/i); + if (!match) return false; + + const algorithm = match[1].toLowerCase(); + return match[2].length === CHECKSUM_HEX_LENGTHS[algorithm]; } function hasImmutableVersion(version) { diff --git a/repository-external-reference-pin-guard/requirements-map.md b/repository-external-reference-pin-guard/requirements-map.md index 3b08d88e..44d4a0c0 100644 --- a/repository-external-reference-pin-guard/requirements-map.md +++ b/repository-external-reference-pin-guard/requirements-map.md @@ -5,8 +5,8 @@ Issue #10 asks for robust project repositories with versioned files, collaborati | Issue #10 area | Coverage in this slice | | --- | --- | | File and metadata versioning | Holds releases when Git submodules or external code are not pinned to immutable commits, including null all-zero commit placeholders. | -| Hash-based integrity | Requires parseable checksums, DOI evidence, or non-floating immutable versions for external datasets and model weights. | -| Computation-aware reproducibility | Blocks reproducibility/export lanes when API data sources are floating, authenticated only, or backed by malformed/future snapshot dates or invalid checksum evidence. | +| Hash-based integrity | Requires full-length SHA checksums, DOI evidence, or non-floating immutable versions for external datasets and model weights. | +| Computation-aware reproducibility | Blocks reproducibility/export lanes when API data sources are floating, authenticated only, or backed by malformed/future snapshot dates, invalid checksum evidence, or truncated checksum evidence. | | Repository identifiers and citation | Prevents DOI publication when external references lack verification timestamps, are stale, future-dated, or lack license/attribution metadata. | | Programmatic access and export | Separates API metadata-only access from export-bundle and DOI publication release lanes. | diff --git a/repository-external-reference-pin-guard/sample-data.js b/repository-external-reference-pin-guard/sample-data.js index ede87d36..ab75331d 100644 --- a/repository-external-reference-pin-guard/sample-data.js +++ b/repository-external-reference-pin-guard/sample-data.js @@ -30,7 +30,7 @@ const riskyRepository = { kind: 'api_source', target: 'https://api.example.invalid/weather/latest', snapshotDate: '', - checksum: 'sha256:abcdef', + checksum: 'sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', authRequired: true, license: 'CC0-1.0', attribution: 'Example Weather API', @@ -56,7 +56,7 @@ const cleanRepository = { id: 'dataset-lab-export', kind: 'linked_dataset', target: 'https://doi.org/10.5281/zenodo.1234567', - checksum: 'sha256:1234567890abcdef', + checksum: 'sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef', doi: '10.5281/zenodo.1234567', license: 'CC-BY-4.0', attribution: 'Example Lab', @@ -67,7 +67,7 @@ const cleanRepository = { kind: 'api_source', target: 'https://api.example.invalid/weather/snapshots/2026-05-01.json', snapshotDate: '2026-05-01', - checksum: 'sha256:abcdef', + checksum: 'sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', authRequired: false, license: 'CC0-1.0', attribution: 'Example Weather API', @@ -84,7 +84,7 @@ const warningRepository = { id: 'model-weights', kind: 'model_weights', target: 'https://models.example.invalid/model-v3.bin', - checksum: 'sha256:feedface', + checksum: 'sha256:feedfacefeedfacefeedfacefeedfacefeedfacefeedfacefeedfacefeedface', version: 'v3.0.1', license: '', attribution: '', diff --git a/repository-external-reference-pin-guard/test.js b/repository-external-reference-pin-guard/test.js index be89aa87..045b10c4 100644 --- a/repository-external-reference-pin-guard/test.js +++ b/repository-external-reference-pin-guard/test.js @@ -38,7 +38,7 @@ function testBlocksFloatingAndNonExportableExternalReferences() { kind: 'api_source', target: 'https://api.example.invalid/weather/latest', snapshotDate: '', - checksum: 'sha256:abcdef', + checksum: 'sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', authRequired: true, license: 'CC0-1.0', attribution: 'Example Weather API' @@ -80,7 +80,7 @@ function testAllowsPinnedExportableReferences() { id: 'dataset-lab-export', kind: 'linked_dataset', target: 'https://doi.org/10.5281/zenodo.1234567', - checksum: 'sha256:1234567890abcdef', + checksum: 'sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef', doi: '10.5281/zenodo.1234567', license: 'CC-BY-4.0', attribution: 'Example Lab', @@ -91,7 +91,7 @@ function testAllowsPinnedExportableReferences() { kind: 'api_source', target: 'https://api.example.invalid/weather/snapshots/2026-05-01.json', snapshotDate: '2026-05-01', - checksum: 'sha256:abcdef', + checksum: 'sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', authRequired: false, license: 'CC0-1.0', attribution: 'Example Weather API', @@ -118,7 +118,7 @@ function testStagesReferencesMissingLicenseAttributionOnly() { id: 'model-weights', kind: 'model_weights', target: 'https://models.example.invalid/model-v3.bin', - checksum: 'sha256:feedface', + checksum: 'sha256:feedfacefeedfacefeedfacefeedfacefeedfacefeedfacefeedfacefeedface', version: 'v3.0.1', license: '', attribution: '', @@ -196,7 +196,7 @@ function testFutureDatedVerificationEvidenceIsNotFresh() { id: 'dataset-future-verified', kind: 'linked_dataset', target: 'https://doi.org/10.5281/zenodo.7654321', - checksum: 'sha256:feedface', + checksum: 'sha256:feedfacefeedfacefeedfacefeedfacefeedfacefeedfacefeedfacefeedface', doi: '10.5281/zenodo.7654321', license: 'CC-BY-4.0', attribution: 'Example Lab', @@ -221,7 +221,7 @@ function testFutureDatedApiSnapshotDoesNotCountAsPinnedEvidence() { kind: 'api_source', target: 'https://api.example.invalid/weather/snapshots/2026-06-01.json', snapshotDate: '2026-06-01', - checksum: 'sha256:abcdef', + checksum: 'sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', authRequired: false, license: 'CC0-1.0', attribution: 'Example Weather API', @@ -261,6 +261,31 @@ function testInvalidApiSnapshotChecksumDoesNotCountAsPinnedEvidence() { assert.equal(packet.referenceSignals.immutablePins, false); } +function testTruncatedApiSnapshotChecksumDoesNotCountAsPinnedEvidence() { + const packet = assessExternalReferences({ + repositoryId: 'repo-reference-truncated-api-checksum', + assessedAt: '2026-05-28T12:00:00Z', + references: [ + { + id: 'api-truncated-checksum', + kind: 'api_source', + target: 'https://api.example.invalid/weather/snapshots/2026-05-01.json', + snapshotDate: '2026-05-01', + checksum: 'sha256:abcdef', + authRequired: false, + license: 'CC0-1.0', + attribution: 'Example Weather API', + lastVerifiedAt: '2026-05-20T08:00:00Z' + } + ] + }); + + assert.equal(packet.status, 'hold_repository_release'); + assert.deepEqual(findingCodes(packet), ['FLOATING_API_REFERENCE']); + assert.ok(packet.actions.includes('pin_external_reference:api-truncated-checksum')); + assert.equal(packet.referenceSignals.immutablePins, false); +} + function testNullGitCommitShaDoesNotCountAsImmutablePin() { const packet = assessExternalReferences({ repositoryId: 'repo-reference-null-git-pin', @@ -293,7 +318,7 @@ function testMissingVerificationEvidenceBlocksOtherwisePinnedReference() { id: 'dataset-needs-verification', kind: 'linked_dataset', target: 'https://doi.org/10.5281/zenodo.2345678', - checksum: 'sha256:abcdef123456', + checksum: 'sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd', doi: '10.5281/zenodo.2345678', license: 'CC-BY-4.0', attribution: 'Example Lab' @@ -316,6 +341,7 @@ const tests = [ testFutureDatedVerificationEvidenceIsNotFresh, testFutureDatedApiSnapshotDoesNotCountAsPinnedEvidence, testInvalidApiSnapshotChecksumDoesNotCountAsPinnedEvidence, + testTruncatedApiSnapshotChecksumDoesNotCountAsPinnedEvidence, testNullGitCommitShaDoesNotCountAsImmutablePin, testMissingVerificationEvidenceBlocksOtherwisePinnedReference ]; From 00969a13f4fbaba4035b87c88053ea9c88e0238a Mon Sep 17 00:00:00 2001 From: KoiosSG Date: Sat, 30 May 2026 11:48:14 +0200 Subject: [PATCH 09/12] Reject placeholder DOI reference evidence --- .../README.md | 2 +- .../acceptance-notes.md | 1 + .../index.js | 8 +++++- .../make-demo-video.py | 2 +- .../reports/demo.mp4 | Bin 52531 -> 53699 bytes .../requirements-map.md | 2 +- .../sample-data.js | 2 +- .../test.js | 26 ++++++++++++++++++ 8 files changed, 38 insertions(+), 5 deletions(-) diff --git a/repository-external-reference-pin-guard/README.md b/repository-external-reference-pin-guard/README.md index 38de92ba..eccc15a7 100644 --- a/repository-external-reference-pin-guard/README.md +++ b/repository-external-reference-pin-guard/README.md @@ -7,7 +7,7 @@ This module checks whether a scientific repository can safely publish a DOI, cit ## What It Checks - Git submodules and external code are pinned to immutable commit SHAs, rejecting null all-zero placeholders. -- Linked datasets and model weights have full-length SHA checksum, DOI, or immutable version evidence; floating aliases such as `latest` do not count. +- Linked datasets and model weights have full-length SHA checksum, parseable DOI, or immutable version evidence; placeholders such as `pending` and floating aliases such as `latest` do not count. - API sources use parseable, non-future dated snapshots with full-length SHA checksum evidence instead of floating "latest" endpoints. - Export bundles do not require authenticated external references. - License and attribution metadata are present before DOI publication. diff --git a/repository-external-reference-pin-guard/acceptance-notes.md b/repository-external-reference-pin-guard/acceptance-notes.md index 53613984..e6770056 100644 --- a/repository-external-reference-pin-guard/acceptance-notes.md +++ b/repository-external-reference-pin-guard/acceptance-notes.md @@ -17,6 +17,7 @@ Expected evidence: - All-zero Git commit placeholders are treated as unpinned references rather than immutable release evidence. - Floating version aliases such as `latest` are blocked unless the reference also has checksum or DOI evidence. - Invalid checksum placeholders such as `pending` do not count as durable identifier or API snapshot evidence. +- Invalid DOI placeholders such as `pending` do not count as durable identifier evidence. - Truncated checksum values such as `sha256:abcdef` do not count as API snapshot evidence. - Future-dated API snapshots do not count as pinned snapshot evidence for DOI/export release. - Otherwise pinned references without verification timestamps are blocked until verification evidence is refreshed. diff --git a/repository-external-reference-pin-guard/index.js b/repository-external-reference-pin-guard/index.js index d229ade2..e1161397 100644 --- a/repository-external-reference-pin-guard/index.js +++ b/repository-external-reference-pin-guard/index.js @@ -92,7 +92,7 @@ function needsDurableIdentifier(reference) { } function hasDurableIdentifier(reference) { - return hasValidChecksum(reference.checksum) || hasText(reference.doi) || hasImmutableVersion(reference.version); + return hasValidChecksum(reference.checksum) || hasValidDoi(reference.doi) || hasImmutableVersion(reference.version); } function hasValidChecksum(checksum) { @@ -104,6 +104,12 @@ function hasValidChecksum(checksum) { return match[2].length === CHECKSUM_HEX_LENGTHS[algorithm]; } +function hasValidDoi(doi) { + if (!hasText(doi)) return false; + const normalized = doi.trim().replace(/^https?:\/\/(dx\.)?doi\.org\//i, ''); + return /^10\.\d{4,9}\/\S+$/i.test(normalized); +} + function hasImmutableVersion(version) { if (!hasText(version)) return false; return !/^(latest|main|master|head|current|stable|dev|nightly)$/i.test(version.trim()); diff --git a/repository-external-reference-pin-guard/make-demo-video.py b/repository-external-reference-pin-guard/make-demo-video.py index 74cc6a06..faeb5e9b 100644 --- a/repository-external-reference-pin-guard/make-demo-video.py +++ b/repository-external-reference-pin-guard/make-demo-video.py @@ -35,7 +35,7 @@ def font(size, bold=False): cards = [ ("hold_repository_release", "#991b1b", "Blocks floating git refs, auth-only APIs, stale dataset evidence"), ("stage_reference_metadata_revision", "#a16207", "Stages pinned references that still need license or attribution"), - ("release_repository_references", "#047857", "Allows DOI/export release only with immutable pins and checksums"), + ("release_repository_references", "#047857", "Allows DOI/export release only with immutable pins, parseable DOIs, and checksums"), ] for index, (status, color, description) in enumerate(cards): diff --git a/repository-external-reference-pin-guard/reports/demo.mp4 b/repository-external-reference-pin-guard/reports/demo.mp4 index 881f51c5b2b366acd9c4da620eef51f71d707b40..afcfae41eb242ff85d3ed2d63d725c5eaa616d23 100644 GIT binary patch delta 12631 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 U2K&#H`7%K!iX delta 11414 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 Date: Sat, 30 May 2026 14:20:21 +0200 Subject: [PATCH 10/12] Harden external reference evidence validation --- .../README.md | 1 + .../acceptance-notes.md | 8 +-- .../index.js | 22 ++++++- .../reports/blocked-packet.json | 19 +++++- .../reports/external-reference-report.md | 2 +- .../reports/summary.svg | 2 +- .../requirements-map.md | 4 +- .../test.js | 66 +++++++++++++++++-- 8 files changed, 109 insertions(+), 15 deletions(-) diff --git a/repository-external-reference-pin-guard/README.md b/repository-external-reference-pin-guard/README.md index eccc15a7..9fc56808 100644 --- a/repository-external-reference-pin-guard/README.md +++ b/repository-external-reference-pin-guard/README.md @@ -8,6 +8,7 @@ This module checks whether a scientific repository can safely publish a DOI, cit - Git submodules and external code are pinned to immutable commit SHAs, rejecting null all-zero placeholders. - Linked datasets and model weights have full-length SHA checksum, parseable DOI, or immutable version evidence; placeholders such as `pending` and floating aliases such as `latest` do not count. +- Supplied checksum and DOI metadata must be valid even when another durable identifier is present, so malformed evidence cannot slip into export or citation packets. - API sources use parseable, non-future dated snapshots with full-length SHA checksum evidence instead of floating "latest" endpoints. - Export bundles do not require authenticated external references. - License and attribution metadata are present before DOI publication. diff --git a/repository-external-reference-pin-guard/acceptance-notes.md b/repository-external-reference-pin-guard/acceptance-notes.md index e6770056..4b958dc4 100644 --- a/repository-external-reference-pin-guard/acceptance-notes.md +++ b/repository-external-reference-pin-guard/acceptance-notes.md @@ -13,12 +13,12 @@ npm run check Expected evidence: -- `reports/blocked-packet.json` blocks repository release when external references are floating, authenticated only, stale, or missing durable identifiers. +- `reports/blocked-packet.json` blocks repository release when external references are floating, authenticated only, stale, missing durable identifiers, or carrying malformed checksum/DOI evidence. - All-zero Git commit placeholders are treated as unpinned references rather than immutable release evidence. - Floating version aliases such as `latest` are blocked unless the reference also has checksum or DOI evidence. -- Invalid checksum placeholders such as `pending` do not count as durable identifier or API snapshot evidence. -- Invalid DOI placeholders such as `pending` do not count as durable identifier evidence. -- Truncated checksum values such as `sha256:abcdef` do not count as API snapshot evidence. +- Invalid checksum placeholders such as `pending` do not count as durable identifier or API snapshot evidence and now produce explicit evidence-repair actions. +- Invalid DOI placeholders such as `pending` do not count as durable identifier evidence and now produce explicit evidence-repair actions. +- Truncated checksum values such as `sha256:abcdef` do not count as API snapshot evidence or export metadata even when another identifier is valid. - Future-dated API snapshots do not count as pinned snapshot evidence for DOI/export release. - Otherwise pinned references without verification timestamps are blocked until verification evidence is refreshed. - `reports/warning-packet.json` stages pinned references that still need license and attribution metadata. diff --git a/repository-external-reference-pin-guard/index.js b/repository-external-reference-pin-guard/index.js index e1161397..c89c2e52 100644 --- a/repository-external-reference-pin-guard/index.js +++ b/repository-external-reference-pin-guard/index.js @@ -37,6 +37,14 @@ function assessExternalReferences(repository) { function assessReference(reference, assessedAt, policy) { const findings = []; + if (hasInvalidChecksumEvidence(reference)) { + findings.push(finding(reference, 'INVALID_CHECKSUM_EVIDENCE', 'blocker', 'Checksum evidence must use a supported algorithm and full-length hexadecimal digest.')); + } + + if (hasInvalidDoiEvidence(reference)) { + findings.push(finding(reference, 'INVALID_DOI_EVIDENCE', 'blocker', 'DOI evidence must be a parseable DOI or DOI URL before release.')); + } + if (isGitReference(reference) && !hasPinnedCommit(reference)) { findings.push(finding(reference, 'FLOATING_GIT_REFERENCE', 'blocker', 'Git reference must be pinned to an immutable commit SHA before release.')); } @@ -110,6 +118,14 @@ function hasValidDoi(doi) { return /^10\.\d{4,9}\/\S+$/i.test(normalized); } +function hasInvalidChecksumEvidence(reference) { + return hasText(reference.checksum) && !hasValidChecksum(reference.checksum); +} + +function hasInvalidDoiEvidence(reference) { + return hasText(reference.doi) && !hasValidDoi(reference.doi); +} + function hasImmutableVersion(version) { if (!hasText(version)) return false; return !/^(latest|main|master|head|current|stable|dev|nightly)$/i.test(version.trim()); @@ -173,6 +189,7 @@ function buildActions(repository, findings) { for (const [referenceId, codes] of byReference.entries()) { if (codes.has('AUTH_REQUIRED_REFERENCE')) actions.add(`replace_or_snapshot_auth_reference:${referenceId}`); if (codes.has('FLOATING_GIT_REFERENCE') || codes.has('FLOATING_API_REFERENCE')) actions.add(`pin_external_reference:${referenceId}`); + if (codes.has('INVALID_CHECKSUM_EVIDENCE') || codes.has('INVALID_DOI_EVIDENCE')) actions.add(`repair_reference_evidence:${referenceId}`); if (codes.has('MISSING_DURABLE_IDENTIFIER')) actions.add(`add_checksum_or_doi:${referenceId}`); if (codes.has('STALE_REFERENCE_EVIDENCE')) actions.add(`refresh_reference_verification:${referenceId}`); if (codes.has('MISSING_LICENSE') || codes.has('MISSING_ATTRIBUTION')) actions.add(`complete_license_attribution:${referenceId}`); @@ -185,7 +202,10 @@ function buildSignals(findings) { const codes = new Set(findings.map((finding) => finding.code)); return { immutablePins: !codes.has('FLOATING_GIT_REFERENCE') && !codes.has('FLOATING_API_REFERENCE'), - exportable: !codes.has('AUTH_REQUIRED_REFERENCE') && !codes.has('MISSING_DURABLE_IDENTIFIER'), + exportable: !codes.has('AUTH_REQUIRED_REFERENCE') + && !codes.has('MISSING_DURABLE_IDENTIFIER') + && !codes.has('INVALID_CHECKSUM_EVIDENCE') + && !codes.has('INVALID_DOI_EVIDENCE'), attributionComplete: !codes.has('MISSING_LICENSE') && !codes.has('MISSING_ATTRIBUTION'), verificationFresh: !codes.has('STALE_REFERENCE_EVIDENCE') }; diff --git a/repository-external-reference-pin-guard/reports/blocked-packet.json b/repository-external-reference-pin-guard/reports/blocked-packet.json index ee8723e6..1eae1c9e 100644 --- a/repository-external-reference-pin-guard/reports/blocked-packet.json +++ b/repository-external-reference-pin-guard/reports/blocked-packet.json @@ -23,6 +23,22 @@ "severity": "blocker", "message": "API source must reference a dated snapshot with checksum evidence." }, + { + "referenceId": "dataset-lab-export", + "kind": "linked_dataset", + "target": "https://data.example.invalid/lab-export.csv", + "code": "INVALID_CHECKSUM_EVIDENCE", + "severity": "blocker", + "message": "Checksum evidence must use a supported algorithm and full-length hexadecimal digest." + }, + { + "referenceId": "dataset-lab-export", + "kind": "linked_dataset", + "target": "https://data.example.invalid/lab-export.csv", + "code": "INVALID_DOI_EVIDENCE", + "severity": "blocker", + "message": "DOI evidence must be a parseable DOI or DOI URL before release." + }, { "referenceId": "dataset-lab-export", "kind": "linked_dataset", @@ -53,6 +69,7 @@ "pin_external_reference:api-weather-source", "pin_external_reference:submodule-analysis-tools", "refresh_reference_verification:dataset-lab-export", + "repair_reference_evidence:dataset-lab-export", "replace_or_snapshot_auth_reference:api-weather-source" ], "referenceSignals": { @@ -70,5 +87,5 @@ } }, "assessedAt": "2026-05-28T12:00:00Z", - "auditDigest": "845fc5612c82a4a307ac3b4d65af240e262d5e164c709f43462cc2b9586c30c6" + "auditDigest": "0cb0a30094dfe5515aec52b275734cc495e22ef6e44921295fac7d26c6f21a52" } diff --git a/repository-external-reference-pin-guard/reports/external-reference-report.md b/repository-external-reference-pin-guard/reports/external-reference-report.md index 8052987c..443bc2ea 100644 --- a/repository-external-reference-pin-guard/reports/external-reference-report.md +++ b/repository-external-reference-pin-guard/reports/external-reference-report.md @@ -2,7 +2,7 @@ | Packet | Status | DOI publication | Export bundle | API access | Findings | | --- | --- | --- | --- | --- | --- | -| blocked-packet.json | hold_repository_release | blocked | blocked | metadata_only | AUTH_REQUIRED_REFERENCE, FLOATING_API_REFERENCE, MISSING_DURABLE_IDENTIFIER, STALE_REFERENCE_EVIDENCE, FLOATING_GIT_REFERENCE | +| blocked-packet.json | hold_repository_release | blocked | blocked | metadata_only | AUTH_REQUIRED_REFERENCE, FLOATING_API_REFERENCE, INVALID_CHECKSUM_EVIDENCE, INVALID_DOI_EVIDENCE, MISSING_DURABLE_IDENTIFIER, STALE_REFERENCE_EVIDENCE, FLOATING_GIT_REFERENCE | | clean-packet.json | release_repository_references | allowed | allowed | allowed | none | | warning-packet.json | stage_reference_metadata_revision | metadata_revision | draft_only | allowed | MISSING_ATTRIBUTION, MISSING_LICENSE | diff --git a/repository-external-reference-pin-guard/reports/summary.svg b/repository-external-reference-pin-guard/reports/summary.svg index 33ddc2d5..a7adb2ab 100644 --- a/repository-external-reference-pin-guard/reports/summary.svg +++ b/repository-external-reference-pin-guard/reports/summary.svg @@ -7,7 +7,7 @@ repo-reference-risk - blocked-packet.json | findings 5 | digest 845fc5612c82a4a3 + blocked-packet.json | findings 7 | digest 0cb0a30094dfe551 diff --git a/repository-external-reference-pin-guard/requirements-map.md b/repository-external-reference-pin-guard/requirements-map.md index ba5831f0..6dd98a49 100644 --- a/repository-external-reference-pin-guard/requirements-map.md +++ b/repository-external-reference-pin-guard/requirements-map.md @@ -5,9 +5,9 @@ Issue #10 asks for robust project repositories with versioned files, collaborati | Issue #10 area | Coverage in this slice | | --- | --- | | File and metadata versioning | Holds releases when Git submodules or external code are not pinned to immutable commits, including null all-zero commit placeholders. | -| Hash-based integrity | Requires full-length SHA checksums, parseable DOI evidence, or non-floating immutable versions for external datasets and model weights. | +| Hash-based integrity | Requires full-length SHA checksums, parseable DOI evidence, or non-floating immutable versions for external datasets and model weights, and blocks malformed checksum evidence even when another identifier is present. | | Computation-aware reproducibility | Blocks reproducibility/export lanes when API data sources are floating, authenticated only, or backed by malformed/future snapshot dates, invalid checksum evidence, or truncated checksum evidence. | -| Repository identifiers and citation | Prevents DOI publication when external references lack verification timestamps, are stale, future-dated, or lack license/attribution metadata. | +| Repository identifiers and citation | Prevents DOI publication when external references lack verification timestamps, are stale, future-dated, contain malformed DOI evidence, or lack license/attribution metadata. | | Programmatic access and export | Separates API metadata-only access from export-bundle and DOI publication release lanes. | ## Non-Overlap diff --git a/repository-external-reference-pin-guard/test.js b/repository-external-reference-pin-guard/test.js index 2789abc5..e3fa836b 100644 --- a/repository-external-reference-pin-guard/test.js +++ b/repository-external-reference-pin-guard/test.js @@ -182,8 +182,12 @@ function testInvalidChecksumDoesNotCountAsDurableIdentifier() { }); assert.equal(packet.status, 'hold_repository_release'); - assert.deepEqual(findingCodes(packet), ['MISSING_DURABLE_IDENTIFIER']); + assert.deepEqual(findingCodes(packet), [ + 'INVALID_CHECKSUM_EVIDENCE', + 'MISSING_DURABLE_IDENTIFIER' + ]); assert.ok(packet.actions.includes('add_checksum_or_doi:dataset-invalid-checksum')); + assert.ok(packet.actions.includes('repair_reference_evidence:dataset-invalid-checksum')); assert.equal(packet.referenceSignals.exportable, false); } @@ -207,8 +211,12 @@ function testDoiPlaceholderDoesNotCountAsDurableIdentifier() { }); assert.equal(packet.status, 'hold_repository_release'); - assert.deepEqual(findingCodes(packet), ['MISSING_DURABLE_IDENTIFIER']); + assert.deepEqual(findingCodes(packet), [ + 'INVALID_DOI_EVIDENCE', + 'MISSING_DURABLE_IDENTIFIER' + ]); assert.ok(packet.actions.includes('add_checksum_or_doi:dataset-invalid-doi')); + assert.ok(packet.actions.includes('repair_reference_evidence:dataset-invalid-doi')); assert.equal(packet.referenceSignals.exportable, false); } @@ -281,8 +289,12 @@ function testInvalidApiSnapshotChecksumDoesNotCountAsPinnedEvidence() { }); assert.equal(packet.status, 'hold_repository_release'); - assert.deepEqual(findingCodes(packet), ['FLOATING_API_REFERENCE']); + assert.deepEqual(findingCodes(packet), [ + 'FLOATING_API_REFERENCE', + 'INVALID_CHECKSUM_EVIDENCE' + ]); assert.ok(packet.actions.includes('pin_external_reference:api-invalid-checksum')); + assert.ok(packet.actions.includes('repair_reference_evidence:api-invalid-checksum')); assert.equal(packet.referenceSignals.immutablePins, false); } @@ -306,8 +318,12 @@ function testTruncatedApiSnapshotChecksumDoesNotCountAsPinnedEvidence() { }); assert.equal(packet.status, 'hold_repository_release'); - assert.deepEqual(findingCodes(packet), ['FLOATING_API_REFERENCE']); + assert.deepEqual(findingCodes(packet), [ + 'FLOATING_API_REFERENCE', + 'INVALID_CHECKSUM_EVIDENCE' + ]); assert.ok(packet.actions.includes('pin_external_reference:api-truncated-checksum')); + assert.ok(packet.actions.includes('repair_reference_evidence:api-truncated-checksum')); assert.equal(packet.referenceSignals.immutablePins, false); } @@ -357,6 +373,45 @@ function testMissingVerificationEvidenceBlocksOtherwisePinnedReference() { assert.equal(packet.referenceSignals.verificationFresh, false); } +function testMalformedOptionalEvidenceBlocksEvenWhenAnotherIdentifierIsValid() { + const packet = assessExternalReferences({ + repositoryId: 'repo-reference-poisoned-evidence', + assessedAt: '2026-05-28T12:00:00Z', + references: [ + { + id: 'dataset-poisoned-evidence', + kind: 'linked_dataset', + target: 'https://doi.org/10.5281/zenodo.3456789', + checksum: 'sha256:abcdef', + doi: '10.5281/zenodo.3456789', + license: 'CC-BY-4.0', + attribution: 'Example Lab', + lastVerifiedAt: '2026-05-20T08:00:00Z' + }, + { + id: 'model-poisoned-citation', + kind: 'model_weights', + target: 'https://models.example.invalid/model-v4.bin', + checksum: 'sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', + doi: 'pending', + version: 'v4.0.0', + license: 'Apache-2.0', + attribution: 'Example Model Lab', + lastVerifiedAt: '2026-05-20T08:00:00Z' + } + ] + }); + + assert.equal(packet.status, 'hold_repository_release'); + assert.deepEqual(findingCodes(packet), [ + 'INVALID_CHECKSUM_EVIDENCE', + 'INVALID_DOI_EVIDENCE' + ]); + assert.ok(packet.actions.includes('repair_reference_evidence:dataset-poisoned-evidence')); + assert.ok(packet.actions.includes('repair_reference_evidence:model-poisoned-citation')); + assert.equal(packet.referenceSignals.exportable, false); +} + const tests = [ testBlocksFloatingAndNonExportableExternalReferences, testAllowsPinnedExportableReferences, @@ -369,7 +424,8 @@ const tests = [ testInvalidApiSnapshotChecksumDoesNotCountAsPinnedEvidence, testTruncatedApiSnapshotChecksumDoesNotCountAsPinnedEvidence, testNullGitCommitShaDoesNotCountAsImmutablePin, - testMissingVerificationEvidenceBlocksOtherwisePinnedReference + testMissingVerificationEvidenceBlocksOtherwisePinnedReference, + testMalformedOptionalEvidenceBlocksEvenWhenAnotherIdentifierIsValid ]; for (const test of tests) { From 30fb0dc86bd733917e473494c897dc22c56d706e Mon Sep 17 00:00:00 2001 From: KoiosSG Date: Sat, 30 May 2026 16:08:41 +0200 Subject: [PATCH 11/12] Hold malformed external reference entries --- .../README.md | 1 + .../acceptance-notes.md | 1 + .../demo.js | 8 +++- .../index.js | 45 +++++++++++++++--- .../make-demo-video.py | 15 +++--- .../reports/demo.mp4 | Bin 53699 -> 59343 bytes .../reports/external-reference-report.md | 1 + .../reports/malformed-packet.json | 36 ++++++++++++++ .../reports/summary.svg | 8 +++- .../requirements-map.md | 2 +- .../sample-data.js | 9 +++- .../test.js | 26 +++++++++- 12 files changed, 134 insertions(+), 18 deletions(-) create mode 100644 repository-external-reference-pin-guard/reports/malformed-packet.json diff --git a/repository-external-reference-pin-guard/README.md b/repository-external-reference-pin-guard/README.md index 9fc56808..78daa062 100644 --- a/repository-external-reference-pin-guard/README.md +++ b/repository-external-reference-pin-guard/README.md @@ -9,6 +9,7 @@ This module checks whether a scientific repository can safely publish a DOI, cit - Git submodules and external code are pinned to immutable commit SHAs, rejecting null all-zero placeholders. - Linked datasets and model weights have full-length SHA checksum, parseable DOI, or immutable version evidence; placeholders such as `pending` and floating aliases such as `latest` do not count. - Supplied checksum and DOI metadata must be valid even when another durable identifier is present, so malformed evidence cannot slip into export or citation packets. +- Malformed external-reference entries create release-blocking repair actions instead of crashing assessment or disappearing from reviewer packets. - API sources use parseable, non-future dated snapshots with full-length SHA checksum evidence instead of floating "latest" endpoints. - Export bundles do not require authenticated external references. - License and attribution metadata are present before DOI publication. diff --git a/repository-external-reference-pin-guard/acceptance-notes.md b/repository-external-reference-pin-guard/acceptance-notes.md index 4b958dc4..277c64ed 100644 --- a/repository-external-reference-pin-guard/acceptance-notes.md +++ b/repository-external-reference-pin-guard/acceptance-notes.md @@ -19,6 +19,7 @@ Expected evidence: - Invalid checksum placeholders such as `pending` do not count as durable identifier or API snapshot evidence and now produce explicit evidence-repair actions. - Invalid DOI placeholders such as `pending` do not count as durable identifier evidence and now produce explicit evidence-repair actions. - Truncated checksum values such as `sha256:abcdef` do not count as API snapshot evidence or export metadata even when another identifier is valid. +- Malformed external-reference entries produce `MALFORMED_REFERENCE_ENTRY` blockers and `repair_reference_entry:*` actions instead of crashing or disappearing from reviewer packets. - Future-dated API snapshots do not count as pinned snapshot evidence for DOI/export release. - Otherwise pinned references without verification timestamps are blocked until verification evidence is refreshed. - `reports/warning-packet.json` stages pinned references that still need license and attribution metadata. diff --git a/repository-external-reference-pin-guard/demo.js b/repository-external-reference-pin-guard/demo.js index 74f01815..c82aa5bc 100644 --- a/repository-external-reference-pin-guard/demo.js +++ b/repository-external-reference-pin-guard/demo.js @@ -2,13 +2,19 @@ const fs = require('fs'); const path = require('path'); const { assessExternalReferences } = require('./index'); -const { riskyRepository, cleanRepository, warningRepository } = require('./sample-data'); +const { + riskyRepository, + cleanRepository, + warningRepository, + malformedRepository +} = require('./sample-data'); const reportsDir = path.join(__dirname, 'reports'); fs.mkdirSync(reportsDir, { recursive: true }); const packets = [ ['blocked-packet.json', assessExternalReferences(riskyRepository)], + ['malformed-packet.json', assessExternalReferences(malformedRepository)], ['clean-packet.json', assessExternalReferences(cleanRepository)], ['warning-packet.json', assessExternalReferences(warningRepository)] ]; diff --git a/repository-external-reference-pin-guard/index.js b/repository-external-reference-pin-guard/index.js index c89c2e52..318017fc 100644 --- a/repository-external-reference-pin-guard/index.js +++ b/repository-external-reference-pin-guard/index.js @@ -12,7 +12,8 @@ const CHECKSUM_HEX_LENGTHS = { function assessExternalReferences(repository) { const policy = { ...DEFAULT_POLICY, ...(repository.policy || {}) }; - const findings = repository.references + const references = normalizeReferenceEntries(repository.references); + const findings = references .flatMap((reference) => assessReference(reference, repository.assessedAt, policy)) .sort(compareFindings); @@ -26,7 +27,7 @@ function assessExternalReferences(repository) { findings, actions: buildActions(repository, findings), referenceSignals: buildSignals(findings), - referenceSummary: summarizeReferences(repository.references), + referenceSummary: summarizeReferences(references), assessedAt: repository.assessedAt }; @@ -35,6 +36,12 @@ function assessExternalReferences(repository) { } function assessReference(reference, assessedAt, policy) { + if (reference.__malformedReferenceEntry) { + return [ + finding(reference, 'MALFORMED_REFERENCE_ENTRY', 'blocker', 'External reference entry must be a structured object before release.') + ]; + } + const findings = []; if (hasInvalidChecksumEvidence(reference)) { @@ -99,6 +106,25 @@ function needsDurableIdentifier(reference) { return ['linked_dataset', 'model_weights', 'external_data'].includes(reference.kind); } +function normalizeReferenceEntries(value) { + if (!Array.isArray(value)) return []; + + return value.map((reference, index) => { + if (isRecord(reference)) return reference; + + return { + id: `malformed-reference-entry-${index + 1}`, + kind: 'unknown', + target: null, + __malformedReferenceEntry: true + }; + }); +} + +function isRecord(value) { + return value && typeof value === 'object' && !Array.isArray(value); +} + function hasDurableIdentifier(reference) { return hasValidChecksum(reference.checksum) || hasValidDoi(reference.doi) || hasImmutableVersion(reference.version); } @@ -187,6 +213,7 @@ function buildActions(repository, findings) { const actions = new Set(); for (const [referenceId, codes] of byReference.entries()) { + if (codes.has('MALFORMED_REFERENCE_ENTRY')) actions.add(`repair_reference_entry:${referenceId}`); if (codes.has('AUTH_REQUIRED_REFERENCE')) actions.add(`replace_or_snapshot_auth_reference:${referenceId}`); if (codes.has('FLOATING_GIT_REFERENCE') || codes.has('FLOATING_API_REFERENCE')) actions.add(`pin_external_reference:${referenceId}`); if (codes.has('INVALID_CHECKSUM_EVIDENCE') || codes.has('INVALID_DOI_EVIDENCE')) actions.add(`repair_reference_evidence:${referenceId}`); @@ -201,13 +228,19 @@ function buildActions(repository, findings) { function buildSignals(findings) { const codes = new Set(findings.map((finding) => finding.code)); return { - immutablePins: !codes.has('FLOATING_GIT_REFERENCE') && !codes.has('FLOATING_API_REFERENCE'), - exportable: !codes.has('AUTH_REQUIRED_REFERENCE') + immutablePins: !codes.has('MALFORMED_REFERENCE_ENTRY') + && !codes.has('FLOATING_GIT_REFERENCE') + && !codes.has('FLOATING_API_REFERENCE'), + exportable: !codes.has('MALFORMED_REFERENCE_ENTRY') + && !codes.has('AUTH_REQUIRED_REFERENCE') && !codes.has('MISSING_DURABLE_IDENTIFIER') && !codes.has('INVALID_CHECKSUM_EVIDENCE') && !codes.has('INVALID_DOI_EVIDENCE'), - attributionComplete: !codes.has('MISSING_LICENSE') && !codes.has('MISSING_ATTRIBUTION'), - verificationFresh: !codes.has('STALE_REFERENCE_EVIDENCE') + attributionComplete: !codes.has('MALFORMED_REFERENCE_ENTRY') + && !codes.has('MISSING_LICENSE') + && !codes.has('MISSING_ATTRIBUTION'), + verificationFresh: !codes.has('MALFORMED_REFERENCE_ENTRY') + && !codes.has('STALE_REFERENCE_EVIDENCE') }; } diff --git a/repository-external-reference-pin-guard/make-demo-video.py b/repository-external-reference-pin-guard/make-demo-video.py index faeb5e9b..ced9d1aa 100644 --- a/repository-external-reference-pin-guard/make-demo-video.py +++ b/repository-external-reference-pin-guard/make-demo-video.py @@ -26,25 +26,26 @@ def font(size, bold=False): img = Image.new("RGB", (1280, 720), "#ffffff") draw = ImageDraw.Draw(img) title_font = font(44, True) -body_font = font(25) -small_font = font(21) +body_font = font(23) +small_font = font(18) draw.rectangle((0, 0, 1280, 92), fill="#0f172a") draw.text((48, 26), "Repository External Reference Pin Guard", fill="#ffffff", font=title_font) cards = [ + ("MALFORMED_REFERENCE_ENTRY", "#991b1b", "Turns malformed external-reference entries into release-blocking repair evidence"), ("hold_repository_release", "#991b1b", "Blocks floating git refs, auth-only APIs, stale dataset evidence"), ("stage_reference_metadata_revision", "#a16207", "Stages pinned references that still need license or attribution"), ("release_repository_references", "#047857", "Allows DOI/export release only with immutable pins, parseable DOIs, and checksums"), ] for index, (status, color, description) in enumerate(cards): - y = 138 + index * 134 - draw.rounded_rectangle((58, y, 1222, y + 96), radius=8, outline="#cbd5e1", width=2, fill="#f8fafc") - draw.ellipse((88, y + 29, 126, y + 67), fill=color) - draw.text((150, y + 22), status, fill="#111827", font=body_font) + y = 116 + index * 104 + draw.rounded_rectangle((58, y, 1222, y + 82), radius=8, outline="#cbd5e1", width=2, fill="#f8fafc") + draw.ellipse((88, y + 22, 126, y + 60), fill=color) + draw.text((150, y + 16), status, fill="#111827", font=body_font) for line_index, line in enumerate(textwrap.wrap(description, width=78)): - draw.text((150, y + 55 + line_index * 26), line, fill="#475569", font=small_font) + draw.text((150, y + 48 + line_index * 22), line, fill="#475569", font=small_font) draw.text((58, 596), "Synthetic evidence only. No external repositories, APIs, DOI registries, or private data sources are contacted.", fill="#334155", font=small_font) img.save(FRAME) diff --git a/repository-external-reference-pin-guard/reports/demo.mp4 b/repository-external-reference-pin-guard/reports/demo.mp4 index afcfae41eb242ff85d3ed2d63d725c5eaa616d23..22941e7f6f17de5a27a5bc34ef2c5b6cb36ad784 100644 GIT binary patch delta 46369 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�o)nd5 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

Wj;p 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.json | findings 7 | digest 0cb0a30094dfe551 + + + repo-reference-malformed-entry + malformed-packet.json | findings 1 | digest 5712c8d01b35d778 + + repo-reference-clean clean-packet.json | findings 0 | digest 5b1ede709bdfe56b - + repo-reference-warning diff --git a/repository-external-reference-pin-guard/requirements-map.md b/repository-external-reference-pin-guard/requirements-map.md index 6dd98a49..138eacc9 100644 --- a/repository-external-reference-pin-guard/requirements-map.md +++ b/repository-external-reference-pin-guard/requirements-map.md @@ -8,7 +8,7 @@ Issue #10 asks for robust project repositories with versioned files, collaborati | Hash-based integrity | Requires full-length SHA checksums, parseable DOI evidence, or non-floating immutable versions for external datasets and model weights, and blocks malformed checksum evidence even when another identifier is present. | | Computation-aware reproducibility | Blocks reproducibility/export lanes when API data sources are floating, authenticated only, or backed by malformed/future snapshot dates, invalid checksum evidence, or truncated checksum evidence. | | Repository identifiers and citation | Prevents DOI publication when external references lack verification timestamps, are stale, future-dated, contain malformed DOI evidence, or lack license/attribution metadata. | -| Programmatic access and export | Separates API metadata-only access from export-bundle and DOI publication release lanes. | +| Programmatic access and export | Separates API metadata-only access from export-bundle and DOI publication release lanes, and blocks malformed reference entries with explicit repair actions. | ## Non-Overlap diff --git a/repository-external-reference-pin-guard/sample-data.js b/repository-external-reference-pin-guard/sample-data.js index 370fc266..adb0da79 100644 --- a/repository-external-reference-pin-guard/sample-data.js +++ b/repository-external-reference-pin-guard/sample-data.js @@ -93,8 +93,15 @@ const warningRepository = { ] }; +const malformedRepository = { + repositoryId: 'repo-reference-malformed-entry', + assessedAt: '2026-05-28T12:00:00Z', + references: [null] +}; + module.exports = { riskyRepository, cleanRepository, - warningRepository + warningRepository, + malformedRepository }; diff --git a/repository-external-reference-pin-guard/test.js b/repository-external-reference-pin-guard/test.js index e3fa836b..14fc3636 100644 --- a/repository-external-reference-pin-guard/test.js +++ b/repository-external-reference-pin-guard/test.js @@ -412,6 +412,29 @@ function testMalformedOptionalEvidenceBlocksEvenWhenAnotherIdentifierIsValid() { assert.equal(packet.referenceSignals.exportable, false); } +function testMalformedReferenceEntriesBlockReleaseInsteadOfCrashing() { + const packet = assessExternalReferences({ + repositoryId: 'repo-reference-malformed-entry', + assessedAt: '2026-05-28T12:00:00Z', + references: [null] + }); + + assert.equal(packet.status, 'hold_repository_release'); + assert.deepEqual(findingCodes(packet), ['MALFORMED_REFERENCE_ENTRY']); + assert.equal(packet.findings[0].referenceId, 'malformed-reference-entry-1'); + assert.ok(packet.actions.includes('repair_reference_entry:malformed-reference-entry-1')); + assert.equal(packet.referenceSignals.immutablePins, false); + assert.equal(packet.referenceSignals.exportable, false); + assert.equal(packet.referenceSignals.attributionComplete, false); + assert.equal(packet.referenceSignals.verificationFresh, false); + assert.deepEqual(packet.referenceSummary, { + total: 1, + byKind: { + unknown: 1 + } + }); +} + const tests = [ testBlocksFloatingAndNonExportableExternalReferences, testAllowsPinnedExportableReferences, @@ -425,7 +448,8 @@ const tests = [ testTruncatedApiSnapshotChecksumDoesNotCountAsPinnedEvidence, testNullGitCommitShaDoesNotCountAsImmutablePin, testMissingVerificationEvidenceBlocksOtherwisePinnedReference, - testMalformedOptionalEvidenceBlocksEvenWhenAnotherIdentifierIsValid + testMalformedOptionalEvidenceBlocksEvenWhenAnotherIdentifierIsValid, + testMalformedReferenceEntriesBlockReleaseInsteadOfCrashing ]; for (const test of tests) { From 287a41dfb38af8d462bc2e24e825b464ff4628e7 Mon Sep 17 00:00:00 2001 From: KoiosSG Date: Sun, 31 May 2026 10:38:04 +0200 Subject: [PATCH 12/12] Block malformed reference manifests --- .../README.md | 1 + .../acceptance-notes.md | 1 + .../demo.js | 9 +++-- .../index.js | 30 ++++++++++++--- .../make-demo-video.py | 11 +++--- .../reports/demo.mp4 | Bin 59343 -> 68232 bytes .../reports/external-reference-report.md | 1 + .../reports/malformed-manifest-packet.json | 36 ++++++++++++++++++ .../reports/summary.svg | 14 +++++-- .../requirements-map.md | 2 +- .../sample-data.js | 15 +++++++- .../test.js | 32 +++++++++++++++- 12 files changed, 132 insertions(+), 20 deletions(-) create mode 100644 repository-external-reference-pin-guard/reports/malformed-manifest-packet.json diff --git a/repository-external-reference-pin-guard/README.md b/repository-external-reference-pin-guard/README.md index 78daa062..6798860a 100644 --- a/repository-external-reference-pin-guard/README.md +++ b/repository-external-reference-pin-guard/README.md @@ -9,6 +9,7 @@ This module checks whether a scientific repository can safely publish a DOI, cit - Git submodules and external code are pinned to immutable commit SHAs, rejecting null all-zero placeholders. - Linked datasets and model weights have full-length SHA checksum, parseable DOI, or immutable version evidence; placeholders such as `pending` and floating aliases such as `latest` do not count. - Supplied checksum and DOI metadata must be valid even when another durable identifier is present, so malformed evidence cannot slip into export or citation packets. +- The external-reference manifest itself must be an array, so object-shaped or missing reviewer data cannot be treated as a clean empty audit. - Malformed external-reference entries create release-blocking repair actions instead of crashing assessment or disappearing from reviewer packets. - API sources use parseable, non-future dated snapshots with full-length SHA checksum evidence instead of floating "latest" endpoints. - Export bundles do not require authenticated external references. diff --git a/repository-external-reference-pin-guard/acceptance-notes.md b/repository-external-reference-pin-guard/acceptance-notes.md index 277c64ed..7177cb8c 100644 --- a/repository-external-reference-pin-guard/acceptance-notes.md +++ b/repository-external-reference-pin-guard/acceptance-notes.md @@ -19,6 +19,7 @@ Expected evidence: - Invalid checksum placeholders such as `pending` do not count as durable identifier or API snapshot evidence and now produce explicit evidence-repair actions. - Invalid DOI placeholders such as `pending` do not count as durable identifier evidence and now produce explicit evidence-repair actions. - Truncated checksum values such as `sha256:abcdef` do not count as API snapshot evidence or export metadata even when another identifier is valid. +- Malformed object-shaped reference manifests produce `MALFORMED_REFERENCE_MANIFEST` blockers and `repair_reference_manifest:*` actions instead of being treated as empty clean audits. - Malformed external-reference entries produce `MALFORMED_REFERENCE_ENTRY` blockers and `repair_reference_entry:*` actions instead of crashing or disappearing from reviewer packets. - Future-dated API snapshots do not count as pinned snapshot evidence for DOI/export release. - Otherwise pinned references without verification timestamps are blocked until verification evidence is refreshed. diff --git a/repository-external-reference-pin-guard/demo.js b/repository-external-reference-pin-guard/demo.js index c82aa5bc..fd6c14e0 100644 --- a/repository-external-reference-pin-guard/demo.js +++ b/repository-external-reference-pin-guard/demo.js @@ -6,7 +6,8 @@ const { riskyRepository, cleanRepository, warningRepository, - malformedRepository + malformedRepository, + malformedManifestRepository } = require('./sample-data'); const reportsDir = path.join(__dirname, 'reports'); @@ -14,6 +15,7 @@ fs.mkdirSync(reportsDir, { recursive: true }); const packets = [ ['blocked-packet.json', assessExternalReferences(riskyRepository)], + ['malformed-manifest-packet.json', assessExternalReferences(malformedManifestRepository)], ['malformed-packet.json', assessExternalReferences(malformedRepository)], ['clean-packet.json', assessExternalReferences(cleanRepository)], ['warning-packet.json', assessExternalReferences(warningRepository)] @@ -47,8 +49,9 @@ const rows = packets.map(([fileName, packet], index) => { `; }).join(''); -const svg = ` - +const svgHeight = 408; +const svg = ` + Repository External Reference Pin Guard Issue #10 release/export gate for submodules, linked datasets, API sources, and model references ${rows} diff --git a/repository-external-reference-pin-guard/index.js b/repository-external-reference-pin-guard/index.js index 318017fc..ea4d621b 100644 --- a/repository-external-reference-pin-guard/index.js +++ b/repository-external-reference-pin-guard/index.js @@ -36,6 +36,12 @@ function assessExternalReferences(repository) { } function assessReference(reference, assessedAt, policy) { + if (reference.__malformedReferenceManifest) { + return [ + finding(reference, 'MALFORMED_REFERENCE_MANIFEST', 'blocker', 'External reference manifest must be an array before release.') + ]; + } + if (reference.__malformedReferenceEntry) { return [ finding(reference, 'MALFORMED_REFERENCE_ENTRY', 'blocker', 'External reference entry must be a structured object before release.') @@ -107,7 +113,16 @@ function needsDurableIdentifier(reference) { } function normalizeReferenceEntries(value) { - if (!Array.isArray(value)) return []; + if (!Array.isArray(value)) { + return [ + { + id: 'reference-manifest', + kind: 'unknown', + target: null, + __malformedReferenceManifest: true + } + ]; + } return value.map((reference, index) => { if (isRecord(reference)) return reference; @@ -213,6 +228,7 @@ function buildActions(repository, findings) { const actions = new Set(); for (const [referenceId, codes] of byReference.entries()) { + if (codes.has('MALFORMED_REFERENCE_MANIFEST')) actions.add(`repair_reference_manifest:${referenceId}`); if (codes.has('MALFORMED_REFERENCE_ENTRY')) actions.add(`repair_reference_entry:${referenceId}`); if (codes.has('AUTH_REQUIRED_REFERENCE')) actions.add(`replace_or_snapshot_auth_reference:${referenceId}`); if (codes.has('FLOATING_GIT_REFERENCE') || codes.has('FLOATING_API_REFERENCE')) actions.add(`pin_external_reference:${referenceId}`); @@ -228,18 +244,22 @@ function buildActions(repository, findings) { function buildSignals(findings) { const codes = new Set(findings.map((finding) => finding.code)); return { - immutablePins: !codes.has('MALFORMED_REFERENCE_ENTRY') + immutablePins: !codes.has('MALFORMED_REFERENCE_MANIFEST') + && !codes.has('MALFORMED_REFERENCE_ENTRY') && !codes.has('FLOATING_GIT_REFERENCE') && !codes.has('FLOATING_API_REFERENCE'), - exportable: !codes.has('MALFORMED_REFERENCE_ENTRY') + exportable: !codes.has('MALFORMED_REFERENCE_MANIFEST') + && !codes.has('MALFORMED_REFERENCE_ENTRY') && !codes.has('AUTH_REQUIRED_REFERENCE') && !codes.has('MISSING_DURABLE_IDENTIFIER') && !codes.has('INVALID_CHECKSUM_EVIDENCE') && !codes.has('INVALID_DOI_EVIDENCE'), - attributionComplete: !codes.has('MALFORMED_REFERENCE_ENTRY') + attributionComplete: !codes.has('MALFORMED_REFERENCE_MANIFEST') + && !codes.has('MALFORMED_REFERENCE_ENTRY') && !codes.has('MISSING_LICENSE') && !codes.has('MISSING_ATTRIBUTION'), - verificationFresh: !codes.has('MALFORMED_REFERENCE_ENTRY') + verificationFresh: !codes.has('MALFORMED_REFERENCE_MANIFEST') + && !codes.has('MALFORMED_REFERENCE_ENTRY') && !codes.has('STALE_REFERENCE_EVIDENCE') }; } diff --git a/repository-external-reference-pin-guard/make-demo-video.py b/repository-external-reference-pin-guard/make-demo-video.py index ced9d1aa..4e22c1a0 100644 --- a/repository-external-reference-pin-guard/make-demo-video.py +++ b/repository-external-reference-pin-guard/make-demo-video.py @@ -33,6 +33,7 @@ def font(size, bold=False): draw.text((48, 26), "Repository External Reference Pin Guard", fill="#ffffff", font=title_font) cards = [ + ("MALFORMED_REFERENCE_MANIFEST", "#991b1b", "Blocks object-shaped or missing reference manifests before they pass as clean audits"), ("MALFORMED_REFERENCE_ENTRY", "#991b1b", "Turns malformed external-reference entries into release-blocking repair evidence"), ("hold_repository_release", "#991b1b", "Blocks floating git refs, auth-only APIs, stale dataset evidence"), ("stage_reference_metadata_revision", "#a16207", "Stages pinned references that still need license or attribution"), @@ -40,12 +41,12 @@ def font(size, bold=False): ] for index, (status, color, description) in enumerate(cards): - y = 116 + index * 104 - draw.rounded_rectangle((58, y, 1222, y + 82), radius=8, outline="#cbd5e1", width=2, fill="#f8fafc") - draw.ellipse((88, y + 22, 126, y + 60), fill=color) - draw.text((150, y + 16), status, fill="#111827", font=body_font) + y = 112 + index * 90 + draw.rounded_rectangle((58, y, 1222, y + 72), radius=8, outline="#cbd5e1", width=2, fill="#f8fafc") + draw.ellipse((88, y + 18, 126, y + 56), fill=color) + draw.text((150, y + 12), status, fill="#111827", font=body_font) for line_index, line in enumerate(textwrap.wrap(description, width=78)): - draw.text((150, y + 48 + line_index * 22), line, fill="#475569", font=small_font) + draw.text((150, y + 42 + line_index * 22), line, fill="#475569", font=small_font) draw.text((58, 596), "Synthetic evidence only. No external repositories, APIs, DOI registries, or private data sources are contacted.", fill="#334155", font=small_font) img.save(FRAME) diff --git a/repository-external-reference-pin-guard/reports/demo.mp4 b/repository-external-reference-pin-guard/reports/demo.mp4 index 22941e7f6f17de5a27a5bc34ef2c5b6cb36ad784..30f2129dc2c52de36ac4e85b07504d3386c9df3d 100644 GIT binary patch delta 56562 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

#WM>ocI55(-X6+GJ55X7&SGRiwlxGN_QH zltKbQvdQW66CBQ*eEm-`_5Ra3NL9=YxwAD;Jb{YAp|xIx0wbl*Jj2Y=gGl0k5~H=& zuOqxrh)kO>Jg0how7a5kWU8A|xABW}YJ%!v*_IabAW*ZdL30zAhKm5u#_vTdY_^Pn z_zt?}BmTPfqj9+l6krkat_4zBu*Cr_URgcdG|w&jv9ur51x|J5@f9999@DOZO37V6 z1!|s5SdM*1*U@4)kjG$h#Lnt}-Ca8t=Uc1&jS_;qe`u$b=t_?hQ){=;j`fiz4@euR z35Cj&giJzI)7GX|o3e9Y}*Yu-2ZbHIf!JvvZaz()PO2=U7`0XOI7N;-QVu zqJa)m%xE3(wy^ZxwO3v#f1|+iU(jp57JIC8#o@6**@5UAWK6heGCx(LdO@ZLjN0x=5_k4O%7U!3O4K~a zsRgB(I}q(8ldR47Qll1s*V{VoHYfjCLT7WNDAh6$;!GslCqR(d{_O&QV7HlfF{xwE zDJElSlQ;46QzPU2Wnk2+goZGg#C!C|>7%w|{lT%bqCDaRThPga-psN4n_pw*mG@#@ z9NbmNRDdVM~VUUumYf9GuYu0W$RpjP&y@H99lNg!DqK+ z1_BC7_t&}#(hB*;Mb-H4Vmiek5y4CB#T7TAK9tRY(g8113giRdz9I4-ex>spW% zmW{`!5cpGO-!+ID+4%R>y1~#K*0OHM-jryPF*D+7*I|)cZ)Z&~FP*gaw-)g^et}#8 zew&?TNg4P1iIgpWc+n(cOQewCYWI=Gq$i3I4*wrt(f#lqyzkvqV8(7*;N(rYW^1K! z_NTL6ZX`6n(MZeiiNt%RASB^I#|Irs;9ld32P+1)QblUAL+5d|M(;#IU!3@2Yjp%4 zb~^Kc<(&pZJL-ZaHjpdlU<%Ki{wW5nF&oU3ChDmd>ex_!v-EY~`CA!SDJt{&hm8B? zM>n?Bhi9F#ou21i&ieny@CE2k%`+H?ahxO{OV~<9?3!l${ zSTNtM#*-)GtWkWULQf0dV0nfL4i2w);wt3-SY?JEieimKm_y?ZgOX0L0O73jlrY&eqg6mUy5HUAtx@VyYD5XQABoV<)p*#gEn_^y73;>s zrtw0z978wYpotSR#F(*wzDVs*)y3Y2F@xGFq-nw%ckL!&uu9gOw#V5W8c=^bE%OO~# zA&pd43XxT9U$LTaF|Q6iIhx1taA;6ET6&eWc19O=77~~JD=|5s)maEN^)IJ-d zX{*E2Ki5FB(Tpkf!05h?q=X8A)G4n53q)@#XZ&XM+q4w45V zxaY7x#cl%`bN|8|+){@G)8{^Yq1wpZTWtq366 zyz95&--$+jXG}0P;{0?WV zyj?3;X!CnTk;F#nVrgt zvSLcNuW7=g(?%K>emAFXmphPu!cwly_124kkwKC!60Y7TLZ^)+7n19_;`wl}fe}#yOH-ccaK2 zXKPZ!kEwF;HDhBeH&|{5V_CCEP~?rUMRG|@L>u?IY%HqE%)*T&sXVBEio=OC_J8`) z;&nEM5ObO)ouJSYBq7 zQuzYfk}L9*Nb&5)8Q;vszR}x+g2GN!3;8(DKX`Y}aJJGw@j*xXmB-k1yZW3KU_)gu z8qd!D?q|nvQ>{`0euw{m=pv!HA&#re54oAkD_8%jYY33mY~A#$Y6_@I0~T`D&8Y|V zYbTtWa|^#3^rsrQbM7s2FvNG8wh) z;_jET#1LYZ+t2n2-fqWu*(ZwGVBNbH17`Ix@WW;D{B97~eq~O zQyl`V=U2(8THHQ7QA=c1)8$$jwP2n^%q6wx?=q-7d&3E|CzosTD5A7C+JNwn$wr0; zcU6SP901|jes|30v8E6y(MP^0=6r0X zkkDBx%CG)qyPg^$owpoP)DR2GmduKK`>&3ob_cn``oq72@iE-WvAppzG{Sg9Ghio1_Ohr4qa$h zYe)5sYq|`vk4rtOG8}2V+vEvu{6Y5mcfr}V_pUVW$6rNj{7>gJU_Y>7k_bM3 zjC#)UjpOup8^e9;<>5j_rW9Ej}_=~D*FX{OT40NieWras}B zy2ODM5ieTNj52Ui<>TI&bMwS?DmF_5ZE=Ag9jpChWw9myrQQfWb*doJAIU+pLRXhwef8W>Gtw}%O5(HGB2#_4xY+CRRNNE=*hK9Bb73H z`H7{bViC zeY?e0evM}o9;n3s)ep!3eYWj$E{R_THI2bQ>=1WR$BR(_HSX~KK8aRPq3%xYf`b|O zuuk9Urh_AcI}7NmzzhRDaru=RwlnHk?%X1ZB##9@?!FaLuBpDBnqq`%Yi6R%DiZ{d;y``&|D0EjT1V^%}Ht9YUOX^X;D=io4~2<_6{zejGX31a;@)n!&&im zAyAnyTsruI&%y)%9ORml5pR$I&%&`jPMCU#-Uyt#6F zlG-G}WcbF${)!}+u=}Chh&7Amhz#w4D)=v%T-9&1WDnDcLDJtp+=Qwi)36fpxATu> z@cZDk!w7dT7UQUbA{yuNP;(pvTOJh7S{hMGi0QDbGj^aJue$|a)}LnKt#XKX(I^z^ zkYPkwgW9#G+UTHv{9?OL@td&z$cs5)_x-zgaH4o$E99;)^sOdBuVHwVH3I$b>&6e? zg+z$XRu__$quJuKk`^T{W{jRcT7vtqG;QYvMkEN)1=!x(dP415Luk~`Nb3C<0_5cV zp)M`c)$iD|bf>xw$XP8Xy>DAg5u6e)7XQrs9Sgc$1><3VyvR+pm~W_gyhktGFXCrC z#N5V}FNl|6?6lV@XYDqC_|RmU!`s|e3Fss^$WtsH{R`1B&ZiyV#G{t}2Y=z^7D&H)QWI^Lo5PdTJu#^_WP&TYoQf& z`m6ik`E_A`N`8uza*`cJSCb(Q@G&&Y zbYPt2Ms>k?tz43UxZ|*Y%6oiVDZ>s`VRE(3PE6gVdZv+B zop5M0n3UXxnx>wXm#gJz&hZzP3vHJlIf1cBn!pRWTo4mnguD6-3dys_11^a4LIN9t zGFaS#h5R1aK<%Qjhx}U`Kbrx3-9EyQ_~2%n_wi@7$8rZ(+W+24R4I6o;MIBlOA1Fu zpOhqjfs5Y1@`pTSzMFRcgzl;kierXEVrQDp-CL648RodFmH?c4{6m%?|I$e1e}^p0 zEvzkHJk3lWGU006g$mg}4d^xZ6p5KT?KPn{gaS$%-gdQmC9op@FN>8-gd4B!qL(#PS z16IDWdcGA;Di(tyVazO#jXfbH1X5WCMxLNk&e%Q{`(CkozqY5>IIBEO)6HIfYVB~!nYQ@b4pWi@>qe&BTM2^iAx=k;i z|A&DlpFl-#z}F)+DkO&DgzuzQu?tp+rMs%nMB)2HQ!OiiR`<34pTtw&Co-IWv;QG! z5zquCm2~9wrik!5qjDgOPIIU)s6Ht`2cDT(u0xor2gj$b?wBgz+>InzorlFf`pZA8 z1DYFF<^arO_5WAzN_H_s4Gp{;Y-ov`b=_E=NB~gN zBLm2Bi!}73xy2P-QD?F*x7k+UJiH^%|Kl_8T^9Q=Y?)T7+Em`FtvTg?zU*)~a6KVQ zb%pG`Gv0F^gH7DPdOSxRZgg)4L76?b;w9T2c_Glyf9toni`x`Ed$`30-nJ$!<|dnF z!HlDcYuHg_iL0|;X5j(p3b4mgo)G-s8x?*WH~|hKO|~pD0<2z)?^mQ(`|e75R>;*o zBbXpyBuh`n(ybVrWZWcw-}ilUju$!;@@@NA;HWJC0ZN*w#L3cabHn(EH~A-{ku=~` zr5-82S=XDeEkAk>>;d5t@IUKg;AKF6-RNB20{#TbFcO#m00RI30{{RBJtyQS<|-(` ztTbXX#2O2DY?pivWDqp#6j~d1*a>2=o7cX(gg!|m4GZC;r8=B{d!#QIS@#6pRl}Kt zn2S&AZW5C;rop47n%vL;4%G~!?VoZk*0fTc6ZQw2^K^@WxqHy6P(r*f0$k1g|F;`j zne<)WKn(VSMQ_{6tAp9>;!wt~oFw28Opq1yji~p46#Q{>UNc!*m6f<;)A%njdgp|t zhC2DDguA~~#dVl}D6^zs{c-RA)##t-Ef-OpaXc7LO~P4eYxH&!b*3u9P2iG}|6iJ1 zg0f;o?PFKR6P9*WT+W1SY;keiZE4&)qPc#=;-Qk+jGalLDtg+@Bo_6z{}kSJ;jzD8 z3A=>cVZzfp##YLf1W)dJd9W(>?8QIsQ|7&PToBMW%82rRwrpwnCO=`aH=rbdU=~>p z>DQT%@3ld_|9AhZFjs=}4l8qGByU|hQ7ZTqZg^>OCL?MG*WSI4eS6{pN@b|4Fmg4B zM4)JI{c<$w8HG|$4I4lL%|V|?7llU#4}lRyFWyV86NY0D6Ac20Rc(1?wk~k-gs?)2 z=%gCnfb_h7@D>yP+r-_Hi0OyI1%{suO5^tJ zG?R01zxz+^zO6&LEO+UcnP7??!W2G_yCG_ONNY3#R+8=Nu(p#=*P`+nVR{&-tP9UU zTz8msCXSij=II7%PYRTPD6a$tXowHN5fT4pgPOH}#Gfyao2Ft4M#O9*NoTaCFMC0c z+WG{2bn%UTI)B{U^y~Ym1!t6A?AOY_bDt4xw=P^x4~m19NbC_(bDG`+dpSzvB*ryW z3}TX@pf$Xn?sWcjg;via8E@%mV9`YS^7tpgy<&9p9W;s4W3*4?re7+u_7DfDcar}d1Ta=#)zI?xl2o+d z$@DlG*2$9K3X$`P_Z3t+GRM32T7$XtU>u--qXGZ%%^%jIF6g-Mj(~svQnz?r;@>`4 ztHTOHp?#SHdF%LPD?#5>%_mZFylzDIttHUoR{aHvW97pTWGP*|9#d=N^W}XlOTLd3 z>-;Ob#gvk?|GByh9a;3m!|qXM-KLKOo)0Qf=Yz4>yRg(3`7|`tpH3Tca#D#kXMrn! z+f2zbc;_y_59*A>AJAOe_?3nW`jx;Xee1)>f84zZ>8}c`BSJIS?Yff~`8u75J_W`_ zBoS^oXGt&W12l%xtUVRF;DV--{a>AC4en|vYlb|X30^(kUIm1`K_;z>Ecak ziAv%!QIFHjOrS!|WZ&(d26*n)A4r{l;jp|s*C7<^!+HOz8a^9kWQ{1vyM-fjtvFo^B zlp;$7lQL5`p3Rh}02V&R{GAawVtz02gYEUnrO}8*F|@p3z@)XaB6L!nNBL=g&-La6 z&qk#Ap1&NOl@52>W1^Ffw2m%P55pEHh$1ARr zz$uTPow5FpsfnwV*Ii+JV7at^x<^okr%^8YuYWdK!^8Wnqd)bk|_qAVTfuUz6B&=jGA|i8QTfiiLm_tDnRuspn zqCx@?JMkLDcn72Db2u2Cv`@cxI*OU+uWN*(%S;*!yRA;*1{M13W1-Wy%CDjyn6H-k zd!sZ{Oi>U1bl#eKFZqD3ek`g$lk`H40e;cAb%c-G+tFt4dlAzm3EJIB4n|r7EZdnE zDBC~^`}XE-co*zTKMJsaB$9pkhD>ZBEX(iGL;z1IbF+;9&I|QGaRO6`T1dPYG#000 zz|GCDjyT3PW0Vj9dR@oENs8~90GTUIle88dz6+(`$*#>9L{GdBqz9Ms$dDT;bXAVO zx1~WCr~%{%v~yu%l6x~W53@{CcGX3Y%b?o@^Ag+y5J$Q{j|r%MQRs2{MF72IAT=dWl!qkJKX~&R8_QU0L2N73Mk8Yn94l5d> zPE{omhG}0;QqW0LlX4=hC599xZ;!?6 z(065Iq0Mn=(O#%JP{u3#*>mo2e5Qz4|bcJPkMiUoY^#sPOS*h*Ww zA{()-BN~bW0Ab$$TW#S$iF9MS`eIzx5-4SK5%}A;=A7?~1<-%OF_U6Pxir_G-5qZK zL@FHh?|(it|5Ucn1^%tMACc4Y48~{+(i+0uhwur13)6KNE9sQi-N>N2x#Cr4v?T+#%ig@&;e-F(>$BOdoXjxl z2?>vHjuP%v#hbQiV7*_<4*8a8p5G^nbEV#5^Xy8~N8SJrP+26bZz&T1SsLFIU|?C| ztqEvq-Ifx;xmao?`)T+INl(yILFjg=Bzn;1WX*lkqu1Ygr&fVzH=Z9F8)^rC z$b$)KiaH(crisBdv|-ad=jf)GeLdFO=!~z_!Rt;b8_<1>TOFr7`wH^-jAEg|meAQB zee#v*7~qS7^G^^@qanxva2^u?>EJkfkptKZY4ev!+2ITt6|{7BG404P_AE&oW<*(? z{dZO0W(UzZfi_Kgn`RKl7x1as=c_G${NvEYdv(z5y>(b$Nwzln!`(GN2rj{c26uwH z1%g9xciXtTTae%y2o~Jk-5r9vLx7KT_c?c@=S@7{Ty`}AMH-fLIY%c@#$)ml}n z2viAcJ1oP(KSLh2debiHvA25HXbs|upjpv8nGGOB+MpMDS2=R)fFRX`$*UTv6zy?w zi&ej!Akv_oT(xj)@SnIlVG>q~ky9#sBCJg6-wGy3yW)D;07$ox_I!YNS;?|W z2+vZ-KH~g7jtJwm5YasZDct)Y&pvh%>zS%Ps8Ju%GdDbP4TtE-8EF}>xhMDXE00&) z6X~Y86{)DE>zIfB3ALHViIMXOJl!&A0ZA8dwnbK8b*vR}An=2l9Uml1Cqt^I6v?1S zH|wW|ZHAoj;J3nK`9J~U>Sv!Avo6#8eVjaDD52FFy3*=HQd+_Vmj)f=fkk>n=eIlo zBuKTfK~41Glg2ivhGyl8&lz!%+HI^!9y)d(w9NWv5%=N_*RiTBKX~k{vlnVOF+Xj# z@}$4Ht(EHLM8R1K-W1G2Qg!|6KyxKX*TY!#hpRE0ICwAH3#7dOw5Hc)Mx2(~bXA48RXkafTD*H~ zU)f(>UbRje6dP-#O134kzqUn@c~R}G+_Jp#RY}Cj#_lo;Eh)#DQ(B+h*W-zo(ol7} zLIO9#!=4})x?c-u$dFWMrhl)Uh*<9{-8uq+If3>>NCKG`xM-{2Jue^PR;~PUH6#plbi^;6~Kz zDl?|f&*`qd<-%Bl%G>LLC~m0g+T^b81H5z%cu2Z1^bG4cL1_(jRt)4s62`m&? zJ_Z0RR{s5#oUp8>l^l`C)Z_hTDhG9{~x7oGHi$c(4*`vxhyx+&+|$8+x9L6EF&b{dkq$3DgQp9V~XA=~^05k1;K#0r> zWege=N`N)p1S{M8Xq5}^J=XD2plmp&Q~_iD_Q`eU%Q=o;S6_$;_GBNCpmN`xaYIUh zT=WvX-qj^?weXroRnE7z0Q!#JUd(qZmo7x#U=bAvB~3@z#YGzJlO*yI@tNvIb9C$& zyEAZ<0fP#6{jg1PHAUrQ6Hn-jp|L&n6Icjt4Aib{6w&Al=ZGT8+&BtQ{|5wJ<*ye- ziOn)6xpN63J6cT>pTfs6RNk8_2yM+u({H>bQ+@BNM2RW(jU9f-+Dc+8*m*i(XTbM; z&cvf@>$-ObUpvKd%1Lr^Vnx2zt@Ib=Y>zKQc);~Zi3}0Xtfu-~h8GyD-nmxc9Sji8 zL^k|_rLIWPP;;sS%TH8axE+`Sex$j3cEMmzRg|BQt&O272Wr25--no;HCE}KO8EMG z1^*645Q{!DuEP3;SY>&%7VQj`NgQiljY(Bp!@kp?LJohH2H_n+bRCO?Eg=-jBBel8_MyA!)1`Ihwx(hpDIX``9l zMg%y>qJuM@nRWIgU1yyt@F) zx0Wv-Ta{=Q7hfe_T32c@qdDPZcd@S`7ZJ1J z&Ewd1T!YOc%Y&Gc6mrGVO>MFbZ(94U5(3Se^3jeN?CUX&Y*pfG)%s8?>c*>5BcOMmN2;L&QjL+@HsBt|D}$$Hw{l#dkkNOPuduKt?1 z(cd-lt&+*$W%c8%l2V-}Mnk8HNSN!-=jD&XrFLh6ejMriILet2iUp9~384lnP3gi7 z6Co&3TrLUsHZBlp!sR`|y*PD)o5PYvjORkZBISpl#-}SKCIEfRp-A-%y54QgVtQB1 za6(aU{ccv+JAGcP648+%k=Mm?g@&-hdQ+_K)p2rdz$GDDB7qyNKI$bCw6fsj3#D&P z-Wur!CW8~#w@(8-dDH-3;Dvxdc>F>5^Bn|X$AiJ?s^z7l((e1QC7#S*+EG)NA%hk! zoT#@WLcN`eG^#&XYVSP4ZU&lM?{=41mvU6u4!1$HG$CCkSjRxli*qd*x8sgVzgo&k zYt#wMj;0)(lqB8YW22hK|9Yy1g}&n=D0B**VK7)_C=8I;uyPOJ3XA_fKCKkSZM>YOVy-ICzgqVKoBVxKlobbdb9L2$IF} z2*q!DFCcMD46Tg~EI3FL@wY$R*l**zOGEnmXzjHiC*qyqy^9wMV27Bmuwt!DYt%1~ zRT~q8s0LG8(yG`hKF|-`))AzEwts!xE#i1d!HTxe!Tba6F>ytf;EL1=6$HZ6W33|G zyGA~+P!Kj`pLiuPA;nxS)Ft2}b33GnVR;j6bSM#6#N7o3utkxeN~bWj{<2c@Ueg?AAtDFO>p)4s$+` zsbQ#-s$P*sM9O@j1}zgLZ8;4ku$bE^kRiyTFB1Wdy7e8$N9ISPh1>CK6u_R2HWi=q zo>d9Vu$9Xec;C&tsGEXLDLUh5uev5S?9G@FxLdTEA3$cHI+fWu<+)yCq^@ggMuj;D zvASJWkusU+vDWmZ_40+sw7>@Vc-UyzX(0ijtQ=!Et57VM%eUb?5?GF+#lYz~^q6fW zAR;DFR$#8peC0;^$yz8n6(06RApE_{{w}54sWJXrpe&qLhh9HId4tq={Sbl(eirwL z)e(1ukN<@?9xE)N-M&O`m0{FdH!UpdaK$?Fx+hp}Gx*PkA5d{M@vm}~2E{)L3{S}x zjhUV{9EH*(3e=%!-)ctXiD&lBZKT7ok2hzF!i|$EHT5PQTSF!8$Uvn+=ZOw#MuASg z1j`$80mWknl{HXDu#PJSYuKL!mo@5U_CDiBp-u{H)KBlOrYJ?9i7R;JZsX%BS+dEKMu~Knc8m% zi=U16v!_<`?_%NCvb99OvFkdp_*i_vm$`)nrr64I9fGrPE-q0x=NIEp--3{Kp#$D( z@P=p;RZFyQv(_Spa!71up+ZZio$;*p7SIG5mL=F) zgMs*b%|$2yCOK87<97wn(iTuMH(kcQ*fpW`C#wo><_$>Q8K|TumMD;=6Zg_~AHQs3 z?h7VTri#jI^1j(+vOq=rN;Qf45z`^z**A~FKCTi!Ov@qgG0{aLoew+*1@`T6u=%A1 zT{?cE;Aj(uM%nv_1iS1L!2C%-p58_D!!i)&43Fb#&;>-DwAT@RDP^Wf^4Xxu(Dt>F z(r|Bi(KScq^|3Ng|CNB;yV{Y&Y2ED)nMu1sL<2Cqk41)Y=5%DGDt5(G+uR^9bjb(> zQVtKcI}34fbu6hkHMMd!EJ9u5Y%n@Ib;BO~odNU?9eGKoW36_tsVKL^Sc5&Yw*x@D zrQvQ^#B*p>{^p9{WBMZ4s)MPuXZw>+W6ZVay3KS zZzlqiVOEOwA|=UMya}nt>djrpx|RWK3i`AZitcFPOZWY$l9u3(+=S23+D2041@oVh zxUwUS$8{{5 zr>cIj<<2%KDs=Td?}w$lA~Tc^%!aB@u!rwWwm;LmICRSv`&-sKjk?S@ZwhQcTN`zc zWh^;|!rTgn1*V&JU1UjKf{Mk3n1kCD@wMBXfTCm3kvdMkP_h0dJ45y8hv);E+t5(^ zDY$eXwC*HVXe?RjP@Y3d|BateRuTo#D)lEpI7pTFu)AK%oLP1=E|E*})(Y7$Hgc4? zfkmkR=YKk&VeJ98?=h+IA&<1O9p z30UmzsV7QX*1OKnFeuM0RhlZp;kQ)r7QsaTsQhxNIGIx;p|jYj5_TZh*ag7H2PM(B zAnv9Ww~pQL=J1s~cx-_wW=;}hzqFam)JgS?oshwUCLT01N8tkxvN%|VIfDsGzMc9X z0EkE}0tK3xSJMrMSUHFfDf4d#@CC#=EJ#fYYGD5cFCW;xjXw>XY!=6U2ad7t z`a$P))P6RSq4xwKBcy`_;(BCRcdRNyiYCU4TY7Ua@9o=nH-gJ~WMgE}a$fMtkXweu zXhbn&eC?6e=>_<}SAjJZ2UhVsF>|BrGJKaw^@^pebk~8lOj@Ro^q|yF=V>=xRR@tbL3|)`6za&{cLyqXnTAWIr)EZd77Bb|x$9*ctmRx_$Y7Y*FsJginAD9jN+RTtEwXu*Z1sN3g|*>RyKM5i#AzYH zE|c5y4Pnca*#115hvRG^$8VhU)f~LAq3-rlb^^BpE4&hsOMVCg|Y#Lsbs-+*j zWqD>avu-3aH+kO{Ts=Sc{>aJLy3P$gd(sK!KSq1+ffRShmhFzt+@Eq^;}c3GUUw5z zE1S|Ps?dIMlpLl2Bn?f#3vxrG2F!!M!_YJmOj}EQ#4x7CBYf=~ z(-yUKI}nPIk`;t6zazaBdSFb2NG{w+0B?$ui466Kg%Nm-14G{TaB(e#|INlGbDNF^ z^}3_H9HjtrfFhXP+eD>QiD2JG#!Lu&=|O*NR&fv%l}cL^7KR}G;e3^;LR-WA^xM~v zV)kmy2_VU;Ma{H4%~I@E1cna0XM2ZjT02p0!#Q_%Q|<+#8y)qPtTlW~zc>RPi|Qvk z^B1}WN!-3&@G0#&N9~7k5(FVwU*?N4&I$MU0R&~+in%K+$s9Pz&c+X=l(%?LcI1;) z>_;-_h{o5v0r9Wdml`D~Zo$!JFSI|KAiSvTnldsHH-21P0wQrYX-3c zrQ%c6Hk zR7dmDu$4QEhbzIi;+SXS2ewyAem`wQ^NYCC*1JYcJytqjR;ahb@C1}B_^}^tGYL{& zk+k_``Ew;!u@+!GA{;uC+Ay=)Akd4HlsL=HyQApMnVog_W(#uj zdxfXYeWU*M(lC_?Q6V#>F67v+uyt^SVvpcQYy|Wg4_Xux6eGB?M_kwnUFJpA?s*(8 z*hS4Yr|(^$hwmE5Ve6qSh4!6p?kmqSOb9j|S<^z(ll5cz{m|*f;Ba$VRSE)y>w8ah zs82OX+SXWCMmf)58+k0xaln9LwFuzIJ3+N6!AY)eevG68nPfuWHh2yEo6aXsUG&Y; zVeW3-#gM>{<6k!3246A48tSQIq7jnz7y9#g=nd3^H}#RnGKN3;HP|6}&LRblnFwx> zLwDA(WS|8_*bYw`^t}meq?s^jqv_6e*S~eBq-;+Q2uK#!Y!g3Na%2RmXWaTXBF=b~ z(yumNx*;@MSdI1hC3~q7d>`?|uXKufvL>lrHf&osRDcnJy)t4>m%`nCb7SYVhaAX? zQQ>v-Mrcod5x0_uiA3f{ZGn-wu7gCkVQG2mLOF)&jW1{K6)KHHob&A&9mWiRO-tbn zdmME}cd!pJQh&#=f!7SUWFR&qi$tO9F1EeB59SfL7Zl=mP)+!-ZwFm^U1gfN>+)4H z1#KUJ3{-0gCJxrnEh7O3&2~*ie%I`t$8Uayf=f5HEV!I?=jMN~eG5IZyYzMs0l7{= zEs0bij>$m@i_wmY^i9(JmIR|pf<6DN?hCdolQTU!nMdsM4pkyRd(_gOq0w*2YnaWW z4rkvLcJA>Y?)1TZxyc*$HRI&Ui`hDbgVy)t*H0har;Sq6C5{Q=^S_j_3HYqsp;qF< zC{d|Gz;EI4A%5M`Z;T+%@x63kzwVtt@ymz9A@5J1^>Gi^6bY&8*tq6JZ)cm%3_V=I zN>QC1?=O-6wuZD1c-ZAPwhSeP%+87opgAOtzq4`hc0OFAqlEN5T&<9Q zm3lrF43Uz)dm~QwNU`UCn2!E_&~tid=E}TpA>c?f8$14dCpz;|y*}hba&$1 zbk=1-j+0~NhZip>!m}vw<$Bu@qbv7tY>u{$M48|hLH-Z4K+M_D56+QSm~%^{4o}XX zQr@D_&yHyFe-)Nb|2EqxaxCOR&O|pud*6?j>Fs&X>wR-S#7<7^FbM^Og)OFikl#($ zcCXHUR2S#!JW$Bgb}+JYz3dqb!A*Yiz`XwTX_I!iCB6om`i-xzj4#Uwd`(@({m@)! zo#*V-YZb_ndjP)5x_&#-x#Rl>DZ=e+8-Z_PIi?3TBX3J@L-#aI-5^9_aNsRpPc5%WKYMTzjfg_<57Iaw!8N79Zj4iV}P~g9U6H{tAF>9O9j^a z!$}r>kXqAjV1?kW?#YAx!z&cNS=AlZv?v^CL#-d?hh#v9DJm9((@L6gP;@qe<-)iC zyZg@c8*h~YqOyJ+@l%4nEaC)ZpVjMmx-YTkH0Qd6A;n)0#D=a1AZOp)1x#(Mr$~h9 zV6#?##3!=wpY!xPqsdpqCPe03+CIWNo~Hed(p@d5VEHt0-C{jm=yxibWRnaxwosN! zAsIwTKOze3u%2Dl08BZtmi1{lPPFrAOXqnd{?RQ-fk*m{{2D*^3wcDK`^6o>I@g_M z23ep^Fc>kRY)Q=G!uu=^k!$q{ZluNGZJ z2kfC}z6rr~8ttEX%AhG<2#e0p5bKVPgYAawQUg0&c-`$<3;4ButMZ;Xo26-Z#Q4)n z$U|bJs~zp8LoV^^DiW*o=1D@eED~k5jOT-|HbI3wiJMS0yqH)HY_f)e$!_T_m`iCq zKpW$t1vX!QNv0h9K%f&*v+JjhI)C5TEa`&IF(&v#)K^m>xf}MLGr|ff;fL8UY27*+ zWPs8#MV0kXSCgWxGzJeC(#IH-fG;sjwcoJ((3}l<#NWF}vh%H_Z4w; zwy4^d^Fe@{sC1`lN@|(9$zHWS*OaFf9S+c)*2*8)WHn-l-}ENFD}HYbCMkLH`6?^4 zwL3tCd?NC288&p*N`oivOk~HpgNYE&)QMyqaWGxj^$s^6^g_Irw|xh+|+NFoLV`yz+&K{2kEE z!RSGAVTV6CgG8Z&;}N;EbSZd2#sMi8=viUJGQ4P7o>>UT>I$7aTR0tWXN?Zd#G`yQ z(#&%HqpR6zk7cm5RsTFoGd}VXd(-E=1{Zv(O#mI(2E~*7kh~%ghEN-(-=B#_s^W$Pcc%<|YM2a(zqkZ6qwV5alk&^_A&i2HUUq z2~i^BkV1ihx~KOxA&3J(Q_%8KqY?CJW}D+#i|MT>i{uUq@th*kpAs8rn{*L%QuyWC zz12^hWLI6f28ixvq$Im>H7@vkUpch*H;i7f(FsOF5!-TNzF;+(Yz!l!n%4qo;EORo zkNmha#z|$lL7iluV^kO<1}u3;tZD-?%!|yT$eouRI3IUFnRA*c*2P~DD2(c#4>B%( zxDG>p_hD@rM%r9Y4m&-#O*ux<{DIN;CcJIWYe~alvBPrPC2&=H=Vk@cR!2SX6~4Q< zd@nPR=@ye{7~jNc{>-}u&B84}UPT@r+yQ2G9Q$jEr2y^I>=p#y+xojY!AbZFF_QUH zI>9qa22O01+Q);#vk4NOkX`~@eB9>@j?Dh$n4^0`_6FG1HFu%hD{>lq4~J7v0j3Tg zp}0Hu9@Z%aKBv23ZKwp{xr~rP-KTd;SGnL^A#bke6?ytR-c8_))OMAmJRT$b^57)Dgm+>f~1)9oY~Q&@H@wqOd!@LTf(s&E5O7utj8 zA-SJsTZ){_h3wSGl%sbFZK&5G-)G!5aC;5H+GNB&#>EKsk-vmQ?EZ>0+mTcgu?zEP zvIm>S$Jnt(8?8x^%@@`Suo9G2+?t?8gn){Flsz;w^6)^BwY_;8PK?Oo>QU7qIk({J z{RJB?hfaShoWHszFn|e3RMG2xVNqiTPnHxxfbOfKpbH~;rxV}Vh-VBWEO7sfTjBDSk0QB4)WLqD!BmyE0 zatYQ^P5JV#2?q3WPB8PUQ=^e{9A;m$VAm?q!yxAxa610>Tf=6 z0K@OaNi8N#X2?rOftJecIyFzO8;b1IuIAx`)YK48>Jc(5>gt9O!%fBy<)iBpWSM)+ z4oQV!rb}lzMbR zzDvH`m5m5g^MV8#(Xa^DiWPX`bT}{t&)=?v#_;0U*OuZ~6*bM7#Vl1%*(8*wq8WTZ z)9wH#Vep+L=^9l|+!;R$4Y1i{%8svhKnZA;AAEY*$g$z~nRz7BOxng#Cs!iHJ+{iK z=g0n5^A0_i5HQ3tsJ^<`DjZF(HN!n^?8zeJ=;Tcx`E3NOokLF_!E4F!E$LL0-aD6ON>p=iQjG-JM0Xr6H-6qB6v=(kg;rOI}kKu z0<=MQRBX3tB9A|io|D?+Rad=_eJ~FY-E~hjMlx6#^SiCw6e0_x$FJL}pP<%)rIT!aWNNK`(}$b%;_#i!s%!UhOcoY9GkFBExo zk}MT{98;7|@&f5DkT3QK-FHI=LN1wDr4gRPrS zdA+<0jgTJtD8*_(9cqp5K40Aqe;| z2@)D3;0(~DzKbV8IRs4{p+mwpI9Lj_FDS&Z#3fyRGN*K1IG$awM#^Dkl%NE(bg=Wr z3+WN?Im}hfWSZvu>k!lY>pfNg>oCaq$P!84UKa|lQo68y!?N@lDQ07t7z^~^Wau)j z7u#sLJH)2i(OD-0`W#Y%hB-hp=GjHf5>D8rk*W@u!^=}W+dZy_L5tHh@=-y=H<4)a zkl1nplif9FtFX#l!Y~qpU$W2#ZaWS7M;u8x2wm2@9V;$OuMbC;iY8zI4S{U6xucko zuYFgp_37^|JFe#R@pd?A!FCpHzwgkba5rRLL4o;ke&zD@JL(Ud8CH6rwXL2Lu6C#| zEit|>^TEGpDMev@H?AR4unwbI$W*_n(zQq~nc^3&D{e)Xra0m!W;%!aDwmz@{Q1Ub zn!OJ4gpf~WrPZs2gu0(SfE_ym;L3>BE?-cK_y!Qe>O?&<&m8tS1*4b`cCX_`>nE39 zI9S!ao9(pjRV?cA4<(R&aS^yB1bZxMb=NV5)Qs5}a#>TLw5S_2NRkow@U9BP)WTZu zgsKvq`}%sL1D7Bx^tMKCA;tlUFPkR0fd56o5OaH(%EsPxd0`3>;3=Zr{DrwRiP6e+ zJyzu`la;0IjVtU7^>Z>XCYzdr_j3nr0VX(a&J}#*b++J+bv9=5yF0Ii^9JfZqb^p< zFe?PV2qQcQw8Y?2Mz)W6YT9}p_%j>!gLid@K2e(CgOKiCyv@k`Vv?NfgdZ06%0FOW z5{Dy;&GYL~?qI8u$@|GMFbm=VcApWV)VB=lWk6KUVb|Yd({E+=6Q#KMU=Qb zffAd(?LM96tA4S#s0qT3u8^_ zQR>0h2t+JOylBO7G+88F2HCW*7gJ$)Qs~1*7e<5wgF=WZqOtL`4z7~!nBkq@OQZ~^ zZCvO!dtKQ59t?i82`8f$?=V~BnmAJDo1%CD!qrTS zW1{lVfnX4jc(MsjC97>1S>svaU~4l>{-n^N>+|&M!M!00xTUUN1wO2Ww3u0*uxj44 z4*gK>nYh_ccqRQVu!`6UZ-z=hp?9e+H7?J_6@3vdh^+?5nx{86`=RP`B>Hw1i}BF+ zi$v{6E{c6S%Ii$s3g#^o3YGUw3L)J2U(=DOb*jx73T?dJF0HJ`g5K5`7+AZ16#hVz z)<&TwI#S`PTw>{?Uzz$HyBUU_Na`gzVL)?+p~)I#b_`vOh8tpqv&ig`q(!3kwgMYL zSuF3u8IipvkXVlNenLV^u?ZgLp=uJ+#@?TLY*WDGfdyIDLlsy;dXvd@j>bqI4GPmCEd7B2lt)YzLTbA zy*HRid`i9EN|GLW$*7FNpPvwr;75Fqs)-m{jl++&0ctnQ^W()p%-KO9t)aYmZ0SVn zlm5xlwY~Y{L&jJ!Y)XMQw}SqbP#j>FQ)a#c3WO{k7j$gYDIVfMM#En8|#!#2{iMbMYt?X#sLU6>zTzlWagn@-(aKynE;q2$!IU z-kDSf5WOV}>&#oIgdgxfBo=q)q*>kv=i=t~$&XXi4^i6F{hBGTOSr@Pm^mkEd}JCR z`gAvf69RP*p)UD>##Zh5e6*KFVjsnu;jVOWA7l!nK^vd15JX_maNz04`?5h_44*O- zjyI==HE(OVi7uVlwGQAKp*!Am7WPu+pnDWu0y>{Xx@+y8svzFKRLB`Hxei8|LNv`L z=}0P$f^<_UW9sRJt76TtpWOAt?DXJx)a<-+pe}BpEmxn{Jp~_GSYjB_pOk#THH>m*U`?DRv@w{ z5}?p}+~5pak@0(4o#{{?rG>vi@RUu({=%fgUY+F~yWUi~ahl6z$IIb*+%ap@U(7#0 zWZ$(@=IOD>hE$hdQI-oS9hF-t=QEP$iGZ->FDG63{!?g?h&H zB$zg$SX4V%`I+boe_N5Xvb%w~i3Y}pwELGJ&#QZY>wuNzN)~jVhOa>qU-(Vs z%CIrrP~>@_xNX6og4{nOwe>8GR(*5$o`MydGi^71NL?9G|KhZuot6fPxReB(9va71D!A#_4N zA?G}F(ZLNpPX}@-+}T$}XngBVPq_Q73J` z32h-lbvk{Fp2QqB3?8h!C;JRirmM&EBe_`}!&VoqPw3%$pfkL79?9LnbzGNxO3mzK zdA&#KGG3FUowTV1ta$ssvz-f8GfILORA&z7NfiJe&Ga~ z2JR!JSw>Oq!n)&k8Bi%a!)tkevDQffk|QXkE`mfcu}d)t&e2@}w34Kwz=pOW)M#80 z_ZnkgyeD2-yeawnxUUCskjh6L=v9ew4#QeU7WOE97~`@ch~R*)73T1|s5;a`4G=O| zx(Hk8+1?kOkQ83F+hx!BAKL{xvhSJY_FKOoTd@zTYVu9DeDDramgo@wBqbXPUa74{ z$~Qi^?pSa>SFXPegkob^!A+}Qd?_&&iZm}%-)Bx{;T+WU)S2-$aTBiuuYK(vHW5nd zU;+x8^?Ki)4W{D~lHUs)XC_oRnG>Yw1x+jIksRvZ-;la?d@AX1j>+OBMkjdXD+sKn z%=jRa)Me(HW$0Xm_*OGP4Q83uJJ+inE-M2vq=HGo28N3|JbcmVfll5#pkeRRX6F!;G zqX%QAf!M>l>#wFE-N_p*5+u;_7CDel%R0oxx4EPj$P#C%xs>ERb*|a|D4a8PAEJLl zc2p8nYGC68w1rhiLpr)Q>U|PI?SL^F<-do2!HN`3lEuXpY*i3xwY4n$72ra#;eza( zpmR$8J{6FW_TzZ49d4nC4p-yI%}!Qw-v3B1u9c@l!kYPw!naR)kUFRB3(1_FZ@gz1 z?t*x|ld+cCHxd-5g76R+R2iB}om|0E=Gyz3?~lPqr+tPBM?!02|6e<^+8r zDrl?aC9zGL^5j!{X34l6B|WJyt!MvooSEK00Wr1kMvvcF zD@6_nzZC?z3L-Xeu$E%3QmKk76FZuC(j5u){&mi34i*Cgweew%W1VugoQJA^hS+rHHy$~2g z93^f8FO!?T?{}i}G$F4b;hyDhbYZ<|j20~NYwiC-od^VsNCkjuk;Tf3 zg672d9enl}PCWslW0Mel`9r>#Hwz(B6`c7eXOxW)pnWn7$^y`c;Ex`p!U2QEOQN%P zTI6h|oLSq0A!P-#jf9<{SK>KbM=`3(=iQnDcrRvExW2v+=Iw8*fj39xCR^~gwPwBD zO=lr^v^J(PK3znecAgvtn!CJ;HVBZ`0bz;ooUUxowGa^ zGYyi9lNvzB3&ePp$!wK_6h5UmCi0DXn~V7s61a%*xkwPM$ltBy?S6MpkTgz7)ErRy zzS4fk#6C$*gB`*ZzTL-E{8nK7rXzP9V$*TUnbkIWnV?=WqC*IVfY%uKBHa<$7!m}{ z+qcFGOI@OnHBKvH_Jsu8R{X1`I(E;(JLmDn#_{(w4$$N4@m$n{pLHSw83_GnC=jKM zDAJ_2Y=?wNaBPv^alEKBz6;B498DE2XSdC5ZYlu9s&vNGK$P*^Y$t$<7dm`a0GB2xF z6)YSfT0kI}K@bQu8{5-v0YGwc#-<|GzT29s{M_A^jY0K78xh>EyH#{J#0%_dNyj8n zhn{4^!k5Fs8N*%r^Yh0<`d4D7zWGsT<1MhDol0?vBrqC*@8m=vkijkd%z>nk{(@5k#73Tc2jwde z==|5>L69GwWo%>9yR~tCLCfH}1Hw@rZ~a9$@A;iiEN&0C=-oXt|IbHI8)Gof|0oEM zdm}WWuwn@aET#=i)JiU*wUV(>s7P z1X51K3k1xQrC_z69>dCiD+!_IHEf8LH9tt;(^?G0=oZbQaak!L>l=ylRG;NynwLU5 z3*f`vD1qU)@?;I~`0RTFZqP?_XY$KsJ0D<6xeK6w`LhD%eHzud-kk&!T{`Kq|{WLb-Xu4`QcD3~UIG;x6|7?q`(=BEeXJ z8Z;qq=)-fU@t57f`Am3?@J^eNMxo#@;2}T%0b&!#P!PeQ1wdo?H=HlZI*8w^<%F{S z1>B4xNOd8g8HD88#W4l~y&9f6$pj^OKYvOAmSOWdXrJ3}V;TkKVd?d=E^y0d$!DZ? ze-P<2Q0Kn~3V{AwpX@ZTivKdw!e5al{Bxv#3-lSpGf<_B>VJ;(`67UyNNfKn(%8uU z=cJ84`|1BqgR!msf7L;M(b(VO_)THA{~X3|3cLTKFa%Op#S3Cp2GD^28#+oS{C9Pf z4)FX@aOr%17+eb3-}lB}JLBIe4fxl_UAo}Ej`UY8{z{5}V`M;3!0(K^bp1b$)c7AE z{b@%3z_0`U-opGk?w+~rpIVsT@2}~(|6HZN4!iVxQ{cZW@BhOYzh_I81yV}>5z@cY z>A#{Hk9Df2e{ae;}M*2Te;~&uJKTzr4a^nAFa(<5y|Ar%e zvz&jF4Syv=;P*NIf2G1d#)iN4Rp39yhQHb$;13SVf1pBvjDMRAeOEZPNWe7??lV@Gqy^f3o4vmD`_e2=NalssGA^=1(^K??wOb+Mi$7 zhJUi*FHVl%pKAZPHvH8k^XJ;|@4Qcct_}a*&-M>i!GEp||FEa@&$Z#tWyhau!{7CF z|LH0H#hd-7r}VEp6~DRF{`8doj{orgpPtf>e~VP%pLj~&cy1`56fL;w;_o0LMkC-C z>YetH98L!7Tf~ppr0hAizF?{@RQik98qDqUNMrlYx=9s&i5dP6Zqk1p)y+>-e<))3 z-!mEA|FE*cmOo>qW|r~n=*0QAsV^EG7`pQ=ju&3L$ZQGuO%;Nvo27v#13I9t80RIop@PEGn zrvIf!{`dC3uKJ%9VEkVk{!i`yi1VLKne+`F09(hb?}Bdy1FOcb_d+Tm1gvTsJJHzA zcSle%!Ll%bukfOA{loc9TgzfTb;-L}4!U3bm_Pf$P$aHF<|gBAzv)8bXVRB5QBH$^ zfP)MSX>Y1_)7@xzXAX_j3aupA(s^FccDrJcNPYOJ>kPp5U_}W8EU`lX>xi_ylXp=p zZ=H6Z8LA=dF!&A~W;UL)z>Wy&iA^CLv74qj;TuJ0Mx(e!>>>_0W^?^Ps=HqVjC_4I ze{0E}gilYJdiNiSy=3cq+CO8PoGw4ojx^5MlCys;n^^U!D6dbPLPlO)i^G?B7<{*e zqH;M;`MDPcnBY<2cq&9XnhY|N1LVH@s5S;+o2(f2 z%W(T6ef>+x0TgN*A6OdFO{70Hn{`Bgql_Jqk}(WFXR=%0@J>0_*b^jWaZVetbT2<_ z8j-BW?OA9y&AJ)B18UVGu?ZO2bz#m5K$nG|&aLtCFTwn3w)^rn!7mT;(CD^Y44J** z%lVYLy|@!{>gEoT6;oI4wJ3tglRxHdVyD%C--rk%&k#3lX~iv_%$9n2q)`tM_1igAh=UGA5y@K0nNCN$%jJD3u^$w^kLtz<4oV43q>ieRdw%RwSwx`lFnOy zOqcy94QP3E!z;o`@Y4F)@-;8sl~K_{lIYT)Y8!0vAMmlLY|5(zMVy6%ZP`HTI-EF! zeJ)DtyP&bBmn#ly?X8>!zL`?cglHO}O|k_+64d(!z(rv2nfp}9DBX)IUwo9(9|A>z zWH_OY_ff!kHs{P3tQcf~rol)JN<+r^)|D=k?5z`iY?l_>@UXNB$Zku+8aF-Y=77Li z?}`g}lpJ`(#e#p5lx5Uou2LGi``xwBt%M*{aN!c80)wMT;KXX)CxEJPcjRS(Vdp;* z@d#xM2%@)n|89-v%e^xQnr7Kymj&1h7~4>%d_nZ6c$auJxOc_(xTQCyIwM^&e8fJV zrjH_w|48h56hj46zOL|3uF8+fR7=gh2dJBR-tbkS3y_i~&4JfQ>o~VaW+XMPb6j61 z5ABM(>KXf_vKv?z19!wnU(oVi?gD$GB^cVk#i4sFZD_X6f>WY~I_wl0*0v#|b%ucE zE0%<_O_uBpk0%?XfUHC#7i79=dMUc^3WMO2e^zhFLJNXq>bASfZLVn7sCeIF_2e>_ zRLJX4`+WPkrwYyU*Lf9*?Y@cyA2e2n%+2F@_&0EkDcsd!RFCUEQL`2DgY@W_4##VN zhvd+?BUR&7Kaz)7CG0W*f0>rBfT7sw7rKO1EGF^fM>Q53%rCBAsl!)W9oi7RsFwwG z+O)Rwzs%TTS=@@#=wUTZG*-v9#`K|@v7*wYQDu;Pq#RT07 z1fq7YkkK&|gVGT{ceV|>@7=VQs*q8D*D?)ki(R+Z@l}R~V>a23Qz^`B>zs8GcoAcS z$5a<~&sc*&M1NfVymdd!7Xox7t1!!m3s%);;%RebF~2LI9Bf?ufUTzfy0f zF%gIg)jp;g`Dv4(om#J*J9fk{R@Jsn~?^tf6(%>uuMnDU+{wDUoS|jVBqE3>$7f%w5dNI(@zJ`#NX{cX z?%5`c<2S-9)hz${^OSaZ#jos((y*j`GY_9PCj9`546pY9Q*udkDCe&hM63IQ8HaKa zGAqR>)r|m_L)cqWNg%<5wx&~uhCHqP>6i^dg2Kun=VM`WntqIw5!F$J964C=8fy`< zw6XB(c!!_DTPeKJ{%3#eT$%y+PW#=c1k%{HQ_s+w3J2Moj^m?sPxgUXQmrKs_}$a` zRVd@C!Sn}&1r2xBRBFfoe>bz0eqmYzxyztn5D)k%+?RW^4?x`s7}lnlB&wN}*5BKC z$V~VcDdRxfzqiS~q21X+=+BEM<-TC^DTwfs6^~Wdn+CArxGQd-NoDyJx3v2=LPjeZ zsXIwqR?GbKaQJPdZ~^kCHV?_)7Q+=;gvJdEHny4fdn;A;ermSG^5=05kn2Nlp0MPX zQpu+~UoH=$2LyhCcDl@vp{b~YgmO!kNDgX88h0%E6udiBVk~oZlD^*E`48|M5{;*# zA%bDwqCUiSyF-a=UjH|%tf}MtOi9D`K11@zOQK*vSe3+me$$b`_XX2JIuY>+vR9eZH%w(u_ z9-tFS+I@Qr42;|O5aD{2d1ejc@e@fk6rwn{* z7JHcHKKdR-{wCEvKex=f)#weNUV6t#pSV_*i!w-D_;wQWOVjffK@u8i^1DW?_H`)H zF>rxwW?1f_GaxB*7uJwBdM9YtvS>LZoezXBjOUU+t$Zr3jm;KG&zd~hBz~RT`?dQ7bGiVpM17gAKH6DkssQNpl5k#mchh=!k zh2oHcK4y$jZBqFC7;`sIDkbwqcRNM)9Z;O??}yPiOL>6Qhd+_XLWWZyi511bB@P9j z&~8(BqLMKCPMQV^9=VpQ9sa#jzu(5Rs5i?^#YppEDPt7XgTu zA)(G&hH98pdGa(E)HIUGgry8qs|Z)h0x|nhAz)6+Uh5MP?y(+wWrOUU^NyyzK<|50 z+TrD+5JhE&5huviHTE>^!80oG>|a*c>YVUx1`LU9%3`_xzB8mwyn+76J^(k+x}{>o=xp5^oy}yCeO-1vXAG_rAxZ2-lnx=| z#TNaTBr#s(yzLIxAaKY;iyx|_+HdqK4!33xN+LNUAqzchUGvxZd>4aZ!3)1K5gSr{ zahDb$43G8jb-?N-cZlSu z!%N+|rclXEfQvP3s08T0I0C0);6@j{8)UX0zI{cnzqXD1^hKg#564ERCt(CGDg{a~bsIyn-Cr$Pc4RkQ3C70o2bVGe~wiJXTh?K=&7`M^1k; z?I7>EB6opsykeIO1x)`ffPd3DJu79~`r`3zz=Qx+eBmOEiL{E^l)Y#z1}}Q!TdBh_ z7pF~^5KHLzB}|Zl8{xjIdz;qLwG0$Z#GWs?U+y5^n>kHRdQylm2fpLOg1yp0M?zzi8A;TxJSIU_vKRB-h6Ea z>3~G9zK7r}kGsY}aAIw36)4prHRu{LUjxwVW*)pjNB14hyH3U_G7d{-axs6%xA+Ue zcsVO9M=uYjIaVc|A}{PXMsv1Uo|_)Msfe7-n(@5S!5($)JN&!Xtp1<`S-V+wNj!bZtfjqcbQSHJ@p%tI8yeN0#0Xy?y~&(gm%#)hocaNuhk(jZDEAJ*s>OV z2N2azc!qy7_Cyi}PU$li>Ww@44!%bANxI}ns6(mR$w^e|pt}v@wzuCXrl|AaXg}kx zJK)H^+F=sh3-4gP_49gXeLi4!FD92Cu=%Ks5OgO1gTFCQ9cR9GYiUamRe=xFDs=R{ z@tL^X{IfZ!P2WqV?X}O8IUb~Bw}PkgZ(QlyuHj!5K3yw5I*ZW7hi;H@ck@*WUWA?m za4~ytu(Zd-dZNOzv2$tLVFBp-93@>?xN{4J0AVb+Q3q}=`I3dXL3-1d8XX&MT0!ZO zusj98Sg9yMIL9v8WjbEpftTJW!!FVWP1fz}1Hal|-({Yk)E)ot5B#IGu*I1cp6>5Q z(aPOvk5{O|j#%wRF>(bEm=6KpC&NKr**X~cdH={0@OD~8WK)ZAslh1}%;~(}z?@%z z7fR9a_rm@z{!#j)I{_tx#euI5f7O*eyG_>sV4NGs+;$3Srjq#}9u6`}sCX_yl@87! zit)}f%n%;BUMtBdrB=A;3hUE-NgS3=&O?FysHVg8w@=9GQRU57LRuRrL*CC_}UB9LY^mghGTlU=`&j zgUZitR8%{)61iR~F8Q=hrJ62IZT=!B>sO1@qC)wH3}cM`Z{2xwxTICxtb2wEJedNe zBEo=bP@m+@g~8+$w)b(6@e%>L;6R|3K70?~q;(T5?9&$XK~R1H7r`J09EM0Px0Rcv z()?HAt5`>8Tk8c30iq8tnXlhFV1)|tRnlrVU57rGa;psoAD7`lOK6z+mb*xwb%OK9 zd`X9&rE-BG+%@~2OBqw0fn?Pv$Sf*Z9{*Z#WeOgi1TWRkA1?O&A}_ZMidC|Q_>+Qz zHH{KW`Ec?W+9cU(T2|Zv9%B4OgZ++2A_|h0eg9LPH3Hyg+!?znDW+`#4#*1Tl8M79 zK`6osu1d<7>QWO^#(QVU;4@>O!SJWM-g?{0!cyX@Arm{|No`ho0$CQ%x(=*u zeGL3SeQgq|ICrE?=cvoJ^-2}+8+!O!`vd|4Gop97f9(oQMt-t(i_q{6f_t1GD4cZd zkdGSh#>4zluL%^U9_H=_CVYu2)K@Jz9=JelihG8UGBfIei1_))iAQPHFKR-}DM!AY zDAnAy=@8VuJp3fQLnofoTwUMd3a*qkH+W?JT-tQJG0H96{j(ViljAZ9Vh{N(DmRU3 zkpzPmjuEDG#M=Y;y<rg zgnGbB?<*+v;on~j0j~FK?8L%n5Buo&3-mkn3-2$R0+F1B@oPcue3+Rebg)HvB2cZm z=TdVG!A^Ynzc2@3HAH*9jd2JV${Xue3o*TC5cOP_4`i+V(d3layS2Sa*^ceg8@tjJ zN*yNW(Vz{=?D2k@}CY+ucHxo7P_;h4228x3p z*~)bT<3XWM^Rq$a(u|=URt|+%^SRBcymK)!Lz~P`I-)fQdrPEpT}(vEkB3q2gpuW9 z_QmSND`m>`7<-z=Y{C|+sRAq$u9SY8A74Wm!wyN${NmE70K*Pkx?jD9FV%a$Kh}|lWrL$fKVAQiTC~ILT z(;`ZA5uUv(wR!elT_E3y=bOL;ZM-?&$-c>(rx~StcaXf$=m=BPCu}J*y8ZFff`-eT z^r&Bg8_n@MP_q2%4^g^>B^D8UI$2+bc9CP0G^kkVJ)R*qRWEg~_|7zK-2F){rl^v* z?}lTiisFHQA$B7DoC32j$Cp+;sBah9b{ZIc6~B>=NBL>}<8d?_fs*Y8zP@!JuPGQj zn%`L%rQB4|Nws#51lE%pF^aOR%)sv}ud4P{&F1R_fE)>=qh7#sr^e_2pEU74DmRRV zqOtU^3dmF4BRv)q*1X`&)oWYlYl|%(;D08m>T*l9c4}*Cwa@k(zItY*^hX0+Xtuk@)!Ms zzADhsb)sK7#_jjjbt2h`Fj7sTG{3ZOV6LP(+)L2MU*5l58Q=AqlG<)SgersGPf`#Z zLcM$4$zUy+>C@vMQFJ~w6+E$R3yHIwGp!VXvs+E1V4YYy`bQ(3oR(SnCQlF$%41j7 zHXBOh>MXgsP%w{f-gY7W#Qt4}Z{jVk#KxmXVaW2_V!#_bwvFr-(NL$7Zlzvz>C4?l zZ(~n73cT1Q0{WtgF!CkJN$IP(p;-x8(~*7P$kRv!Y`vdYlilX$dejw%4w@sC(VukS zuU^Z8d%8uyiL<<1r3C!VhU*`q_2=&BV5RXxXYdjCCg*v$KAyqfMg$sAN1~k?Ybp=7 z$DEP*ht_k0^{Mt75h1KnAdk1rtAXKYSVJa;=s_j$TMjg@QFaoE1ZYF_EpM)9G z)kYa!_LmE$tCeh5$w6*u!Tg~Af9smt5B#b!hg=EJeTDZ9d!1x`9bV#G$;8eE$8JusA*U#OmJVi;$G9UD*Z_$~*L~!WU3GM9b!1jD(eqmf z$^E(K!4=d#pR9*qWCkEdd>7A}^8kBR0Ud5h4lRH^i^uJ&Z{PC0g-}-`KZtaMCrL5G z7)bwmtA4Pn;npi$Zob4ny*Otzy;m-bYJOYdC^mz3-B-HWK=?dadr*u+67yM4~DWI_#UV=2APGSOA8B3bzEFd4ioUKkpmO zlph}7-_tYEX{4-{40~WJb~#A@8k6nKU(W0&E4r&X$e3%ucLbGbqRw8JoXHR)ot=_V zWS1+s5mc}t#sk^yH}AwOOP_gfb`7--K3`r^3+fUMsL6QAehW_v8^k~n6}fdd?UZE& z@-J1(A3Xmw(1O&&A!gTCcnd%xj6x52KF*99cZRUpxk+mQW7&0`sT)DNtB0M0qZE0o za6z-QuM@>!?z@oFUNJ;gO?{^tNcIjJS+||SM?_3*1Mt;5CAWE1NV2c=Y(-niwSK8_ z6}S4rghfnWAmS{mRqpYF*PPi_2cP6bymaY*a- zH!~%>11zF83St(YSA$*$TlCO08%ZH~ro119eNFUM&&wUm@SEq6OP2Ep?E%*lfhN5d z$xKJLPnX129Ikp-eMyRR?1IOG^#}r!N;6QHIeAkU*{JA|TQ2!}4DZ}4JfaS@-QK}D z_Ce<*7>O`uzf5V+nxh$;j=ogI7A-I-SeX|);B^H$3#!i~z<<`2@KKnF#@Ke?PGW1V zdPrBGYnU%sgWtkF>m)J%kJ;vI8^~WmS}pCtNb`pnKfGM6UW!}@qd@wbX|NsE+uWGP zNKML0XYt87`kLL|gv^6@KkQ)pz1)kR1vQ`!I%iN!t?75lxMyrK!k)XkLpq%+EjS1*T{N2}U=awi9<#=EmN&Zkit5Y6;Ime4shw6^c}A z)JWxneIz($%cL)>vUBeB;NWs83D(uAx0yp|H~MA#ls{b4p6{1scwj^&RQw0eu7S|f zPaTumH_qk2)^FCWClkWUB|V(RVHHLLEY9CRzc7)IMdn3>y~j9k1cfxBPa2C-l3B9$ z_@RR;(BN)B!ku&^W_34yOalfS_$k$iln|T={tyzyzkd+Eeh3Bip-SAnCPJSuf(@>M zk`=0H>mp6~(52vw$fK8P^$~wDn(Av*EEUKsiy!?$g#K7E-zt7$^W)tSfQbyYY@-hn z6Yu^ZS4nA)s0$)oGq#b~yXN7ram=D-^+l-Hvgd4kKR<1`DRxm@^8}dOZh7Xt2F`JQ zt-ePZNK#3-T}T5MxADreqPtd!P83KMGD+Q~uY9Juqu(EytxWFCXx`#Y_HZi3Ra#6o#8Yewl39KDyOkbLJ*Y=E$L2Qsqm)p zQQn7+R&DltpuC6feFILuatOXa!YYEuR9>PR{Pf1*GVtV}qhh;Tc2)=M_qRpqsE;T* zx6_LL*p&(`qK61KW@w`k2K$z*kQT1iSw0KFOBT;o{hVD#UR-d;O{Z7uqsVE&!DpUL z-&>MoiX##nW!BTjp3wu`4+GaOC2?;>@{sOR#3`AUeOZG)|!ICJ3x z2OjLM5(7CTohytEKemPrYxoGjy(6VJ8T|$veg%Gp>CH)>);&5E6cy|hAz>r1|E49C zutP|Sf|7-Qwgw(Cun?{7Asvz*r6s}X1uVRIuG56|JPl=PpJ~m6Jeq=Mbv4*A)MP@uE0^Y) z0sgJ8Gmf4*CWq{rJ?)aer)%o_G4yU+0or&cz$2Pz7thD%kd;9SeI#G`#F@7!wL zyyNf9AM9r;mdfL~vx9jF{TOD%7?UO8_{#&$Zubb9{O)WjrQ^rk@(_fTiw3HC$ZJd> zhgCz7n#K3$$Du?RY?#41f6uL}UVkGrui|o1kDI>haM__%=DLp*f$!vJ9YodepK!Q~ z0zR?*4B{{1V)WiN!qr%xaC&Pc2)Vh+-ERv0!VJU{cNQ;6C3H+oIwVUQ4)e zisW$gO5DaRWHXTJSTXt@>HQlXGhX^p8?d7{IpsxYXzz>&$g1t*v2}l~w$}0dObx$v zlE(0A5+Pm@E1B8G%SMZ-yZEGu+kwAH*}tAc+5V}<;_=4>j_S^)4mY?+4?+<9JIP0P zf!K(KiUFL)!1j+@BY*h{sVOr7fk{iWpM=o97>hK&sZ@+d4|w5T5We3k%7Fe!9w4HQ+=x4AUBR5#5E}s6U05vaU$0#w8?nJC z@@I`Yl`TPgn6!i;@X7ZYYIczYZQC|kFNbIbfg{l+Bc%#SM{ ziFa<9CIGXdKqXSNkH;6bw z+L|^LcJ;(=V&GZhE$5b{67_yN1H#C)Ja1o~!uj>2*@pC~)jVmiUwxe~jXNW)0KzgG z9$PRujl!>pA^PlQD*wD7qrhu-r10}%ACq?3`SZ+s2d~G2X2gTnyyXE>Xh*`B!9uqO zfo01IPCVJ*{V3fO3nqJ(3*a{gG3vH=deQpalhGTz?$2)^a`urK`gm^b<3UGHKeHv) zdMuC4?>0b*!mBAUduuuy6~^jyCk2w1Db|z-uNO#XyoDCCqbccM7n_6y5f|mAMWF_F zQ8Ln;=#quj*hYuWr zACoKaa^eq-@O*!G*g>b%FNA}qNy#VQRS6Z#cFip4=z`%(;Xa!}YxYz2CiSazs_#qO zpYBdk+Ho80q+UbJf2{3Y-fmpe^ipARdY`rZ;z_@Y5}!}}ff6(Qh((b{6u;{SeragK zKDhsuY9<^C)5#Vn5eDQhB|>|cCXmgPhn+pPS8FWYQYJSjjgwfM(o|z zv2Zlm)>s&Jgx6>M2hbB|QTom!$Vs8z z905@oi+19C^t(}9lZBKD zuIedUyfka%mGx00b70#wC=n^_#+M6>wU=muMP#Ycx+00M$u%=vkLvj!Xvw!T$LiN1RFh#Ep)24j7ls zOqG`pj@&K^_qQ8>el(B;UH@i9Do0_$t+jQUlZjjTd=$3}LW##S~&~ z!M-Czpc5`dva?NK;x)pON^k|6C?@~ONbu{xq7$I0p5T5Nps$eW`;}=OE&1oxQfwih zw8VB6e$(4p5wd}*~c=!SL;63zkv9F&t9=6xUZQkp|DZ-t0)0xA8fd+k9gxbiwOEeTgWK(M3IQ>k>aelwA9l(9| zUHa)0W?zpPzJp|gX(0VEj`YYK*~V@&lwkz~50S{Wr-Rqq54p16zHmVcHRwHl`rr+H zycQu_ZR?9RQX>a;CGWP0(9d{R^thH-AJCqc;z_C`ZaIwjY4|z}XBisWnFiRnk5M%K zB=&MPcpQosX0BmkCPH~>G(S*i?12M$#y|ptQJE(W@@6eb-NMKCDCTel0kvmW89oI} z>!DYztS49OVw2#6aM-*br)lnbqIB3Ddf=}vz^EVMYGMWX0;QhcVrE^&_y&>IK!+1C zB{?%VCZ(iE%?Kajqx}ilE=Oqj&YFv_0`fX!^;Tjx^iv1FgLq<)cF#tXuXo8NZrjN zs}1(E2`!us<$cO5Nlcaf+$jLj2Qc1}&1t_uoS{``M>EJyF$5^)y+i>aoW0t1!5me` z*^*bH9`gugqt|uQ(tORHDKM#3!ZbaMF*Yqm-(&~ov;Mhp&|p&PlM$!hp0dL1WJq2f zu*A9<0v{m7mlEkZz4LIg#T?n~lNDa1^GSxRx}QbJ!gh7@FJ_WrIXbYkmCyUFh*k@i zIL!gnPp&?IuWhI8FAk(PWyV3($MrG3iS~xHE{xYrmE1Y82ozMK%#I*t-WMtT6^+clo+V@HQfI?^&( z!HqY(aZsc(3mLNYo$WTB!EUd@(GY3H;z;LrxnB5VPgaLsVr)f>^=5SW6-h$~c8uR# zx;^IU(Y7)$_s+8O?^E#v~t)! zszbE8VgsjK-46-FQ?$Bz#VWQdR8&z9>ZSDg+3NP&`u3;NA=%TmqsvuIrvFG&;DF|j zge>tuBSa}#>xUMVhtttSiyc8+>P;;4Q2Z;(=Q+GMKTd3*{+CS+o0qQ7Xp!gJzo*u~ z^9|hz2Y4j;XR0Nxz}6Lwt+`k)1G;tlV8k=u3Auc+bU}4n#C_iVf_lSnCuBBbag{@& zMbBg{XYLv89a|@19$b%{8tu*{-3KlQWCOBR#`Fik>ePi?SfB`YR_0=p>#+e5#UaWM zzHx3mF82dCJhsxm!s5dlH|CNdtUqkE$= z!43O3PUm%Y)_$+ls6nIXFf`g@DX8X`&ZUuYMs@n+E^mX>n1IAiqZxoZZ za_GfLIg}%cecNA2H*iqjTt*8FS@yiTU_JbAmF9jezBZQimSLcpVujY2m-1fkY!EwD z?sHsKzJ+z4ullb!@_~1h7QbwEjtvN3jX5BBmcQ23E7!0PXl$6+9`7n(*>G8(NhaDf4l2D4d_4lqDlqN_h7Rr z_hMUMaav4ce%c|6U}t^*R6R=h4w>$zCA8ZWNa&L zr4Gz9P0hu8X`x#LW>Nr^#opu#;@`t$N_%ktH1WSaHsd_YfpR-buVr@cqsI#@MxsUT zG*Ti$*I!jdhwFMdi-s*P1aKhAfnPe*yq)@P*V>KTii7g1Zt@QbHVm(K$JS;(IY_@N zv`|$wTb^qSCixx>q)B2OH9BaKUKgQd(D28nK=U`AoJRzjrQvXue)-(zix5JpVYWm|`C=$g39fUOkWp@qaiOo*ZG@~;z&Vd6@J)HP`I3Q(S} zABRx>B=jP!X#nVgjQ!xXu4Yu%Z9nV*Ay7dOeBPhqSy%$k#FFdK#2Pejlx=QF&3A-; zo=x4fy)ez8HM$M8HHqy%p4B(feWE~alr=?dar!>`eC^6BAwhdDSL?V}=&Y((lZ;-~2R!$7*6Rg!UD=qV{Tvh)j?sL8DK{3q zuLFGe>W=i|1p(%ezh$IYPox8M=p)iy1eKUoZxhtqn%z0DBGwg&Us{E68P?P@!3Bc1 zAdc%&I3`Kx%s{GI6zuPhyu)Ym;nuA8xxQdrR%&Pa6QM?#i9Bun3IW-U?0FNXs_#wA zvR%?snm7fix%i-P^860yHnr*iUHqr&ey1-15`wz+DSW9oGbW6XJ;%3PJ4Zk5QZE>$ge;R(@J_ z^)5c70MbGhGa;!$|9|fvIYfbklZa?UV>Rz57^(yn{|7jlIQ;k}lLLUo1)ABpOxC0^ zePrm=TIF1)g01gB12>>CENC4U%Q1P*a_Gh3eF2s@8X3vLLvr>Vj;kEI1T{uHQ*FOZ z;QLj2p~h9n7>)A|sm%=tZ~ zXzrrN{&}jK=@kN{&-yE#A0Ne|!(|d4{|hbu5&^QuFT1_XbF?gMDjI+F&OO$xsF1eN z?KeaMy%@Ki5Ete}-o8G;?kLLF6ZIbgF71)k+19sTQvIAcAJq|eCz|O5xcWYIox0(f z+*k#zb^cz*H!cPMY5Z*}+BO}=$+aegM3rrB6S~xx;lR#R%w)a{atl@81p|RR;C283 zJcsuLIqaPp9REbC{OhAgw@5YmTX(lH(Akas`trKL)+rcsxV-zbYpXljVTip{>?;}K zJ7Vrkm2OjO<;W$fH3Uz?hDR->MUFp=!H1}1 zVx>W3i7HQ*%JRrDX2TGipY`S3yzL@6`@P$tF2vJ@7KiWcGHEn{Xq5}}5A{RH!gtX6 z238%fTTc$a9X)u9=>20l_fAX!3|>MkR5Lj?b0`J@rjkL#Y(~4PgEoM%=S&Viyqm7G z>BB<=Fp#6Iv-I*D_bnarf*uJB{#X@?7{vOOj!IFN6r@Ly$P(YWJsWz0iT{ZkN;}1I z3U0IJtoW#c4T5Z)t{Z4FVw%9n`Xk`#URVV%J3jGU^r8dKdkx|QY)~}9G^@sL{@}@UVB}2gu(XTuagPfn=J%dM! zvIzv3H_rrzu87~GJch^UI65Eh%b$HJFx-bwL4Aco`(;N}lSp}nNI!6$=M(U>E#&oY z*qiDkuRwDql8zn4<+j0F8O0Z};lUqX4-1$e`7X^xc(%P~hU&ga(sAVlWnVFTXptE_ zTJGr$96b~2k9FN*Ebcr(t-3rbT9KMx27d?E=2BWrcchslO^z-CCWABd7;*|D*f?(` ztgAdb&87u9ej{?H!zls=zmT&spnh^o9R#$7E`e9>z8i|B={EV3nVjuO?dtC=Yf-}! zE4mthLo?->Z_i?xn7n;6pg$g_^o7rmY9P}6$;X5hz68!?h&ypq!1j#nAG#36Xl(?T zBfBfrbsWTf6G!;$j$E2B5%I~e9!AF9gH^$Mc*K0$K z>Fm-G4`D!5o~xQ3Fr;95C>N0mF&Y4D#Kc4xsU3ITCm?{jL{2=$-L6CBrMp}4qJAyc zuKecO1T!a%^}LL>BGPlVOx}Ry1ie_zE*rdl|1<7WT4BB+GNa*If2FOazy(mZmJMoM zl;A$^R%~uU{wVCmuhNn(;<0XyCp%eVCPMg}SA_ z7%A9TCJ+7&?tq$EuM@A39K@>kSI6>gy@foYNcq)aHEFP3+FpoFjSZKrYpeq<;Zqpy zWorraEG$c~f_Eo99Yi*Bp9sjW(I-QCyf3~nijX`T?7CTJybp26n^nRVzECk9Jv5laZ@x%%p{mLF7c2x>eQVx~H zy&~^8{IG5?EqTOkNAN?`Ab!GD{BNP5wXt`EM}M4&-VH-**Gs11XbA9D{xgYcRxo#* zz)d&T?Ba=)xx{51WtfMcChizB;Oy?S!MKeQjDo|E5O&jrl_pg@rDLDQ&(?f4S%Com92_R5>;fLxcb%3>jL0~@Ot*BYaP{s)%9=|uF)u5d?ShOL zQREHk6rOtok(;u=RvpB|VR-weMcl-u_QvMVEdOKC7jdVNx5}L-&%IFh`=~FFe&8}w zZ-MzDoQ#5x7$)YtJYa|8($a92#I>tf%CB}4A$Fd+` z78)xGAfQ3YofK_SzM!ja@hsG6dN51;dWwWwqmop^`JG58l%*rD;JZMe;6$mm_w`O6 zzMgpXPdV-`TL#uJEXNEeLo5=hGKSJH9-FoeGM%VKzT|WK+R?9M!%rGE>Yj)P-LX0> zoN6tl4Ajp6dQJRcD9TgYQvnSr_swrI(w`D$RN;_y=^5mccW1VOU-kpsD19$=I-u^> z&S6qpL|7Sh>xW8(r|f&e*?y)?DFmXZ8ay^vO7Z~)iY9st1ymZ&Uo!M+nR{~>#yt^f zgBUPE1XiNn&S3>hmmRAUFd7QA)@#LFm=Ub@j93wXvn`nlISWyKrq+&Q`1_Lxmjgak zSY{z|?Rrn@Rti{-neriQd{Y+VWQNG$Ntei7ad((!#1;|elxDMg*V~_qBmE!ARMoU| z!`XzQ@!?*dqMrabiALVNLC7(3$i=0K+?byr{3)&U`z~}^?D^fDT#0bpPyJdkCI*TG zVlHw3d!7_W5VJ`(58uS5VNr0diPWjHKHh|G8d@o$!EJ}aoZ&K3{nv~=9@x5Sj&a3T z&M3#Gx`95=r`Cjb9PYIjdP?cQc6-5pdLS#KtI5hT$RDpBot=^Dz$vk0dg zI`TLX=Y$oxm%*BQ$PcQ3PkCfY+%y&Z`9I29`~9A<9kBX^ENXCMPK>& z%h%opBX^2os)t0v8uIXf0e{(npP&j$&K8Vfh{QrfFZWsI{#VSq2lYh|XJLCngnRcbHQlzX@r@R(6ovMX>qK zu%T&^a^eNYcPF}8P<2*# z8k$8nRXhAv(jKP)(-3)aV7qJOf2t`sD7n1hhIl&&(7znyll@q_J9mJW4X}w%Hmdz2`_-|wP1+2~#0hQpE10XEs| zNd`-n4gN#r(e^5aYD)J2_y7iw4x%yk$iD$+{?>M}e&u&Em7=wBh+jK@&ctT8ZzS^F zJwHqHTcO0?&r_@H9Irnm$a`LOcsmBk6K{W^ule;x3*-9Qe_OfS7KU5ai@H)}Yp^hz z#XeMXaxO){<+Q2JQ0EnkLvfFUdXei-%snC-ZOr1JyC152fj%*atO%vPiBpjylq=2w z7xwz0~wxpx2Z zrZ<8KfG#G$i?kkpQPAt&_YV?#nh6PX*r`)#LM!-n=3NFUnf`_JTc3>rG*VGzrTlU+ zk6z@MoIA+W!=It8K!9$%+>R0KGRU_lfu~*D7$c}^j%YK*!jOW}brzhUkUa)7I1Rt{wqKnpW@%xqe|xV*au1uA zHI1BlLw%A%hQ{nHg6A{G9~6L>`;xz!$so5YLsg>^;3YZ4fhsaicCe?|JNjeqiae}e z%l>}?_^s;>d-~`R`ahkmgJ2$m0zHMYeSZk`^P-x6V3s4kx?@jhc08OidA}f^Mni3i zc%2r|qY@Iu8-3$ftwi_hBIp`uA@gXOr9$&T!zErw=sKhHmRsmKQUAt2H}Ul1CDjK% z)sRBgdUA1yO*Fm{HPQmIr)(jb5bgRM=I$B5`_g>NpB82aTN!d2JQ2=HhU zG>k?7>;w9R41eF&V|lOSEps_E4ZACqR5P8_!g2T^1(WCKIzEdvt0+_(VN|$Z-RA*wKtQU6 z(q1dC%qODEtbSQ~O~^{#pA$}6)czLhK`v2ZXCGC_>~F7j?S4GnefHcPcb{EBd~b+< zk;nHvJEiw)0*P~bh%j?|D2y|NC>JBeQl&Jl+e$}L@<;LZmIGYd>mkp^!cSf* z$~$0qU=4OVt%s#e4=xDBJuwQJFw$dxgIA0`AkLC|Kj@P5W1w;-=+l5H{zYOsL(|+G z^98a|RROHdH%rhGI=iB5m#a3zNiXm%2hZqN`&JdVjHm*?#sBy7Ex|FnR@#S3mSC)L z7RRMaS=^YKgMFZf>G3I{*G1^#v&shpxZg1T?QnEdn#}fLFZNzu^NH(|l~xabA|`(a zkm?31*IL7I;w&44t{7}`$)WJHQk1cR>_t3`9Fz380Sswe=&%jQ{hK zn?#*CXHzG4U{x@Fs!u?5dgDT?X?RAPXDaGbsa8wODUB6-krd}?<_vB=NEO3=G z>6@nmJ~=0r&&|kCQqr^7hDv3BTjFv1Kk;_*8P$v$c(4ztyje z)7U{kq~gs|-vsR7%jAcDhABBm_sd6?(RuC{FF)W~<~H}dEUAxV!xUh#I?d4gKtp=+ zqUw&Z@ll0>8}$WP$sl~U{@=zca~cV+%IWta^* zuhyZ^w@=%^H>DK9@PrBfpO!W9@OVJSjLP~F@)$m?g(p|^S^mR_u%CSP5qJ+~mb8iQFh?4KY!mPN{D=tRVf+hI+AVTMtuEW| zL4G5axXq4E*}*f;z*Z!NQD1N;5X&iAZl-;m*VXcNfN!NXLY?>hXjx=HpZMRY%zuN~ z@x)Bx&#_;I&|1^T(fYxm>*$A$buvDL%oW{}xYluidC35OjT?4v^NJ9qg_WCg6RnBX z$Uz8pN7=fwrJIeU ziYvvU40!cW0iVE;W86jfVT-?9-S@8{XqPHxoXO1%x(FZUt*ep2A|%R)JzBEJ=YK(l z#=GE;A)t1DFTCTkV7v$)!w-G>;JkZX-{K-snAzl4K-1wPzlYs#dqAos>PQl9D#;|b1xVbG%ccPgrn%(*P>qF2jx&`Jv? ztQiNwhS7szVas%IpT?+}d*1>s&MUH2609P?K0YNS4m z>?X3U;@c}z)5k<_ck*oZZHvw)+s4us8*2L&vllO^nNYXUVoyxj5OF$%Qp)Y(lpeRx z&H^TXF?KvVe8zXebjg|r67cDNy&fnF{ z)fj3`yX8v_>m*{`2+=CFN~mo36&@}Xi@afHSSh8`yULKuU49>1y95U|B^1zyp2eF62;cSxno+$}yu98_F zrN{&3_$TK-`sm=ujYa8(%8xeZBC-C)-w(C`v9R&unr8p^vcV0v%aeN|!uvKh)DJ&@ z#s73&+E_hm5t+9?>p|)KtYLq!1(>ym`zJ`FAV#l8;a zG8JbE=8i&4h*6?FR@jzJAh5h7*l#j_4~?d}mELtV%SihemY13+x|sh{ zUvC9GsTXF&UU%M2IYOBRKa%auAmW?diU=por#@E93(=fkoG8x_Xna!tN#?n48_RsDv{lklbEMZy11;HgXWT$K`bN)x*=>;$ z)|%)4iRt6t<`kD=(BxezAX($gl2oo%FXQ9A5>mvp2~Q0_8lf5}1lM3-AwNf) z%jCukX5?N8U~~qu#gH+Z(D!Dq?%4kt0;gT;->>=TlPzpuBKCx%B?1?JL}H$7NgwcS z6~X8^((Rn&l@7U~u-wDgZlRRxM|9KSQLwc{9nxw=T~y$W3qE^G7M zb%)nfG|GFtCtpU*eM709H{Kw+gp@}BUmA?E9;^JdJX_5hBq+Qf`3hMiP?I3`^xZXN zxfQ*qnKnTVZhg!9NdSJ3t#%LY-rt#$SjxBpOPI!>p21~|_lMeFk88EzK?wtG+*li? zMJvQI<1Fc1q%{Bkd+galj|^)SeMJ%FN*{Ct$E4&**d@~TW@ znz^pn(hqdNI{j3vQc2`4$pC@Id0<7YHCToM)Z0cPYylj5U6R!SH zM$naB(vgHUiGMj?m%lTUZ4ayn^2#$a6%YC%Pc+kfyR#}%d8p-^296za-~a#?0fR)k zDqMUkpKs;w);_B!509ZxN@CO#);yWU|GZAFQeWB;yO;J({ZAg8!5W{y>=x{Uws+-g zTV?HK(mbhuQ-3%;-&YG#8qZBiJyv5CZbVSFZ(-@k_gFrNQqd%Z;-Sa^pFg70exwu( z+>SfFy>a!jY-v27^)VoFt&Fh=haBgSH|@FD8H88h5luypgfEbVKAmJ10jt=VMo`ul zty2z15pRYzX{%twN*_s`nsxDAod!diYg>n^P6H=@{z|$ent@A9gPI@^&T35^S?J89 z<>JerTy?1bucSd7AvG)Y3O>wM^NL9RW0uZhwmUn0E<>6@R1eg=52LSM(rypYbH2n7 z(Y&KzoLr$7{kIu9s8KQE>@re#0MCC{7s>HpvPf{?P`M7ewXfjiGTTl_Y# zE*I94QDh{Myi)r~h5KujO{=jLh1+*a9zg(qSg;s76y_*d8$c19`lwh3rs@-JjcfQn zJSlrQdQq&9Lvg6Kem=6WJ~WH13G!UKzE<5lv+i^^C9Vxd{Lj@exo}6jxlJ$#u|@+O z-|JhN!agJ0s2w$(V2D*e`!l7mTh!>#*0m`jDxh9#(8<9fvy{o#Q&7=-155#HwYn;Q zV-+^hw=-}4i0r07Xv4#Z!WTQ3hwTOh@Q}ShnosXzM5&Rq1OIr-+1ORGK+Hf)`)gZ8 zc1~Z{>)^cK`AhLa^NPRuDJr84fHOOH*ZK|EiGauiRT)N`w#C{Ctyd20`izxdDPO`0 z_UVTL#U=&|s7B=?PxtJd?T0=cO`vIi8`gT`zeI2S3MJ}i6@pmKr@Gn+`5WMF<6}~J zMyVKG<|gnMaPkD7GF}Y^-s1f9LO2IIv;TFVah;s}F5JtB;k6hcg zKHJyPqmt=G0@Pv^!B6%v%64sC@w#{#X-TA0yn=0sP8@m6<7~GL&|nB)oP}S1j7y?l zt-pJJw0ds1!|B>!02Of2Di9uK)J3Bzt9%=p0{)#-OzS-$48pVB@EPep-;|sgNOpX@ zFDhF(CGH~qS?}-sPMs8d&3M+eenLwBX=}Ngv=!XQwO$GW(OF-d8T8Lt3Jy*UH)7}y zGZ}PC7BFbS(#MXhkdk9CWXYC)Y;h!=_mTYP{DUK@ylDeV@1>L@-5zv+F%|0>JDwDk zXU@7F{}B~o@Dr7@)H*gw9Aw_!VA>bVV$;F=@2)9WxD-$G(1hEu<0Zj?FuSiN| zgaZ6edSA?$SA}r#>TR`CMQNBo9FcFuU}G6{eK{fLP?pz!K}WK172JqinB39nTOL+=l~2tW(ySBrB~E|@93=oj*g1CB z>&WI)&N;g|MNC#w==Z1I$lC!_5uYXX8>-G8;*k83M97`$v>G%9B&pCK%k*D4% zI9uZwDnYqb61C0D>)2k8ZXyoYLS}>PwmZd8;juGThHLp?KJ8L}_XEiXe`XUS&>j|& z`-5_Dk_WdMuK1XG#E2R1%m(RdY;TV=VGS4GS1{!`MVz`Uu%9ZXC)vzVyIJrzt39u0 z99Smw9CXiccAPsSV4l$@STJp!>lw{u+Ixc|$%Cb+GRdVJqGc~aP3$3Qq+BWnXqZ$` zSe@PIyHRpN4yciTpBxZB*_z{_nx*6SscK43^{>|if!`Ln*p+C^W6r1<$3K7|^rHcH z(Ek{PQS_mymxB^;HuuB8(q1!MYG_G-2#Jw0hogk>%QsIlc7`g&pS$@W$2a|r>Shc! z@H)M!foCN|;&jxX?2p^EBV;-=LQ0i!?IFig5E>kYgEG>8F%%3Ib9m@&YRPA0AVVnh z+^xk=W8A;lq_K0s5dnS2S~FojmJ68N$EGA?27%I0RZO(R?vZ8=GgwB;bw6xFX9*N( zEfx9;Ux$Z00S5x%^tp3`88Dx=uP|GUN(aRp(<0M8l;r^WnT^GTQgkbDsQul9o?%ygau98+*BM4g=?!8OF!%;0QUNHdah~5O^xCpgHq5>*(2>Z z&@=~?{S*}4|NaQA&W*A;8fuI_p~_sp;eOr(&z6LLo$aYzFV`p7(t(XX1n!L9{Ao=f zm!3^QbDvFL z|CWyDsd2cgOWpz*H{XY=*Oq*yvF{vH@JDce0+|?Bd6wemc`c}A(KM0AoPBOXI@i12 z)nFy=>5tC^Tuc`z00095oH;x@_x7+3zkKNyQ@6efETL-S0d;Sw>8X3q=DfPiy!RIf z5R{IqK4v}M#~cbk^f{CtAj=-3(>G6(k>?A|HW5-PpCIjl8&(DOZ0pY zOt?&076oym`M|O`vwg-+|H!cyCogO}?<5asZllP)98^U0h&xrrqHId&TU9Pw?`8)JYkC8oJi2 zCTF(ywl;LAsY)(N+B4I9p-`g}ie6kH`FfM=YP{0)KZYhSY#CbW;A{^#mHRtI5OO*j zO8GL}Klk`udsCZRktse}>eRwE-$~@ypPI=mpukEL{u|tH z@{>f|wL3{`#Inxwab!`#_D+^UOa2YZt@C?!G<1UGy>`%#A`Xp2U#$rVr#*by062Lq zK_GOd?EJ(Q=iB9Of9s{kn{__`2!9HF+C9zEXui<5*lt3;d`FMJ*9}g8s{)1}m`<{CrU>>Rqn@Je z0unpz;mfa~qQPa9^?7Q4fKx71<@fy{W}an-%Ue@NXxJSI&L$eE$ijsuB8T~~#!V(P zqQ#MU3=fkJ{>fl1`tMIrM}mNaCT*XrRs)QY9D}mP$XIfHBNW$NsqnSlPp}FTW5Yz0 zlVh@jWr!g%e2`=$&^P7$3BK$;ocbYO#cDumZmT*w!M;1OeN72}Mb7iEnj?<-nh}$k zpP*-2-Zeh`jSg%Fg{3pXDqA`1S+8X+we9Spw5kcU+7q2alg96AgCL3!&c2eiy}(3g z5nz&~$*E=eQt-$fg%LFQ;H$?>RvIa5RWzNc(bo8}&8(X=zB zr!BBtcBH!GmybpQ0-j2#|6Lp<_pHlUNM4+{$SkBVxG;{Kudt#XCZ~7;uSCr zilmcbg9Z#m1l5^`I(ke_ZGJe!;_S_l<(+NJce%vx0(ACDe3*?DxR#pXfj5tT+ z=L(vr`#5`lj(TeAz)db;88t^E%-%;)jBl6hmc897QAw?po#tdk`v8Z~+K1((Q#}tW zM1_dbqmA)JB@fx3aYpab(v~!e#|w`b+jw{_B$Ml6>+i6PnDQ9qdj4;-Su9;@9q8Xy zSx_P-Ms+p_RIaByGp*AIEAVIfX4|pC`Jf`D*PBLv2(2F8ZX7-J%iUo@)3%qWTk#i8 zRtU6*>6cTkYLgnoB}Kax6Hfx-5omK0F^2sqyz@Qu%fupc3fd2wsM>`>o_7yYS7k;6Rt)L z-eAptP|v-&t6op>{m(!fqi>6UG5(IX^H7rNBiQq(PGcu`w7MYV>k9R~ zYv38T`ttG;=g(jcN9g}RJ3L%_tm(#e(Y2+gl|?yg5Rk}o(-h4w5f>T;a~~d%jDj?; z1oJpFcqpP%|Jx;za$oV9APg86Ij3i0G!39+8rFmXtAkHa;E7xDd5|B@TstWG)!d> z2`WSH>}$4)Y1ao0N;u3uRz+?j2ao|ivAWv4E(;fjk6kD{#d>nJtTMak)$|Vcb_wqg z1TKY!83x=r#0lkYoIVa_RHbPQbvDk(bKC-VjmV7?vMwTMIh&_Z1ic%{v>u;x&Il9G za1zz{!CY#}Z`t6IU_i5m&NQ2U_(mTnW71GxP17w0wg16CcBC|u*1$FGZ*O0F!_c9; zxEhnT;#ve1%ob}_$d&x zt!Ng)VAxzSDvs*OrL^Q1oni?}qP-5bVC0ndfmUn$fRmMfi?I|Rr<%ywwD1lG1WL+w8+t_T9=?gbP$srAKj@V612?%l zj2XK@2KZWgDa2IQRpB5jD8AmWC)}jJ59sNy)bG#6PONqnGdZ1si)<{u*(#0F>lU3y%GonLhqfo}O z?*uiXqOywgT9Mu8Td2V?PzxCvRJy7^UEY4q2c2;ratkn5|1Pj23BC?Tc+Tvu`_;a^ zk?)<0ebqz(novs5@-MC~A=myOhP0&o7wsJ_NMPPJpe)19dMftcr^;tRLc3~gqpDJ` zs6LvCNPxY6UvEt|-XE~h(&x|`Jp{7=73^#V>vnW(xq(HV8gM#$`DK;FD2h?^*hPFrs;4x3;=kyB!kvL_vUntY_Gt}6lz?-9-y-$9 z3o&0$Gg%{$L8=_AIeXGQ-F2!-C4f=y_$Zfan2=_{B0D-j(QdCjH>D9^quf=YYny2& z8kQ{*Fm=}-J_>MSp%^~NOB)}FzNS^JGzk0LFnoM`Gp}70TeZuSobLn6^k5|@eKdVM zJY5lgf}H4dd7(~MmC@51c@vGUIsS_Of5W2J@r9@54&65r<|iITEwlOC&BGR#8EUb7 z3Xy2~?H5A^jt5q3eKorg*|>%taW>}#CkYi1^1#{ zkX9~sCG|r%f-b`E&vOSI`ICsE!}DMhE?cFl5a#XYJF9$>q0Nl!LyM;yuh+T=7vTSY z8OLZgXEBNqNbvY5f-U%6T%Go1ugi~G?i{Z2mHR?J1gsc)*?7g`t^3Kf##G#k`0=#Q zCDZeDqZW9gCdPm^2KoUD6z5(^=a+M*J;nVtbx`FYNi~=MJBw+%zdy z#<$H}Zy)7PRSxPi&UfE7kNWKy1MPOKN)4>UmDuiyMfEG47G9WiOn<+W<>R4$b8%N* zlKKdoi3R_9Mu8KFxCf;dzz-+7svvSqOiYxq@S#6EF1n70OpbAZ#q2E$?V4du_sbLM z{dPQzwQa`#HS?hj3NpvcD4M&!CKyYijDV&wEPzSmU+>O#n@3Hgvczzct$z@^pAG5S zZl00IE16%=H%i~1<`Jtv2PM3JVjem$Jz|od{zxQrtdwUj9pJ;<4MLw6evuw_P@&8?%t)Fah zPOBVgf^lJy#zG`;fg#@F{TM0`VWZzjN?n|?QsX^C8qsVl;l%hhS~2p}H7MhRp{q*p zi4Vg6*f`)Mu}4{!mz#X<_^jxA6KZWskmwp52l3d-Ds4v>J5pi)?V3YxXP@MNk=Wx; zGM)*&n8ZS4u(>^!2Ih@_RoWS{Nar^gYy{P62}9HG7tt5XwIu-vbiVMb_Cjw(tPp|2 zK?j~!Ofrr82mGn9s@oNgn zuG2MyO5K%@ZxBS8R1D!IG{Kk_qzWOsCF0d{ZFy7BcXpAsmRN*Po8`?t?7scud z>d;wtfXo>6(xJG22r0G|oU5nfic3^{YBh~agG2zyGOZNDW>08>eI;tEb_DVb`vit0z zJm_DsbWuXq^;_qJeQy-R9CmC0ZJ$C-BIbW>zK`RWzJqE5uWWwEzw;V=Pv>0lR+YvR z^%7iBxef7uIGGW`vh$BWuh$?7$>Q{mZ??QR=5pn9{@&w3y;`uTwgZsE;w^Z<)Ny#$ReMI z>>|7}L7JMHIz@`YRk~G`O_1t?E;M;WLa5*37MMY-p8933qAn~Pm4?ELwzS$j=q?z+ z(s61QooJ(EF!KE%VZdO}?+{ft0}7SGPH0XPx+D2_wLr6-iwW&GW*B^4$#o(IzgTi%&%!$WDgomDtk}$dIvgr(>qUGTWw)+3oK?0(39!hYS?@t z?MoT+{#Qjd{CV3w3Fqb7!(Ja{%}qRfz7Gw5YDON{EMw_ny{1%G zp!c#2z@>cGrPJ?GR@d->>mt4w`QXTRW^ov)N*1!!(|lFfTLdU%s#}hdk%S{LP^`v( zY@hwm$guKbHEy|Z-BOAsYC2P%;596JkWMIdukr#Plk{|hObyGoR0s05u->{-+#W80rUl&3##Rm73BtHJTzOC76cI9#A=j(XZ21uG@=^39!4;KLw6Lr z?tviXY6jESFqc1m0zIqeicdu>q+={3d1FrC>g$tXFhzXUXZ@GLO2h~D7)n(AJn4bW^5?I zLO?fd&Tqmj8DX27(RPvA)$FQsjD;cI?x3X{so{ z@TSe=>yJT3u-^9ko_6E}+{I2IKpI}svi&AMv_5D&=C+X#vW=McJdVkK?^(H@fzAM( z`)Bb{TAQg!dyHGRu}|7_MeC5HV|@)}NZQN%u5D0Uswc`a@)!9DiwhXzyTzcZrLCB2cU%#=PZ{a_0{J&N?;jZKj4t#3OWQR;In*GQn_$Owr?1 zh1}5|Gl_b)3&(Ym5NygabNQ)sPYTQh00Ek*ic4@L`Rn8U5pgcIbf;1()-gr*x|BW{ z8yeT=1noMjM&oGtj%2PUh(f&TdAugohv|#UhxDt3 z*F-`-ydjTaw7k;ln6V`d;c{rT?@4e2ECF^t#|@7cy!5pvPKRTknvAlygJ)8lwPt!u z`Dn{?3I@s?XZu(cb*x+iUE-4vN&POuSQNc%ykx~T3R>lg;FyKw<7N=B) zP4N%FQrIMGP6&O|#XYF=Y(`91J|bLC11R=~F(l_Kxo9m9n|&G*{CK4EvkotAXm$TD zhnxl`2rS&jvPb=+*@PUf%sh7Cc7d)pL_(J_@C1D3j;G9jX+l`y!Yqn^!%A{S zIzgp8C7qC>z)WlQ?TQRepPSwZiu$puG3sWLNR>&Hc5=I~jZhp&UKsY=p8nR;-|#Fc znBuX-UkYvvt#?*^1){6Q+iw)A(b#%Y$qN0Vt8Uwm;m@pL%)BmI;FxW#Le~UQsm8Ho z7W~D;=Lxlc24T2@RRqUHBN35@KLj}%L5x~M04KFpWfpXWu5T@+O7w1NN0x4HCAdck zL!^_Uh~~(&W&B{Mg^258A5!UfHVeJvtcalLvNc3`Ay_tb{dk*!9W{=CXs00S4e!i7 z-H0&wF8g+E7bOXyx{W+FinM+|c+(2LK{xWY$$J`q^0R;w9Y^fd%E(^;0raNfVGv2DkjRgwK4?_8_` zP*s9|E{JVBT3HCOwzaw62*wsi0a89y7%bm$ft1tz|VN;9*S}`Y-t5xVUmA1bv~v<9Oz2u|7t zUmH+Av58Z4H<5iJgM~^WX^|^Y)rwKWU11WB8o{)yY!VEaqYaZ4F0k;|{7bMv=sID4 zy{=kq%Ap%LsXtFn2=T+c@4~g?SiyJIkT%ZIler^~S>l$w*zZN}nDF%5(RksoB_qORvzim=-%9 zDYK57Y~kn?zGL(SfUz_ZEpE1&F`#d)R?50izBx<7ga~dR6UzZ63&s z{btwF>c67!?k`C-{A)~qkf+ebHFqA+4V6IKa_WkaRnfS`1#LG7M zU5&1mU4mY5=`@o~U!sM-GaEtSsaNb+sUsA5Bq#jVc_Y^kNgmF`vEwnv+AsFVgq2EZ zD#)1Rw_ zziKeTA776Ov=;{xpDy@==xa-N>p0e`!OSCa=fx~oISos$ly%E@(!j)jSUP&``D+(q zo^2t00lLt<%Y=CfZA*J9x;tVZfIImNG>k5POWVIOX$q%lysQPt zzGW}m)x%=UxFs?#$}W&>EB?M77zRMNRe6<}Y0X-_w@u+)o0!PMvdAF1#1d|j{Z!C0 zqHRFK<_T-o!yDZf)-LybKY!x=)>JP)5OK_!>3_8V%cuYV3=>gZKfy<11grL{89uHTda=Um16Nwn##};euq)7F^=HIB&s?ZX7fSj6>t@=Aeb)p&9^j z50gb!MbqE?NViCbc+B-htgL+=5YpJnI586-lfDxu*U`*J!TPqFe`8DE40`bd6xv;XMclr z8v*&VK&zTevb4$a`9(_=14lbCZv)>Ir~zhGP0k&qf#C?rcmSoV-s!kyTpJ0aIrV%} zf$%Q`D5iRWVT>RikojjRc3=PiCqMuI z0{{R6001)}i{C=iszP!isl}R~Hh(?&s|HaEsoBk+zDJVU?da+jDvkAASneW5#O((B zA$zZZ9klEEp9XZRxH+1OJIy=>fMN2RqnJ+eTKoNfW6Kne;_x()2i^~=nlssvlm&J` z`{xq(EIkFVN=3f;YY^)Cx88nLCZsB1^=cg~o0rb#&4=>quiEAD3YyCQiM&*WBwg(nht_%0=6oGZ%wDeuwbPi4NDe&vTW<492wqSX# zptCi9`@j$N;*rc!(c43k*X}^hCZ+#&!lZj@F|jsPMwrf&oB{aGKPHM}x3e{fGk}i| z^~1Z9&(qkAFFi`8ne#C_n177gTpKx^z(#9h@8;gpRchYx-By-zY6?ZdKwx>h_Z^q? z%h4^IQ2z-g?Vxx*5fJ`>8GTR9YmIWq7DUm1>O=v=&{IaUI*F+4z|C8tUQxkU{5EFndGPA?6bDDwlvzwGXQ!%?g)WGJGk2 z=xAw}=ms-Io36$dx%YWoao$JDliuHSvCY}dt@=4Iqt*)JoZ0Wgc5g-CX$qZ+2e#=Y z)|j0&kouK&xir;j{4mzp=-HbXT~d}vP2zQ4Ptb3= z0M4>KgbLE79%dckkOgMOt9hU@;a+Qhi+LUHEcahU^sQo8dGO4G$60sfb%rbC+*=)^ z+433#s@n#;xhL<9+C;Z~PXN~?p&qcZKnrF1Wf)?7WaOZbVUms!E`*r}d0%?V+-yxj z6%pCW_}V|i{4smtVzT@zggEQ7AU3&=6&kH*BvWuO+NU4qNU9DC6_?DZx4SaAsTo0|C8gn_Ul;g!!aV3x=?1x8g*NUR zxf%##GroCr6mVI2g=E9+N0Zw0V-gQSt9-s5qhIm>_ySD&svLKV2e`q1?8qK@SQ9u< zilv>IF9t%US-*!_`Mb@X(l=nqiP@u&^6iZE#2`ELstIQdgkI<>-<5I}inM;DN%@VL zACB*zwbr4>&r!{;uXt>P;<3(deKX7Nmb8D{DJHzMG`asftlH}5t8}wH4dy~38P!=b z&qc^=eO4PZj! z)B!weQWeY2S;z9bMUq!riwqJwEIbEn)c@H%dD8kKJO1!8NT1`R4RMMuDxgiwEa&e4 zNo&`ks+q5=3vUe19-!#?A~^!#!Q<|pC74pU=cT?m^>hCET)IAgCx4!(8wPSfTp5*n z@w2p(4X8hnEPr>Wr}Q_%X35GD3A^V;v6H?n0Yi<1V*d;OBmMV5&SOql&)(|E_ZoNw z_9=?By=pSN5@-&N%tz>~lw%HYGkfF>6{G!YG<`T4=KDL)hY6V9Z*sLV)WI!Ant%j+ve zzm`r$oiYWz<&+-0Lw6veu+qNcD95th2Ogs~6?=X9t5Fkk(I1_r)Awtf%DQOdjiSf-Rg?+=3r!425ntn;`h6CBb-c^$ zfQZ|T>I_bQ556K^EniXjB1`Ae{(UGa^rj=`e1%=QPFN;SYX|j3`Y zgQxH3y^)e#t9xC)r`*^mMp5ab0-Tj##*adp{5_Tj=3*4khUz>5I7s)Vk%>L|0;F^+ zVu>js(&JK^srnTG*yyPDt7Kt_-`*}Y4U#JotuXL^puatuj*T@_H;R9em9cnh`++JR z<^F2Ya`u&k(-YlhCRof&boh;fn+(8)Z+7?IK_V00xXAJd#i!#T?5B^O_G{++C?XPu zJs5o26tNBTY1hDGAf1?!ylzkV3eOfUMP zKs5M&`Uf|uVwR=De`2)REdV;V%0P7`92q=t7i_UvPNA@0$q<<4tnc;t;Qs^kebCY) zmJ0CLv?hMh+7GQ0D0nV`EnA>LE`#-?v3jc93biB%F2|Aqs+}Z=4CzI*&e$ zA#rw@x^lR1?Op{{2y_oN#gpJ~v3r%5+_Y*lFTWES)%-~$jp)p{u8iz=%j?m4;ogS3 zYQOe0#8YURy3ccbrx1r}mnzc|w!`Ck{ZIj+@pCPl2&S%vK{85mv>txHp_8GWYP%bM zqBS`ZJ)G^oe8lVOpCEDJV~k$26Y-Y~FDLQqW1ZRpxD0-gXg*>nM*xb^q_dG$Th+Mz z{Q>}V;*Q;vdbvmuQWnSX;K%JwOEgzMJN(Az;V96$1*=#wg|p|4T?xIV$Z~lunR}yN8kJaNd3mAl|@-ZC<)Xb zV@O)cX}JWm|6`O4{O0TP)tv7sX8%leqFROIPF{2@t#AF=+vTQ2dlis4Fg7qt7;t9` zU@4=*9*=+Px$UMPI9~5cI*{DASN>ikORSzU&TAK!+byDr{8x=yAZg}5H!f^oOAAY_gy=@`*H72#^|r!Yp*?Pj#aBx&0V$15z|n3ZndJAmg%Bt9$ERG z3@=r}Mn;H&M>{C9?7&GI*_4<+z0|8Tj8f*;Lb37}t6n=_rNCvm(sxL2hr!`4C)gNH={Z-x*P^bCiG649*>OpFA0tY9iq; zfDtsae{uDrNQ@7?J{sAZ#tjv&OV2*FjzIq!v@L%Molf@pXogW`xjfz_5HG$j zP0jz>!jX$T7Fi_H{GNBrB(#_}!x@yW1L1C7z867tg&(A}9^Dxqzh^K=KeBy2y)r9i z^R+~rx3hzej6MauRSuBBnyHDo;E^jA-3O_OKg&```?hWH7EA-Im)P*e(nDw%!pmt+ z6D_X@4$gYf94E*bdmsyPG}$9%gi*M;XzidCQ>=%WT9+tZUN_Wy^M6O$F$m$l{gM^At|@3pmw)m(HGO zAINz}=qp+WTyJ%j7THU;bmVx4c3q;6Vd}*nwiLJ7v@|BvB6vJBpPgc%=~n64LGJ|n z;}Ul5;Tm5dvF164Qk>tP5>*|f zRLj0eD&>yx4b549jaj?E0ix=6OKa#q0WeWuMj|vV^U5G8fE^xH_tV7V-p^pDMEoG# zJ&-eSDft<*Fe*;2z{tlIQSrJyHKJG6rGh*uWCHdv-)H^;EG#{(lmvb$HDcbA75P;F z98H~UGa~e383x5LowQSrJEAqci0j)U5FY@AI8*U2Ml=rLJt$#MswxV|diTLEYp2ao z6OB`qdRlj~ZQdcwEs>fCl}UvKG)tRO_R&)>eq4tnSvU{2Zf$^8YTc{%B)b_PxD^W< z!*o`ra>i#y@0ai$xiRhPmozwMtxH~rNynX2+nY?)DTM|&GL$eL5P^xr(IZNxobisY z!Lehk*t5~ECUyaaD*Zd`|XCyU3_Tv9Uii!tX9SgASJ4P8lvJ$RVI zF6p^1vN$b^ahga$v9asK7proC;K_@I@jcLH24}&_hn^%aCS|{<)SZ`dgOQhbTHByh z;4Qy7I~2$QyV>SpGkMl+CyH3q_u-2S{U^W34*peLiIERG2*mgxd9HUIlezs?1F_gs zm5yk5!()boxXPL)HkZ6eT;LOh=<K6oQnE%!qzS?~XfV zL!VV{jN7H->q^xtZHCMya6a_7hg;uf#1`_&L5>RTJoDoerOTb?~Xd3d$#p zUpO;vxdCI`QWEs>*+ys-M*EnKu1VCzmO2mY+qq&;15KIM?k&@*v{86Gy@;g=1SOsC zU_=Lsez&NW`&Q18RsC!ur5)lgHRmnAqi_{t1QtLzQk za&{5Nl16Egdf8|PBb+%$iK}6yYkApoKb8n}<`7y}~}S6olpZd+9DkAu6rgizhv1LR}XXS`tQd1n7)AZaD<&{y1<^r^kz&z*LZ@oQd-CC zCT>-`l{Kg_h3;1_TLa=~v*=CaD9(b%vj8yC7i3=F$5adR4C4>;r%~UBJ>tiVcg3@v zwHQw;d-j+BNR~%7a7rXzV3xeuwITK*k1+(rg9jBHR5)Camtf*VI^}FHqNQEm*UamB z7;xJB+2CIM#>1!T4Hf%L(2R2CX6Gnc$n>N7*Tgl^V_)d$!qC}khE(1!$EYycEhTc3 z*+$7=21{p(m#40KD)IKWmt3n|Efu!==)T$sTZ^2E#p0s~Yby=$u%A)PDWFt9kP@~A!mhLyn0F_Jl?dLm=b2dAD=x$SBhq!t0g~yeRk~zpzADj>s$OeS z;G3SMv`HnI>vYs0=Q6^Ss<|bi@$oNZBJt&UmF7$>*ycz>4b37O>#kpY%_R$8_?UVo z&EN}_ONql+3g{@!2BEw8XEoAM!fj64V9VZ|Xax*&+kthq>yw2#!c|?~i2j{1j_bH* zOl>-zMfZ-yBM3G))We=$vQ=9hB~UVdPb-6>(u}CP3T+M+Yo5#6t@*%?`a~41>9_@P zbv>m5xCR{i_iBP}1SZFR+d0k7@|&F_R&T?jZoc=Aadu)c(E1U#9UG#{A6G2Am%5%o|X znShs&N4UBz&CvI9qmm}J<$;W-E&W!-q?>K8y|yFuP|@bx^3KsKOSB^&#t1)H*D}d4 z@|86L+BrQtC9^?SvrQAUN)j40DUnSS30A1~y&2J_S7_Mxa&6)WDz31&z$)87@QX5C zLUmhQB(J{dJF0SG$J)&94WD*p`=XoK%Rb)ZHj48x9X9e83hq!w%#9j_p<)XoW1|nVv**GtYC5fYRfVL zMI$wpGd!?SvCJ4?hZ3B4WAWJFeQY|z`C`7Mq$`x4d4zU}wUnK%na!%f9+SA5ZoB?S zUB>-1<=E-GH{a}AFvbf(w4PgyY8;j-Ig%0oZ|~GfFg}xT5jr2wo<63Urpsi|>ym#aKnh;18H z{n;ZX&fHz8eA(Hn%Dxdatf2lF5Ad!*Aqs%z=pR9&KDAyco?Ir9QaL?Q33E}I1D=tO z5v{Hv&1v!Z5oR1Et5g&*;?K|&s(k-A=nGczv3?}Bfq(jBCenafhp*Lwn-FHcMXr-n z;gFj&3vb+esN)VRWk#(%N+i-&Kh!^;@njCdep=d|uHx(O{-Ccuw%dAlQ9Mmb!=VG3 zT138))dXRBTs^KtO54Rg{V5xAsjbI}NMr4eThyg-UI|?>9F6ldA5>1bPzm_KKZlS* zqLXV0*SBPJvFU?NO)%mPzwZl5H)&+7Jf|1@64^ zw(CaE`73SqwfE8GnUQfztm2#U_y@hvO2k#uihBsTSxQzUd+d!wM{W$cNEP(sBbG(6 zVamJ?1rN8RC;)T}sqjwUb90Z4(mIwW4{{fvKtv!kWSw#PUHitLliB z|AA;rzC%1q$6^w))LVTib3RgL=*(3myOMyO`zE0P znU8v>oD5g*SrM?*?4mt!N4^KRba$RkzuK?3xp_)KTiV4tUA3s608TOvE)X+4?zkB> zt+RpDhJmbT)ghZWoxLfgyff&iAy{uV1|AyqF&eR{yu40CYW3`G`C%iiwKa=BHxzpW7yh?C zViGUA)?LCSRYnIX$G)jaj`AlUYYiHtwS<$n*EFn9bxvZ9H=hLa$oF`w9iHfzjP$doo<)jwkh9Rq9M=IFZB*}8JO)X+KUR_EHK{guV;YYBC9 z#)^j-n90_8sxHu;MS`X2I8_mMWy5V70`ZABF*6e{H6M37ZKS7hAexKE%sx8mshNoXnvaY%$X=2isBa&e2!D0hXEc$@}mAgr7^JS{cuTpz}xG#B%u zv^eO9gaaED<3~hkfNadh1Rqtw5emhF@Uz~@7Z-dQq{e>` zZA=$3!{LCQYsi^mdvg&MC46moeNB-mlBeSJz=Hnu70SGie4M4~^Cu{}?j>0gJAG`2 z)n|vGPR#5XXgvPA8`g7CS{1t0jUjvbk+beeE0EvPjJ(ElA?;?9Jfr#fbkw=Us#Nq7e z8pWEGZ+NjiorW5DtUf;ahLV33f4gnT+a~?ZQ+Y95T10W8-H}i+@E`=&vn38d8}jgG z>%*jR;MWE2x+90wJY?Vl6r>pd0GTO~cYXwl=>Gcf#+lunvM`hANx<^kxwLD`N}G|T znELt}X-2vj)5h;DDb(b7&U^{CYZ5g@x*B@Km2QErR^R;1_a9{yy541Jj;r?2Ty6Et2sjnVmz;eNW~I zrCB3dOvA8q{EBK)VU>>c_=I8^r)>@(_lB==H~Ac6~5az}Mz5muwK$oL{1CnW{mQg^WKS6frF7Z))d2 zj=b^odaMwN!-z+krypDH)9CB@YN}Yps84uvC|NaV-#1|(Aj1+9SC`^lA|Ft=AF3}k zj+Ts=)xe-vV4A5kYZuuF@7u%N0MldD$fmhc5)vq3TZQzXe4R8r=p}utxOkR{#QO!W zVwI8mHIJI5+jQ+aK=M5rPTOxV+nQSilKvBMfTsJq2CS?rtxtekhWy3?N;4?3shn3D zte6su)uurTe6Zi*MPW^3nlO`62c2V13N#Tx^fpFwW~pOGq$s0ZZ`>)xC||WCni({K zqV4{OHkg`PdjKqZS(6#|woX;bV=hCoqc?E4oUoP$J9J*HeF;}JlQlV-6#>7Nvz48E zDEm3^{rOD;sMUl9A>qmTS>uI`)~|AVbTNq1Ub>%+$-< zS<$%B8m+PWwz8K`IjmUmyPy}WD)3D=r7vfaMVe2^GnW;VAkG)^1WbBTIHSh+o!C^hyb8yCo|H7RenLLF-u)=;5qVO(HGeFt)WGO=g$jhzi*<~%?E%hdi# zyS#uFVc?Y=Zy|k!a(e4IiSyFLd1NqMdlmU zeeQo0m{S1CeJZzFw5Ewjwv_fzD&E`0Dd{KLV9NJ~S^QD`8MD{`fJG7V_8wb|j#)ANBCwBP6R{&+Bgd<8zIHSy6GTeYv{W_|$q zw$2});!IMx6p&cpuO`n+KYkj7S|b>m48YWkdL@Ao#lj_`gnHj{Q=4#E@tqWVFX{Ie z%q!eqT*HZO2Pvqim_z|=@uEfm0!O&t$b?m6mY;`eM;h%SkeLH~2EgKnJy-8s-v>y5 z6(Flm<%;|OsN0_$KLbEV@Ch#y!&h}Ff6l<7DHQ080ig6$7y)vfN*GlregiBFhFiHM zBCZ)edMGdL?oaabUtkdHH+azeoF)P{12`mltO;`dXedho09j9A`F|X0tZh|i11_;#Y$<$Z zC}85zIX`iAH>HktQ6yI<06;Sw;57q45d4T$;s@;bI2`-}J`G_T<737+&=x+C9+=DG z@)r!r0bB4ZOmj-^MC#A5VG+xy{8yy< z@7aPkFUW@kQLj6^t z!tc!CN%Ge%|1S;oA8WjS)KhoXP#MMkszObzKnCJKe@aDgE&4wroBq9s2LEXM-)hnR zsnN(l4j@ - + + Repository External Reference Pin Guard Issue #10 release/export gate for submodules, linked datasets, API sources, and model references @@ -10,18 +10,24 @@ blocked-packet.json | findings 7 | digest 0cb0a30094dfe551 + + + repo-reference-malformed-manifest + malformed-manifest-packet.json | findings 1 | digest cd76d8b327ffca47 + + repo-reference-malformed-entry malformed-packet.json | findings 1 | digest 5712c8d01b35d778 - + repo-reference-clean clean-packet.json | findings 0 | digest 5b1ede709bdfe56b - + repo-reference-warning diff --git a/repository-external-reference-pin-guard/requirements-map.md b/repository-external-reference-pin-guard/requirements-map.md index 138eacc9..11b12135 100644 --- a/repository-external-reference-pin-guard/requirements-map.md +++ b/repository-external-reference-pin-guard/requirements-map.md @@ -8,7 +8,7 @@ Issue #10 asks for robust project repositories with versioned files, collaborati | Hash-based integrity | Requires full-length SHA checksums, parseable DOI evidence, or non-floating immutable versions for external datasets and model weights, and blocks malformed checksum evidence even when another identifier is present. | | Computation-aware reproducibility | Blocks reproducibility/export lanes when API data sources are floating, authenticated only, or backed by malformed/future snapshot dates, invalid checksum evidence, or truncated checksum evidence. | | Repository identifiers and citation | Prevents DOI publication when external references lack verification timestamps, are stale, future-dated, contain malformed DOI evidence, or lack license/attribution metadata. | -| Programmatic access and export | Separates API metadata-only access from export-bundle and DOI publication release lanes, and blocks malformed reference entries with explicit repair actions. | +| Programmatic access and export | Separates API metadata-only access from export-bundle and DOI publication release lanes, and blocks malformed reference manifests or entries with explicit repair actions. | ## Non-Overlap diff --git a/repository-external-reference-pin-guard/sample-data.js b/repository-external-reference-pin-guard/sample-data.js index adb0da79..041a8ef7 100644 --- a/repository-external-reference-pin-guard/sample-data.js +++ b/repository-external-reference-pin-guard/sample-data.js @@ -99,9 +99,22 @@ const malformedRepository = { references: [null] }; +const malformedManifestRepository = { + repositoryId: 'repo-reference-malformed-manifest', + assessedAt: '2026-05-28T12:00:00Z', + references: { + dataset: { + id: 'dataset-not-in-list', + kind: 'linked_dataset', + target: 'https://doi.org/10.5281/zenodo.4567890' + } + } +}; + module.exports = { riskyRepository, cleanRepository, warningRepository, - malformedRepository + malformedRepository, + malformedManifestRepository }; diff --git a/repository-external-reference-pin-guard/test.js b/repository-external-reference-pin-guard/test.js index 14fc3636..1405818f 100644 --- a/repository-external-reference-pin-guard/test.js +++ b/repository-external-reference-pin-guard/test.js @@ -435,6 +435,35 @@ function testMalformedReferenceEntriesBlockReleaseInsteadOfCrashing() { }); } +function testMalformedReferenceManifestBlocksRelease() { + const packet = assessExternalReferences({ + repositoryId: 'repo-reference-malformed-manifest', + assessedAt: '2026-05-28T12:00:00Z', + references: { + dataset: { + id: 'dataset-not-in-list', + kind: 'linked_dataset', + target: 'https://doi.org/10.5281/zenodo.4567890' + } + } + }); + + assert.equal(packet.status, 'hold_repository_release'); + assert.deepEqual(findingCodes(packet), ['MALFORMED_REFERENCE_MANIFEST']); + assert.equal(packet.findings[0].referenceId, 'reference-manifest'); + assert.ok(packet.actions.includes('repair_reference_manifest:reference-manifest')); + assert.equal(packet.referenceSignals.immutablePins, false); + assert.equal(packet.referenceSignals.exportable, false); + assert.equal(packet.referenceSignals.attributionComplete, false); + assert.equal(packet.referenceSignals.verificationFresh, false); + assert.deepEqual(packet.referenceSummary, { + total: 1, + byKind: { + unknown: 1 + } + }); +} + const tests = [ testBlocksFloatingAndNonExportableExternalReferences, testAllowsPinnedExportableReferences, @@ -449,7 +478,8 @@ const tests = [ testNullGitCommitShaDoesNotCountAsImmutablePin, testMissingVerificationEvidenceBlocksOtherwisePinnedReference, testMalformedOptionalEvidenceBlocksEvenWhenAnotherIdentifierIsValid, - testMalformedReferenceEntriesBlockReleaseInsteadOfCrashing + testMalformedReferenceEntriesBlockReleaseInsteadOfCrashing, + testMalformedReferenceManifestBlocksRelease ]; for (const test of tests) {