Protect authenticated federation sources with exact runtime URL bindings

Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a137ca-5c77-7a71-b9ae-23ad9b0b5684
This commit is contained in:
tegwick 2026-10-15 01:25:49 +02:00
parent 03cd049773
commit b181240b35
10 changed files with 1388 additions and 3 deletions

View file

@ -0,0 +1,55 @@
{
"id": "REUSE-WP-0025-CONSUMER-CANDIDATE-REVIEW-R1",
"reviewed_at": "2026-10-14T23:08:33.016513+00:00",
"review_scope": "Consumer code, receipt-only verification helper, exact metadata URL configuration and local image preparation integration only; not credential provisioning, production rollout, registry admission or runtime approval.",
"owner_review": {
"reviewer": "reuse-surface-owner (agent reuse-surface, codex)",
"decision": "approved",
"comment": "REUSE-WP-0025-T02. INTENT.md Registry First, Consumer Experience Matters, and Internal and External Evidence Must Stay Separate: the reviewed native patch makes source credentials usable only for operator-approved exact HTTPS URLs, before any caller-selected credential lookup; redirects are refused. The helper verifies native acquisition of the consented seven indexes and seven entries by exact hashes/schema without stale-cache fallback and returns bounded receipts. Exact candidate source/helper/config/test and preparation patch digests are bound below. 227 tests pass in explicit fixture environment and source hashes match the locally smoke-verified image. This approves consumer preparation integration only; baseline proposal unchanged-image reader delivery remains changes_requested. No credential execution, founder approval or production success is inferred."
},
"workplan_id": "REUSE-WP-0025",
"task_id": "REUSE-WP-0025-T02",
"intent_sha256": "511d1029a7aefc67b68a6363ed3ce8f803f2516c00062ff805263dffe26c771b",
"candidate_artifacts": {
"reuse_surface/federation.py": "dbaa40f25cc0f090143578cd1c7068cb2cb00960fafd17d5239bf8a5bac514dd",
"reuse_surface/private_source_verify.py": "c67a284091cc4dd62dca56658a14b8ea1357e2b3df1518120da4c51e0ee8d85c",
"tests/test_private_source_verify.py": "5f0c0b30b98b4db96d695bdda952b25707916e297d566744fadb6dde7bea18b2",
"docs/assessments/cust81-private-reader/runtime-auth-source-allowlist-r1.json": "e1948c537e206b30fc72b9e4732a3f600d92e131813e6f7ecfd4bfbb18c27286",
"docs/assessments/cust81-private-reader/suite-environment-validation.json": "84f9c410f09e0dd5c0c90987744bc9f6e85292d2e28e4db88859ee0b24e68bd2",
"docs/assessments/cust81-private-reader/reuse-owner-preparation-r1.patch": "da9634481ce80658dfce815d3539ba023234938dc76163dfd93d7677be95ed51"
},
"local_image": {
"manifest_digest": "sha256:2364b7e7859daccf9340a063654e2b09eed1bc27e0adf7b23cbb4b30135a7db0",
"receipt_path": "/home/worsch/the-custodian/docs/assessments/netkingdom-2026-10-14/hardened-reader-local-image-r1.json",
"receipt_sha256": "ed7c2516925d7f16b573a70b5e48d5656a4875e9eb94bcc8760a8bdcbe07f59c",
"published": false,
"deployed": false,
"credentials_provisioned": false
},
"existing_auth_source_inventory": {
"receipt_path": "/home/worsch/the-custodian/docs/assessments/netkingdom-2026-10-14/live-authenticated-source-inventory-r1.json",
"receipt_sha256": "ba669d6231c8c611191c7ad28f5914d6c47332032b23b0ea40a13f753e883073",
"checked_at": "2026-10-14T23:01:13.254261+00:00",
"authenticated_source_count": 0,
"must_recheck_before_rollout": true
},
"preserved_baseline_review": {
"path": "docs/assessments/cust81-private-reader/owner-review-r1.md",
"decision": "changes_requested",
"scope": "Original R1 same-image credential delivery proposal; preserved, not rewritten."
},
"remaining_execution_gates": [
"Platform/Forgejo/apps/mason owner reviews of exact current CCR and implementation.",
"Exact founder credential and live rollout decision remains separate.",
"Publish and independently verify registry image digest before rendering actual release values.",
"Recheck metadata-only authenticated source inventory and materialized exact14 reader allowlist before approved rollout.",
"Run receipt helper in actual hub environment with native authenticated fresh acquisition, then exact70 hosted audit."
],
"does_not_approve": [
"Credential provision or access grant",
"Live production mutation or rollout",
"Other owner roles",
"Registration/admission status change",
"Entire objective completion"
]
}

View file

@ -0,0 +1,40 @@
{
"id": "REUSE-WP-0025-CCR0046-CONSUMER-REVIEW-R2",
"reviewed_at": "2026-10-14T23:19:37.233425+00:00",
"workplan_id": "REUSE-WP-0025",
"task_id": "REUSE-WP-0025-T01",
"ccr_id": "CCR-2026-0046",
"revision": 2,
"review": {
"reviewer": "reuse-surface-owner (agent reuse-surface, codex)",
"decision": "approved",
"comment": "REUSE-WP-0025-T01; INTENT.md Registry First, Consumer Experience Matters and Internal and External Evidence Must Stay Separate. Reviewed exact CCR-2026-0046 revision2, provisioner, exact-token recovery, bootstrap contract and ESO policy SHA256 listed below solely for consumer delivery boundary. The exact seven consented sources/commits/hash rows match original pinned disclosure preparation. Separate reader KV and env protect scoped writer callers; contract prohibits delivery to baseline/current image and requires full reviewed HTTPS/redirect/credential-before-use allowlist enforcement plus exact fourteen metadata URLs. Final actual hub helper must prove native index AND entry hashes without stale cache; 70-ID hosted audit remains independent. Recovery confines revocation to separately approved exact dedicated PAT, preserves shared runtime KV/Secret/public sources, and does not remint after ambiguity. Full native code/helper/config preparation integration review is separately approved and pinned below. This owner judgement approves preparation integration of this consumer boundary, not human credential/rollout go, provisioner execution, status/admission changes, other owners or deployment success."
},
"artifacts": {
"credential-change-requests/CCR-2026-0046-reuse-surface-forgejo-source-read.yaml": "90522912fb78fed72e625382fb7114a0e9aafe76d59e36bffecab83c5bb7d643",
"scripts/provision-reuse-surface-forgejo-source.py": "abf60a754596baa1610d23b1fd367385b0222ac8aeaebba0f2cfb7ec4c62055b",
"scripts/revoke-reuse-surface-forgejo-source.py": "f78d1b26fbff93c6cc481a896d9fb9b9ce93049b8b3267fa41a64bc57dadb162",
"docs/proposals/2026-10-15-reuse-private-reader/bootstrap-contract.json": "2bb72671e0a5f230497ab8ef2967a20ee68d1f2cf081f07c84f6db3442e18d8b",
"openbao/policies/workload-kv-read-reuse-surface-runtime-eso.hcl": "6320f6c2d262d924ea16291d301d5f9eeb7efdb6ce7ea141c1a41d277d86b01b"
},
"consumer_preparation_review": {
"path": "docs/assessments/cust81-private-reader/candidate-owner-review-r1.json",
"sha256": "853cb3b721d83ba5aeb0847111cc47f8094b733f870059cca9834b2c1a5a6219",
"decision": "approved"
},
"preserved_baseline": "Original same-image reader delivery review remains changes_requested; this R2 consumer boundary resolves that design defect without altering earlier evidence.",
"execution_authorized": false,
"required_before_execution": [
"Human exact credential and separately scoped rollout decisions, with all required independent owner reviews.",
"Published independently verified image digest and reviewed release config for the full security patch.",
"Recheck metadata-only live authenticated-source inventory (last snapshot0) and validate exact14 runtime reader URLs.",
"Post-rollout native authenticated helper receipt plus separate registration and exact70 hosted completion audit."
],
"not_proven": [
"Real Forgejo reader scope",
"Live OpenBao/ESO materialization",
"Production image/config rollout",
"Actual authenticated metadata fetch",
"Hosted private capability admission"
]
}

View file

@ -0,0 +1,75 @@
{
"id": "CUST81-PRIVATE-NATIVE-FETCH-RECEIPT-R1",
"checked_at": "2026-10-14T22:43:42.958330+00:00",
"proposal_sha256": "7819eb51d249f5c7aff4df9fb520afcfb76603b05a4104439499102b6c20af99",
"disclosure_sha256": "46ac4fe49a08054cc215aade2fbaf3b36ee334520997857ed84f530b52da9d35",
"consent_sha256": "4a4602ad926e3af855d6ddba4731430d33e4a7432c507ba0a5193b9f43056b52",
"cache_used": false,
"all_verified": true,
"sources": [
{
"repo": "rapp-openbao",
"commit": "35672be138036c8433a5ac5de91e068c03c2b124",
"index_sha256": "044efa3d02b90e1872f2516c581159d388a8080a689f76fcd78bb4d048d6ee64",
"verified": true,
"entry_sha256": [
"9de890da536c34ac2b50576e2c4a9c03792c8a07545d2a0566ace68ac10a293e"
]
},
{
"repo": "rapp-policy-nexus",
"commit": "088b78ac03b0cebeec34a69aae3569eb7ec2f9c3",
"index_sha256": "e68bdedf61eee9ca2026f46a2434ce384c26234616e74f7a5d08a06c75b3bb00",
"verified": true,
"entry_sha256": [
"21415ed5e89dcf8bd2df0c8bc99b07d2c87173809c37fa2582de6d336918a126"
]
},
{
"repo": "rapp-postgres",
"commit": "a9f569c96d74aa384ac8d3ac4aa960e4061550b5",
"index_sha256": "d939333eed9d85172e006f526c445fbe2602a721d53f7c0d14bc68286ae08776",
"verified": true,
"entry_sha256": [
"64503872abb24bb28f291264e860ab094c6abb721fbfe90b47258ad13b77af44"
]
},
{
"repo": "rapp-sbom-nexus",
"commit": "adbedd349e8df97be43a1f57db7095af45ff29d1",
"index_sha256": "d2ee0f193d2198bf8f16ce64c90ae7664e59a2bc307ad711426af3fd47deb057",
"verified": true,
"entry_sha256": [
"1a15e37bd3d19c4c89ef25803667937f549ade1cd27bedfa85132ac48ffe3f48"
]
},
{
"repo": "rapp-telemetry",
"commit": "f158307e24b86bab88a1af4830ff6b4f85afdeb5",
"index_sha256": "ee8801f143ed5cf064205710a61c2bb24efc6ea8585d5786d6b679426ec4c1d4",
"verified": true,
"entry_sha256": [
"a67dbf6905223c04b1c003d5f967841038743c8c1479812f5cf0bb55ad6cee77"
]
},
{
"repo": "rapp-tenant-engine",
"commit": "9bdc86572728783a5ed94266f04f7b12d414c557",
"index_sha256": "d8e9c1282350b5d2fd4f4d69712aa7a5fbcd2367bb1a7fad1b6eb16a97e5d732",
"verified": true,
"entry_sha256": [
"e7cf0485cfdb6f497281638d81f908b5c2fe1053125c6ef28130504909d1d49e"
]
},
{
"repo": "rapp-user-engine",
"commit": "f35108f9e1b8702fb6c526fe42b2fec5ca032738",
"index_sha256": "95b4ed2d0b189f6847b1c0899f740d1da46933a8f40491e1a02f2d4e57c819fc",
"verified": true,
"entry_sha256": [
"84ec4fdce99134c88c110104cac93bdea36cffb5ba34e046b9ad161fb860dce2"
]
}
],
"transport": "fake-only local committed metadata; no authenticated network fetch or runtime evidence"
}

View file

