From fa64e4f86801f1382c79eec3697a7df4754f4825 Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 30 Oct 2026 23:06:13 +0100 Subject: [PATCH] Correct live image source pin and reconcile service attribution evidence Assistant: codex Assistant-Model: gpt-6.1-sol Assistant-Session: 01a18e2d-f513-7742-b8e7-12af0b744ff3 --- ...service-contract-conformance-2026-10-27.md | 10 +++ ...-provenance-reconciliation-2026-10-30.json | 61 +++++++++++++ ...ce-provenance-reconciliation-2026-10-30.md | 87 +++++++++++++++++++ docs/resource-evidence/README.md | 6 ++ registry/release-units/coulomb-social.yaml | 2 +- scripts/verify-packaged-source.py | 67 ++++++++++++++ ...0012-durable-recovery-service-readiness.md | 12 +++ 7 files changed, 244 insertions(+), 1 deletion(-) create mode 100644 docs/release/service-provenance-reconciliation-2026-10-30.json create mode 100644 docs/release/service-provenance-reconciliation-2026-10-30.md create mode 100644 scripts/verify-packaged-source.py diff --git a/docs/release/service-contract-conformance-2026-10-27.md b/docs/release/service-contract-conformance-2026-10-27.md index 1a2a572..a5e1594 100644 --- a/docs/release/service-contract-conformance-2026-10-27.md +++ b/docs/release/service-contract-conformance-2026-10-27.md @@ -26,3 +26,13 @@ WP-0012 owns the operating/service returns above. WP-0013 owns privacy/content verdicts; WP-0014 owns all-space reconciliation and the separate cohort/apex cutover decision. Existing canonical cross-owner records remain in their owners; this assessment creates no credential grant or service acceptance. + +October 30 source/attribution follow-through: actual retained image bytes match +all69packaged files at dd83c90, while the release-unit's796a1557source differs in +eight paths. Corrected that source pin without changing the image or live service. +The actual finance parser rejects the legacy resource ID as a client attribution +key. Resource/default tenant, retained cohort SQL tenant and financial entity are +distinct identifiers; their client × app × instance mapping is still unproven. +The local compatibility catalog has no matching service record; this does not +prove absence on the ops-hub owner surface. Detailed bounded proof and next +returns: service-provenance-reconciliation-2026-10-30.{md,json}. diff --git a/docs/release/service-provenance-reconciliation-2026-10-30.json b/docs/release/service-provenance-reconciliation-2026-10-30.json new file mode 100644 index 0000000..87e2786 --- /dev/null +++ b/docs/release/service-provenance-reconciliation-2026-10-30.json @@ -0,0 +1,61 @@ +{ + "schema": "coulomb.packaged-source-provenance.v1", + "image": "forgejo.coulomb.social/coulomb/coulomb-social@sha256:9a646d8e01a61ba5316d3c2eb0273064e17f2d0300ad07af766ccedda65ecb18", + "network": "none", + "read_only_root": true, + "entrypoint_bypassed": true, + "database_contact": false, + "production_changes": false, + "comparisons": [ + { + "commit": "dd83c90d73a1f7153581949424603e7b38eec014", + "packaged_file_count": 69, + "source_file_count": 69, + "different_files": 0, + "all_packaged_source_bytes_match": true + }, + { + "commit": "796a1557e9e5ff68800f9676d050d5b1efe7a138", + "packaged_file_count": 69, + "source_file_count": 70, + "different_files": 8, + "all_packaged_source_bytes_match": false + } + ], + "actual_packaged_manifest_sha256": "a8a86bc44c5dcc9340aafdc8aebed09dbf04f366d0f57a7ae781f55143c4c958", + "dependency_or_build_reproducibility_proved": false, + "observed_at": "2026-10-30T22:04:08.096662+00:00", + "verifier_source_sha256": "99d734f20331e8d699081d3d77e7a0d0b3bc676be69ce101377bc69eae6c70d5", + "native_read_only_deployment": { + "uid": "2dbe661a-d232-4477-bbd1-833813077fbe", + "image": "forgejo.coulomb.social/coulomb/coulomb-social@sha256:9a646d8e01a61ba5316d3c2eb0273064e17f2d0300ad07af766ccedda65ecb18", + "replicas": 1 + }, + "image_oci_revision_label": null, + "registry_previous_source": "796a1557e9e5ff68800f9676d050d5b1efe7a138", + "registry_corrected_source": "dd83c90d73a1f7153581949424603e7b38eec014", + "identity_reconciliation": { + "schema": "coulomb.service-identity-reconciliation.v1", + "observed_on": "2026-10-30", + "legacy_resource_id": "resource:tenant:coulomb:coulomb-social", + "legacy_id_is_fin_client_key": false, + "client_attribution": null, + "mapping_status": "unresolved_not_inferred", + "finance_parser_source_sha256": "bfee11197bdb3d10453a655f75319f446069c59c5edf14ca027023b44597c18b", + "resource_inventory_tenant": "tenant:coulomb", + "resource_financial_entity": "entity:coulomb", + "retained_accepted_cohort_tenant": "tenant:platform", + "deployment_values_default_tenant": "tenant:coulomb", + "application_id": "coulomb-social", + "state_hub_catalog_get_slug_http_status": 404, + "state_hub_catalog_repo_results": 0, + "state_hub_missing_record_does_not_prove_ops_hub_absence": true, + "booked_cost_or_allocation_invented": false, + "external_writes": false + }, + "source_references": { + "/home/worsch/resource-control/data/resources/coulomb-social-production.json": "d50477b5c30f93e6adf648cf8c7b9c00471e3f002d668bad381a3f3462ed7da4", + "/home/worsch/railiance-apps/helm/coulomb-social-values.yaml": "f6a8a70da3c885167654aa362ad3fbb46a72e791ed5028e7ef41bbd7fd9e7ea6", + "/home/worsch/fin-hub/docs/fin-resource-authority-contract-v0.1.md": "10926027035c1afe115a654af3eaf49ec3c9ab278573f474a5d2e0c20ae7f4c3" + } +} diff --git a/docs/release/service-provenance-reconciliation-2026-10-30.md b/docs/release/service-provenance-reconciliation-2026-10-30.md new file mode 100644 index 0000000..756bc40 --- /dev/null +++ b/docs/release/service-provenance-reconciliation-2026-10-30.md @@ -0,0 +1,87 @@ +# Service source and attribution reconciliation + +WP-0012-T03 remains open. This check corrects release-source evidence and +identifies the missing client attribution join; it does not deploy or register +anything, book cost, approve an identity mapping or finish service conformance. + +## Current image source + +A read-only native deployment query still observes deployment UID +`2dbe661a-d232-4477-bbd1-833813077fbe`, one replica and image digest +`9a646d8e01a61ba5316d3c2eb0273064e17f2d0300ad07af766ccedda65ecb18`. +The October 8 release receipt and current deployment-owner values name source +`dd83c90d73a1f7153581949424603e7b38eec014`. The app release-unit declaration +instead named `796a1557e9e5ff68800f9676d050d5b1efe7a138`. + +The retained digest image has no OCI revision label, so that label cannot prove +either source claim. `scripts/verify-packaged-source.py` bypasses its entrypoint +and hashes the entire packaged application plus manage.py, pyproject.toml and +the renamed entrypoint. It compares those bytes with exact Git objects, without +starting Django, mounting host files, pulling an image or contacting a database. +The disposable container has no network and a read-only root. + +All 69 packaged files match dd83c90 exactly. Commit 796a1557 has 70 source files +and eight differing/missing packaged paths. The release-unit declaration now +pins dd83c90, matching both the actual packaged source and owning release values. +The image digest, production and prepared storage proposal are unchanged. +This comparison proves source-byte equality, not dependency provenance or build +reproducibility. It does not retag or rebuild the historical artifact. + +Repeat using the locally retained immutable image: + +```sh +python3 scripts/verify-packaged-source.py \ + --image forgejo.coulomb.social/coulomb/coulomb-social@sha256:9a646d8e01a61ba5316d3c2eb0273064e17f2d0300ad07af766ccedda65ecb18 \ + --source dd83c90d73a1f7153581949424603e7b38eec014 \ + --source 796a1557e9e5ff68800f9676d050d5b1efe7a138 +``` + +This command reports each comparison; inspect `all_packaged_source_bytes_match`. +It does not select or publish a source pin automatically. + +## Client attribution remains unresolved + +The existing `resource:tenant:coulomb:coulomb-social` value is an authoritative +resource-control inventory ID and that inventory's dedicated allocation key. +It is not a fin-hub client attribution key. Running the actual fin-hub parser +rejects it. Fin-hub's current contract requires the three externally authoritative +dimensions and derives `client:|app:|instance:`; resource/infrastructure +IDs retain their separate namespace. Do not simply rename the resource ID. + +The inspected sources establish different axes: + +| Axis | Evidence | +| --- | --- | +| Product/application | `coulomb-social` | +| Resource inventory tenant | `tenant:coulomb` | +| Resource financial consumer | `entity:coulomb`; procurer is `entity:railiance` | +| Deployment values' default tenant | `tenant:coulomb` | +| Retained accepted-cohort SQL selection | `tenant:platform` | +| Legal client baseline | The accepted business-app contract says Binky Hedgehog GmbH is client #1. | + +Those values do not establish a canonical client × app × instance mapping by +themselves. A default tenant is not proof of every stored row's tenant, and a +financial entity is not automatically a client ID. Keep the native data and all +existing IDs unchanged. WP-0014's explicit source/tenant/grant reconciliation +must preserve the accepted cohort's actual tenant rather than changing it to +make a cost join pass. + +Required return under the existing WP-0012-T03: an authoritative mapping for the +client and instance, linked to the resource/deployment and actual tenant scope; +then the same canonical key through finance ingestion and a per-instance report +backed by actual costs/authoritative shared allocation. Missing amounts stay +unknown. CPU requests, a synthetic CSV or a new alias cannot prove booked cost. + +The local State Hub compatibility catalog returns 404 for the exact service slug +and zero rows for `repo_slug=coulomb-social`. This proves only that local surface +lacks the record. Ops-hub documents a hub-core-hosted owner surface and a separate +attended bootstrap; these local observations do not prove absence there or +authorize bootstrap. Its current typed compatibility schema also lacks a client +instance relation. A prose description alone would not satisfy the service +contract's complete client/environment/endpoint registration requirement. + +The companion JSON retains bounded observations, source hashes and comparison +counts. It contains no application bodies, credentials, provider costs or +fabricated identity mapping. Ruff and whitespace checks pass; application +behavior/tests are unchanged, so the existing 383-case full gate is not claimed +as a newly executed acceptance result for this metadata correction. diff --git a/docs/resource-evidence/README.md b/docs/resource-evidence/README.md index 769311f..2c7adbf 100644 --- a/docs/resource-evidence/README.md +++ b/docs/resource-evidence/README.md @@ -28,3 +28,9 @@ Do **not** put secret values, provider credentials, or invoices here. Inventory pointer (resource-control): `resource-control/data/resources/coulomb-social-production.json`. + +The resource ID above is not a fin-hub client attribution key. The current +client × app × instance mapping remains unresolved; see +[service provenance and attribution reconciliation](../release/service-provenance-reconciliation-2026-10-30.md). +Do not reinterpret historical forecast identifiers or missing costs as a +validated finance join. diff --git a/registry/release-units/coulomb-social.yaml b/registry/release-units/coulomb-social.yaml index e541748..552c6cb 100644 --- a/registry/release-units/coulomb-social.yaml +++ b/registry/release-units/coulomb-social.yaml @@ -43,4 +43,4 @@ pins: digest: hashAlgorithm: SHA-1 normalisationAlgorithm: gitCommit/v1 - value: 796a1557e9e5ff68800f9676d050d5b1efe7a138 + value: dd83c90d73a1f7153581949424603e7b38eec014 diff --git a/scripts/verify-packaged-source.py b/scripts/verify-packaged-source.py new file mode 100644 index 0000000..67b4fe1 --- /dev/null +++ b/scripts/verify-packaged-source.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 +"""Compare retained OCI application bytes with exact Git commits, without startup. + +No pull, mounts, network, application entrypoint, database or external writes. +Inventory follows the runtime COPY instructions in this repo's Dockerfile. +This proves packaged source equality, not dependency/build reproducibility. +""" + +import argparse +import hashlib +import json +import re +import subprocess + +PROBE = """import hashlib,json,pathlib +r=pathlib.Path('/app') +f={str(p.relative_to(r)):hashlib.sha256(p.read_bytes()).hexdigest() + for p in (r/'coulomb_social').rglob('*') + if p.is_file() and '__pycache__' not in p.parts and p.suffix != '.pyc'} +for n in ['manage.py','pyproject.toml','docker-entrypoint.sh']: + f[n]=hashlib.sha256((r/n).read_bytes()).hexdigest() +print(json.dumps(f,sort_keys=True)) +""" + + +def canonical(value): + return json.dumps(value, sort_keys=True, separators=(",", ":")).encode() + + +def verify(image, sources): + if not re.fullmatch(r"forgejo\.coulomb\.social/coulomb/" + r"coulomb-social@sha256:[a-f0-9]{64}", image): + raise ValueError("Exact retained application image digest required") + if not sources or any(not re.fullmatch(r"[a-f0-9]{40}", source) for source in sources): + raise ValueError("Full source commit hashes required") + actual = json.loads(subprocess.check_output([ + "docker", "run", "--rm", "--pull=never", "--network", "none", "--read-only", + "--cap-drop", "ALL", "--security-opt", "no-new-privileges", "--entrypoint", "python", + image, "-c", PROBE], timeout=60)) + comparisons = [] + for source in sources: + paths = subprocess.check_output([ + "git", "ls-tree", "-r", "--name-only", source, "coulomb_social", "manage.py", + "pyproject.toml", "scripts/docker-entrypoint.sh"], text=True).splitlines() + expected = {} + for name in paths: + packaged = (name.removeprefix("scripts/") + if name == "scripts/docker-entrypoint.sh" else name) + expected[packaged] = hashlib.sha256(subprocess.check_output( + ["git", "show", source + ":" + name])).hexdigest() + differences = sum(expected.get(n) != actual.get(n) for n in set(expected) | set(actual)) + comparisons.append({"commit": source, "packaged_file_count": len(actual), + "source_file_count": len(expected), "different_files": differences, + "all_packaged_source_bytes_match": differences == 0}) + return {"schema": "coulomb.packaged-source-provenance.v1", "image": image, + "network": "none", "read_only_root": True, "entrypoint_bypassed": True, + "database_contact": False, "production_changes": False, "comparisons": comparisons, + "actual_packaged_manifest_sha256": hashlib.sha256(canonical(actual)).hexdigest(), + "dependency_or_build_reproducibility_proved": False} + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--image", required=True) + parser.add_argument("--source", action="append", required=True) + arguments = parser.parse_args() + print(json.dumps(verify(arguments.image, arguments.source), indent=2)) diff --git a/workplans/CSOC-WP-0012-durable-recovery-service-readiness.md b/workplans/CSOC-WP-0012-durable-recovery-service-readiness.md index 8a9ce3a..9afd360 100644 --- a/workplans/CSOC-WP-0012-durable-recovery-service-readiness.md +++ b/workplans/CSOC-WP-0012-durable-recovery-service-readiness.md @@ -269,6 +269,18 @@ the app cannot read/export it. Include any future retained journals in operator offboarding handoff and explicit expiry under the open service contract work. No production date journal or expiry was created by the isolated rehearsal. +2026-10-30 service-source/attribution follow-through: read-only native metadata +still observes the old digest and one replica. An entrypoint-bypassed, network-none, +read-only retained-image comparison proves all69packaged files match dd83c90; +the registry's796a1557source differs in eight paths. Corrected only the app +release-unit source pin. The actual fin-hub parser rejects the resource inventory +ID as a client attribution key. The resource/default tenant (tenant:coulomb), +accepted-cohort SQL tenant (tenant:platform) and financial entity (entity:coulomb) +must remain distinct until an authoritative client/instance mapping is returned. +No identity rekey, cost, finance ingestion or ops bootstrap is inferred. +Local service-catalog slug404/repo0rows does not establish owner-surface absence. +Proof/next returns: docs/release/service-provenance-reconciliation-2026-10-30.{md,json}. + ## Completion Finish when every task above has its stated evidence and acceptance, or hand off any newly discovered residual to a live work record first. Cross-owner dependencies remain their existing canonical records.