From 005709a37228ba9e6d5a658aada0b62bf49649f5 Mon Sep 17 00:00:00 2001 From: tegwick Date: Sun, 1 Nov 2026 11:48:25 +0100 Subject: [PATCH] INFD-WP-0010-T02: pin service image ca75f0be (main-c228583) for the v14 release Owner CI run 6 built forgejo.coulomb.social/coulomb/informed-decision @sha256:ca75f0be03af0bd96a66b08d2949bdc2d16365a93ffabcd6593074b565e8f01b from c228583. Verified read-only: - zlib 1.3.2-r1 (floor check passes) - installed modules equal the source at c228583 - 13/13 container checks - Trivy 0 HIGH/CRITICAL; 2 UNKNOWN musl findings, the same as the live image Pinned in admission.candidate.json and re-rendered service.candidate.json. The runtime ConfigMap is unchanged (informed-decision-runtime-b488b96a0953). This commit is the release's RELEASE_SHA. Nothing applied. Co-Authored-By: Claude Opus 5.5 Assistant: claude-code Assistant-Model: opus Assistant-Process: 5502@bnt-lap001 Assistant-Session: 68b3b02f-5d0f-4e71-8421-796f62e50196 --- deploy/lifecycle/README.md | 8 +-- deploy/lifecycle/RELEASE-INFD-WP-0010-T02.md | 29 +++++++--- deploy/lifecycle/admission.candidate.json | 2 +- deploy/lifecycle/service.candidate.json | 2 +- .../container.json | 32 +++++++++++ .../image-verification.json | 54 +++++++++++++++++++ ...nt-existing-and-proportionate-decisions.md | 9 ++++ 7 files changed, 125 insertions(+), 11 deletions(-) create mode 100644 docs/evidence/2026-11-01-present-existing-release/container.json create mode 100644 docs/evidence/2026-11-01-present-existing-release/image-verification.json diff --git a/deploy/lifecycle/README.md b/deploy/lifecycle/README.md index c9f1a9e..3263cfd 100644 --- a/deploy/lifecycle/README.md +++ b/deploy/lifecycle/README.md @@ -216,7 +216,9 @@ retaining the current schema-5 database. Evidence: docs/evidence/2026-10-05-life INFD-WP-0010-T02, together with access-engine compact-sitting v14. The candidate files carry the v14 review pin (`sha256:8911458f…fc300fde`), the `nk-bind-executor` present_existing registry row (daily limit 10) and an 8081 ingress peer for exactly `sso` + `app.kubernetes.io/name=bounded-executor`. The state-hub row is unchanged and -outcome_read stays off. **The image pin is still the live `f5588f49…`, because no owner-CI full-service image -exists yet. Do not sync this candidate until it is replaced:** the live image rejects the new registry row, -which would fail all intake. Founder runbook, verification and rollback: +outcome_read stays off. The service image is pinned to owner-CI `main-c228583`, +`sha256:ca75f0be03af0bd96a66b08d2949bdc2d16365a93ffabcd6593074b565e8f01b`. Verified: zlib 1.3.2-r1, installed source +equal to c228583, 13/13 container checks, 0 HIGH/CRITICAL. The runtime ConfigMap is `informed-decision-runtime-b488b96a0953`. +Never pair these registries with the old image: it rejects the new row, so all intake would fail. Founder runbook, +verification and rollback: [RELEASE-INFD-WP-0010-T02.md](RELEASE-INFD-WP-0010-T02.md). diff --git a/deploy/lifecycle/RELEASE-INFD-WP-0010-T02.md b/deploy/lifecycle/RELEASE-INFD-WP-0010-T02.md index 160cd2e..31bc88d 100644 --- a/deploy/lifecycle/RELEASE-INFD-WP-0010-T02.md +++ b/deploy/lifecycle/RELEASE-INFD-WP-0010-T02.md @@ -5,7 +5,23 @@ Founder approval (2026-11-01, relayed by the net-kingdom coordinator): release p access-engine compact-sitting v14. Every command below is founder-run, with `export KUBECONFIG=$HOME/.kube/config-railiance01`. -## Status: blocked on the service image (gate G0) +## Status: image pinned (gate G0 closed 2026-11-01) + +Owner CI (`service-image.yaml`, run 6, source `c228583`) published `main-c228583`, digest +`forgejo.coulomb.social/coulomb/informed-decision@sha256:ca75f0be03af0bd96a66b08d2949bdc2d16365a93ffabcd6593074b565e8f01b`. The owner verified it read-only: + +- the label revision is `c228583`, and the user is 10001 +- `apk info --exists 'zlib>=1.3.2-r1'` passes; zlib is 1.3.2-r1 (runtime 1.3.2), libuuid is 2.42.3-r1, and pip is absent +- the runtime smoke passes, and the installed modules equal the source at `c228583` +- `tools/smoke_container.py --workload` passes 13/13 +- Trivy (the same pinned scanner as earlier releases, DB of 2026-11-01) finds **0 HIGH/CRITICAL**. It reports + 2 UNKNOWN: CVE-2026-107891 in musl/musl-utils 1.2.6-r2, fixed in 1.2.6-r3. The live `f5588f49` image carries + the same musl, so this is not a regression. + +Evidence: `docs/evidence/2026-11-01-present-existing-release/`. RELEASE_SHA is the commit that pinned this digest: +`git -C ~/informed-decision log -1 --format=%H -- deploy/lifecycle/admission.candidate.json` on main. + +### History: why the gate existed No CI image exists for current `main`. This repository has no Forgejo workflow that builds the full service image. Its two workflows build single-purpose overlays on fixed base digests: @@ -43,8 +59,8 @@ included. It also does not send `approval_action`. | | Current, live (rollback target) | Candidate | | --- | --- | --- | -| Argo `informed-decision` targetRevision | `312ab97e876e17341bf16f9e95397e14c2ac2720` | `` (step 0) | -| Service image | `…/informed-decision@sha256:f5588f496b1f267d07cdc9f5208e6f2f241f74b739c23924b03702dec13a5c23` | `` (G0) | +| Argo `informed-decision` targetRevision | `312ab97e876e17341bf16f9e95397e14c2ac2720` | RELEASE_SHA (the image-pin commit, see Status) | +| Service image | `…/informed-decision@sha256:f5588f496b1f267d07cdc9f5208e6f2f241f74b739c23924b03702dec13a5c23` | `…/informed-decision@sha256:ca75f0be03af0bd96a66b08d2949bdc2d16365a93ffabcd6593074b565e8f01b` (`main-c228583`) | | Runtime ConfigMap | `informed-decision-runtime-6c221878d051` | `informed-decision-runtime-b488b96a0953` | | Review policy pin | compact-sitting `v13` `sha256:31be5985c0c1e6b0c3a039ed7310d1e94daf523a94f6d926e6e8d759d3711873` | `v14` `sha256:8911458f36f1a60598aa19592a2d752a74dffe2617fd86238407ac87bc300fde` | | Helm `flex-auth-informed-decision-sitting` (access-engine) | revision 13, image `6c6dc263…`, v13 policy path | access-engine's v14 release (`2de0f86`), prepared in parallel | @@ -63,7 +79,7 @@ Candidate source changes in this commit: `net-kingdom-admins`, `daily_limit: 10`, `present_existing {approval_actor: service:nk-bind-executor, actions: [bounded-execution]}`. The state-hub row is byte-identical, and `outcome_read` stays off (T05 waits for STATE-WP-0101). -## Step 0: pin the image (after G0; owner agent or founder) +## Step 0: pin the image (DONE 2026-11-01, owner agent; kept for reference) ```bash cd ~/informed-decision @@ -75,7 +91,8 @@ python3 tools/render_deployment.py --input deploy/lifecycle/admission.candidate. python3 tools/smoke_container.py --image forgejo.coulomb.social/coulomb/informed-decision@ \ --receipt docs/evidence/-present-existing-release/container.json --workload git commit -am "INFD-WP-0010-T02: pin service image for the v14 release" && git push -RELEASE_SHA=$(git rev-parse HEAD) +# Founder, before step 1: +RELEASE_SHA=$(git -C ~/informed-decision log -1 --format=%H -- deploy/lifecycle/admission.candidate.json) ``` Only the image line and the re-rendered `service.candidate.json` change. The runtime ConfigMap name stays @@ -172,7 +189,7 @@ Possible without the executor: 409. No memo is stored, no budget is spent, and nothing is created, entered or consumed in approval-engine. ```bash cd ~/informed-decision - IMAGE=forgejo.coulomb.social/coulomb/informed-decision@ + IMAGE=forgejo.coulomb.social/coulomb/informed-decision@sha256:ca75f0be03af0bd96a66b08d2949bdc2d16365a93ffabcd6593074b565e8f01b NAME=infd-probe-$(date -u +%H%M%S) # --overrides (merge patch) replaces the generated container: it carries name and image OVR='{"spec":{"serviceAccountName":"nk-bind-executor","automountServiceAccountToken":false, "securityContext":{"runAsNonRoot":true,"runAsUser":10001,"seccompProfile":{"type":"RuntimeDefault"}}, diff --git a/deploy/lifecycle/admission.candidate.json b/deploy/lifecycle/admission.candidate.json index 458daf1..39213fe 100644 --- a/deploy/lifecycle/admission.candidate.json +++ b/deploy/lifecycle/admission.candidate.json @@ -1,5 +1,5 @@ { - "image": "forgejo.coulomb.social/coulomb/informed-decision@sha256:f5588f496b1f267d07cdc9f5208e6f2f241f74b739c23924b03702dec13a5c23", + "image": "forgejo.coulomb.social/coulomb/informed-decision@sha256:ca75f0be03af0bd96a66b08d2949bdc2d16365a93ffabcd6593074b565e8f01b", "policy": { "origin": "http://flex-auth-informed-decision-sitting.flex-auth.svc.cluster.local:8080", "package": "informed-decision.compact-sitting", diff --git a/deploy/lifecycle/service.candidate.json b/deploy/lifecycle/service.candidate.json index 5377d35..ca08762 100644 --- a/deploy/lifecycle/service.candidate.json +++ b/deploy/lifecycle/service.candidate.json @@ -96,7 +96,7 @@ "containers": [ { "name": "informed-decision", - "image": "forgejo.coulomb.social/coulomb/informed-decision@sha256:f5588f496b1f267d07cdc9f5208e6f2f241f74b739c23924b03702dec13a5c23", + "image": "forgejo.coulomb.social/coulomb/informed-decision@sha256:ca75f0be03af0bd96a66b08d2949bdc2d16365a93ffabcd6593074b565e8f01b", "securityContext": { "allowPrivilegeEscalation": false, "readOnlyRootFilesystem": true, diff --git a/docs/evidence/2026-11-01-present-existing-release/container.json b/docs/evidence/2026-11-01-present-existing-release/container.json new file mode 100644 index 0000000..697a476 --- /dev/null +++ b/docs/evidence/2026-11-01-present-existing-release/container.json @@ -0,0 +1,32 @@ +{ + "status": "passed", + "image_id": "sha256:ca75f0be03af0bd96a66b08d2949bdc2d16365a93ffabcd6593074b565e8f01b", + "repo_digests": [ + "forgejo.coulomb.social/coulomb/informed-decision@sha256:ca75f0be03af0bd96a66b08d2949bdc2d16365a93ffabcd6593074b565e8f01b" + ], + "checks_passed": 13, + "checks": [ + "installed container entrypoint serves with projected configuration", + "non-root read-only runtime has no external network or published port", + "private config/database modes enforced; package installer absent", + "configured review refuses anonymous access and reports audit-unready status", + "private listener refuses anonymous lifecycle access and exposes no browser routes", + "public listener exposes no private workload route", + "a second writer cannot acquire the active evidence volume", + "synthetic uncertain intent and undelivered evidence remain explicit", + "consistent backup created while serving; overwrite refused", + "SIGTERM closes the serving writer without forced kill", + "restart preserves immutable content and unresolved submission without retry", + "separate restored volume preserves exact content and unresolved state", + "incomplete owner configuration exits before serving" + ], + "fixture_only": true, + "external_network": "none", + "content_snapshot_sha256": "7c377d9159da33bdc491f81a3444d3d581c1711664dcfbb6df2a6f899b49f425", + "native_identity_policy_audit_proven": false, + "published": false, + "deployed": false, + "factory_attempts": 0, + "paid_model_calls": 0, + "cleanup_complete": true +} diff --git a/docs/evidence/2026-11-01-present-existing-release/image-verification.json b/docs/evidence/2026-11-01-present-existing-release/image-verification.json new file mode 100644 index 0000000..4b609e6 --- /dev/null +++ b/docs/evidence/2026-11-01-present-existing-release/image-verification.json @@ -0,0 +1,54 @@ +{ + "image": "forgejo.coulomb.social/coulomb/informed-decision@sha256:ca75f0be03af0bd96a66b08d2949bdc2d16365a93ffabcd6593074b565e8f01b", + "tag": "main-c228583", + "source_revision": "c228583b609aaa7f0e45ea1fcda4f26e121ad2c5", + "built_by": "owner CI service-image.yaml run 6 (success)", + "verified_read_only_2026-11-01": { + "label_revision_matches": true, + "user": "10001:10001", + "zlib_floor": "apk info --exists 'zlib>=1.3.2-r1' passed; zlib-1.3.2-r1, runtime 1.3.2", + "libuuid": "2.42.3-r1", + "pip_absent": true, + "runtime_smoke": { + "uid": 10001, + "zlib_runtime_version": "1.3.2", + "compression_vectors_pass": 4, + "malformed_zlib_refusals": 3, + "crypto_jwt_waitress_smoke": true, + "network_accessed": false, + "database_opened": false + }, + "installed_modules_equal_source_at_c228583": true, + "container_checks": "13/13 passed (tools/smoke_container.py --workload), see container.json" + }, + "scan": { + "scanner": "aquasec/trivy@sha256:62b1e65e8869bc4b4c6aa4fa2b21595256c7c2f6018a9d9ad61caf87187c1969", + "scanners": "vuln", + "os": { + "Family": "alpine", + "Name": "3.24.1" + }, + "db_updated_at": "2026-11-01T07:08:40Z", + "high_critical_findings": 0, + "findings": [ + { + "id": "CVE-2026-107891", + "package": "musl", + "installed": "1.2.6-r2", + "fixed": "1.2.6-r3", + "severity": "UNKNOWN" + }, + { + "id": "CVE-2026-107891", + "package": "musl-utils", + "installed": "1.2.6-r2", + "fixed": "1.2.6-r3", + "severity": "UNKNOWN" + } + ], + "exit_code": 0, + "report_sha256": "72a31d2435ac8b65925ffc5548d72419492334426f0b91ff5b9d707618485ca6", + "note": "The two UNKNOWN musl findings are also present in the live image f5588f49 (musl 1.2.6-r2): not a regression." + }, + "deployed": false +} diff --git a/workplans/INFD-WP-0010-present-existing-and-proportionate-decisions.md b/workplans/INFD-WP-0010-present-existing-and-proportionate-decisions.md index 0cd4da3..a7d9b1c 100644 --- a/workplans/INFD-WP-0010-present-existing-and-proportionate-decisions.md +++ b/workplans/INFD-WP-0010-present-existing-and-proportionate-decisions.md @@ -111,6 +111,15 @@ Same day, step 0 in source: `.forgejo/workflows/service-image.yaml` builds the f publishes `main-`. The `Containerfile` builds the wheel in-image and installs the overlay's hash-pinned zlib-1.3.2-r1 offline, failing the build below 1.3.2-r1. A local build passed 13/13 container checks. The image pin waits for the digest from CI. +**Image pinned (2026-11-01):** CI run 6 published `main-c228583` = +`sha256:ca75f0be03af0bd96a66b08d2949bdc2d16365a93ffabcd6593074b565e8f01b`. Verified read-only: +- zlib 1.3.2-r1 (and the floor check passes) +- installed modules equal the source at c228583 +- 13/13 container checks +- Trivy 0 HIGH/CRITICAL; 2 UNKNOWN in musl, the same as live + +It is pinned in `admission.candidate.json` and `service.candidate.json`. The runtime ConfigMap is unchanged +(`…b488b96a0953`). The pin commit is RELEASE_SHA. The release itself is founder-run. Then here: the policy pin, a registry row, a release, and a native proof with synthetic BEA content. Optional: for `bounded-execution`, require a packet item whose digest equals `target.admission_digest`, once the admission