@ -0,0 +1,102 @@
# Reuse-surface independent consumer preparation review
Disposition: **changes_requested** for reader provisioning proposal
`CUST81-PRIVATE-READER-PROVISIONING-PREPARATION-R1`, SHA256
`7819eb51d249f5c7aff4df9fb520afcfb76603b05a4104439499102b6c20af99`.
Reviewer: delegated reuse-surface owner preparation worker, supervised local scope.
This review does not authorize credentials, approve another owner's implementation,
claim deployment success, or grant permanent repo authority.
INTENT requires inspectable registry membership and evidence-driven consumer
reliability. Acquisition must protect source custody while making the explicitly
consented metadata discoverable. The proposal's seven-repository reader, separate
KV path and exact commit pins fit that purpose, but its unchanged-image rollout
assumption fails consumer credential isolation.
## Findings and prepared correction
1. Native `fetch_remote_index_text` originally supplies Authorization to urllib's
default opener. Redirect handling copies headers to the redirect target. A
source redirect can disclose the PAT to another origin or unreviewed path.
Prepared patch rejects **all authenticated redirects**, even same-origin ones.
Anonymous federation keeps its previous behavior.
2. Hub registration accepts caller-selected `auth_env`, `auth_header` and `url`.
Composition passes these to `_auth_headers`, which reads the named runtime env
and sends its value to that URL. A holder of the writer token can therefore
induce credential exfiltration without a redirect. Prepared patch validates
operator-owned `REUSE_SURFACE_AUTH_SOURCE_ALLOWLIST` JSON before looking up the
credential. Exact allowed env name and URL are mandatory; missing/malformed
configuration fails closed. Authenticated HTTP is rejected.
3. `resolve_source_index_path(refresh=True)` may return stale cache after remote
failure. A fresh composition timestamp alone cannot prove private acquisition.
Prepared helper calls native fetch directly, never the resolver/cache path,
and verifies exact consented index **and Markdown entry** SHA256 plus capability
identity, owner and entry schema. Failed receipts contain bounded categories,
never raw exception text, bodies, headers, or secrets.
## Exact prepared artifacts
- `reuse_surface/federation.py` SHA256
`dbaa40f25cc0f090143578cd1c7068cb2cb00960fafd17d5239bf8a5bac514dd`
- `reuse_surface/private_source_verify.py` SHA256
`c67a284091cc4dd62dca56658a14b8ea1357e2b3df1518120da4c51e0ee8d85c`
- `tests/test_private_source_verify.py` SHA256
`5f0c0b30b98b4db96d695bdda952b25707916e297d566744fadb6dde7bea18b2`
- `runtime-auth-source-allowlist-r1.json` SHA256
`e1948c537e206b30fc72b9e4732a3f600d92e131813e6f7ecfd4bfbb18c27286`
is the exact fourteen commit-pinned index/entry URLs for reader env
`REUSE_SURFACE_FORGEJO_SOURCE_READ_TOKEN`. Serialize this object as the runtime
value of `REUSE_SURFACE_AUTH_SOURCE_ALLOWLIST`; do not use host wildcards.
## Validation and limits
Focused fake transport tests cover native Bearer header handling, all fourteen
fetches, no cache path, mismatched index/entry hashes, tampered consent packet,
missing authentication, sanitized errors, same/cross-origin redirects without
second requests, HTTP rejection, missing/malformed/unapproved allowlists, and
broadened reader URL scope. Focused tests: **30 passed**. Whole test suite initially
reported **226 passed, 1 failed**: existing `test_federation_compose` resolved a
required sibling index to missing `/tmp/access-engine/registry/indexes/capabilities.yaml`.
The first sibling fixture preparation also stopped at maturity-engine's untracked
registry index, and that partial fixture run reported **226 passed, 1 failed**.
Both outcomes remain in `suite-environment-validation.json`; no consumer test
failure or failed preparation is hidden.
With the complete task-owned fixture environment, the unchanged source patch
passes the **entire suite: 227 passed, 1 existing dependency warning**. Command:
`/home/worsch/reuse-surface/.venv/bin/python -m pytest -q tests`, cwd
`/tmp/cust81-reuse-suite-fixtures-r1/reuse-surface`. That fixture contains sixty
required local registry indexes and thirty-nine seeded anonymous caches to avoid
live network dependencies. Fifty-nine local indexes are copied from committed
HEAD; maturity-engine's existing untracked index is copied read-only and labeled
as a test fixture, never publication evidence. Member indexes are only read;
composition writes its own copied registry/cache. No foreign checkout is written.
Tests rewrite generated catalog/graph files in their own fixture checkout; earlier
generated changes in the integration checkout were restored to its HEAD.
`local-consented-metadata-validation.json` proves schema and exact hashes for all
seven repositories' consented committed metadata using a fake transport and a
fixture-only token. It is explicitly **not** a network, credential, rollout or
live federation verification receipt.
Static `registry/federation/sources.yaml` contains no `auth_env`, but public hub
registration responses intentionally omit it and do not prove live SQLite dynamic
source inventory. This patch changes authenticated-source behavior: every existing
authenticated lane needs a reviewed exact-URL allowlist entry. Before rollout,
platform/apps must safely inventory only auth env names and registered URLs,
preserve approved existing lanes in runtime config, and prove no unrelated runtime
secret name can be routed. No raw env dump or Secret read is required for that
inventory. Until this migration and the reviewed new consumer image are complete,
do not deliver the new PAT to the existing hub image.
After separate exact credential/rollout approval, invoke the helper from inside
the hub process environment with the pinned proposal/disclosure/consent files:
```sh
python -m reuse_surface.private_source_verify --proposal /review/private-reader-provisioning-preparation-r1.json --disclosure /review/private-source-disclosure-proposal-r1.json --consent /review/private-source-owner-consent-r1.json
```
It accepts no credential argument and returns only bounded metadata receipts.
Exit zero means all seven native index/entry fetches matched pinned consent; it
does not prove registration/federation completion. Final admission still needs
separate live source registrations and exact 70-ID fresh hosted audit.

View file

@ -0,0 +1,18 @@
{
"REUSE_SURFACE_FORGEJO_SOURCE_READ_TOKEN": [
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-openbao/raw/registry/capabilities/capability.railiance.openbao-package.md?ref=35672be138036c8433a5ac5de91e068c03c2b124",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-openbao/raw/registry/indexes/capabilities.yaml?ref=35672be138036c8433a5ac5de91e068c03c2b124",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-policy-nexus/raw/registry/capabilities/capability.railiance.policy-publication-package.md?ref=088b78ac03b0cebeec34a69aae3569eb7ec2f9c3",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-policy-nexus/raw/registry/indexes/capabilities.yaml?ref=088b78ac03b0cebeec34a69aae3569eb7ec2f9c3",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-postgres/raw/registry/capabilities/capability.railiance.postgres-isolation-recovery.md?ref=a9f569c96d74aa384ac8d3ac4aa960e4061550b5",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-postgres/raw/registry/indexes/capabilities.yaml?ref=a9f569c96d74aa384ac8d3ac4aa960e4061550b5",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-sbom-nexus/raw/registry/capabilities/capability.railiance.sbom-runtime-package.md?ref=adbedd349e8df97be43a1f57db7095af45ff29d1",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-sbom-nexus/raw/registry/indexes/capabilities.yaml?ref=adbedd349e8df97be43a1f57db7095af45ff29d1",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-telemetry/raw/registry/capabilities/capability.railiance.telemetry-package.md?ref=f158307e24b86bab88a1af4830ff6b4f85afdeb5",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-telemetry/raw/registry/indexes/capabilities.yaml?ref=f158307e24b86bab88a1af4830ff6b4f85afdeb5",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-tenant-engine/raw/registry/capabilities/capability.railiance.tenant-engine-package.md?ref=9bdc86572728783a5ed94266f04f7b12d414c557",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-tenant-engine/raw/registry/indexes/capabilities.yaml?ref=9bdc86572728783a5ed94266f04f7b12d414c557",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-user-engine/raw/registry/capabilities/capability.railiance.user-engine-package.md?ref=f35108f9e1b8702fb6c526fe42b2fec5ca032738",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-user-engine/raw/registry/indexes/capabilities.yaml?ref=f35108f9e1b8702fb6c526fe42b2fec5ca032738"
]
}

View file

