Correct live image source pin and reconcile service attribution evidence
Some checks failed
Use-case regression gate / usecase-regressions (push) Has been cancelled
Some checks failed
Use-case regression gate / usecase-regressions (push) Has been cancelled
Assistant: codex Assistant-Model: gpt-6.1-sol Assistant-Session: 01a18e2d-f513-7742-b8e7-12af0b744ff3
This commit is contained in:
parent
16c685f956
commit
fa64e4f868
7 changed files with 244 additions and 1 deletions
|
|
@ -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}.
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
87
docs/release/service-provenance-reconciliation-2026-10-30.md
Normal file
87
docs/release/service-provenance-reconciliation-2026-10-30.md
Normal file
|
|
@ -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:<id>|app:<id>|instance:<id>`; 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.
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -43,4 +43,4 @@ pins:
|
|||
digest:
|
||||
hashAlgorithm: SHA-1
|
||||
normalisationAlgorithm: gitCommit/v1
|
||||
value: 796a1557e9e5ff68800f9676d050d5b1efe7a138
|
||||
value: dd83c90d73a1f7153581949424603e7b38eec014
|
||||
|
|
|
|||
67
scripts/verify-packaged-source.py
Normal file
67
scripts/verify-packaged-source.py
Normal file
|
|
@ -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))
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue