Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
188 commits
Select commit Hold shift + click to select a range
13ae4b5
feat(sandbox): restack patch-validator image on protected main
seonghobae Aug 17, 2026
9e521fa
feat(sandbox): expose image receipt verifier
seonghobae Aug 17, 2026
8d356de
test(sandbox): measure patch-validator image production
seonghobae Aug 17, 2026
0132a7c
feat(reviewer): expose image validation profile
seonghobae Aug 17, 2026
db19caf
test(image): reproduce exact-toolchain and WORKDIR failures
seonghobae Aug 17, 2026
0be65c4
fix(image): build dependencies with exact Node toolchain
seonghobae Aug 17, 2026
1a8f627
test(image): align contract with exact Node toolchain
seonghobae Aug 17, 2026
7773eaa
merge(main): refresh patch-validator image on live base
seonghobae Aug 17, 2026
08ae8e3
fix(test): remove unused patch runtime import
seonghobae Aug 17, 2026
ca13042
fix(ci): pin patch-validator evidence upload to Node 24 action
seonghobae Aug 17, 2026
8793e9b
test(ci): include patch-validator in upload-artifact inventory
seonghobae Aug 17, 2026
dd301d0
test(image): align static builder contract with retained npm tool
seonghobae Aug 17, 2026
4453f72
docs(changelog): record current patch-validator image evidence
seonghobae Aug 17, 2026
b656acb
test(ci): align upload-artifact pin with workflow
seonghobae Aug 17, 2026
027bdc5
test(image): require bundled Node license notice
seonghobae Aug 17, 2026
3d2e2f8
fix(image): retain Node runtime license notice
seonghobae Aug 17, 2026
9812503
test(image): require runtime license evidence
seonghobae Aug 17, 2026
08d2b2c
fix(image): retain runtime license evidence
seonghobae Aug 17, 2026
d194a79
docs(image): record Node license retention
seonghobae Aug 17, 2026
bb79114
merge main into patch-validator image after #409
seonghobae Aug 17, 2026
e4e3c12
merge current main into patch-validator image after #411
seonghobae Aug 17, 2026
81898d3
test(ci): require bounded patch-validator head retries
seonghobae Aug 17, 2026
6888682
fix(ci): bound transient patch-validator head retries
seonghobae Aug 17, 2026
a24ac57
test(ci): bound static validator build budget
seonghobae Aug 17, 2026
e4c6ce5
fix(ci): give static validator build bounded runway
seonghobae Aug 17, 2026
f78e1d0
Merge protected main into patch-validator image branch
seonghobae Aug 17, 2026
8ad405d
Merge protected main into patch-validator image branch
seonghobae Aug 17, 2026
b4b2781
Merge protected main into patch-validator image branch
seonghobae Aug 17, 2026
73809f0
Merge protected main into patch-validator image branch
seonghobae Aug 17, 2026
6096b7a
Merge protected main into patch-validator image branch
seonghobae Aug 17, 2026
cda4a56
test(image): reproduce npm install PATH failure
seonghobae Aug 17, 2026
4e878ca
fix(image): expose installed Node during npm install
seonghobae Aug 17, 2026
8858e8d
merge main into patch-validator image lane
seonghobae Aug 17, 2026
cbccd9e
merge protected main security fix into patch-validator image lane
seonghobae Aug 17, 2026
2df0be4
merge main workflow-registry hardening into patch-validator image lane
seonghobae Aug 18, 2026
d56a685
merge protected credential-capability contract into patch-validator i…
seonghobae Aug 18, 2026
e7a5639
merge protected runtime documentation into patch-validator image lane
seonghobae Aug 18, 2026
3b830e2
merge protected private-reporting evidence into patch-validator image…
seonghobae Aug 18, 2026
ae1c4b6
merge protected governance evidence into patch-validator image lane
seonghobae Aug 18, 2026
018e509
test(image): require static GCC runtime for Node link
seonghobae Aug 18, 2026
1317e7e
fix(image): install static GCC runtime for Node link
seonghobae Aug 18, 2026
f71ae68
test(image): preserve Unicode property escape probe
seonghobae Aug 18, 2026
679a50f
fix(image): preserve Unicode property escape probe
seonghobae Aug 18, 2026
930973c
test(patch-validator): align Unicode probe contract
seonghobae Aug 18, 2026
c43bb7e
test(image): require Grype DB before static scan
seonghobae Aug 18, 2026
ade1439
fix(image): materialize Grype DB before static scan
seonghobae Aug 18, 2026
d40bc87
test(image): require Grype scan of generated binary SBOM
seonghobae Aug 19, 2026
a2faf0f
test(image): restore current scanner contract after diagnostic RED
seonghobae Aug 19, 2026
65a1360
fix(image): scan the generated static-runtime SBOM
seonghobae Aug 19, 2026
8f8237c
test(image): lock Grype to generated binary SBOM
seonghobae Aug 19, 2026
b1fdbdd
test(image): retain Grype failure diagnostics
seonghobae Aug 19, 2026
8f103da
fix(image): retain bounded Grype diagnostics
seonghobae Aug 19, 2026
c2a130a
Merge protected main into patch-validator image lane
seonghobae Aug 19, 2026
c345668
Merge protected main into patch-validator image lane
seonghobae Aug 19, 2026
db8a82b
test(image): require valid isolated Grype config
seonghobae Aug 19, 2026
3a16197
fix(image): use valid isolated Grype config
seonghobae Aug 19, 2026
2726c78
Merge protected main into patch-validator image lane
seonghobae Aug 19, 2026
1ac98c4
test(image): align embedded Grype config contract
seonghobae Aug 19, 2026
03818ac
test(image): require complete embedded identity diagnostics
seonghobae Aug 19, 2026
df42a48
test(image): drop non-causal identity aggregation probe
seonghobae Aug 19, 2026
fcd08d9
test(image): bind Ada scanner identity
seonghobae Aug 19, 2026
0f9da62
fix(image): scan bundled Ada dependency
seonghobae Aug 19, 2026
4dda175
test(image): require reviewed c-ares runtime identity
seonghobae Aug 19, 2026
b5e218b
test(image): require reviewed c-ares and Brotli identities
seonghobae Aug 19, 2026
32ddb3e
test(image): require reviewed native identity catalog parity
seonghobae Aug 19, 2026
55091fa
test(image): make native identity parity regression executable
seonghobae Aug 19, 2026
bd810ec
feat(image): centralize reviewed embedded runtime identities
seonghobae Aug 19, 2026
3ce7d8a
feat(image): generate embedded runtime inventory from reviewed catalog
seonghobae Aug 19, 2026
f01d92e
test(image): cover reviewed inventory and disabled QUIC metadata
seonghobae Aug 19, 2026
c5b42d9
fix(image): generate runtime inventory from reviewed catalog
seonghobae Aug 19, 2026
09f957c
test(image): bind workflow to canonical embedded catalog
seonghobae Aug 19, 2026
db518b6
fix(image): verify embedded runtime with shared reviewed catalog
seonghobae Aug 19, 2026
e9f165e
test(image): verify shared runtime identity catalog end to end
seonghobae Aug 19, 2026
6dd09b1
test(image): bind GitHub PURLs to exact upstream tags
seonghobae Aug 19, 2026
9c1dc8a
fix(image): bind GitHub identities to exact release tags
seonghobae Aug 19, 2026
1e318ed
merge main into feat/patch-validator-image-on-main
seonghobae Aug 19, 2026
10d721b
merge main into feat/patch-validator-image-on-main
seonghobae Aug 19, 2026
515f130
test(image): require reviewed nbytes identity
seonghobae Aug 19, 2026
fa8fe6b
fix(image): review nbytes runtime identity
seonghobae Aug 19, 2026
948c23d
test(sandbox): classify ncrypto as Node-internal metadata
seonghobae Aug 19, 2026
2049a07
fix(sandbox): classify ncrypto as Node-internal metadata
seonghobae Aug 19, 2026
72dc043
merge(main): converge patch-validator image after #433
seonghobae Aug 19, 2026
245c6dd
test(sandbox): require reviewed simdjson identity
seonghobae Aug 19, 2026
070dd57
fix(sandbox): add reviewed simdjson identity
seonghobae Aug 19, 2026
daaa184
test(sandbox): require reviewed uvwasi identity
seonghobae Aug 19, 2026
d26684e
fix(sandbox): add reviewed uvwasi identity
seonghobae Aug 19, 2026
e230c0d
test(sandbox): require reviewed simdutf identity
seonghobae Aug 19, 2026
b6a10dc
fix(sandbox): add reviewed simdutf identity
seonghobae Aug 19, 2026
afc1a73
test(sandbox): require reviewed V8 CPE normalization
seonghobae Aug 19, 2026
b3c978f
fix(sandbox): bind patched V8 to upstream CPE
seonghobae Aug 19, 2026
b830aaf
test(sandbox): require reviewed zlib fork identity
seonghobae Aug 19, 2026
2a2f8af
fix(sandbox): add reviewed zlib fork identity
seonghobae Aug 19, 2026
558dd6b
test(supply-chain): bind embedded inventory to exact image digest
seonghobae Aug 19, 2026
05e258e
fix(supply-chain): validate embedded inventory image digest
seonghobae Aug 19, 2026
02fbd28
test(patch-validator): accept real Grype provider provenance digest
seonghobae Aug 20, 2026
c2a8701
fix(patch-validator): accept Grype provider provenance digest
seonghobae Aug 20, 2026
b0678a1
test(image): bind CPE findings to reviewed search identity
seonghobae Aug 20, 2026
a8da761
fix(image): bind CPE findings to reviewed query identity
seonghobae Aug 20, 2026
cfd3cc7
merge main into feat/patch-validator-image-on-main after #435
seonghobae Aug 20, 2026
2f92d41
test(supply-chain): reject ambiguous SBOM image identity
seonghobae Aug 20, 2026
82066ec
fix(supply-chain): reject ambiguous SBOM image identity
seonghobae Aug 20, 2026
3abd6c0
test(image): bind smoke receipt to repository
seonghobae Aug 20, 2026
44f7609
fix(image): bind smoke receipt to repository
seonghobae Aug 20, 2026
74bb911
test(supply-chain): reject replaced receipt paths after read
seonghobae Aug 20, 2026
6f4c411
fix(supply-chain): reject replaced receipt paths after read
seonghobae Aug 20, 2026
40e6d07
Merge protected main into patch-validator image hardening
seonghobae Aug 20, 2026
a823f20
test(image): require QUIC applicability evidence
seonghobae Aug 21, 2026
03a6d9e
fix(image): retain Node QUIC build evidence
seonghobae Aug 21, 2026
a812892
test(image): bind QUIC applicability to runtime metadata
seonghobae Aug 21, 2026
060f4ca
refactor(image): use existing QUIC runtime evidence
seonghobae Aug 21, 2026
923a206
test(image): require reviewed QUIC applicability layer
seonghobae Aug 21, 2026
c4ddfd2
fix(image): review QUIC-only OpenSSL applicability
seonghobae Aug 21, 2026
07a273e
fix(image): apply reviewed runtime applicability
seonghobae Aug 21, 2026
9436248
merge main into patch-validator image
seonghobae Aug 21, 2026
683cce0
test(image): require reviewed embedded CVE applicability
seonghobae Aug 21, 2026
484dd15
fix(image): apply exact reviewed embedded CVE scope
seonghobae Aug 21, 2026
213b414
test(image): match retained V8 scanner evidence
seonghobae Aug 21, 2026
e36ccde
fix(image): bind V8 applicability to scanner CPE version
seonghobae Aug 21, 2026
806964c
merge main into feat/patch-validator-image-on-main
seonghobae Aug 21, 2026
19536c1
merge protected main into feat/patch-validator-image-on-main
seonghobae Aug 21, 2026
7030f00
merge protected main into feat/patch-validator-image-on-main
seonghobae Aug 22, 2026
b92d333
docs(changelog): preserve patch-validator active PR truth
seonghobae Aug 22, 2026
b988107
merge: converge patch-validator image with protected main
seonghobae Aug 22, 2026
6006f5c
merge: converge patch-validator image with protected main
seonghobae Aug 22, 2026
336d97a
merge: preserve current main in patch-validator image lane
seonghobae Aug 22, 2026
2ce601a
docs(changelog): restore patch-validator image evidence entry
seonghobae Aug 22, 2026
171ca19
fix(changelog): preserve protected tail after image entry
seonghobae Aug 22, 2026
898b1a6
merge: inherit protected OIDC trust in patch-validator lane
seonghobae Aug 22, 2026
84bec28
test(patch-validator): bind CPE fixtures to reviewed scanner provenance
seonghobae Aug 22, 2026
50fd923
test(patch-validator): update static-runtime fixtures for reviewed CP…
seonghobae Aug 22, 2026
c2fa278
test(patch-validator): align changelog assertion with current evidenc…
seonghobae Aug 22, 2026
11c073c
merge: inherit latest protected OIDC trust in patch-validator lane
seonghobae Aug 22, 2026
5427bf7
test(patch-validator): follow reviewed identity validation order
seonghobae Aug 22, 2026
7ea5db8
test(patch-validator): bind CycloneDX fixture to Noema smoke repository
seonghobae Aug 22, 2026
75d890b
test(patch-validator): bind mutated CPE matches to scanner provenance
seonghobae Aug 22, 2026
9011b51
fix(patch-validator): remove unreachable identity error normalization…
seonghobae Aug 22, 2026
31d4b80
test(patch-validator): reject impossible Grype evidence dates
seonghobae Aug 22, 2026
74fb751
test(patch-validator): cover malformed Grype calendar and clock evidence
seonghobae Aug 22, 2026
86d8b08
fix(patch-validator): validate Grype timestamp calendars
seonghobae Aug 22, 2026
d901d90
test(patch-validator): cover RFC3339 calendar branches
seonghobae Aug 22, 2026
11f9a51
merge(main): inherit current protected OIDC trust
seonghobae Aug 22, 2026
aba4b81
merge(main): converge patch-validator on current protected main
seonghobae Aug 22, 2026
d130cc0
fix(branch): preserve protected scheduler evidence in patch-validator…
seonghobae Aug 22, 2026
f8fc040
docs(patch-validator): restore image evidence changelog
seonghobae Aug 22, 2026
fee3527
docs(patch-validator): preserve runner capability example
seonghobae Aug 22, 2026
ba8fc6e
merge(main): preserve runner timestamp integrity in patch-validator s…
seonghobae Aug 22, 2026
1ccdfc2
merge(main): preserve future readiness timestamp integrity in patch-v…
seonghobae Aug 22, 2026
cd9fe0a
merge(main): preserve acquisition audit output integrity in patch-val…
seonghobae Aug 22, 2026
6fd8f1a
merge(main): preserve saleable-readiness output integrity in patch-va…
seonghobae Aug 22, 2026
c6ad229
merge(main): preserve security-evidence output integrity in patch-val…
seonghobae Aug 22, 2026
65ab23a
merge(main): preserve deployment evidence output integrity in patch-v…
seonghobae Aug 22, 2026
b95498e
merge(main): preserve current OIDC trust in patch-validator stack
seonghobae Aug 22, 2026
0ec19f3
merge(main): converge patch-validator image on current protected main
seonghobae Aug 22, 2026
d64adf0
merge(main): converge patch-validator image after canonical head iden…
seonghobae Aug 22, 2026
c006915
merge(main): converge patch-validator image after retained evidence i…
seonghobae Aug 22, 2026
fe5c98c
chore(patch-validator): converge protected release-publication truth
seonghobae Aug 22, 2026
c570612
chore(patch-validator): converge protected publication identity
seonghobae Aug 22, 2026
b8c97be
chore(patch-validator): preserve acquisition audit mode
seonghobae Aug 22, 2026
b6acaa3
chore(patch-validator): converge protected subject identity
seonghobae Aug 22, 2026
0702d2c
chore(patch-validator): converge protected release identity
seonghobae Aug 22, 2026
b14003c
chore(patch-validator): converge current protected trust
seonghobae Aug 22, 2026
87a460d
chore(patch-validator): converge workflow evidence hardening
seonghobae Aug 22, 2026
0736220
chore(patch-validator): converge current protected main
seonghobae Aug 22, 2026
29afed3
chore(patch-validator): converge acquisition receipt integrity
seonghobae Aug 22, 2026
e045518
chore(patch-validator): converge protected release SBOM identity
seonghobae Aug 22, 2026
4056dc4
chore(patch-validator): converge workflow registry integrity
seonghobae Aug 22, 2026
d476fe2
test(patch-validator): reject future scanner provenance
seonghobae Aug 22, 2026
7ea74d5
fix(patch-validator): reject future scanner provenance
seonghobae Aug 22, 2026
dd69b97
chore(patch-validator): converge release evidence integrity
seonghobae Aug 22, 2026
e570b3a
chore(patch-validator): converge protected evidence hardening
seonghobae Aug 23, 2026
17d9529
chore(patch-validator): converge runner evidence hardening
seonghobae Aug 23, 2026
0e60ac4
docs(patch-validator): preserve current changelog lineage
seonghobae Aug 23, 2026
306edb3
docs(patch-validator): restore canonical changelog newline
seonghobae Aug 23, 2026
210bedd
chore(patch-validator): converge observability evidence hardening
seonghobae Aug 23, 2026
2c1b63b
chore(patch-validator): converge direct KPI evidence hardening
seonghobae Aug 23, 2026
62519d9
chore(patch-validator): converge direct KPI metric integrity
seonghobae Aug 23, 2026
e949c1c
chore(patch-validator): converge threshold KPI parser hardening
seonghobae Aug 23, 2026
a59a19b
chore(patch-validator): converge acquisition deployment integrity
seonghobae Aug 23, 2026
1ceb040
chore(patch-validator): converge canonical acquisition timestamp inte…
seonghobae Aug 23, 2026
d083fcb
chore(patch-validator): converge canonical release target identity
seonghobae Aug 23, 2026
843376e
chore(patch-validator): converge canonical release URL identity
seonghobae Aug 23, 2026
7f3472e
test(patch-validator): reject binary scans without Grype database pro…
seonghobae Aug 23, 2026
c70acb2
fix(patch-validator): bind binary scan to validated Grype database
seonghobae Aug 23, 2026
f55bf1b
chore(patch-validator): converge current protected main
seonghobae Aug 23, 2026
af9432c
chore(patch-validator): converge KPI source-method hardening
seonghobae Aug 23, 2026
62e6ddf
chore(patch-validator): converge current evidence integrity truth
seonghobae Aug 23, 2026
c1d8ca4
chore(patch-validator): preserve pilot readiness truth
seonghobae Aug 23, 2026
8714900
chore(patch-validator): converge pilot readiness main
seonghobae Aug 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
597 changes: 597 additions & 0 deletions .github/workflows/patch-validator-image.yml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- strict production KPI provenance를 fail-closed로 강화한다. `collectedAt`은 canonical UTC 시각만 허용하고 미래·존재하지 않는 달력값을 거부하며, `records`는 coercion 없는 양의 safe-integer JSON number로 authenticated log record count와 일치해야 한다. production log는 `O_NOFOLLOW`로 연 verified regular-file descriptor의 identity·size·mode·mtime·ctime을 재검증하면서 동일 verified bytes로 snapshot을 생성해 symlink·pathname replacement·descriptor drift가 KPI authority를 제조하지 못하게 한다.
- 인수 준비성 감사의 buyer/data-room 증거 경계를 실패-폐쇄로 강화한다. `updated_at`은 canonical ISO date 또는 timezone-bearing timestamp만 허용하고 존재하지 않는 달력값·비정규 형식·미래 시각을 거부하며, 명시된 evidence max-age 설정과 매출·고객·LOI·비율 지표는 coercion 없이 유효 도메인을 만족해야 한다. immutable release asset의 `bytes`도 실제 양의 safe-integer JSON number만 인정해 문자열·범위 밖 값이 매각 준비 증거를 제조하지 못하게 한다.
- 루트 `README.md`를 구매자/운영자 표면으로 재작성한다. 제품 정의, 단독 실행, 호스트 호출(HTTP API·`contracts/orchestrator-gateway.json`), 운영 설정을 앞에 두고 naruon·곁(gyeot) 허브-리프 호출을 지원 경로로 문서화한다. CloudAgent/OpenCode 절차, PR 스택, exact-head CI, writer/agent 경계는 `CONTRIBUTING.md`와 `docs/development/contributor-and-agent-procedure.md`로 옮기며 삭제하지 않는다. `test/readme-customer-facing.test.ts`가 README에 봇 매뉴얼 잔여가 남지 않는지 고정한다.
- repository-owned patch-validator image는 Node.js 24.19.0을 fully static으로 빌드한 `scratch` runtime을 사용하고, `process.versions` 기반 embedded dependency inventory, exact image SHA-256, CycloneDX/Syft/Grype/Trivy evidence, no-network/read-only/non-root smoke를 동일 exact-head receipt에 결합한다.
- 비리뷰 LLM 작업인 `hourly-product-development`를 리뷰와 동일한 `contextual-orchestrator` 게이트웨이 계약(`NOEMA_LLM_API_URL` `/v1`, 모델 별칭 `contextual-orchestrator`, 전용 `NOEMA_LLM_API_KEY`)으로 전환한다. Llama Nemotron → Nemotron Super → DeepSeek 순차 NIM 후보 폴백과 `NVIDIA_NIM_API_KEY` 직접 호출을 제거하고, 공유 `scripts/verify-orchestrator-gateway.mjs`가 `/healthz` 신원과 직접 공급자 호스트를 실패-폐쇄한다. 리뷰어의 `NOEMA_FALLBACK_*` / PydanticAI `FallbackModel` 순차 폴백도 제거해 남은 설정은 실패-폐쇄한다. 동일 계약을 `contracts/orchestrator-gateway.json`으로 공개해 `ContextualWisdomLab/naruon` 판단·결정 에이전트가 1급 소비자로 재사용할 수 있게 한다. naruon 배선은 별도 저장소 PR이다. 상위 공급자 키는 오케스트레이터 KV에 남기며 OIDC 토큰 중개·App 신원·3-runner 샌드박스 경계는 유지한다.
- 검증된 active-orphan 워크플로 하나를 운영자가 호출할 수 있는 `operations:workflow-registry-disable` 경로를 추가한다. 저장소와 워크플로 ID를 `NOEMA_MAINTAINER_TOKEN_PATH` 위임 토큰 파일 읽기 전에 검사하고, 신선한 전체 레지스트리 감사·즉시 live refresh·프로세스 로컬 plan·보호된 main/워크플로 재검증·사후 전체 감사 봉투(`schema_version` 1, `PASS`/`FAIL`, `remaining_failure_codes`, `remaining_active_orphan_ids`)를 통과한 뒤에만 영수증을 유지한다. 성공 종료와 `post_audit_status: FAIL`은 해당 ID만 `disabled_manually`가 되었고 레지스트리는 아직 더럽을 수 있음을 뜻하므로, 운영자는 영수증의 `remaining_active_orphan_ids`로 다음 단일 호출을 이어간다. 배치 비활성화·자가 수리 워크플로·거버넌스 완화는 추가하지 않으며 호출 계약은 doctoring에 기록한다.
- 읽기 전용 `operations:runner-assignment` audit를 추가해 exact workflow run/source head에 대한 runner assignment를 완전 pagination으로 진단하고, 신선한 unassigned queue는 bounded grace 이후 실패-폐쇄한다. 이 증빙은 runner assignment와 required Check/CI, formal review, merge, release, deployment authority를 분리하며 assigned runner 이후 workflow failure를 성공으로 승격하지 않는다.
Expand Down
99 changes: 99 additions & 0 deletions Dockerfile.patch-validator
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# syntax=docker/dockerfile:1.7@sha256:a57df69d0ea827fb7266491f2813635de6f17269be881f696fbfdf2d83dda33e

FROM alpine:3.24.1@sha256:79ff19e9084a00eece421b2523fb93e22d730e2c0e525905de047e848e56d95f AS node_builder

ARG NODE_VERSION=24.19.0
ARG NODE_SOURCE_SHA256=f6d95e10a0431ee1067fc6aabe9f762908b4716dd35324e1ddb4b1466b76659f

RUN apk add --no-cache \
binutils-gold \
g++ \
gcc \
libgcc \
libgcc-static \
linux-headers \
make \
python3 \
py3-setuptools \
xz

ADD --checksum=sha256:${NODE_SOURCE_SHA256} https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}.tar.xz /tmp/node.tar.xz

RUN mkdir -p /usr/src/node \
&& tar -xJf /tmp/node.tar.xz --strip-components=1 -C /usr/src/node

ENV PATH="/opt/node/bin:${PATH}"
WORKDIR /usr/src/node

RUN ./configure \
--prefix=/opt/node \
--fully-static \
--with-intl=small-icu \
--without-corepack \
--disable-single-executable-application \
&& make -j"$(getconf _NPROCESSORS_ONLN)" V= \
&& make install \
&& test "$(/opt/node/bin/node --version)" = "v${NODE_VERSION}" \
&& test "$(/opt/node/bin/npm --version)" = "11.17.0" \
&& /opt/node/bin/node --input-type=module --eval='/\p{ID_Continue}/u.test("a")' \
&& ! readelf -l /opt/node/bin/node | grep -q 'Requesting program interpreter' \
&& ! readelf -d /opt/node/bin/node | grep -q '(NEEDED)' \
&& strip /opt/node/bin/node \
&& printf '%s\n' \
'{"name":"node","version":"24.19.0","cpe":"cpe:2.3:a:nodejs:node.js:24.19.0:*:*:*:*:*:*:*","license":"MIT","type":"binary","architecture":"x86_64","appCpe":"cpe:2.3:a:nodejs:node.js:24.19.0:*:*:*:*:*:*:*","system":"nodejs","vendor":"nodejs","sourceRepo":"https://github.com/nodejs/node"}' \
>/tmp/node-package-note.json \
&& objcopy \
--add-section .note.package=/tmp/node-package-note.json \
--set-section-flags .note.package=noload,readonly \
/opt/node/bin/node \
&& readelf -p .note.package /opt/node/bin/node \
| grep -Fq 'cpe:2.3:a:nodejs:node.js:24.19.0:*:*:*:*:*:*:*' \
&& test "$(/opt/node/bin/node --version)" = "v${NODE_VERSION}" \
&& /opt/node/bin/node --input-type=module --eval='/\p{ID_Continue}/u.test("a")' \
&& ! readelf -l /opt/node/bin/node | grep -q 'Requesting program interpreter' \
&& ! readelf -d /opt/node/bin/node | grep -q '(NEEDED)'
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed

FROM node_builder AS dependencies

WORKDIR /build

COPY package.json package-lock.json ./
RUN npm_config_os=wasip1-threads npm_config_cpu=wasm32 \
npm ci --include=optional --ignore-scripts --no-audit --no-fund \
&& npm pkg delete devDependencies.@cloudflare/workers-types devDependencies.wrangler \
&& npm_config_os=wasip1-threads npm_config_cpu=wasm32 \
npm prune --include=optional --ignore-scripts --no-audit --no-fund \
&& test -f node_modules/typescript/bin/tsc \
&& test -f node_modules/vitest/vitest.mjs \
&& test -f node_modules/@vitest/coverage-v8/package.json \
&& test -f node_modules/@rolldown/binding-wasm32-wasi/package.json \
&& test -z "$(find node_modules -type f -name '*.node' -print -quit)" \
&& test ! -e node_modules/@cloudflare/workers-types \
&& test ! -e node_modules/wrangler \
&& test ! -e node_modules/workerd \
&& test ! -e node_modules/miniflare

FROM scratch AS runtime

ARG SOURCE_REVISION
LABEL org.opencontainers.image.source="https://github.com/ContextualWisdomLab/noema" \
org.opencontainers.image.revision="${SOURCE_REVISION}" \
org.opencontainers.image.title="Noema Patch Validator" \
org.opencontainers.image.description="Credential-free exact-head text patch validation runtime" \
org.opencontainers.image.documentation="https://github.com/ContextualWisdomLab/noema/blob/main/docs/patch-validator-image.md"