@ -0,0 +1,628 @@
{
"id": "REUSE-WP-0025-SUITE-ENVIRONMENT-R1",
"fixture_checkout": "/tmp/cust81-reuse-suite-fixtures-r1/reuse-surface",
"fixture_only": true,
"sources": [
{
"repo": "access-engine",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "7d59022dac9da4d8dcbecab936d3cea9b154c8c51478b378932fd9ebe5ec7e02"
},
{
"repo": "activity-core",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "536d359366ccf3db3b2b0d390635bc2c5311bd37ac7ff89dae11d809ef15b848"
},
{
"repo": "agentic-resources",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "42986b7a274ef510166e566a9756d594a6f88706189bc97ac889bab86b20240d"
},
{
"repo": "approval-engine",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "b6812fd12dc530270fb66bae592c828f56f17f2fc86759cb04d750162fc619a4"
},
{
"repo": "artifact-store",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "200802ac737195721a52d6d345104f2302fbdc35b4122b431bd2255f4e5552bc"
},
{
"repo": "audit-core",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "6a1d7dbb442f0fd0e481d54fb0acbee37ef2e693198b6f2108e154d3c3795e0e"
},
{
"repo": "can-you-assist",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "ce106e5c106453635075dd1b5906762d516e84601af4d5620c9a7faab444be46"
},
{
"repo": "citation-engine",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "e02914ffe937c8342022d92b5bfa6906aef560edeb6e90f80826cbf8e0620ada"
},
{
"repo": "citation-evidence",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "628e338df6da2f0966675e8facf91f52cc3ac4a0c81417b33e1284045db1dfad"
},
{
"repo": "citation-work",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "c20b96c226bb9465d7154c127ee19a94396c7b03307e7581ff827eba42651d86"
},
{
"repo": "commerce-canon",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "6e1186aad49634b9725bc2cfa051c42b2ac13e5c4abe4bade7b39c0483f4242d"
},
{
"repo": "config-atlas",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "d0325d71a5de1e756c080dc9abc3162536b9700cc37942a028ad2f65bad9bfef"
},
{
"repo": "coordination-engine",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "f7a2c140ac1a7628a2106b1047b59e208879257b23ffed6dceef8ecf6c3bd420"
},
{
"repo": "core-hub",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "31cb09dd3b04a7891533387479ecb340b543445b64a849d9973ee857efa4cca1"
},
{
"repo": "domain-tree",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "c20b96c226bb9465d7154c127ee19a94396c7b03307e7581ff827eba42651d86"
},
{
"repo": "email-connect",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "5bce1e037a368816811a21dd9123ebf47f1a7d293c424c661d30fa14f2366231"
},
{
"repo": "emergent-security",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "268d9192dc9b97da462d46fe5b40ea33e678840b23944ab0cd73622c130bdef6"
},
{
"repo": "evidence-anchor",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "c20b96c226bb9465d7154c127ee19a94396c7b03307e7581ff827eba42651d86"
},
{
"repo": "evidence-binder",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "2664dfb5668238051b7cd540470ee2f7a5557415c53462fa4f14474829f3ce46"
},
{
"repo": "evidence-source",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "7b2a3c7b108fbdc69828b088915418c87dedfee5e202e4546defe68d8df64667"
},
{
"repo": "feature-control",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "2335b614d120a3e954d55389448b4c8462bfab3582de2e0bbae02dd5474dd132"
},
{
"repo": "fin-hub",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "c6bb1aa6b770f684721fae9f1576f2c2f0128d1b758f4e33b8a277e0b4ff087a"
},
{
"repo": "gate-house",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "2b63d94375d29649c41a7eae7cfb3f6e35210fd3438aa5013f3ddc22a662511a"
},
{
"repo": "glas-harness",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "8f86dbdaf6535c909ff19967f7806d85c1f7a09db1e999033abf9b9007ed805b"
},
{
"repo": "guide-board",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "abbc20c7ab14bcbdb73679a5143355c7ad3a7441b8f8e7bf5a1af393c7d1c1e1"
},
{
"repo": "helix-forge",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "c20b96c226bb9465d7154c127ee19a94396c7b03307e7581ff827eba42651d86"
},
{
"repo": "hub-core",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "a78d185973e0d0600f6ff05470ff3b840130fca4ed7922edaf08155d246e9008"
},
{
"repo": "human-resources",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "d72d6b4f1479992e33400ed7c950cdc7112ead9c22abd38275717f0ae9255787"
},
{
"repo": "ihp-railiance-probe",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "c20b96c226bb9465d7154c127ee19a94396c7b03307e7581ff827eba42651d86"
},
{
"repo": "info-tech-canon",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "6015ec78772586e6e351422741430be8c40d7c7116403ee4b92933df342c4c72"
},
{
"repo": "informed-decision",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "b43ea44c725dcbd59fe957ffc307805e0aabc23b60a4a9049005c70ca4871a62"
},
{
"repo": "infospace-bench",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "74ba65dad84faffd6ce0e6d771f8650abe76b87a6ee09ee007780bd13c5cd9b2"
},
{
"repo": "issue-core",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "70eb00870ed87072aeb0f7c38de0a879f1b3910fe6f976b982a191e261e8e7be"
},
{
"repo": "kaizen-agentic",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "0236d486d6df6d928e7fd9f186a02273c8a59d534abb026603f7128876fbe776"
},
{
"repo": "key-cape",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "901d15c15cacd844cf19a1a7b74c890ce5e0b00a3372a9e10bd7114f328596c8"
},
{
"repo": "kings-guard",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "8a143864a6ce9a7b6c5a0f64eb75f67cfa99c2b9b155baac4f81a261d3a5312c"
},
{
"repo": "kontextual-engine",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "5a5980f37031c15fc9b332f143ddbfbd6c2789ff6c6ec0f4c3e971cbc506830e"
},
{
"repo": "llm-connect",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "27420d2b21fb45cf6cf6ac41890518f6b5a8c10027594a7e95ec535715a01296"
},
{
"repo": "markitect-filter",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "95d2743d4201f6b89efedebfcd34fdb03e3f832fa00b6f4f646015c3264dfb60"
},
{
"repo": "markitect-main",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "ba7e29cc82fd4d1eff61e48b1d870714f2d9c97531e839c469f892602509f137"
},
{
"repo": "markitect-quarkdown",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "67c718d9bb8221b9b58ab30cbf9eb1cf340e2d2ecc1d77cb4b5bdaf28fa5befc"
},
{
"repo": "markitect-tool",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "9159a4af2783b17602c23ca4b72b552641d5e1c3170a4dee1aee69c3ba9371d2"
},
{
"repo": "maturity-engine",
"kind": "required_local_index",
"origin": "worktree_untracked_registry_fixture_not_publication_evidence",
"sha256": "42b4cd1f9c6fe0960acadd10a337a579a6313fa46c2ff5a2a34bbacf2749d049"
},
{
"repo": "net-kingdom",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "6fadeb0e89729a9226d6eebd44fbb07723512a3ebe6737f5a1113b14829447ed"
},
{
"repo": "open-cmis-tck",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "e8fe7a7d0d3af104009f996c466353467e737069d0c2d04f880a86ae60d76bda"
},
{
"repo": "open-reuse",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "f5e8b9cd3ceb7e336a2afc5097065a6c0453cc697c8c4aa2d2c39c1d1fe4fe66"
},
{
"repo": "ops-bridge",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "aefd795eb16fcfdebc108450826a0f62e000bc61e9d78007bc6221bc2328e40c"
},
{
"repo": "ops-hub",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "6fea9fee803a5d55ece3daefdfda0efff11eae8d2a0b719fbd0dec64f4f85314"
},
{
"repo": "ops-mason",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "5eb499bc819c874835b8e6727ccbd5f9889ebb6f25a90018e3e574e5b6082b32"
},
{
"repo": "ops-warden",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "4d3aba70ead10c826814dc766f9d23e3e0ce52475330acf57905bf62b01c819c"
},
{
"repo": "phase-memory",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "e84b7603c98ae48879002b16a8302fb0e0e1b6c6e1099565570a8d8f98478d31"
},
{
"repo": "policy-nexus",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "c1eb3e23621de354a9081cbf29a2f3d772b5f8538aaceca417574cde5a04c021"
},
{
"repo": "rail-knative",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "e044b8f2f6bc1b8aa7c672ee33dfac69d6813fd672388713a70ab7ea4d4052c0"
},
{
"repo": "rail-kubernetes",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "699f69facea1ce4e71d90fe0790db19b68d3a546015453651d3afc808d31d09d"
},
{
"repo": "railiance-apps",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "2a550acf8545e95bd81842bb1b00f4db46c4dbb42b522823f043e948667ddf2c"
},
{
"repo": "railiance-bootstrap",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "feefcc699e045a1a72f254d71f46460ad2362ed23c9de6e54c952711fcb33788"
},
{
"repo": "railiance-cluster",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "0e67a2aca183ee7ef9c4c04e618fcb03647120f456a133e84a8f42c2b8d8fcde"
},
{
"repo": "railiance-enablement",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "4b1f91b0da94e3098916f3e360b20b9926be4dd8683d6fb167a027aaf04ebfac"
},
{
"repo": "railiance-fabric",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "f473644906fe3f331702b407c3519e6a3cd0d96d362cf30d80e03aac53c3b862"
},
{
"repo": "railiance-forge",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "4df605d617b7656ffb94a43ab4633c8fc69ec723f68f5f5b8d5f24ad8efb6b98"
},
{
"repo": "railiance-infra",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "14a76b1f1dd317a1d426502ff5f80780e9551cd1cd600543de6fb9a84cb8ada2"
},
{
"repo": "railiance-master",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "f36cb2765ec04064314f43866f9a87a94a4f0f728adfaad46739f232b4986c0a"
},
{
"repo": "railiance-platform",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "0315d526165368e0a513de6b15932778d43c3e6045c589c95060f555fca3202e"
},
{
"repo": "railiance-telemetry",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "82f3f2d188e2d7ebea71b7262e106c5f48feaf39a2da881bb645ff9352884205"
},
{
"repo": "rapp-openbao",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "044efa3d02b90e1872f2516c581159d388a8080a689f76fcd78bb4d048d6ee64"
},
{
"repo": "rapp-playwright",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "79645df817858f96230f2443d66796d1078185c7afef5948f6a38632234d33bb"
},
{
"repo": "rapp-policy-nexus",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "e68bdedf61eee9ca2026f46a2434ce384c26234616e74f7a5d08a06c75b3bb00"
},
{
"repo": "rapp-postgres",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "d939333eed9d85172e006f526c445fbe2602a721d53f7c0d14bc68286ae08776"
},
{
"repo": "rapp-sbom-nexus",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "d2ee0f193d2198bf8f16ce64c90ae7664e59a2bc307ad711426af3fd47deb057"
},
{
"repo": "rapp-telemetry",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "ee8801f143ed5cf064205710a61c2bb24efc6ea8585d5786d6b679426ec4c1d4"
},
{
"repo": "rapp-tenant-engine",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "d8e9c1282350b5d2fd4f4d69712aa7a5fbcd2367bb1a7fad1b6eb16a97e5d732"
},
{
"repo": "rapp-user-engine",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "95b4ed2d0b189f6847b1c0899f740d1da46933a8f40491e1a02f2d4e57c819fc"
},
{
"repo": "reef-railiance",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "84a89c376021e3cb980c02c41d1a31396b874bebcc3801c2d1a9a33ae4195eb5"
},
{
"repo": "rein-aharness",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "20990ed0e016b3330a0d44e9b86bfff8966e82bc8800469ec0f320cfa8a63fbc"
},
{
"repo": "rein-openweights",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "2f4e59b2dbc7ea6078405f5c2f2be0aebd9434bee171a429b9ebe6baa83f3c2b"
},
{
"repo": "repo-manager",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "ba068a8dd7a282664e94e2acdbbb170a2ba48e260e7ce0ec8eaaa8aee6f9e7c2"
},
{
"repo": "repo-scoping",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "480d7c57759d6997d7bd531e966c207bb290e978f9fe831d6d246b5592c3dd71"
},
{
"repo": "repo-seed",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "8cb4e4baacd95a070a96db6d72f4fb3019cffda95606c65896f796ccac0c9c7c"
},
{
"repo": "resource-control",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "31b16f7d824e376f21de44aff46d5d532d3679d5e72035ce84813572b11bbd44"
},
{
"repo": "reuse-surface",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "a77c952e9e1a37a3504ccd7001a7a2493d60d46f147f277071829cd05646e31c"
},
{
"repo": "risk-nexus",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "53f0bf9e0aa06a6db0aa991f0ebdaa1d2bf74cfaf4e30eed8c003a4d2186a746"
},
{
"repo": "role-engine",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "1188e02e0333664b3554d11c59c12942fef9e29e6491b186dcec67e6ae3e8a5c"
},
{
"repo": "runbook-tutorials",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "a74fa708c4fea755f5c52504bd227393888cca78c043349cdc182c4d783390e5"
},
{
"repo": "sand-boxer",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "a182d5672d088e80b79eacff9cb37fc2f3518c3c100537e18d125abc7f169e96"
},
{
"repo": "sbom-nexus",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "ed6efd581483d0058a3928b365b933cbbd98c035b0a75c866156a69961d74edc"
},
{
"repo": "secrets-engine",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "d5d903336d05ccd0b75a49f7be7e866ef89c6bdb6444e8c747a5ffa934a6bbe2"
},
{
"repo": "security-canon",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "9b9f9348e560a72d8032f62b2ba4820d81fe182353ccc886e4f5c57cbdea563f"
},
{
"repo": "shard-wiki",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "b0bb63c0a080e46c60f24a87959c529da5e725334ed69c4ba985c39107c54ef9"
},
{
"repo": "state-hub",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "eab454bd985ab6ab83c38fd29e6e58ebdfe1e09bbc5388edddaa07a88133619a"
},
{
"repo": "tegwick-control",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "c20b96c226bb9465d7154c127ee19a94396c7b03307e7581ff827eba42651d86"
},
{
"repo": "tenant-engine",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "4131f1b63e52306f267204cdfb0faa90d6550f8bca51f97cf1062becea95d805"
},
{
"repo": "the-custodian",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "cfe7f25e91fee824347aa22ccee2a70e7dd58ac06a7106f7e2ec9e54dc163020"
},
{
"repo": "user-engine",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "7133c52c2013cea70d07d33960f145c370d33a8b4397c1dc927769fcaf200cbd"
},
{
"repo": "vantage-point",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "cc5cf52ead95adc2920db84299d994e54def089d3f8fd852e10d9857ab0fdd2e"
},
{
"repo": "vergabe-teilnahme",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "73ffd306894d9839f4800aa028144883d012bf0fe74a310ad09ef9296c627d56"
},
{
"repo": "whitehat-security",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "e4bf9bac7f62f60cf10a9fbd25aa8200c22f13d61861862ff5fa1cc90b55f37c"
},
{
"repo": "whynot-control",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "c20b96c226bb9465d7154c127ee19a94396c7b03307e7581ff827eba42651d86"
},
{
"repo": "whynot-design",
"kind": "anonymous_cache_seed_not_runtime_evidence",
"origin": "committed_HEAD_fixture",
"sha256": "541104bcafb17dcf7d26dabbce7ff93b2025a0bc6cad9bec71ac145f5ec72669"
},
{
"repo": "zone-engine",
"kind": "required_local_index",
"origin": "committed_HEAD_fixture",
"sha256": "b6b196089a3011f16e8a38f6914589efc72a29ee3aca4bc0c5e3cf30bee97ec4"
}
],
"foreign_repo_writes": false,
"network_fetch_needed": false,
"preserved_prior_outcomes": [
{
"environment": "original isolated checkout without siblings",
"passed": 226,
"failed": 1,
"failure": "required access-engine sibling missing"
},
{
"environment": "partial fixture preparation failed at untracked maturity-engine registry",
"passed": 226,
"failed": 1,
"failure": "required maturity-engine fixture missing; preparation failure not hidden"
}
],
"final_result": {
"command": "/home/worsch/reuse-surface/.venv/bin/python -m pytest -q tests",
"cwd": "/tmp/cust81-reuse-suite-fixtures-r1/reuse-surface",
"exit_code": 0,
"passed": 227,
"failed": 0,
"warnings": 1,
"duration_seconds": 7.8,
"warning": "Starlette httpx testclient deprecation",
"consumer_source_sha256": "dbaa40f25cc0f090143578cd1c7068cb2cb00960fafd17d5239bf8a5bac514dd"
}
}

