Repository navigation
feat(supply-chain): build, attest, and activate the patch-validator image #66
Description
Goal
Maintain a buyer-verifiable patch-validator lifecycle: reviewed source → exact image/runtime/SBOM/vulnerability receipts → protected integration → protected-main operational acceptance → immutable publication/signature/attestation → controlled activation. Validator evidence never inherits reviewer/model/GitHub-write/provider-routing/quarantine/security/outbound/release authority.
Current protected authority — 2026-09-18 KST
Fresh protected Noema is GitHub-verified main@227e746662d29dcc8fe360f055b7fdb7857c09fd after normal #722 integration. There is currently 1 open source lane, Draft #723 on current documentation-convergence head; #723 records protected #722 private-reporting evidence and does not modify patch-validator image/runtime authority.
The former canonical image/runtime repair lane #566 is protected history, not an active candidate. Exact 772bfba546d75ed2495d57ce43d3d390230b85fe reached application CI 34347187052, reviewer-ci 34347186941, required Security Scan 34347187127, and patch-validator-image 34347186922 terminal SUCCESS on the unchanged exact before normal merge as e19e8a67cb02d30876a6f33795213591284e3ddb.
That integration retained the authenticated BuildKit GHA cache contract, exact patch-validator image/source binding, static self-contained runtime inspection, no-network/read-only/non-root smoke, SBOM and vulnerability evidence, V8 PURL/CPE normalization, narrowly bound reviewed applicability exclusions, and the actual c-ares 1.34.8 remediation with Node-owned Linux config/GYP/GN integration. The detailed RED→GREEN forensic lineage remains in merged #566 and its doctoring evidence; this issue no longer treats its former in-progress image job as current authority.
The dependent lane-ordering repairs also completed normally. #573 exact 3307e5d519b45c66767f406d56fc3ecd6e1dcaf6 reached all four terminal SUCCESS gates and merged as 6e9b68d8302a4c3e8b2af65f592c16e51d368482; #570 exact 902cb600d53966d8a1d18789ab65ac026d0fdf9f later reached its four unchanged-exact GREEN gates and merged as f83d42817ac90aad4159e7b8649eed5b9a6f8740. #572 then closed only after verified complete successor inheritance into protected #570; #564 likewise closed as the repaired successor lineage replaced its valid workflow/test contract while deliberately excluding the invalid unconditional CHANGELOG sentence. These closures are successor consolidation, not discarded valid delta.
Current protected .github/workflows/patch-validator-image.yml still has workflow_dispatch, exact source binding through SOURCE_SHA, credential-free checkout, live PR-head refusal, GitHub-hosted ubuntu-24.04, pinned Trivy/Syft/Grype acquisition, and the dedicated verify-patch-validator-image job. The workflow remains an evidence producer; it does not by itself publish or activate an image.
#722 now provides a completed authority-separation control rather than a pending one. Its exact b4563512dce9ce9084548cad29f247911949c359 received patch-validator-image run 35250633717/105301819414 SUCCESS on runner 1002015367, but that PR did not merge until its independent current-head review and all other applicable exact-head gates, including Security second-wave Trivy/Scorecard, were also terminal GREEN. It then normally merged as 227e746662d29dcc8fe360f055b7fdb7857c09fd. A successful PR-head validator image job therefore remains source-lane evidence only: it is neither independent merge authority nor immutable publication/protected-main operational acceptance for #66.
Protected source/image criteria
- Exact-source quarantine and dedicated validator-image implementation are protected.
node_patch_verify_v1, exact source/image/receipt binding, supply-chain pinning and credential-free isolation are preserved.- Real no-network/read-only/non-root smoke and hostile-result-channel regressions exist.
- CycloneDX, Trivy, Syft/Grype, static-runtime/component and exact-image receipt verification exist.
- Reviewed identities/provenance are required for independently versioned bundled runtime components.
- Malformed/ambiguous image identity, unreviewed provenance, cross-repository smoke evidence, duplicate image authority and receipt-path replacement fail closed.
- Raw scanner evidence remains separate from reviewed applicability evidence.
- Historical GPL-family Wrangler/Miniflare/Sharp/Libvips tooling path is removed from protected source.
- CVE-2026-84373 is removed from protected source with explicit WASI platform binding retained.
- Authenticated BuildKit GHA cache import/export and cached expensive stages were reality-proven before fix(ci): repair patch-validator cache and embedded-runtime evidence #566 integration.
- c-ares 1.34.8 source integrity, Node Linux integration prerequisites and built
process.versions.ares === "1.34.8"were bound rather than suppressed.
Remaining executable boundary
Protected source/image readiness is not immutable publication or activation. Remaining evidence must be acquired from the exact protected revision used for publication:
- select an actual release-ready protected head only after applicable source, private-reporting operational follow-up (security: enable and evidence private vulnerability reporting #73), governance/release prerequisites and other material buyer gaps are satisfied; PR inventory alone does not nominate a release candidate;
- execute and retain a fresh protected-main
workflow_dispatchimage verification receipt on that exact candidate; a PR-headpatch-validator-imagePASS is historical/source-lane evidence only; - publish only an immutable image digest after that operational acceptance;
- sign/attest through a verified repository-controlled or keyless identity isolated from untrusted execution, binding repository, exact source, workflow path/ref, builder/runner identity, image digest and build parameters;
- verify signature/provenance/SBOM/source/signer identity before reviewer consumption or activation;
- bind transfer/release rights to the SemVer tag, exact source, immutable image, SBOM, dependency-license inventory, NOTICE/attribution and provenance; vulnerability success is not legal-rights evidence;
- keep activation disabled until protected operational/publication evidence passes, then exercise rollback/rotation/recovery and retain buyer-verifiable receipts.
Fresh 2026-09-18 GitHub Release inventory remains 0. #36 owns immutable Noema release publication evidence; #40 owns production Environment governance; #3 owns authenticated production KPI. Current Draft #723 blocks only its own documentation-convergence lane and must earn its own exact-head evidence; it does not satisfy or cancel #66 operational image acceptance.
Guardrails
Do not weaken #27, fabricate #29/#227 identity provisioning, configure #40 by documentation, synthesize #3 production KPI evidence, choose outbound licensing, treat a PR-head image PASS as protected-main/release authority, or write central .github, contextual-orchestrator, quarantine, AppGuardrail or EgressWeave source from this owner lane. Source copies, cross-service SQL and mutable sibling dependencies remain forbidden.
Related: #3, #5, #9, #27, #29, #36, #40, #66, #73, #227, #564, #566, #570, #572, #573, #574, #582, #714, #719, #721, #722, #723.
Activity
seonghobae commentedon Aug 6, 2026
Security acceptance clarification: result producer must be privilege-separated
PR #65 exact head
df9829aed39d8f447002b4eb411e7cab3285cb15currently bind-mounts the sole hostresult.jsonwritable and runs the validator plus repository-controlled validation subprocesses under the same non-root UID/GID. Descriptor-safe host reading, byte limits, schema validation, request rebinding, and zero-exit consistency do not by themselves authenticate the producer: same-UID untrusted code can attempt to keep a background writer alive and race/replace the final evidence file after the trusted entrypoint writes it.Treat the existing “result replacement” criterion as requiring a real adversarial proof, not only path/symlink stability tests:
PASSEDJSON before/during/after validator completion;This is tracked under #66 rather than opening a duplicate issue because #66 already owns runtime activation and adversarial result-replacement verification. It does not justify weakening or bypassing PR #65's current RED CI, independent approval, CodeRabbit, or branch-protection gates.
seonghobae commentedon Aug 6, 2026
2026-08-07 runtime-remediation assessment
PR #67 remains bound to exact head
7c4604ca25492b779cbb85b5b807e7bc989f42b0; no concurrent head change was observed before this write. Its fail-closed image scan remains correctly RED on five MEDIUM findings in the signedgcr.io/distroless/nodejs24-debian13runtime.Current upstream evidence does not support a safe same-family digest refresh:
nodejs24-debian13tracks Debian 13/trixie and is rebuilt from Debian updates: https://github.com/GoogleContainerTools/distrolessCVE-2026-5435remains unfixed for Debian trixie and is markedno-dsa: https://security-tracker.debian.org/tracker/CVE-2026-5435CVE-2026-5450is fixed only in Debian forky/sid, not trixie: https://security-tracker.debian.org/tracker/CVE-2026-5450CVE-2026-5928andCVE-2026-6238as open for trixie: https://security-tracker.debian.org/tracker/source-package/glibcCVE-2026-27171is fixed in forky/sid zlib but remains vulnerable withno-dsain trixie: https://security-tracker.debian.org/tracker/CVE-2026-27171A potential alternative is a signed, SBOM-attested Chainguard Node runtime. However, the current public
latesttrack is Node 26, the standard image specification reports a shell, and versioned Node 24/minimal variants require registry entitlement rather than being a verified drop-in public dependency:Therefore no branch change, vulnerability exception, VEX assertion, severity downgrade, or rerun-only remediation is justified. The safe next paths are:
PR #67 must remain draft and unmergeable until one of those paths passes without weakening the existing MEDIUM/HIGH/CRITICAL gate.
seonghobae commentedon Aug 7, 2026
Acceptance tightening from exact-head review of PR #67 at
95a9219e1087b1dc5d4a2fb3c8f8c2f0b4ca2b9e:The current
scratchimage's fully-static Node 24.19.0 executable is positively identified as Node by Syft and evaluated as a Node CPE by Grype, but that is not yet sufficient embedded-component evidence. Node's upstream build documentation states that dependencies are bundled into the Node binary by default, and Node exposes dependency versions throughprocess.versions. The current injected.note.packagedescribes only Node itself, so bundled OpenSSL, zlib, libuv, nghttp2, Brotli, c-ares, llhttp, SQLite, and any other native dependency can remain invisible as independently matched vulnerability subjects.Add these fail-closed acceptance requirements before publication/activation:
Primary sources to cite in the corresponding doctoring update: Node.js
BUILDING.mdfor bundled dependencies, Node.jsprocess.versionsfor runtime dependency-version inventory, and Grype's package/matcher/SBOM documentation for supported package identities and matching boundaries. This comment does not change #27/#29 governance gates or authorize merge/release.seonghobae commentedon Aug 17, 2026
2026-08-17 fresh owner-lane update: the protected exact-source prerequisite is now already integrated on
mainat29a64e144eda0fb52a25f3c682b3cbfa2a2dedf9. I audited stale #67 against its former #65 base and rebuilt only its image/supply-chain delta directly on current protected main as Draft #407 (feat/patch-validator-image-on-main, exact head0132a7c74eabc8782c8049409ca0cd3100dba5be). The clean successor preserves the credential-freenode_patch_verifyruntime, scratch/non-root execution, exact receipt/image/source binding, SBOM/component evidence, no-network smoke boundary, and exact production coverage; it also preserves current-main orchestrator/acquisition/security/coverage behavior rather than importing stale stack metadata. No outbound license annotation was added. Fresh #407 application CI, reviewer-ci, central Security Scan, andpatch-validator-imageevidence are still queued and therefore non-passing; predecessor #67 checks/reviews are not being transferred. #67 will remain open until #407 proves semantic/evidence parity on its unchanged exact head.seonghobae commentedon Sep 7, 2026
Fresh exact-head evidence narrows the current image-lane delay. PR #543 exact
b14b37ca12b3b6ae1999d250a393997ffff04dec, run34071938978, job101590775349is not waiting for runner assignment: GitHub-hosted runner1001730092started at2026-09-07T01:50:48Z, exact checkout/stale-head refusal/Trivy/Syft/Grype/toolchain/dependency materialization/Buildx all completed by01:51:17Z, and the job has remained insideBuild exact-head patch-validator imagesince then. Later smoke/SBOM/receipt steps have not started.The current #550 workflow gives that build a 150-minute step timeout inside a 180-minute job and uses shared
type=ghaBuildKit cache scopenoema-patch-validator-image; the Dockerfile intentionally rebuilds checksum-pinned OpenSSL 3.5.8 and fully-static Node 24.19.0 from source before the scratch runtime. Several current-main PR generations are simultaneously in the same image-build phase, so this is build-cost/cache-population throughput evidence, not a repository-wide hosted-runner outage.I am not changing the Dockerfile/runtime/security boundary or overlapping #550/#540 workflow owners from this issue. Any repair should preserve the static/non-root/scratch runtime and exact-source receipts. The next safe RCA is to compare BuildKit cache-hit/export evidence once the first current generation completes; if repeated current generations still rebuild the immutable Node/OpenSSL layer despite a populated exact cache, fix the cache-key/build graph in the canonical #550→#540 lane test-first rather than weakening image verification.
seonghobae commentedon Sep 8, 2026
Fresh operational RCA found a causal gap in the existing BuildKit cache claim and opened #558.
Protected
patch-validator-imageusedtype=gha,scope=noema-patch-validator-imagebut ran only onpull_request/workflow_dispatch. GitHub cache access is branch-scoped: sibling PR branches cannot restore each other's cache; they can restore current/base/default branch cache. That matches live evidence: #540 exact image build succeeded after ~104 minutes, while later sibling #547 again entered the long static Node build. Protectedmainhad no image-workflow push run to seed a default-branch cache.#558 uses TDD rather than weakening image verification: test-only
a67a5ab1f4b15ed5269497cfd1fd0c06cfc72a56makes missing main-cache seeding deterministic RED; current production exact2e83e1c6ad743adf0e4528383252c681eb6638ecadds onlypush: branches: [main](3 lines) to the existing workflow. All exact-head, static-runtime, isolation, SBOM, scanner, and receipt gates remain unchanged. The PR is Draft with fresh exact gates non-terminal.If #558 normally integrates, the protected merge commit will exercise the image workflow on
main, simultaneously providing the protected-main operational run this issue requires and seeding the default-branch cache available to later sibling PRs. A successful push run still does not itself authorize immutable registry publication, signing/attestation, activation, or release.seonghobae commentedon Sep 8, 2026
#558 refinement after the first repair: unconditional
push: mainwould have scheduled the 150-minute image lane on every unrelated protected merge. A second test-only RED (ec60444efd072afd7b58e988daa10269edea57b6) now requires protected-main seeding to be purpose-scoped; current exactf9f1445150969de9d278a0b0ae391a2d2e3b2a13addspathsonly for the workflow/Dockerfile/package lock and validator runtime/verifier authority. Because #558 itself changes the workflow path, its eventual protected merge still guarantees one protected-main operational image run and default-branch cache seed, while unrelated merges no longer create redundant long jobs.seonghobae commentedon Sep 8, 2026
2026-09-08 fresh cache-restore measurement update: the stale candidate SHAs in the issue body have been superseded by ordinary branch convergence. Current usable later-PR canary is #556 exact
860714cba46dba06260a5dce09d0e9152fcb0a8c, patch-validator-image run34197596517, job101968826382. The job was assigned to GitHub Actions runner1001773181; checkout, stale-head guard, Trivy, Syft/Grype, exact dependency materialization and Buildx setup all completed successfully.Build exact-head patch-validator imagestarted at2026-09-08T07:18:54Zand remained in progress at the fresh read.This is not yet cache-hit or cache-failure evidence. Protected seed run
34179912851took about 67 minutes in the build step, and the current build has not reached a terminal state or exposed final BuildKit evidence. Do not cancel or weaken the 150-minute static-runtime build solely from elapsed time. Once terminal, compare actual build duration/cache import evidence against the seed and separate Node/OpenSSL compilation from final exact-head layers before deciding whether a cache restoration defect exists.seonghobae commentedon Sep 8, 2026
Fresh post-seed measurement authority is now available from normally merged #556, superseding the old queued
bd481.../737b...candidate references in this issue.860714cba46dba06260a5dce09d0e9152fcb0a8c→ protected merge36e5cf957ee20a8bb3e19ff50fea6c97771d2ba134197596517, job101968826382: terminal SUCCESS; job assigned to GitHub-hosted runner, started2026-09-08T07:18:27Z, completed09:20:05ZBuild exact-head patch-validator image:07:18:54Z→09:18:18Z, 1h 59m 24s02:33:12Z→03:40:20Z)So the first valid later merged candidate is about 52m16s slower in the image-build step, not faster. This is evidence that the cache-performance acceptance is not demonstrated; it is not by itself proof that BuildKit failed to import/restore cache, because the available Actions metadata does not expose the build log/cache-hit lines. Do not call this a cache hit or cache miss from duration alone. The next causal action remains to retain/import explicit BuildKit cache-path evidence (or a deterministic cache-reuse receipt) so cache import, static Node/OpenSSL compilation, final layers and image load can be distinguished. Publication/signature/provenance/activation criteria remain open.
seonghobae commentedon Sep 9, 2026
Fresh owner-side finding (2026-09-09 KST): there is now a configuration-level reason not to treat the protected ~67-minute seed plus #559's ~69-minute sibling build as merely ambiguous timing. Protected
.github/workflows/patch-validator-image.ymlinvokesdocker buildx buildmanually with--cache-from=type=gha,scope=noema-patch-validator-image/--cache-to=type=gha,mode=max,..., but it has no step that exposes the GitHub Actions cache runtime URL/token to the later inline shell step. Docker's current official GHA-cache documentation explicitly distinguishes this case:docker/build-push-actionpopulates the URL/token automatically, while a manually invoked inlinedocker buildxcommand must manually expose the runtime variables. See https://docs.docker.com/build/cache/backends/gha/ and https://docs.docker.com/build/ci/github-actions/cache/.That is a source/config finding, not an elapsed-time inference. Do not call any current IN_PROGRESS job a cache miss from duration alone. The next repair lane should first add an executable RED contract that rejects a manual
type=ghainline build without an approved, exact-pinned runtime-auth exposure mechanism (or replace the manual build with an exact-pinned Docker-maintained build action that owns that transport). The GREEN must preserve--load,mode=max, the shared scope, exactvalidator_depscontext, exact source-revision label, static runtime, smoke/SBOM/scanner receipts and fail-closed behavior. It should also retain explicit cache import/export evidence so a later protected-main seed plus sibling PR can prove restoration rather than infer it.Do not add this repair to #559/#562/#563/#564: those live lanes own disjoint docs, reviewer dependency, and hourly-prompt paths, and each current PR already triggers the expensive image gate. Keep the cache repair as a separate path-isolated successor after the active source/doc lanes have enough terminal evidence to avoid manufacturing another simultaneous static-Node build.
seonghobae commentedon Sep 9, 2026
2026-09-10 KST authority refresh: #566 is no longer an open repair lane. It normally integrated as the GitHub-verified protected merge
main@e19e8a67cb02d30876a6f33795213591284e3ddb, preserving its authenticated GHA BuildKit cache/static-runtime/provenance repairs. Independent #570 exacte6a1d1ab14b5dbee6ed23ce74affd85698bcd40eand #573 exact3307e5d519b45c66767f406d56fc3ecd6e1dcaf6are both based on this protected source and each has application CI/reviewer-ci/Security Scan SUCCESS; their patch-validator-image jobs34360855737and34361013034remain assigned and in the exact image-build step after checkout, stale-head refusal, dependency materialization and Buildx setup succeeded. Do not classify elapsed build time as cache failure or transfer predecessor image evidence. #574 is independent Tool Capability/State work and now exact0e7b24dd...; it also consumes protected image authority without copying this implementation.