ENV NAPI_RS_FORCE_WASI=error

USER 65532:65532
WORKDIR /workspace

COPY --from=node_builder --chown=65532:65532 /opt/node/bin/node /nodejs/bin/node
COPY --from=node_builder --chown=65532:65532 --chmod=0444 /usr/src/node/LICENSE /licenses/node/LICENSE
COPY --from=dependencies --chown=65532:65532 /build/node_modules /opt/noema/node_modules
COPY --chown=65532:65532 patch-validator/entrypoint.mjs /opt/noema/entrypoint.mjs
COPY --chown=65532:65532 patch-validator/validate-patch.mjs /opt/noema/validate-patch.mjs
COPY --chown=65532:65532 patch-validator/runtime.mjs /opt/noema/runtime.mjs
COPY --chown=65532:65532 patch-validator/validator-tsconfig.json /opt/noema/validator-tsconfig.json
COPY --chown=65532:65532 patch-validator/validator-vitest.config.mjs /opt/noema/validator-vitest.config.mjs

ENTRYPOINT ["/nodejs/bin/node", "--input-type=module", "--eval", "import { runCli } from '/opt/noema/runtime.mjs'; import { runEntrypoint } from '/opt/noema/entrypoint.mjs'; process.exitCode = runEntrypoint({ runCliImpl: runCli, writeDiagnostic: (message) => process.stderr.write(message) });"]
10 changes: 10 additions & 0 deletions Dockerfile.patch-validator.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
*
!package.json
!package-lock.json
!patch-validator/
patch-validator/*
!patch-validator/entrypoint.mjs
!patch-validator/validate-patch.mjs
!patch-validator/runtime.mjs
!patch-validator/validator-tsconfig.json
!patch-validator/validator-vitest.config.mjs
69 changes: 69 additions & 0 deletions docs/doctoring/patch-validator-embedded-scan-assessment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Doctoring amendment: raw embedded-runtime scanner evidence

## Status

- **Decision date:** 2026-08-07
- **Applies to:** PR #67 patch-validator static-runtime evidence
- **Release claim:** none
- **Production activation claim:** none
- **Workflow migration state:** direct raw per-component scanning is implemented for the reviewed identity catalog; integrated acceptance remains fail-closed until the exact runtime component set is fully reviewed and exact-head verification passes

This amendment supersedes the earlier locally synthesized completion model. The exact-head regressions demonstrated that a zero-match component could look complete without proving that Grype evaluated the reviewed package identity, and that independently valid per-component results could still be substituted across artifacts or vulnerability-database snapshots.

## Finding

An empty vulnerability match list is negative finding evidence, not proof that a particular package identity was evaluated. The earlier workflow constructed a local completion object after an aggregate SBOM scan and used generic package identities for native dependencies. That was insufficient for a fully static Node runtime because an unsupported or weak identity could produce zero matches without distinguishing “evaluated and clean” from “no applicable matcher.”

The workflow now builds its inventory only from a bounded reviewed identity catalog, updates the Grype vulnerability database once, disables per-component automatic database updates, scans each reviewed PURL or CPE directly, and retains each raw scanner result. Any `process.versions` dependency without a reviewed identity aborts evidence generation instead of being omitted, converted to a generic package, or marked locally complete. The verifier independently rejects unsupported identities, synthetic completion fields, mismatched match artifacts, blocking findings, and database drift.

## Control decision

The embedded-runtime evidence boundary uses a **reviewed identity catalog** keyed by the exact `process.versions` key. A bundled dependency is eligible for scanning only when the catalog binds that key to the expected inventory name and to exactly one scanner-supported identity form:

1. an exact npm PURL whose package name and version match the catalog and `process.versions`; or
2. an exact CPE 2.3 application identity whose reviewed vendor, product, and version match the catalog and `process.versions`.

Unknown keys, generic PURLs, wildcard or placeholder CPE vendors/products, arbitrary aliases, and identities inferred from receipt-controlled fields are explicit release blockers. Current catalog entries are deliberately bounded; adding a new native dependency requires evidence review rather than automatic identity fabrication.

Every bundled dependency must carry **raw Grype** JSON for a direct scan of that exact reviewed identity. The verifier requires:

- scanner descriptor `grype` at the pinned version;
- scanner source type consistent with PURL or CPE and a source target exactly equal to the reviewed identity;
- a valid vulnerability-database status record;
- bounded provider metadata with capture timestamps and input digests;
- no ignored matches;
- every reported match artifact bound back to the same reviewed PURL or CPE and exact component version;
- no MEDIUM, HIGH, CRITICAL, or UNKNOWN finding; and
- the **same vulnerability database** identity across every component scan.

The canonical shared database identity is derived from the database schema/build metadata plus sorted provider capture/input metadata and is retained in verification output. This makes database drift visible rather than allowing two components in one acceptance decision to be evaluated against different snapshots.

The workflow updates Grype's vulnerability database once, freezes per-component auto-update for the scan set, invokes each reviewed PURL or CPE directly, and retains the raw scanner result. A local “completed” flag, aggregate-only SBOM result, scanner process exit alone, or grouped synthetic result is not evidence of component evaluation. The workflow and verifier both fail closed when the reviewed catalog is incomplete; a red exact-head action caused by an unmapped runtime dependency is therefore expected evidence of a missing review, not a reason to weaken the gate.

## Why this is stricter than zero findings

Grype's *Supported scan targets* documentation treats individual PURL and CPE identities as explicit scan targets. Its vulnerability-database documentation also explains that the database is locally cached and can be updated explicitly. Noema therefore binds acceptance to the literal scanner target and one shared database snapshot rather than inferring assessment from an empty match array.

The National Vulnerability Database maintains the Official Common Platform Enumeration (CPE) Dictionary. Noema treats an authoritative NVD CPE mapping as reviewed identity evidence where a CPE is used; a merely syntactically valid CPE is not sufficient. For example, NVD records OpenSSL under vendor/product `openssl:openssl`, and NVD's analysis of CVE-2026-40170 maps ngtcp2 through reviewed CPE configurations including `nghttp2:ngtcp2` while identifying 1.22.1 as the fixed floor. Those mappings are controls, not heuristics generated from a package name at runtime.

Node.js documents `process.versions` as version information for Node.js and its dependencies. Noema uses it as the exact-runtime dependency declaration that the reviewed component set must match, not as a cryptographic proof of binary composition. `modules` and `napi` remain explicitly reviewed runtime metadata rather than fabricated vulnerable packages.

## Residual risk

Raw scanner evidence does not prove that vulnerability databases are complete or that every upstream project has an authoritative ecosystem identity. Catalog omissions therefore fail closed. The scanner binary, database acquisition path, hosted runner, workflow source, CPE/PURL review process, and upstream advisory coverage remain part of the trust chain. Future registry publication must separately bind signature, SBOM, vulnerability evidence, SLSA provenance, and the published digest before release acceptance.

## APA 7th references

Anchore. (2026). *Supported scan targets*. Anchore Open Source. https://oss.anchore.com/docs/guides/vulnerability/scan-targets/

Anchore. (2026). *Vulnerability database*. Anchore Open Source. https://oss.anchore.com/docs/guides/vulnerability/database/

National Institute of Standards and Technology. (2025). *Official Common Platform Enumeration (CPE) dictionary*. National Vulnerability Database. https://nvd.nist.gov/products/cpe

National Institute of Standards and Technology. (2026). *CVE-2026-40170 detail*. National Vulnerability Database. https://nvd.nist.gov/vuln/detail/CVE-2026-40170

Node.js contributors. (2026). *Process: `process.versions`* (Node.js v24 documentation). OpenJS Foundation. https://nodejs.org/download/release/latest-v24.x/docs/api/process.html#processversions

OWASP Foundation. (2025). *CycloneDX specification 1.7*. https://cyclonedx.org/specification/overview/

Souppaya, M., Scarfone, K., & Dodson, D. (2022). *Secure Software Development Framework (SSDF) version 1.1: Recommendations for mitigating the risk of software vulnerabilities* (NIST Special Publication 800-218). National Institute of Standards and Technology. https://doi.org/10.6028/NIST.SP.800-218
Loading
Loading