View file

@ -1,8 +1,10 @@
from __future__ import annotations
import os
import json
import re
import urllib.error
import urllib.parse
import urllib.request
from datetime import date, datetime, timezone
from pathlib import Path
@ -103,11 +105,44 @@ def _auth_headers(source: dict[str, Any]) -> dict[str, str]:
return {header_name: token}
class _RejectAuthenticatedRedirect(urllib.request.HTTPRedirectHandler):
"""Never replay a source credential at a redirect target.
A private source must register its final URL. This also rejects same-origin
redirects because a path change can escape the reviewed repository scope.
"""
def redirect_request(self, req, fp, code, msg, headers, newurl):
raise ConnectionError("authenticated source redirect refused")
def fetch_remote_index_text(url: str, source: dict[str, Any]) -> str:
headers = {"User-Agent": USER_AGENT, **_auth_headers(source)}
if source.get("auth_env"):
if urllib.parse.urlsplit(url).scheme.lower() != "https":
raise ValueError("authenticated source requires HTTPS")
# Registrations are writable data, not credential-routing authority.
# Operators must bind each allowed environment name to exact URLs in
# runtime configuration before the credential itself can be read.
try:
allowlist = json.loads(os.environ.get("REUSE_SURFACE_AUTH_SOURCE_ALLOWLIST", "{}"))
allowed_urls = allowlist.get(source["auth_env"], [])
permitted = isinstance(allowed_urls, list) and url in allowed_urls
except (ValueError, AttributeError, TypeError):
permitted = False
if not permitted:
raise ValueError("authenticated source URL is not runtime-authorized")
auth_headers = _auth_headers(source)
headers = {"User-Agent": USER_AGENT, **auth_headers}
request = urllib.request.Request(url, headers=headers)
# urllib's default redirect handler copies Authorization to the target.
# Anonymous federation retains its existing redirect behavior.
opener = (
urllib.request.build_opener(_RejectAuthenticatedRedirect()).open
if auth_headers
else urllib.request.urlopen
)
try:
with urllib.request.urlopen(request, timeout=30) as response:
with opener(request, timeout=30) as response:
return response.read().decode("utf-8")
except urllib.error.HTTPError as exc:
raise ConnectionError(

View file

@ -0,0 +1,178 @@
"""Owner-prepared, receipt-only native acquisition check for CUST81 revision 1.
Run inside the hub environment after a separately approved credential rollout:
python -m reuse_surface.private_source_verify --proposal FILE --disclosure FILE
--consent FILE
No credentials are accepted as arguments. No bodies or exception text are emitted.
This command does not register sources or use the federation cache.
"""
from __future__ import annotations
import argparse
import hashlib
import json
import os
import re
from datetime import datetime, timezone
from pathlib import Path
from typing import Any
from urllib.parse import quote
import yaml
from jsonschema import Draft202012Validator
from reuse_surface import federation
from reuse_surface.registry import load_schema
PROPOSAL_SHA256 = "7819eb51d249f5c7aff4df9fb520afcfb76603b05a4104439499102b6c20af99"
DISCLOSURE_SHA256 = "46ac4fe49a08054cc215aade2fbaf3b36ee334520997857ed84f530b52da9d35"
CONSENT_SHA256 = "4a4602ad926e3af855d6ddba4731430d33e4a7432c507ba0a5193b9f43056b52"
AUTH_ENV = "REUSE_SURFACE_FORGEJO_SOURCE_READ_TOKEN"
REPOSITORIES = frozenset({
"rapp-openbao", "rapp-policy-nexus", "rapp-postgres", "rapp-sbom-nexus",
"rapp-telemetry", "rapp-tenant-engine", "rapp-user-engine",
})
def _sha(content: bytes) -> str:
return hashlib.sha256(content).hexdigest()
def _load(path: Path, expected: str) -> dict[str, Any]:
data = path.read_bytes()
if _sha(data) != expected:
raise ValueError("packet_digest_mismatch")
return json.loads(data)
def _raw_url(repo: str, commit: str, path: str) -> str:
if not re.fullmatch(r"[0-9a-f]{40}", commit):
raise ValueError("invalid_commit")
if not re.fullmatch(r"registry/(indexes|capabilities)/[a-zA-Z0-9._-]+\.(yaml|md)", path):
raise ValueError("invalid_metadata_path")
return (
f"https://forgejo.coulomb.social/api/v1/repos/coulomb/{repo}/raw/"
f"{quote(path, safe='/')}?ref={commit}"
)
def _prepared_sources(proposal_path: Path, disclosure_path: Path, consent_path: Path):
proposal = _load(proposal_path, PROPOSAL_SHA256)
disclosure = _load(disclosure_path, DISCLOSURE_SHA256)
consent = _load(consent_path, CONSENT_SHA256)
if (
consent["consent_status"] != "approved"
or consent["proposal_sha256"] != DISCLOSURE_SHA256
or consent["proposal_id"] != disclosure["id"]
or consent["proposal_revision"] != disclosure["revision"]
or set(consent["repositories"]) != REPOSITORIES
):
raise ValueError("invalid_consent")
sources = proposal["sources"]
approved = {source["repo"]: source for source in disclosure["sources"]}
if len(sources) != 7 or {source["repo"] for source in sources} != REPOSITORIES:
raise ValueError("invalid_source_scope")
for source in sources:
owner = approved[source["repo"]]
files = {item["path"]: item["sha256"] for item in owner["files"]}
if (
source["consented_commit"] != owner["commit"]
or source["capability_ids"] != owner["capability_ids"]
or source["index_sha256"] != files["registry/indexes/capabilities.yaml"]
or source["auth_env"] != AUTH_ENV
or source["native_raw_url"] != _raw_url(
source["repo"], owner["commit"], "registry/indexes/capabilities.yaml"
)
):
raise ValueError("source_not_consented")
yield source, files
def verify(proposal_path: Path, disclosure_path: Path, consent_path: Path) -> dict[str, Any]:
receipt: dict[str, Any] = {
"id": "CUST81-PRIVATE-NATIVE-FETCH-RECEIPT-R1",
"checked_at": datetime.now(timezone.utc).isoformat(),
"proposal_sha256": PROPOSAL_SHA256,
"disclosure_sha256": DISCLOSURE_SHA256,
"consent_sha256": CONSENT_SHA256,
"cache_used": False,
"all_verified": False,
"sources": [],
}
try:
# Exhaust all packet checks before any native network request.
sources = list(_prepared_sources(proposal_path, disclosure_path, consent_path))
expected_urls = {
_raw_url(source["repo"], source["consented_commit"], path)
for source, files in sources for path in files
}
allowlist = json.loads(os.environ.get("REUSE_SURFACE_AUTH_SOURCE_ALLOWLIST", "{}"))
actual_urls = allowlist.get(AUTH_ENV)
if (
not isinstance(actual_urls, list)
or len(actual_urls) != 14
or set(actual_urls) != expected_urls
):
raise ValueError("runtime_scope_not_exact")
schema = Draft202012Validator(load_schema())
except Exception:
receipt["error"] = "packet_scope_or_schema_validation_failed"
return receipt
for source, files in sources:
row = {
"repo": source["repo"],
"commit": source["consented_commit"],
"index_sha256": source["index_sha256"],
"verified": False,
"entry_sha256": [],
}
receipt["sources"].append(row)
try:
index_text = federation.fetch_remote_index_text(source["native_raw_url"], source)
if _sha(index_text.encode("utf-8")) != source["index_sha256"]:
raise ValueError("index_hash_mismatch")
index = yaml.safe_load(index_text)
entries = index["capabilities"]
if not isinstance(entries, list) or [e["id"] for e in entries] != source["capability_ids"]:
raise ValueError("unexpected_capability_ids")
for entry in entries:
if not {"id", "name", "summary", "vector", "domain", "status", "owner", "path"} <= entry.keys():
raise ValueError("invalid_index_row")
if entry["owner"] != source["repo"] or entry["path"] not in files:
raise ValueError("unconsented_entry")
entry_url = _raw_url(source["repo"], source["consented_commit"], entry["path"])
entry_text = federation.fetch_remote_index_text(entry_url, source)
digest = _sha(entry_text.encode("utf-8"))
if digest != files[entry["path"]]:
raise ValueError("entry_hash_mismatch")
front = re.match(r"^---\n(.*?)\n---", entry_text, re.DOTALL)
if front is None:
raise ValueError("missing_front_matter")
metadata = yaml.safe_load(front.group(1))
schema.validate(metadata)
if metadata["id"] != entry["id"] or metadata["owner"] != source["repo"]:
raise ValueError("entry_identity_mismatch")
row["entry_sha256"].append(digest)
row["verified"] = True
except Exception:
# Never stringify errors: HTTP handlers and parsers can embed bodies,
# headers, credentials, or private source text in their messages.
row["error"] = "native_fetch_or_metadata_validation_failed"
receipt["all_verified"] = len(receipt["sources"]) == 7 and all(
row["verified"] for row in receipt["sources"]
)
return receipt
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
for name in ("proposal", "disclosure", "consent"):
parser.add_argument(f"--{name}", type=Path, required=True)
args = parser.parse_args()
receipt = verify(args.proposal, args.disclosure, args.consent)
print(json.dumps(receipt, sort_keys=True))
return 0 if receipt["all_verified"] else 1
if __name__ == "__main__":
raise SystemExit(main())

View file

@ -0,0 +1,188 @@
import hashlib
import io
import json
from email.message import Message
from urllib.request import HTTPSHandler, build_opener
from urllib.response import addinfourl
import pytest
import yaml
from reuse_surface import federation, private_source_verify as verifier
def _digest(text):
return hashlib.sha256(text.encode()).hexdigest()
@pytest.fixture
def packets(tmp_path, monkeypatch):
"""Fake owner-consented bodies; no estate credential or network transport."""
approved, sources, bodies = [], [], {}
for repo in sorted(verifier.REPOSITORIES):
cap_id = f"capability.fixture.{repo}"
commit = "a" * 40
path = f"registry/capabilities/{cap_id}.md"
metadata = {
"id": cap_id, "name": "Fixture", "summary": "Fixture metadata",
"owner": repo, "status": "draft",
"maturity": {"discovery": {"current": "D3", "target": "D5"}, "availability": {"current": "A2", "target": "A5"}},
"external_evidence": {"completeness": {"level": "C1"}, "reliability": {"level": "R0"}},
}
entry = "---\n" + yaml.safe_dump(metadata) + "---\nPrivate fixture body\n"
index = yaml.safe_dump({"capabilities": [{
"id": cap_id, "name": "Fixture", "summary": "Fixture metadata", "vector": "D3 / A2 / C1 / R0",
"domain": "infotech", "status": "draft", "owner": repo, "path": path,
}]})
index_url = verifier._raw_url(repo, commit, "registry/indexes/capabilities.yaml")
bodies[index_url] = index
bodies[verifier._raw_url(repo, commit, path)] = entry
sources.append({"repo": repo, "capability_ids": [cap_id], "consented_commit": commit,
"native_raw_url": index_url, "index_sha256": _digest(index), "auth_env": verifier.AUTH_ENV})
approved.append({"repo": repo, "capability_ids": [cap_id], "commit": commit, "files": [
{"path": "registry/indexes/capabilities.yaml", "sha256": _digest(index)},
{"path": path, "sha256": _digest(entry)},
]})
disclosure = json.dumps({"id": "fixture", "revision": 1, "sources": approved})
consent = json.dumps({"consent_status": "approved", "proposal_sha256": _digest(disclosure),
"proposal_id": "fixture", "proposal_revision": 1, "repositories": sorted(verifier.REPOSITORIES)})
proposal = json.dumps({"sources": sources})
paths = []
for name, text in (("proposal", proposal), ("disclosure", disclosure), ("consent", consent)):
path = tmp_path / f"{name}.json"
path.write_text(text)
paths.append(path)
monkeypatch.setattr(verifier, f"{name.upper()}_SHA256", _digest(text))
return paths, bodies
def _transport(monkeypatch, bodies, mutate=None):
calls = []
class FakeResponse:
def __init__(self, body):
self.body = body
def __enter__(self):
return self
def __exit__(self, *args):
return False
def read(self):
return self.body.encode()
class FakeOpener:
def open(self, req, timeout):
assert req.get_header("Authorization") == "Bearer fixture-secret"
assert timeout == 30
calls.append(req.full_url)
body = bodies[req.full_url]
return FakeResponse(mutate(req.full_url, body) if mutate else body)
monkeypatch.setenv(verifier.AUTH_ENV, "fixture-secret")
monkeypatch.setenv("REUSE_SURFACE_AUTH_SOURCE_ALLOWLIST", json.dumps({verifier.AUTH_ENV: list(bodies)}))
monkeypatch.setattr(federation.urllib.request, "build_opener", lambda handler: FakeOpener())
# Deliberately prohibit composition/cache resolution; direct fetch must work.
monkeypatch.setattr(federation, "resolve_source_index_path", lambda *a, **k: pytest.fail("cache path used"))
return calls
def test_exact_consented_native_index_and_entries_no_cache(packets, monkeypatch):
paths, bodies = packets
calls = _transport(monkeypatch, bodies)
receipt = verifier.verify(*paths)
assert receipt["all_verified"]
assert not receipt["cache_used"]
assert len(calls) == 14
assert all("?ref=" + "a" * 40 in url for url in calls)
output = json.dumps(receipt)
assert "fixture-secret" not in output
assert "Private fixture body" not in output
@pytest.mark.parametrize("suffix", [".yaml", ".md"])
def test_changed_unconsented_body_fails(packets, monkeypatch, suffix):
paths, bodies = packets
_transport(monkeypatch, bodies, lambda url, text: text + "changed" if suffix in url else text)
receipt = verifier.verify(*paths)
assert not receipt["all_verified"]
assert all(not row["verified"] for row in receipt["sources"])
def test_packet_tampering_rejected_before_fetch(packets, monkeypatch):
paths, _ = packets
paths[0].write_text(paths[0].read_text() + " ")
monkeypatch.setattr(federation, "fetch_remote_index_text", lambda *a: pytest.fail("network before consent checks"))
assert verifier.verify(*paths)["error"] == "packet_scope_or_schema_validation_failed"
def test_missing_auth_fails_before_transport(packets, monkeypatch):
paths, bodies = packets
monkeypatch.setenv("REUSE_SURFACE_AUTH_SOURCE_ALLOWLIST", json.dumps({verifier.AUTH_ENV: list(bodies)}))
monkeypatch.delenv(verifier.AUTH_ENV, raising=False)
monkeypatch.setattr(federation.urllib.request, "build_opener", lambda *a: pytest.fail("transport without auth"))
receipt = verifier.verify(*paths)
assert not receipt["all_verified"]
assert all(not row["verified"] for row in receipt["sources"])
def test_error_output_never_embeds_secret_or_body(packets, monkeypatch):
paths, bodies = packets
monkeypatch.setenv("REUSE_SURFACE_AUTH_SOURCE_ALLOWLIST", json.dumps({verifier.AUTH_ENV: list(bodies)}))
def failure(*args):
raise ValueError("fixture-secret Private fixture body")
monkeypatch.setattr(federation, "fetch_remote_index_text", failure)
output = json.dumps(verifier.verify(*paths))
assert "fixture-secret" not in output
assert "Private fixture body" not in output
def test_broadened_runtime_reader_scope_fails_before_fetch(packets, monkeypatch):
paths, bodies = packets
monkeypatch.setenv("REUSE_SURFACE_AUTH_SOURCE_ALLOWLIST", json.dumps({verifier.AUTH_ENV: list(bodies) + ["https://attacker.invalid/"]}))
monkeypatch.setattr(federation, "fetch_remote_index_text", lambda *a: pytest.fail("broadened scope used"))
assert not verifier.verify(*paths)["all_verified"]
@pytest.mark.parametrize("target", ["https://attacker.invalid/stolen", "https://forgejo.coulomb.social/other/repo"])
def test_native_auth_redirect_never_replays_header(monkeypatch, target):
calls = []
class FakeHTTPS(HTTPSHandler):
def https_open(self, req):
calls.append(req.full_url)
headers = Message()
headers["Location"] = target
result = addinfourl(io.BytesIO(b""), headers, req.full_url, 302)
result.msg = "Found"
return result
# Use real urllib opener/redirect/error processors and fake HTTPS transport.
opener = build_opener(FakeHTTPS(), federation._RejectAuthenticatedRedirect())
monkeypatch.setattr(federation.urllib.request, "build_opener", lambda *a: opener)
monkeypatch.setenv("FIXTURE_AUTH", "fixture-secret")
monkeypatch.setenv("REUSE_SURFACE_AUTH_SOURCE_ALLOWLIST", json.dumps({"FIXTURE_AUTH": ["https://forgejo.coulomb.social/approved"]}))
with pytest.raises(ConnectionError, match="redirect refused"):
federation.fetch_remote_index_text("https://forgejo.coulomb.social/approved", {"repo": "fixture", "auth_env": "FIXTURE_AUTH"})
assert calls == ["https://forgejo.coulomb.social/approved"]
def test_authenticated_http_rejected_before_transport(monkeypatch):
monkeypatch.setenv("FIXTURE_AUTH", "fixture-secret")
monkeypatch.setattr(federation.urllib.request, "build_opener", lambda *a: pytest.fail("cleartext transport"))
with pytest.raises(ValueError, match="HTTPS"):
federation.fetch_remote_index_text("http://forgejo.coulomb.social/approved", {"repo": "fixture", "auth_env": "FIXTURE_AUTH"})
@pytest.mark.parametrize("config", [None, "broken-json", "[]", '{"FIXTURE_AUTH":"https://attacker.invalid/"}', '{"OTHER_AUTH":["https://attacker.invalid/"]}'])
def test_unapproved_auth_target_rejected_before_credential_lookup(monkeypatch, config):
if config is None:
monkeypatch.delenv("REUSE_SURFACE_AUTH_SOURCE_ALLOWLIST", raising=False)
else:
monkeypatch.setenv("REUSE_SURFACE_AUTH_SOURCE_ALLOWLIST", config)
monkeypatch.setattr(federation, "_auth_headers", lambda *a: pytest.fail("unauthorized credential lookup"))
with pytest.raises(ValueError, match="runtime-authorized"):
federation.fetch_remote_index_text("https://attacker.invalid/", {"repo": "fixture", "auth_env": "FIXTURE_AUTH"})

View file

@ -0,0 +1,66 @@
---
id: REUSE-WP-0025
type: workplan
title: "Bind private source reader to consented metadata URLs"
domain: infotech
repo: reuse-surface
status: blocked
owner: reuse-surface-owner-preparation-worker
created: "2026-10-15"
updated: "2026-10-15"
flavor: implementation
depends_on: [CUST-WP-0081]
---
Prepared in an isolated owner checkout under the user's explicit worker-agent
request. This worker has supervised local preparation scope only; no founder
credential approval, permanent repo-owner authority, deployment, or source-owner
consent is inferred. The custodian integration agent handles hub synchronization
after accepting the proposed owner workitem. No State Hub mutation is performed
from this isolated checkout.
## Independent consumer review
```task
id: REUSE-WP-0025-T01
status: done
priority: high
```
Reviewed consumer INTENT, native authenticated acquisition, public API registration
fields, and stale-cache behavior. The deployed baseline is unsuitable for a new
private reader: registered auth_env/URL can route runtime credentials to arbitrary
hosts; urllib's default redirect handler also forwards Authorization. Review is
`changes_requested`; metadata consent does not authorize reader provisioning.
See docs/assessments/cust81-private-reader/owner-review-r1.md.
## Prepare native boundary and verification helper
```task
id: REUSE-WP-0025-T02
status: done
priority: high
```
Patch rejects authenticated cleartext URLs and all redirects, and requires an
operator-controlled exact env-to-URL allowlist before credential lookup. Receipt
helper invokes native fetch directly for all seven consented index/entry pairs,
checks exact hashes and entry schema, and never uses cached fallback. Fake
transport tests and local committed metadata validation are preparation evidence,
not live authenticated fetch receipts.
## Review, publish and verify deployed consumer
```task
id: REUSE-WP-0025-T03
status: wait
priority: high
```
Owner review and exact credential/rollout disposition remain pending. Platform/apps
must inventory every existing authenticated dynamic registration without reading
Secret values, migrate approved exact URLs, and deliver a reviewed image containing
the fix plus the exact reader allowlist. Then run helper inside the hub environment
with the owner-provided packets, verify all seven sources fresh, and hand a
sanitized receipt to the custodian for registration and final 70-capability audit.
No new PAT is delivered to the current baseline consumer.