From 5f6935cfbda98f01a7fbe70be9ec3ad170210e71 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 14:39:18 +0900 Subject: [PATCH 01/14] test: require protected current media authority docs --- ...-current-lifecycle-media-authority.test.ts | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 test/procedural-current-lifecycle-media-authority.test.ts diff --git a/test/procedural-current-lifecycle-media-authority.test.ts b/test/procedural-current-lifecycle-media-authority.test.ts new file mode 100644 index 000000000..a4373326a --- /dev/null +++ b/test/procedural-current-lifecycle-media-authority.test.ts @@ -0,0 +1,31 @@ +import { readFileSync } from "node:fs"; + +import { describe, expect, it } from "vitest"; + +describe("protected procedural current-lifecycle media documentation authority", () => { + it("records protected #704 without promoting Workflow / Task or production authority", () => { + const baseline = readFileSync("docs/product-technical-gap-baseline.md", "utf8"); + const changelog = readFileSync("CHANGELOG.md", "utf8"); + const source = readFileSync("src/agent-runtime/procedural-current-lifecycle.ts", "utf8"); + + expect(changelog).toContain("Protected #704"); + expect(changelog).toContain("42b15e865bdf88fde622c3bba2c0b123770d18be"); + expect(changelog).toContain("e8c2002e5af8fa5611880091dab81916bb716c35"); + expect(changelog).toContain("application/json; charset=utf-8"); + expect(changelog).toContain("invalid_workflow_state_response"); + expect(changelog).toContain("best-effort cleanup"); + + expect(baseline).toContain( + "merged PR #704 exact `42b15e865bdf88fde622c3bba2c0b123770d18be`", + ); + expect(baseline).toContain("GitHub-verified normal merge `e8c2002e5af8fa5611880091dab81916bb716c35`"); + expect(baseline).toContain("application/json; charset=utf-8"); + expect(baseline).toContain("stable `invalid_workflow_state_response`"); + expect(baseline).toContain("best-effort cleanup"); + expect(baseline).toContain("immutable release"); + expect(baseline).not.toContain("#704 transfers Workflow / Task lifecycle authority to Agent Runtime"); + + expect(source).toContain("function isJsonMediaType(value: string | null): boolean"); + expect(source).toContain("Noema current workflow-state response used an unsupported media type"); + }); +}); From 0ee17ac90708ef9266a0984aa256f96586d10a70 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 14:52:37 +0900 Subject: [PATCH 02/14] docs: record protected current workflow media admission --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48bfccd82..ee55d9291 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ - Add a Noema-owned exact-claim evidence receipt contract whose execution and research producers serialize one canonical artifact that binds every receipt semantic field, including command/result/isolation/network or source revision/excerpt/retrieval policy. Admission accepts only a receipt ID from untrusted model output. The owner API first verifies the exact authenticated OpenCode-handoff manifest digest, canonical envelope bytes, reviewed producer-to-kind policy, and repository/head/workflow/run/attempt identity before it can construct an immutable typed index; admission then reconstructs each canonical artifact and verifies time/claim/artifact identity. The version-2 manifest now binds a separate producer-authenticated `ClaimEvidenceRequirement` containing the exact claim, independently required evidence kind, and `context` or `finding` publication authority. Raw current-head source lines are context only: they are withheld from finding-reference prompts and cannot publish a finding or `request_changes`; an explicitly producer-authorized source finding remains usable and retains exact path/line checks. Finding-free model `request_changes` and `blocked` verdicts cannot bypass receipt admission to publish a vacuous blocking review. Requirement/receipt kind mismatch, fixed-artifact semantic substitution, caller-supplied receipt dictionaries, model self-classification, stale identities, cross-kind receipts, marker-only sandbox output, noncanonical artifact bytes, and expired receipts fail closed before the GitHub publisher. This remains the owner prerequisite for ContextualWisdomLab/.github#1641 and issue #555. The reviewed `sandboxed_verify` adapter exists in owner source, but its actual central stdout/stderr/marker-to-manifest wiring and the trusted research producer are not yet integrated; exact-head hosted GREEN, immutable release, and the verified central consumer bump remain required. ## Unreleased +- Protected #704 exact `42b15e865bdf88fde622c3bba2c0b123770d18be`, integrated by GitHub-verified normal merge `e8c2002e5af8fa5611880091dab81916bb716c35`, requires Agent Runtime to admit private Workflow / Task Execution current-state evidence only when a successful response declares the owner-emitted JSON media type `application/json; charset=utf-8` (media-type parameters remain acceptable). Missing or non-JSON media types fail closed with the stable `invalid_workflow_state_response` classification before bounded parsing. Rejected-media body cancellation is best-effort cleanup: synchronous throw, asynchronous rejection, null body, or non-settling cleanup cannot replace or delay the fail-closed decision. The existing fixed 1 MiB retained buffer, 10-second absolute read deadline, fatal UTF-8/JSON admission, canonical execution binding, and reader-lock lifecycle remain unchanged. Workflow / Task lifecycle truth, provider/model routing, destination/outbound policy, credential authority, quarantine/security, Policy / Approval, State / Checkpoint, release/deployment, and foreign-domain authority remain with their existing owners; protected source/checks/merge are not an immutable release, deployed Durable Object recovery, or production p95/heap evidence. - Protected #702 exact `2b31805eb2b81b6078fefe1ebcce8007b6ca5169`, integrated by GitHub-verified normal merge `cf7f4279dbf83213557e987f0ee8fb52b12fcccf`, behaviorally verifies Noema's shared Cloudflare deploy/status/recovery request boundary rather than relying on source-text header presence. The three direct clients use `requestCloudflareJson`; executable tests observe the actual `fetch` request, require `Accept: application/json` and the owner bearer to override conflicting caller values, preserve unrelated caller headers such as `Content-Type`, enforce the existing 120-second request deadline, and continue into the 1 MiB bounded JSON reader. `Accept` remains request-side representation preference rather than provider response-shape authority. Cloudflare/provider truth, destination/outbound policy, credential authority, quarantine/security, recovery-state, release/deployment and foreign-domain authority remain with their existing owners; protected source/test/CI evidence is not an immutable release, production deployment, controlled recovery rehearsal, deployed p95/heap or production KPI evidence. - PR #701 source exact `80d3d579ad4a08ccb3f21e2735c7fb0bebc7b492` makes Noema's direct Cloudflare deploy/status/recovery control-plane clients explicitly negotiate machine-readable Cloudflare-generated errors with `Accept: application/json` before their existing 1 MiB bounded JSON response reader. Cloudflare's 2026-05-05 error-response contract documents HTML as the default for generated errors when `Accept` is absent or `*/*`, and structured JSON when `application/json` is requested; Noema still treats negotiation as preference rather than shape authority and retains fail-closed fatal UTF-8/JSON/provider-error admission. Existing 120-second request bound, fixed retained buffer, reader/cancellation lifecycle, exact recovery-state checks, credential capability, destination/outbound policy, Cloudflare/provider authority and release/deployment authority remain unchanged. This source PR is not an immutable release, production deployment, controlled recovery rehearsal, or deployed p95/heap evidence. - Protected #699 bounds Agent Runtime's private Workflow / Task Execution current-state response read at exact source `e52408745efc73351c098227ae4c85c309fdd0c9` with a 10-second absolute read deadline. Deadline expiry preserves the stable `invalid_workflow_state_response` fail-closed contract, requests reader cancellation only as best-effort cleanup, clears the deadline timer, and releases the reader lock on every terminal path. The existing fixed 1 MiB retained buffer, byte ceiling, fatal UTF-8/JSON admission, canonical execution binding, and Workflow / Task Execution ownership remain unchanged. Workflow / Task lifecycle, provider/model routing, outbound, credential, quarantine/security, release/deployment, and foreign-domain authority stay with their existing owners; this protected source is not an immutable release, deployed Durable Object recovery, or production p95/heap evidence. PR #699. @@ -143,4 +144,4 @@ - `/exchange` 401 응답에 `WWW-Authenticate: Bearer realm="noema"` challenge를 추가하고 인증 누락은 `invalid_request`, 잘못된 토큰은 `invalid_token`으로 구분. - `x-request-id`/`x-correlation-id` 및 client IP 계열 헤더를 길이/문자 기준으로 제한해 로그 오염과 rate-limit key 폭주를 방지. - `KRW 2,000,000,000` 매각 가능성 Goal 등록서, buyer due diligence index, library/submodule 경계 판단서를 추가하고 `npm run acquisition:audit`로 ARR/LOI/이전성/saleable evidence를 실패-폐쇄 방식으로 검증. -- Protected #695 normalizes synchronous reader acquisition on the contextual-orchestrator `/healthz` response consumer at exact source `c9d526093e543167645383e937096fd089b337f8`. If a locked or otherwise non-stream-readable response body makes `response.body.getReader()` throw synchronously, Noema fails closed with `contextual-orchestrator health response body is not stream-readable` instead of leaking a runtime-specific stream exception. The existing 65,536-byte ceiling, optional caller-supplied deadline with no invented default timeout, fixed retained buffer, best-effort cancellation, fatal UTF-8, duplicate-key/JSON admission, and reader-lock lifecycle after successful acquisition remain unchanged. Contextual-orchestrator service/provider/model routing, credentials, outbound authority, quarantine/security authority, release/deployment authority, and foreign-domain truth remain with their existing owners; protected source is not an immutable release or deployed availability/p95/recovery evidence. PR #695. +- Protected #695 normalizes synchronous reader acquisition on the contextual-orchestrator `/healthz` response consumer at exact source `c9d526093e543167645383e937096fd089b337f8`. If a locked or otherwise non-stream-readable response body makes `response.body.getReader()` throw synchronously, Noema fails closed with `contextual-orchestrator health response body is not stream-readable` instead of leaking a runtime-specific stream exception. The existing 65,536-byte ceiling, optional caller-supplied deadline with no invented default timeout, fixed retained buffer, best-effort cancellation, fatal UTF-8, duplicate-key/JSON admission, and reader-lock lifecycle after successful acquisition remain unchanged. Contextual-orchestrator service/provider/model routing, credentials, outbound authority, quarantine/security authority, release/deployment authority, and foreign-domain truth remain with their existing owners; protected source is not an immutable release or deployed availability/p95/recovery evidence. PR #695. \ No newline at end of file From d12ca3b87c3b76d56232d75713e2f65951908cba Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 14:54:32 +0900 Subject: [PATCH 03/14] docs: converge protected current workflow media authority --- docs/product-technical-gap-baseline.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 9b7e4e998..878dbbc27 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -8,7 +8,7 @@ Current protected source는 mutation·merge·release 시점에 live protected `m Dated central control-plane observation for this repair는 central `.github/main@cb0872c9a20d5584703dffacca65c096fc034c6c`다. Noema runtime의 reviewed immutable central consumer pin은 `c9052e607e5f3cc76e73207e7786b21500721b79`이고 runtime authority 표현은 `ALLOWED_WORKFLOW_SHA = c9052e607e5f3cc76e73207e7786b21500721b79`다. Moving foreign head와 reviewed immutable pin을 같은 권위로 취급하지 않으며 central moving head가 전진했다고 consumer pin을 자동 승격하지 않는다. -Protected history에는 merged PR #535 exact `82b20b293f0a5f0ac0e69857c1b61dddfe478491`, merged PR #540 exact `05bc2d47c3899ebe17538070f9a30172f90307ac`, merged PR #542 exact `ca839298fcaeec409091dc909789b6f87eb67fdc`, merged PR #547 exact `30b7e7e5cdab8de65715834a16f994b2047eafa6`, merged PR #550 exact `f2ec2dc6709814070cc3e3d6932ce280aee966db`, merged PR #553 exact `3bd9f543e97ce856f78b1c608141436298ce9e74`, merged PR #558 exact `2f91bf8641212ecae435b5fbcc9084cc0acd6295`, merged PR #556 exact `860714cba46dba06260a5dce09d0e9152fcb0a8c`, merged PR #560 exact `5aab7c098f3478069127f34e398326415ec599a4`, merged PR #582 exact `0f20a4dc78e423fd5df49e137a4eb286c7075ea4`, documentation-authority integration #583, protected procedural graph source #585/#586, documentation convergence #587/#588/#590/#595, workflow-backed current-state integration #589, procedural decision/evaluation/authentication integrations #591/#592/#593/#594/#596, State / Checkpoint history #597, Policy / Approval CAS #601, publication preflight #603, Workflow / Task exact-object operability integration #605, documentation-authority convergence #606, merged PR #607 exact `0afd68d2e33b7fd9be2307ba78b370b534cc0f54`, merged PR #610 exact `0a516bc54d682817ffea3206ec8b24b214aa94ea`, merged PR #612 exact `a919be3bc2a04068e25a4592e0c9c26f8e63534b`, merged PR #614 exact `77c5116a2e58e8a154ee893a3825da19c9c1f357`, merged PR #616 exact `da8461f1f5a6d02d926dd295fc88abe2c6167dfa`, documentation-authority convergence PR #617 exact `38b3b56837d875d19ae458f3f5491951ad7afb1c`, merged PR #618 exact `fb166ec6ecc769a19fd4ae4502f6d0994fc89e33`, merged PR #620 exact `b746846e4890c84b568bb29937594e1b17364fa1`, documentation-authority convergence #639, merged PR #640 exact `72ff4897822b5a8122540509346be4f3278a1379`, merged PR #641 exact `73f13b3a3826c5d6f7aafc89d1ff23747f8cf8e9`, merged PR #642 exact `3427e5a66d7a0ea9379ddc7915ba2b3d1872c492`, merged PR #643 exact `b13903e3208232086871d7f117f8f20e753eb583`, merged PR #644 exact `79a89f5775d0fb56de9f1908c1927df0b498b70f`, merged PR #645 exact `1b4dc38581e99b92342769dd03059f5015ee9f04`, merged PR #646 exact `3005086fca2c6376fae951b774230fa1c06ba587`, merged PR #647 exact `ea3a36bc65df88153aa69a05e3144f0b5352b5a6`, merged PR #648 exact `133ce20c4bb7fb9ba05e3e4bedeb0492334faf38`, merged PR #649 exact `f334f40193da8811a6e15efcb2d589aa80104931`, merged PR #650 exact `f59fce008a4da70f89e9927f692b823506594ed5`, documentation-authority convergence #651, merged PR #652 exact `23fabd95f3ef886c6bef0ae9ff6ead50dc0ce342`, documentation-authority convergence PR #653 exact `41ff085c89e27a97a00ce85ced968931f506a147`, merged PR #654 exact `f8d4b6b6b095c7674037a9ea5281b9ffa2f0f864`, merged PR #655 exact `dc851fc9ea67e38799e8c30cf4916a31c9e9661e`, merged PR #657 exact `fa4a2ab25231fa4c8b9a8451a4da6f29e04abaf7`, documentation-authority convergence PR #658 exact `5fe54442068646ad9581d39b23dd6d60a737aa66`, merged PR #659 exact `6357ac65db6a0db9f3bbb3f82196853b787f33cc`, merged PR #661 exact `5a5e147c5a7168277332eb828652b4aea4f7f2ba`, merged PR #663 exact `29dfa79692ec55cdc23ed892081425630ac916b5`, merged PR #665 exact `592ae00f090f642e8cb71ffb132d4a8b7bfe993a`, merged PR #668 exact `efaaebae161a71b1274f5aa0f26e27376a3edb3a`, merged PR #670 exact `14b4c9a46692df0084a03b9a3b2ae4acf1178a83`, merged PR #673 exact `6f9dc4ca047817e4c9ef5ae8a55816493b1c558d`, merged PR #676 exact `f8de7fc27d475c76477271fa50dd7032afd82a6c`, merged PR #681 exact `7072822253b1975cea76dcd7922e1a01d67e7681`, merged PR #678 exact `ac367cb535525742a1b6f3682d3ab5b14ef66f23`, merged PR #683 exact `01adb5af3d26788926164003bc44a761f5ff3654`, merged PR #685 exact `93dcf4c50018ce051e3ca917a4e1d63cbca3102d`, merged PR #687 exact `98ec07552f4081bd4ff6b25f1f3ed691c0f3f2b9`, 그리고 merged PR #689 exact `b838c352a7cd0f7f58a905857537a3a9675a56f2`가 포함돼 있다. 이 식별자는 역사 증거이지 open-candidate authority가 아니다. +Protected history에는 merged PR #535 exact `82b20b293f0a5f0ac0e69857c1b61dddfe478491`, merged PR #540 exact `05bc2d47c3899ebe17538070f9a30172f90307ac`, merged PR #542 exact `ca839298fcaeec409091dc909789b6f87eb67fdc`, merged PR #547 exact `30b7e7e5cdab8de65715834a16f994b2047eafa6`, merged PR #550 exact `f2ec2dc6709814070cc3e3d6932ce280aee966db`, merged PR #553 exact `3bd9f543e97ce856f78b1c608141436298ce9e74`, merged PR #558 exact `2f91bf8641212ecae435b5fbcc9084cc0acd6295`, merged PR #556 exact `860714cba46dba06260a5dce09d0e9152fcb0a8c`, merged PR #560 exact `5aab7c098f3478069127f34e398326415ec599a4`, merged PR #582 exact `0f20a4dc78e423fd5df49e137a4eb286c7075ea4`, documentation-authority integration #583, protected procedural graph source #585/#586, documentation convergence #587/#588/#590/#595, workflow-backed current-state integration #589, procedural decision/evaluation/authentication integrations #591/#592/#593/#594/#596, State / Checkpoint history #597, Policy / Approval CAS #601, publication preflight #603, Workflow / Task exact-object operability integration #605, documentation-authority convergence #606, merged PR #607 exact `0afd68d2e33b7fd9be2307ba78b370b534cc0f54`, merged PR #610 exact `0a516bc54d682817ffea3206ec8b24b214aa94ea`, merged PR #612 exact `a919be3bc2a04068e25a4592e0c9c26f8e63534b`, merged PR #614 exact `77c5116a2e58e8a154ee893a3825da19c9c1f357`, merged PR #616 exact `da8461f1f5a6d02d926dd295fc88abe2c6167dfa`, documentation-authority convergence PR #617 exact `38b3b56837d875d19ae458f3f5491951ad7afb1c`, merged PR #618 exact `fb166ec6ecc769a19fd4ae4502f6d0994fc89e33`, merged PR #620 exact `b746846e4890c84b568bb29937594e1b17364fa1`, documentation-authority convergence #639, merged PR #640 exact `72ff4897822b5a8122540509346be4f3278a1379`, merged PR #641 exact `73f13b3a3826c5d6f7aafc89d1ff23747f8cf8e9`, merged PR #642 exact `3427e5a66d7a0ea9379ddc7915ba2b3d1872c492`, merged PR #643 exact `b13903e3208232086871d7f117f8f20e753eb583`, merged PR #644 exact `79a89f5775d0fb56de9f1908c1927df0b498b70f`, merged PR #645 exact `1b4dc38581e99b92342769dd03059f5015ee9f04`, merged PR #646 exact `3005086fca2c6376fae951b774230fa1c06ba587`, merged PR #647 exact `ea3a36bc65df88153aa69a05e3144f0b5352b5a6`, merged PR #648 exact `133ce20c4bb7fb9ba05e3e4bedeb0492334faf38`, merged PR #649 exact `f334f40193da8811a6e15efcb2d589aa80104931`, merged PR #650 exact `f59fce008a4da70f89e9927f692b823506594ed5`, documentation-authority convergence #651, merged PR #652 exact `23fabd95f3ef886c6bef0ae9ff6ead50dc0ce342`, documentation-authority convergence PR #653 exact `41ff085c89e27a97a00ce85ced968931f506a147`, merged PR #654 exact `f8d4b6b6b095c7674037a9ea5281b9ffa2f0f864`, merged PR #655 exact `dc851fc9ea67e38799e8c30cf4916a31c9e9661e`, merged PR #657 exact `fa4a2ab25231fa4c8b9a8451a4da6f29e04abaf7`, documentation-authority convergence PR #658 exact `5fe54442068646ad9581d39b23dd6d60a737aa66`, merged PR #659 exact `6357ac65db6a0db9f3bbb3f82196853b787f33cc`, merged PR #661 exact `5a5e147c5a7168277332eb828652b4aea4f7f2ba`, merged PR #663 exact `29dfa79692ec55cdc23ed892081425630ac916b5`, merged PR #665 exact `592ae00f090f642e8cb71ffb132d4a8b7bfe993a`, merged PR #668 exact `efaaebae161a71b1274f5aa0f26e27376a3edb3a`, merged PR #670 exact `14b4c9a46692df0084a03b9a3b2ae4acf1178a83`, merged PR #673 exact `6f9dc4ca047817e4c9ef5aa0f26e27376a3edb3a`, merged PR #676 exact `f8de7fc27d475c76477271fa50dd7032afd82a6c`, merged PR #681 exact `7072822253b1975cea76dcd7922e1a01d67e7681`, merged PR #678 exact `ac367cb535525742a1b6f3682d3ab5b14ef66f23`, merged PR #683 exact `01adb5af3d26788926164003bc44a761f5ff3654`, merged PR #685 exact `93dcf4c50018ce051e3ca917a4e1d63cbca3102d`, merged PR #687 exact `98ec07552f4081bd4ff6b25f1f3ed691c0f3f2b9`, 그리고 merged PR #689 exact `b838c352a7cd0f7f58a905857537a3a9675a56f2`가 포함돼 있다. 이 식별자는 역사 증거이지 open-candidate authority가 아니다. 이 baseline과 executable documentation-authority test는 active documentation-authority lane 하나만 write한다. mutation 직전 open PR/Issue/branch를 fresh-read해 writer를 결정하며 merged/closed historical PR 번호를 active sole writer로 고정하지 않는다. 다른 feature lane의 과거 baseline blob은 ordinary/non-force semantic convergence 때 current authority로 승계하지 않는다. @@ -154,3 +154,11 @@ The existing 65,536-byte ceiling, optional caller-supplied deadline with no inve Protected history includes merged PR #699 exact `e52408745efc73351c098227ae4c85c309fdd0c9`. Protected #699 closes the stalled-read liveness gap on Agent Runtime's private Workflow / Task Execution current-state response path: after successful reader acquisition, a 10-second absolute read deadline prevents an HTTP 200 response that never yields another chunk from pinning procedural guidance indefinitely. Deadline expiry preserves the stable `invalid_workflow_state_response` fail-closed contract, requests cancellation only as best-effort cleanup, clears the deadline timer, and releases the reader lock on every terminal path. The existing fixed 1 MiB retained buffer, byte ceiling, fatal UTF-8/JSON admission, canonical execution binding, and Workflow / Task Execution ownership remain unchanged. #699 remains protected source/test evidence; immutable release, deployed Durable Object recovery, and production p95/heap evidence remain separate. Workflow / Task lifecycle, provider/model routing, outbound, credential, quarantine/security, release/deployment, and foreign-domain authority stay with their existing owners. + +## Protected procedural current-lifecycle media admission — merged PR #704 + +Protected history includes merged PR #704 exact `42b15e865bdf88fde622c3bba2c0b123770d18be`, integrated by GitHub-verified normal merge `e8c2002e5af8fa5611880091dab81916bb716c35`. Protected #704 closes the representation-admission gap on Agent Runtime's private Workflow / Task Execution current-state response path: successful owner evidence must identify its representation as `application/json; charset=utf-8` before Noema performs bounded procedural-state parsing, while equivalent JSON media-type parameters remain admissible. Missing or non-JSON media types fail closed with the stable `invalid_workflow_state_response` classification. + +Rejected-media response-body cancellation is best-effort cleanup only: synchronous cleanup throw, asynchronous rejection, null body, or non-settling cancellation cannot replace or delay the fail-closed decision. The existing fixed 1 MiB retained buffer, byte ceiling, 10-second absolute read deadline, fatal UTF-8/JSON admission, canonical execution binding, and reader-lock lifecycle after successful acquisition remain unchanged. + +#704 remains protected source/test evidence; immutable release, deployed Durable Object recovery, and production p95/heap evidence remain separate. Workflow / Task lifecycle truth stays with its Durable Object owner. #704 does not transfer provider/model routing, destination/outbound policy, credential authority, quarantine/security, Policy / Approval, State / Checkpoint, release/deployment, or foreign-domain authority into Agent Runtime. \ No newline at end of file From 35f29ff10ca0075c0008eb351edb16c9b493d310 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 15:05:48 +0900 Subject: [PATCH 04/14] docs: restore protected history authority --- docs/product-technical-gap-baseline.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 878dbbc27..985d27734 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -8,7 +8,7 @@ Current protected source는 mutation·merge·release 시점에 live protected `m Dated central control-plane observation for this repair는 central `.github/main@cb0872c9a20d5584703dffacca65c096fc034c6c`다. Noema runtime의 reviewed immutable central consumer pin은 `c9052e607e5f3cc76e73207e7786b21500721b79`이고 runtime authority 표현은 `ALLOWED_WORKFLOW_SHA = c9052e607e5f3cc76e73207e7786b21500721b79`다. Moving foreign head와 reviewed immutable pin을 같은 권위로 취급하지 않으며 central moving head가 전진했다고 consumer pin을 자동 승격하지 않는다. -Protected history에는 merged PR #535 exact `82b20b293f0a5f0ac0e69857c1b61dddfe478491`, merged PR #540 exact `05bc2d47c3899ebe17538070f9a30172f90307ac`, merged PR #542 exact `ca839298fcaeec409091dc909789b6f87eb67fdc`, merged PR #547 exact `30b7e7e5cdab8de65715834a16f994b2047eafa6`, merged PR #550 exact `f2ec2dc6709814070cc3e3d6932ce280aee966db`, merged PR #553 exact `3bd9f543e97ce856f78b1c608141436298ce9e74`, merged PR #558 exact `2f91bf8641212ecae435b5fbcc9084cc0acd6295`, merged PR #556 exact `860714cba46dba06260a5dce09d0e9152fcb0a8c`, merged PR #560 exact `5aab7c098f3478069127f34e398326415ec599a4`, merged PR #582 exact `0f20a4dc78e423fd5df49e137a4eb286c7075ea4`, documentation-authority integration #583, protected procedural graph source #585/#586, documentation convergence #587/#588/#590/#595, workflow-backed current-state integration #589, procedural decision/evaluation/authentication integrations #591/#592/#593/#594/#596, State / Checkpoint history #597, Policy / Approval CAS #601, publication preflight #603, Workflow / Task exact-object operability integration #605, documentation-authority convergence #606, merged PR #607 exact `0afd68d2e33b7fd9be2307ba78b370b534cc0f54`, merged PR #610 exact `0a516bc54d682817ffea3206ec8b24b214aa94ea`, merged PR #612 exact `a919be3bc2a04068e25a4592e0c9c26f8e63534b`, merged PR #614 exact `77c5116a2e58e8a154ee893a3825da19c9c1f357`, merged PR #616 exact `da8461f1f5a6d02d926dd295fc88abe2c6167dfa`, documentation-authority convergence PR #617 exact `38b3b56837d875d19ae458f3f5491951ad7afb1c`, merged PR #618 exact `fb166ec6ecc769a19fd4ae4502f6d0994fc89e33`, merged PR #620 exact `b746846e4890c84b568bb29937594e1b17364fa1`, documentation-authority convergence #639, merged PR #640 exact `72ff4897822b5a8122540509346be4f3278a1379`, merged PR #641 exact `73f13b3a3826c5d6f7aafc89d1ff23747f8cf8e9`, merged PR #642 exact `3427e5a66d7a0ea9379ddc7915ba2b3d1872c492`, merged PR #643 exact `b13903e3208232086871d7f117f8f20e753eb583`, merged PR #644 exact `79a89f5775d0fb56de9f1908c1927df0b498b70f`, merged PR #645 exact `1b4dc38581e99b92342769dd03059f5015ee9f04`, merged PR #646 exact `3005086fca2c6376fae951b774230fa1c06ba587`, merged PR #647 exact `ea3a36bc65df88153aa69a05e3144f0b5352b5a6`, merged PR #648 exact `133ce20c4bb7fb9ba05e3e4bedeb0492334faf38`, merged PR #649 exact `f334f40193da8811a6e15efcb2d589aa80104931`, merged PR #650 exact `f59fce008a4da70f89e9927f692b823506594ed5`, documentation-authority convergence #651, merged PR #652 exact `23fabd95f3ef886c6bef0ae9ff6ead50dc0ce342`, documentation-authority convergence PR #653 exact `41ff085c89e27a97a00ce85ced968931f506a147`, merged PR #654 exact `f8d4b6b6b095c7674037a9ea5281b9ffa2f0f864`, merged PR #655 exact `dc851fc9ea67e38799e8c30cf4916a31c9e9661e`, merged PR #657 exact `fa4a2ab25231fa4c8b9a8451a4da6f29e04abaf7`, documentation-authority convergence PR #658 exact `5fe54442068646ad9581d39b23dd6d60a737aa66`, merged PR #659 exact `6357ac65db6a0db9f3bbb3f82196853b787f33cc`, merged PR #661 exact `5a5e147c5a7168277332eb828652b4aea4f7f2ba`, merged PR #663 exact `29dfa79692ec55cdc23ed892081425630ac916b5`, merged PR #665 exact `592ae00f090f642e8cb71ffb132d4a8b7bfe993a`, merged PR #668 exact `efaaebae161a71b1274f5aa0f26e27376a3edb3a`, merged PR #670 exact `14b4c9a46692df0084a03b9a3b2ae4acf1178a83`, merged PR #673 exact `6f9dc4ca047817e4c9ef5aa0f26e27376a3edb3a`, merged PR #676 exact `f8de7fc27d475c76477271fa50dd7032afd82a6c`, merged PR #681 exact `7072822253b1975cea76dcd7922e1a01d67e7681`, merged PR #678 exact `ac367cb535525742a1b6f3682d3ab5b14ef66f23`, merged PR #683 exact `01adb5af3d26788926164003bc44a761f5ff3654`, merged PR #685 exact `93dcf4c50018ce051e3ca917a4e1d63cbca3102d`, merged PR #687 exact `98ec07552f4081bd4ff6b25f1f3ed691c0f3f2b9`, 그리고 merged PR #689 exact `b838c352a7cd0f7f58a905857537a3a9675a56f2`가 포함돼 있다. 이 식별자는 역사 증거이지 open-candidate authority가 아니다. +Protected history에는 merged PR #535 exact `82b20b293f0a5f0ac0e69857c1b61dddfe478491`, merged PR #540 exact `05bc2d47c3899ebe17538070f9a30172f90307ac`, merged PR #542 exact `ca839298fcaeec409091dc909789b6f87eb67fdc`, merged PR #547 exact `30b7e7e5cdab8de65715834a16f994b2047eafa6`, merged PR #550 exact `f2ec2dc6709814070cc3e3d6932ce280aee966db`, merged PR #553 exact `3bd9f543e97ce856f78b1c608141436298ce9e74`, merged PR #558 exact `2f91bf8641212ecae435b5fbcc9084cc0acd6295`, merged PR #556 exact `860714cba46dba06260a5dce09d0e9152fcb0a8c`, merged PR #560 exact `5aab7c098f3478069127f34e398326415ec599a4`, merged PR #582 exact `0f20a4dc78e423fd5df49e137a4eb286c7075ea4`, documentation-authority integration #583, protected procedural graph source #585/#586, documentation convergence #587/#588/#590/#595, workflow-backed current-state integration #589, procedural decision/evaluation/authentication integrations #591/#592/#593/#594/#596, State / Checkpoint history #597, Policy / Approval CAS #601, publication preflight #603, Workflow / Task exact-object operability integration #605, documentation-authority convergence #606, merged PR #607 exact `0afd68d2e33b7fd9be2307ba78b370b534cc0f54`, merged PR #610 exact `0a516bc54d682817ffea3206ec8b24b214aa94ea`, merged PR #612 exact `a919be3bc2a04068e25a4592e0c9c26f8e63534b`, merged PR #614 exact `77c5116a2e58e8a154ee893a3825da19c9c1f357`, merged PR #616 exact `da8461f1f5a6d02d926dd295fc88abe2c6167dfa`, documentation-authority convergence PR #617 exact `38b3b56837d875d19ae458f3f5491951ad7afb1c`, merged PR #618 exact `fb166ec6ecc769a19fd4ae4502f6d0994fc89e33`, merged PR #620 exact `b746846e4890c84b568bb29937594e1b17364fa1`, documentation-authority convergence #639, merged PR #640 exact `72ff4897822b5a8122540509346be4f3278a1379`, merged PR #641 exact `73f13b3a3826c5d6f7aafc89d1ff23747f8cf8e9`, merged PR #642 exact `3427e5a66d7a0ea9379ddc7915ba2b3d1872c492`, merged PR #643 exact `b13903e3208232086871d7f117f8f20e753eb583`, merged PR #644 exact `79a89f5775d0fb56de9f1908c1927df0b498b70f`, merged PR #645 exact `1b4dc38581e99b92342769dd03059f5015ee9f04`, merged PR #646 exact `3005086fca2c6376fae951b774230fa1c06ba587`, merged PR #647 exact `ea3a36bc65df88153aa69a05e3144f0b5352b5a6`, merged PR #648 exact `133ce20c4bb7fb9ba05e3e4bedeb0492334faf38`, merged PR #649 exact `f334f40193da8811a6e15efcb2d589aa80104931`, merged PR #650 exact `f59fce008a4da70f89e9927f692b823506594ed5`, documentation-authority convergence #651, merged PR #652 exact `23fabd95f3ef886c6bef0ae9ff6ead50dc0ce342`, documentation-authority convergence PR #653 exact `41ff085c89e27a97a00ce85ced968931f506a147`, merged PR #654 exact `f8d4b6b6b095c7674037a9ea5281b9ffa2f0f864`, merged PR #655 exact `dc851fc9ea67e38799e8c30cf4916a31c9e9661e`, merged PR #657 exact `fa4a2ab25231fa4c8b9a8451a4da6f29e04abaf7`, documentation-authority convergence PR #658 exact `5fe54442068646ad9581d39b23dd6d60a737aa66`, merged PR #659 exact `6357ac65db6a0db9f3bbb3f82196853b787f33cc`, merged PR #661 exact `5a5e147c5a7168277332eb828652b4aea4f7f2ba`, merged PR #663 exact `29dfa79692ec55cdc23ed892081425630ac916b5`, merged PR #665 exact `592ae00f090f642e8cb71ffb132d4a8b7bfe993a`, merged PR #668 exact `efaaebae161a71b1274f5aa0f26e27376a3edb3a`, merged PR #670 exact `14b4c9a46692df0084a03b9a3b2ae4acf1178a83`, merged PR #673 exact `6f9dc4ca047817e4c9ef5ae8a55816493b1c558d`, merged PR #676 exact `f8de7fc27d475c76477271fa50dd7032afd82a6c`, merged PR #681 exact `7072822253b1975cea76dcd7922e1a01d67e7681`, merged PR #678 exact `ac367cb535525742a1b6f3682d3ab5b14ef66f23`, merged PR #683 exact `01adb5af3d26788926164003bc44a761f5ff3654`, merged PR #685 exact `93dcf4c50018ce051e3ca917a4e1d63cbca3102d`, merged PR #687 exact `98ec07552f4081bd4ff6b25f1f3ed691c0f3f2b9`, 그리고 merged PR #689 exact `b838c352a7cd0f7f58a905857537a3a9675a56f2`가 포함돼 있다. 이 식별자는 역사 증거이지 open-candidate authority가 아니다. 이 baseline과 executable documentation-authority test는 active documentation-authority lane 하나만 write한다. mutation 직전 open PR/Issue/branch를 fresh-read해 writer를 결정하며 merged/closed historical PR 번호를 active sole writer로 고정하지 않는다. 다른 feature lane의 과거 baseline blob은 ordinary/non-force semantic convergence 때 current authority로 승계하지 않는다. @@ -161,4 +161,4 @@ Protected history includes merged PR #704 exact `42b15e865bdf88fde622c3bba2c0b12 Rejected-media response-body cancellation is best-effort cleanup only: synchronous cleanup throw, asynchronous rejection, null body, or non-settling cancellation cannot replace or delay the fail-closed decision. The existing fixed 1 MiB retained buffer, byte ceiling, 10-second absolute read deadline, fatal UTF-8/JSON admission, canonical execution binding, and reader-lock lifecycle after successful acquisition remain unchanged. -#704 remains protected source/test evidence; immutable release, deployed Durable Object recovery, and production p95/heap evidence remain separate. Workflow / Task lifecycle truth stays with its Durable Object owner. #704 does not transfer provider/model routing, destination/outbound policy, credential authority, quarantine/security, Policy / Approval, State / Checkpoint, release/deployment, or foreign-domain authority into Agent Runtime. \ No newline at end of file +#704 remains protected source/test evidence; immutable release, deployed Durable Object recovery, and production p95/heap evidence remain separate. Workflow / Task lifecycle truth stays with its Durable Object owner. #704 does not transfer provider/model routing, destination/outbound policy, credential authority, quarantine/security, Policy / Approval, State / Checkpoint, release/deployment, or foreign-domain authority into Agent Runtime. From a2243b506ae803a82a64dc1beef6c6858dfc4454 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 15:09:10 +0900 Subject: [PATCH 05/14] docs: preserve changelog newline --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee55d9291..368179de5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -103,7 +103,7 @@ - credential-bearing GitHub App REST 요청의 egress를 exact `https://api.github.com` origin으로 고정. 새 Worker entrypoint가 `/exchange` 전에 `GITHUB_API_BASE`의 scheme·origin·userinfo·port·path·query·fragment를 검증하고, lookalike/malformed 설정은 rate-limit·OIDC parsing·private-key 사용·GitHub API 호출 전에 `503 ERR_GITHUB_API`로 실패-폐쇄하며 허용 값도 canonical origin으로 치환한다. `/health`는 설정 복구 중에도 유지하고 원본 설정값은 응답·로그에 노출하지 않는다. - `src/**/*.ts` 전체에 statements·branches·functions·lines 100% coverage threshold를 강제하고, `/exchange` wrapper·OIDC replay guard·distributed limiter의 fail-closed 및 malformed-decision 경계를 회귀 테스트로 고정했다. 새 source branch가 coverage를 낮추면 CI가 즉시 실패한다. - `/exchange` distributed rate-limit identity가 없는 요청을 shared `unknown` bucket으로 합치지 않고 `503`으로 실패-폐쇄하도록 강화. Cloudflare의 `CF-Connecting-IP`가 정확히 하나의 유효한 IPv4/IPv6가 아니면 Durable Object lookup과 bearer parsing 전에 중단하고, 유효한 IPv6는 canonical form으로 정규화하여 동일 주소의 표기 차이가 rate-limit bucket을 분할하지 않도록 한다. -- CI 검증 중 공개된 `undici` 취약점 묶음(GHSA-4cwx-7wf7-3272 포함)을 제거하기 위해 Wrangler→Miniflare 경유 transitive dependency를 patched `7.29.0`으로 override하고 lockfile을 재생성했다. `npm audit --audit-level=high`가 0건으로 복구하고 release gate가 취약 버전에서 실패-폐쇄하도록 유지한다. +- CI 검증 중 공개된 `undici` 취약점 묶음(GHSA-4cwx-7wf7-3272 포함)을 제거하기 위해 Wrangler→Miniflare 경유 transitive dependency를 patched `7.29.0`으로 override하고 lockfile을 재생성했다. `npm audit --audit-level=high`가 0건으로 복구하여 매일 실패하던 `readiness-audit` 스케줄 및 `release:verify` 게이트를 복구. - EOL 상태인 Node.js 20을 배포 계약에서 제거하고 `engines.node >=22` 및 배포 가이드의 지원 중 LTS 요구사항을 일치시켰다. - SQLite-backed OIDC replay guard의 alarm cleanup을 current-claim-aware 방식으로 강화. Cloudflare alarm의 at-least-once·지연·재시도 실행이 만료 후 교체된 활성 `jti` claim을 삭제하지 않도록 저장된 현재 expiry를 transactionally 재검증하고, 활성 claim이면 해당 만료 시각과 grace period로 reschedule하며 expired/empty storage만 삭제한다. - SQLite-backed `/exchange` rate limiter의 alarm cleanup을 current-window-aware 방식으로 강화. Cloudflare alarm의 지연·재시도 실행이 새 60초 window의 활성 bucket을 삭제해 요청 예산을 조기 재개하지 않도록 저장된 window deadline을 transactionally 재검증하고, 아직 활성인 경우 실제 reset 시각으로 reschedule하며 expired/empty storage만 삭제한다. @@ -144,4 +144,4 @@ - `/exchange` 401 응답에 `WWW-Authenticate: Bearer realm="noema"` challenge를 추가하고 인증 누락은 `invalid_request`, 잘못된 토큰은 `invalid_token`으로 구분. - `x-request-id`/`x-correlation-id` 및 client IP 계열 헤더를 길이/문자 기준으로 제한해 로그 오염과 rate-limit key 폭주를 방지. - `KRW 2,000,000,000` 매각 가능성 Goal 등록서, buyer due diligence index, library/submodule 경계 판단서를 추가하고 `npm run acquisition:audit`로 ARR/LOI/이전성/saleable evidence를 실패-폐쇄 방식으로 검증. -- Protected #695 normalizes synchronous reader acquisition on the contextual-orchestrator `/healthz` response consumer at exact source `c9d526093e543167645383e937096fd089b337f8`. If a locked or otherwise non-stream-readable response body makes `response.body.getReader()` throw synchronously, Noema fails closed with `contextual-orchestrator health response body is not stream-readable` instead of leaking a runtime-specific stream exception. The existing 65,536-byte ceiling, optional caller-supplied deadline with no invented default timeout, fixed retained buffer, best-effort cancellation, fatal UTF-8, duplicate-key/JSON admission, and reader-lock lifecycle after successful acquisition remain unchanged. Contextual-orchestrator service/provider/model routing, credentials, outbound authority, quarantine/security authority, release/deployment authority, and foreign-domain truth remain with their existing owners; protected source is not an immutable release or deployed availability/p95/recovery evidence. PR #695. \ No newline at end of file +- Protected #695 normalizes synchronous reader acquisition on the contextual-orchestrator `/healthz` response consumer at exact source `c9d526093e543167645383e937096fd089b337f8`. If a locked or otherwise non-stream-readable response body makes `response.body.getReader()` throw synchronously, Noema fails closed with `contextual-orchestrator health response body is not stream-readable` instead of leaking a runtime-specific stream exception. The existing 65,536-byte ceiling, optional caller-supplied deadline with no invented default timeout, fixed retained buffer, best-effort cancellation, fatal UTF-8, duplicate-key/JSON admission, and reader-lock lifecycle after successful acquisition remain unchanged. Contextual-orchestrator service/provider/model routing, credentials, outbound authority, quarantine/security authority, release/deployment authority, and foreign-domain truth remain with their existing owners; protected source is not an immutable release or deployed availability/p95/recovery evidence. PR #695. From 17d5edfdde97de0438fd98056ffe30583a93bcb2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 15:09:53 +0900 Subject: [PATCH 06/14] docs: restore changelog historical text --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 368179de5..ee55d9291 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -103,7 +103,7 @@ - credential-bearing GitHub App REST 요청의 egress를 exact `https://api.github.com` origin으로 고정. 새 Worker entrypoint가 `/exchange` 전에 `GITHUB_API_BASE`의 scheme·origin·userinfo·port·path·query·fragment를 검증하고, lookalike/malformed 설정은 rate-limit·OIDC parsing·private-key 사용·GitHub API 호출 전에 `503 ERR_GITHUB_API`로 실패-폐쇄하며 허용 값도 canonical origin으로 치환한다. `/health`는 설정 복구 중에도 유지하고 원본 설정값은 응답·로그에 노출하지 않는다. - `src/**/*.ts` 전체에 statements·branches·functions·lines 100% coverage threshold를 강제하고, `/exchange` wrapper·OIDC replay guard·distributed limiter의 fail-closed 및 malformed-decision 경계를 회귀 테스트로 고정했다. 새 source branch가 coverage를 낮추면 CI가 즉시 실패한다. - `/exchange` distributed rate-limit identity가 없는 요청을 shared `unknown` bucket으로 합치지 않고 `503`으로 실패-폐쇄하도록 강화. Cloudflare의 `CF-Connecting-IP`가 정확히 하나의 유효한 IPv4/IPv6가 아니면 Durable Object lookup과 bearer parsing 전에 중단하고, 유효한 IPv6는 canonical form으로 정규화하여 동일 주소의 표기 차이가 rate-limit bucket을 분할하지 않도록 한다. -- CI 검증 중 공개된 `undici` 취약점 묶음(GHSA-4cwx-7wf7-3272 포함)을 제거하기 위해 Wrangler→Miniflare 경유 transitive dependency를 patched `7.29.0`으로 override하고 lockfile을 재생성했다. `npm audit --audit-level=high`가 0건으로 복구하여 매일 실패하던 `readiness-audit` 스케줄 및 `release:verify` 게이트를 복구. +- CI 검증 중 공개된 `undici` 취약점 묶음(GHSA-4cwx-7wf7-3272 포함)을 제거하기 위해 Wrangler→Miniflare 경유 transitive dependency를 patched `7.29.0`으로 override하고 lockfile을 재생성했다. `npm audit --audit-level=high`가 0건으로 복구하고 release gate가 취약 버전에서 실패-폐쇄하도록 유지한다. - EOL 상태인 Node.js 20을 배포 계약에서 제거하고 `engines.node >=22` 및 배포 가이드의 지원 중 LTS 요구사항을 일치시켰다. - SQLite-backed OIDC replay guard의 alarm cleanup을 current-claim-aware 방식으로 강화. Cloudflare alarm의 at-least-once·지연·재시도 실행이 만료 후 교체된 활성 `jti` claim을 삭제하지 않도록 저장된 현재 expiry를 transactionally 재검증하고, 활성 claim이면 해당 만료 시각과 grace period로 reschedule하며 expired/empty storage만 삭제한다. - SQLite-backed `/exchange` rate limiter의 alarm cleanup을 current-window-aware 방식으로 강화. Cloudflare alarm의 지연·재시도 실행이 새 60초 window의 활성 bucket을 삭제해 요청 예산을 조기 재개하지 않도록 저장된 window deadline을 transactionally 재검증하고, 아직 활성인 경우 실제 reset 시각으로 reschedule하며 expired/empty storage만 삭제한다. @@ -144,4 +144,4 @@ - `/exchange` 401 응답에 `WWW-Authenticate: Bearer realm="noema"` challenge를 추가하고 인증 누락은 `invalid_request`, 잘못된 토큰은 `invalid_token`으로 구분. - `x-request-id`/`x-correlation-id` 및 client IP 계열 헤더를 길이/문자 기준으로 제한해 로그 오염과 rate-limit key 폭주를 방지. - `KRW 2,000,000,000` 매각 가능성 Goal 등록서, buyer due diligence index, library/submodule 경계 판단서를 추가하고 `npm run acquisition:audit`로 ARR/LOI/이전성/saleable evidence를 실패-폐쇄 방식으로 검증. -- Protected #695 normalizes synchronous reader acquisition on the contextual-orchestrator `/healthz` response consumer at exact source `c9d526093e543167645383e937096fd089b337f8`. If a locked or otherwise non-stream-readable response body makes `response.body.getReader()` throw synchronously, Noema fails closed with `contextual-orchestrator health response body is not stream-readable` instead of leaking a runtime-specific stream exception. The existing 65,536-byte ceiling, optional caller-supplied deadline with no invented default timeout, fixed retained buffer, best-effort cancellation, fatal UTF-8, duplicate-key/JSON admission, and reader-lock lifecycle after successful acquisition remain unchanged. Contextual-orchestrator service/provider/model routing, credentials, outbound authority, quarantine/security authority, release/deployment authority, and foreign-domain truth remain with their existing owners; protected source is not an immutable release or deployed availability/p95/recovery evidence. PR #695. +- Protected #695 normalizes synchronous reader acquisition on the contextual-orchestrator `/healthz` response consumer at exact source `c9d526093e543167645383e937096fd089b337f8`. If a locked or otherwise non-stream-readable response body makes `response.body.getReader()` throw synchronously, Noema fails closed with `contextual-orchestrator health response body is not stream-readable` instead of leaking a runtime-specific stream exception. The existing 65,536-byte ceiling, optional caller-supplied deadline with no invented default timeout, fixed retained buffer, best-effort cancellation, fatal UTF-8, duplicate-key/JSON admission, and reader-lock lifecycle after successful acquisition remain unchanged. Contextual-orchestrator service/provider/model routing, credentials, outbound authority, quarantine/security authority, release/deployment authority, and foreign-domain truth remain with their existing owners; protected source is not an immutable release or deployed availability/p95/recovery evidence. PR #695. \ No newline at end of file From 748188b968daa527270c8103ba4118bb5a72bae8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 15:20:12 +0900 Subject: [PATCH 07/14] test: require accurate workflow media documentation --- test/procedural-current-lifecycle-media-authority.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/procedural-current-lifecycle-media-authority.test.ts b/test/procedural-current-lifecycle-media-authority.test.ts index a4373326a..9cd7390d4 100644 --- a/test/procedural-current-lifecycle-media-authority.test.ts +++ b/test/procedural-current-lifecycle-media-authority.test.ts @@ -11,7 +11,7 @@ describe("protected procedural current-lifecycle media documentation authority", expect(changelog).toContain("Protected #704"); expect(changelog).toContain("42b15e865bdf88fde622c3bba2c0b123770d18be"); expect(changelog).toContain("e8c2002e5af8fa5611880091dab81916bb716c35"); - expect(changelog).toContain("application/json; charset=utf-8"); + expect(changelog).toContain("application/json with optional `charset=utf-8` parameter"); expect(changelog).toContain("invalid_workflow_state_response"); expect(changelog).toContain("best-effort cleanup"); @@ -19,7 +19,7 @@ describe("protected procedural current-lifecycle media documentation authority", "merged PR #704 exact `42b15e865bdf88fde622c3bba2c0b123770d18be`", ); expect(baseline).toContain("GitHub-verified normal merge `e8c2002e5af8fa5611880091dab81916bb716c35`"); - expect(baseline).toContain("application/json; charset=utf-8"); + expect(baseline).toContain("application/json with optional `charset=utf-8` parameter"); expect(baseline).toContain("stable `invalid_workflow_state_response`"); expect(baseline).toContain("best-effort cleanup"); expect(baseline).toContain("immutable release"); From 568b6dc104fbe0510e9fdd5da68f57893b4db90b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:07:33 +0900 Subject: [PATCH 08/14] docs: align current workflow media contract --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee55d9291..344ff0de2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ - Add a Noema-owned exact-claim evidence receipt contract whose execution and research producers serialize one canonical artifact that binds every receipt semantic field, including command/result/isolation/network or source revision/excerpt/retrieval policy. Admission accepts only a receipt ID from untrusted model output. The owner API first verifies the exact authenticated OpenCode-handoff manifest digest, canonical envelope bytes, reviewed producer-to-kind policy, and repository/head/workflow/run/attempt identity before it can construct an immutable typed index; admission then reconstructs each canonical artifact and verifies time/claim/artifact identity. The version-2 manifest now binds a separate producer-authenticated `ClaimEvidenceRequirement` containing the exact claim, independently required evidence kind, and `context` or `finding` publication authority. Raw current-head source lines are context only: they are withheld from finding-reference prompts and cannot publish a finding or `request_changes`; an explicitly producer-authorized source finding remains usable and retains exact path/line checks. Finding-free model `request_changes` and `blocked` verdicts cannot bypass receipt admission to publish a vacuous blocking review. Requirement/receipt kind mismatch, fixed-artifact semantic substitution, caller-supplied receipt dictionaries, model self-classification, stale identities, cross-kind receipts, marker-only sandbox output, noncanonical artifact bytes, and expired receipts fail closed before the GitHub publisher. This remains the owner prerequisite for ContextualWisdomLab/.github#1641 and issue #555. The reviewed `sandboxed_verify` adapter exists in owner source, but its actual central stdout/stderr/marker-to-manifest wiring and the trusted research producer are not yet integrated; exact-head hosted GREEN, immutable release, and the verified central consumer bump remain required. ## Unreleased -- Protected #704 exact `42b15e865bdf88fde622c3bba2c0b123770d18be`, integrated by GitHub-verified normal merge `e8c2002e5af8fa5611880091dab81916bb716c35`, requires Agent Runtime to admit private Workflow / Task Execution current-state evidence only when a successful response declares the owner-emitted JSON media type `application/json; charset=utf-8` (media-type parameters remain acceptable). Missing or non-JSON media types fail closed with the stable `invalid_workflow_state_response` classification before bounded parsing. Rejected-media body cancellation is best-effort cleanup: synchronous throw, asynchronous rejection, null body, or non-settling cleanup cannot replace or delay the fail-closed decision. The existing fixed 1 MiB retained buffer, 10-second absolute read deadline, fatal UTF-8/JSON admission, canonical execution binding, and reader-lock lifecycle remain unchanged. Workflow / Task lifecycle truth, provider/model routing, destination/outbound policy, credential authority, quarantine/security, Policy / Approval, State / Checkpoint, release/deployment, and foreign-domain authority remain with their existing owners; protected source/checks/merge are not an immutable release, deployed Durable Object recovery, or production p95/heap evidence. +- Protected #704 exact `42b15e865bdf88fde622c3bba2c0b123770d18be`, integrated by GitHub-verified normal merge `e8c2002e5af8fa5611880091dab81916bb716c35`, requires Agent Runtime to admit private Workflow / Task Execution current-state evidence only when a successful response declares the owner-emitted JSON media type application/json with optional `charset=utf-8` parameter; other media-type parameters are rejected. Missing or non-JSON media types fail closed with the stable `invalid_workflow_state_response` classification before bounded parsing. Rejected-media body cancellation is best-effort cleanup: synchronous throw, asynchronous rejection, null body, or non-settling cleanup cannot replace or delay the fail-closed decision. The existing fixed 1 MiB retained buffer, 10-second absolute read deadline, fatal UTF-8/JSON admission, canonical execution binding, and reader-lock lifecycle remain unchanged. Workflow / Task lifecycle truth, provider/model routing, destination/outbound policy, credential authority, quarantine/security, Policy / Approval, State / Checkpoint, release/deployment, and foreign-domain authority remain with their existing owners; protected source/checks/merge are not an immutable release, deployed Durable Object recovery, or production p95/heap evidence. - Protected #702 exact `2b31805eb2b81b6078fefe1ebcce8007b6ca5169`, integrated by GitHub-verified normal merge `cf7f4279dbf83213557e987f0ee8fb52b12fcccf`, behaviorally verifies Noema's shared Cloudflare deploy/status/recovery request boundary rather than relying on source-text header presence. The three direct clients use `requestCloudflareJson`; executable tests observe the actual `fetch` request, require `Accept: application/json` and the owner bearer to override conflicting caller values, preserve unrelated caller headers such as `Content-Type`, enforce the existing 120-second request deadline, and continue into the 1 MiB bounded JSON reader. `Accept` remains request-side representation preference rather than provider response-shape authority. Cloudflare/provider truth, destination/outbound policy, credential authority, quarantine/security, recovery-state, release/deployment and foreign-domain authority remain with their existing owners; protected source/test/CI evidence is not an immutable release, production deployment, controlled recovery rehearsal, deployed p95/heap or production KPI evidence. - PR #701 source exact `80d3d579ad4a08ccb3f21e2735c7fb0bebc7b492` makes Noema's direct Cloudflare deploy/status/recovery control-plane clients explicitly negotiate machine-readable Cloudflare-generated errors with `Accept: application/json` before their existing 1 MiB bounded JSON response reader. Cloudflare's 2026-05-05 error-response contract documents HTML as the default for generated errors when `Accept` is absent or `*/*`, and structured JSON when `application/json` is requested; Noema still treats negotiation as preference rather than shape authority and retains fail-closed fatal UTF-8/JSON/provider-error admission. Existing 120-second request bound, fixed retained buffer, reader/cancellation lifecycle, exact recovery-state checks, credential capability, destination/outbound policy, Cloudflare/provider authority and release/deployment authority remain unchanged. This source PR is not an immutable release, production deployment, controlled recovery rehearsal, or deployed p95/heap evidence. - Protected #699 bounds Agent Runtime's private Workflow / Task Execution current-state response read at exact source `e52408745efc73351c098227ae4c85c309fdd0c9` with a 10-second absolute read deadline. Deadline expiry preserves the stable `invalid_workflow_state_response` fail-closed contract, requests reader cancellation only as best-effort cleanup, clears the deadline timer, and releases the reader lock on every terminal path. The existing fixed 1 MiB retained buffer, byte ceiling, fatal UTF-8/JSON admission, canonical execution binding, and Workflow / Task Execution ownership remain unchanged. Workflow / Task lifecycle, provider/model routing, outbound, credential, quarantine/security, release/deployment, and foreign-domain authority stay with their existing owners; this protected source is not an immutable release, deployed Durable Object recovery, or production p95/heap evidence. PR #699. @@ -27,7 +27,7 @@ - Distributed `/exchange` rate-limit의 private Durable Object request(256-byte)와 decision response(4,096-byte) bounded reader는 reader를 획득한 뒤의 모든 terminal path에서 lock을 반환한다(terminal paths after reader acquisition). Declared-length overflow와 null-body validation은 before reader acquisition 경로이므로 해제할 reader lock이 없다. 기존 fixed-buffer byte ceiling, fatal UTF-8·duplicate-key·JSON admission, bucket/identity/Durable Object authority는 유지하며, 이 protected source는 immutable release나 deployed heap/p95 evidence를 대신하지 않는다. PR #657. - OIDC replay guard의 bounded decision response(4,096 bytes)와 internal claim request(512 bytes) stream reader가 성공·timeout·read failure·fail-closed cleanup 뒤 reader lock을 반환한다. 기존 byte ceiling, cancellation, fatal UTF-8·duplicate-key·JSON admission, replay/storage authority는 유지하며, 이 protected source는 immutable release나 deployed heap/p95 evidence를 대신하지 않는다. PR #655. - Agent Runtime의 workflow-backed procedural current-state ACL이 private Workflow / Task Execution Durable Object 응답을 `Response.json()`으로 선버퍼링하지 않고 고정 `Uint8Array`에 chunk-wise 수신해 **1 MiB retained-byte ceiling**을 적용한다. 한도를 넘는 chunk는 copy 전에 실패-폐쇄하고 stream cancellation failure가 안정적인 진단을 덮지 않으며 reader lock을 정리한다. Fatal UTF-8/JSON admission과 exact execution/plan/task 검증은 유지한다. 이 protected source는 immutable release, deployed Durable Object p95/recovery, graph publication 또는 activation authority를 대신하지 않는다. PR #652. -- Distributed `/exchange` rate-limit의 private Durable Object request(256 bytes)와 decision response(4,096 bytes) bounded stream reader가 허용 chunk를 배열에 누적하지 않고 각 byte ceiling 크기의 고정 `Uint8Array`에 직접 복사하도록 바꾼다. 합법적인 high-fragmentation stream이 accepted-byte ceiling과 별개로 retained chunk object/backing-store 수와 두 번째 합산 allocation을 키우지 않으며 초과 chunk는 copy 전에 실패-폐쇄한다. 기존 cancellation, fatal UTF-8·duplicate-key·JSON admission, bucket/identity/Durable Object authority는 유지한다. 이 source hardening은 immutable release나 deployed heap/p95 evidence를 대신하지 않는다. PR #650. +- Distributed `/exchange` rate-limit의 private Durable Object request(256 bytes)와 decision response(4,096-byte) bounded stream reader가 허용 chunk를 배열에 누적하지 않고 각 byte ceiling 크기의 고정 `Uint8Array`에 직접 복사하도록 바꾼다. 합법적인 high-fragmentation stream이 accepted-byte ceiling과 별개로 retained chunk object/backing-store 수와 두 번째 합산 allocation을 키우지 않으며 초과 chunk는 copy 전에 실패-폐쇄한다. 기존 cancellation, fatal UTF-8·duplicate-key·JSON admission, bucket/identity/Durable Object authority는 유지한다. 이 source hardening은 immutable release나 deployed heap/p95 evidence를 대신하지 않는다. PR #650. - Base credential-exchange의 OIDC discovery/JWKS·GitHub API bounded JSON response reader가 허용 chunk를 배열에 누적하지 않고 65,536-byte 고정 버퍼에 직접 복사하도록 바꾼다. Stream fragmentation이 accepted-byte ceiling과 별개로 retained chunk object/backing-store 수와 두 번째 합산 allocation을 키우지 않으며, 초과 chunk는 복사 전에 실패-폐쇄한다. 기존 10초 wall-clock deadline, cancellation, fatal UTF-8·duplicate-key·JSON admission, OIDC/GitHub identity·credential authority는 유지한다. 이 source hardening은 immutable release나 production p95/heap evidence를 대신하지 않는다. PR #646. - Workflow registry disable/plan 운영 경로의 GitHub JSON 응답 reader도 고정 `Uint8Array(MAX_RESPONSE_BYTES)`에 직접 수신해 합법적인 고분할 stream이 chunk-object retention과 두 번째 합산 allocation을 키우지 않도록 한다. Oversize는 copy 전에 실패-폐쇄하며 기존 pagination·registry identity·single-workflow disable authority는 유지한다. 이 source hardening은 live registry cleanliness나 immutable release evidence를 대신하지 않는다. PR #645. - Trivy v0.74.0의 vendor-severity diagnostic은 취약점 정책을 약화하거나 로그를 조용하게 만들 이유가 아니므로 reviewer-ci·central review·patch-validator image의 severity source를 기본 `auto`로 유지한다. OS vendor advisory와 backport-aware severity attribution(`SeveritySource`/`VendorSeverity`)을 보존하고 `--vuln-severity-source`를 강제하지 않으며, diagnostic은 의도적으로 visible 상태로 남긴다. Severity threshold·exit behavior·ignore policy·scanner coverage는 변경하지 않는다. PR #637. @@ -144,4 +144,4 @@ - `/exchange` 401 응답에 `WWW-Authenticate: Bearer realm="noema"` challenge를 추가하고 인증 누락은 `invalid_request`, 잘못된 토큰은 `invalid_token`으로 구분. - `x-request-id`/`x-correlation-id` 및 client IP 계열 헤더를 길이/문자 기준으로 제한해 로그 오염과 rate-limit key 폭주를 방지. - `KRW 2,000,000,000` 매각 가능성 Goal 등록서, buyer due diligence index, library/submodule 경계 판단서를 추가하고 `npm run acquisition:audit`로 ARR/LOI/이전성/saleable evidence를 실패-폐쇄 방식으로 검증. -- Protected #695 normalizes synchronous reader acquisition on the contextual-orchestrator `/healthz` response consumer at exact source `c9d526093e543167645383e937096fd089b337f8`. If a locked or otherwise non-stream-readable response body makes `response.body.getReader()` throw synchronously, Noema fails closed with `contextual-orchestrator health response body is not stream-readable` instead of leaking a runtime-specific stream exception. The existing 65,536-byte ceiling, optional caller-supplied deadline with no invented default timeout, fixed retained buffer, best-effort cancellation, fatal UTF-8, duplicate-key/JSON admission, and reader-lock lifecycle after successful acquisition remain unchanged. Contextual-orchestrator service/provider/model routing, credentials, outbound authority, quarantine/security authority, release/deployment authority, and foreign-domain truth remain with their existing owners; protected source is not an immutable release or deployed availability/p95/recovery evidence. PR #695. \ No newline at end of file +- Protected #695 normalizes synchronous reader acquisition on the contextual-orchestrator `/healthz` response consumer at exact source `c9d526093e543167645383e937096fd089b337f8`. If a locked or otherwise non-stream-readable response body makes `response.body.getReader()` throw synchronously, Noema fails closed with `contextual-orchestrator health response body is not stream-readable` instead of leaking a runtime-specific stream exception. The existing 65,536-byte ceiling, optional caller-supplied deadline with no invented default timeout, fixed retained buffer, best-effort cancellation, fatal UTF-8, duplicate-key/JSON admission, and reader-lock lifecycle after successful acquisition remain unchanged. Contextual-orchestrator service/provider/model routing, credentials, outbound authority, quarantine/security authority, release/deployment authority, and foreign-domain truth remain with their existing owners; protected source is not an immutable release or deployed availability/p95/recovery evidence. PR #695. From abc2d3b261459ba1e6f67017875dc8ed78cca40c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:09:14 +0900 Subject: [PATCH 09/14] docs: align current workflow media contract --- docs/product-technical-gap-baseline.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 985d27734..348167818 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -157,7 +157,7 @@ The existing fixed 1 MiB retained buffer, byte ceiling, fatal UTF-8/JSON admissi ## Protected procedural current-lifecycle media admission — merged PR #704 -Protected history includes merged PR #704 exact `42b15e865bdf88fde622c3bba2c0b123770d18be`, integrated by GitHub-verified normal merge `e8c2002e5af8fa5611880091dab81916bb716c35`. Protected #704 closes the representation-admission gap on Agent Runtime's private Workflow / Task Execution current-state response path: successful owner evidence must identify its representation as `application/json; charset=utf-8` before Noema performs bounded procedural-state parsing, while equivalent JSON media-type parameters remain admissible. Missing or non-JSON media types fail closed with the stable `invalid_workflow_state_response` classification. +Protected history includes merged PR #704 exact `42b15e865bdf88fde622c3bba2c0b123770d18be`, integrated by GitHub-verified normal merge `e8c2002e5af8fa5611880091dab81916bb716c35`. Protected #704 closes the representation-admission gap on Agent Runtime's private Workflow / Task Execution current-state response path: successful owner evidence must identify its representation as application/json with optional `charset=utf-8` parameter; other media-type parameters are rejected before Noema performs bounded procedural-state parsing. Missing or non-JSON media types fail closed with the stable `invalid_workflow_state_response` classification. Rejected-media response-body cancellation is best-effort cleanup only: synchronous cleanup throw, asynchronous rejection, null body, or non-settling cancellation cannot replace or delay the fail-closed decision. The existing fixed 1 MiB retained buffer, byte ceiling, 10-second absolute read deadline, fatal UTF-8/JSON admission, canonical execution binding, and reader-lock lifecycle after successful acquisition remain unchanged. From 35006799e27e3bc18ac8d7604898391bfff6bef5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:11:57 +0900 Subject: [PATCH 10/14] fix: restore historical changelog wording --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 344ff0de2..1643c167c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,7 +27,7 @@ - Distributed `/exchange` rate-limit의 private Durable Object request(256-byte)와 decision response(4,096-byte) bounded reader는 reader를 획득한 뒤의 모든 terminal path에서 lock을 반환한다(terminal paths after reader acquisition). Declared-length overflow와 null-body validation은 before reader acquisition 경로이므로 해제할 reader lock이 없다. 기존 fixed-buffer byte ceiling, fatal UTF-8·duplicate-key·JSON admission, bucket/identity/Durable Object authority는 유지하며, 이 protected source는 immutable release나 deployed heap/p95 evidence를 대신하지 않는다. PR #657. - OIDC replay guard의 bounded decision response(4,096 bytes)와 internal claim request(512 bytes) stream reader가 성공·timeout·read failure·fail-closed cleanup 뒤 reader lock을 반환한다. 기존 byte ceiling, cancellation, fatal UTF-8·duplicate-key·JSON admission, replay/storage authority는 유지하며, 이 protected source는 immutable release나 deployed heap/p95 evidence를 대신하지 않는다. PR #655. - Agent Runtime의 workflow-backed procedural current-state ACL이 private Workflow / Task Execution Durable Object 응답을 `Response.json()`으로 선버퍼링하지 않고 고정 `Uint8Array`에 chunk-wise 수신해 **1 MiB retained-byte ceiling**을 적용한다. 한도를 넘는 chunk는 copy 전에 실패-폐쇄하고 stream cancellation failure가 안정적인 진단을 덮지 않으며 reader lock을 정리한다. Fatal UTF-8/JSON admission과 exact execution/plan/task 검증은 유지한다. 이 protected source는 immutable release, deployed Durable Object p95/recovery, graph publication 또는 activation authority를 대신하지 않는다. PR #652. -- Distributed `/exchange` rate-limit의 private Durable Object request(256 bytes)와 decision response(4,096-byte) bounded stream reader가 허용 chunk를 배열에 누적하지 않고 각 byte ceiling 크기의 고정 `Uint8Array`에 직접 복사하도록 바꾼다. 합법적인 high-fragmentation stream이 accepted-byte ceiling과 별개로 retained chunk object/backing-store 수와 두 번째 합산 allocation을 키우지 않으며 초과 chunk는 copy 전에 실패-폐쇄한다. 기존 cancellation, fatal UTF-8·duplicate-key·JSON admission, bucket/identity/Durable Object authority는 유지한다. 이 source hardening은 immutable release나 deployed heap/p95 evidence를 대신하지 않는다. PR #650. +- Distributed `/exchange` rate-limit의 private Durable Object request(256 bytes)와 decision response(4,096 bytes) bounded stream reader가 허용 chunk를 배열에 누적하지 않고 각 byte ceiling 크기의 고정 `Uint8Array`에 직접 복사하도록 바꾼다. 합법적인 high-fragmentation stream이 accepted-byte ceiling과 별개로 retained chunk object/backing-store 수와 두 번째 합산 allocation을 키우지 않으며 초과 chunk는 copy 전에 실패-폐쇄한다. 기존 cancellation, fatal UTF-8·duplicate-key·JSON admission, bucket/identity/Durable Object authority는 유지한다. 이 source hardening은 immutable release나 deployed heap/p95 evidence를 대신하지 않는다. PR #650. - Base credential-exchange의 OIDC discovery/JWKS·GitHub API bounded JSON response reader가 허용 chunk를 배열에 누적하지 않고 65,536-byte 고정 버퍼에 직접 복사하도록 바꾼다. Stream fragmentation이 accepted-byte ceiling과 별개로 retained chunk object/backing-store 수와 두 번째 합산 allocation을 키우지 않으며, 초과 chunk는 복사 전에 실패-폐쇄한다. 기존 10초 wall-clock deadline, cancellation, fatal UTF-8·duplicate-key·JSON admission, OIDC/GitHub identity·credential authority는 유지한다. 이 source hardening은 immutable release나 production p95/heap evidence를 대신하지 않는다. PR #646. - Workflow registry disable/plan 운영 경로의 GitHub JSON 응답 reader도 고정 `Uint8Array(MAX_RESPONSE_BYTES)`에 직접 수신해 합법적인 고분할 stream이 chunk-object retention과 두 번째 합산 allocation을 키우지 않도록 한다. Oversize는 copy 전에 실패-폐쇄하며 기존 pagination·registry identity·single-workflow disable authority는 유지한다. 이 source hardening은 live registry cleanliness나 immutable release evidence를 대신하지 않는다. PR #645. - Trivy v0.74.0의 vendor-severity diagnostic은 취약점 정책을 약화하거나 로그를 조용하게 만들 이유가 아니므로 reviewer-ci·central review·patch-validator image의 severity source를 기본 `auto`로 유지한다. OS vendor advisory와 backport-aware severity attribution(`SeveritySource`/`VendorSeverity`)을 보존하고 `--vuln-severity-source`를 강제하지 않으며, diagnostic은 의도적으로 visible 상태로 남긴다. Severity threshold·exit behavior·ignore policy·scanner coverage는 변경하지 않는다. PR #637. @@ -54,7 +54,7 @@ - `noema-core` provider-neutral Shared Kernel을 추가하여 이미 해석된 PydanticAI `Model`과 역할별 prompt/schema만 받아 Agent를 구성한다. 문자열 model identifier와 provider discovery·credential·routing·retry·failover는 Shared Kernel 밖에 두고 `Agent(..., retries=0)`으로 repository-local model-attempt authority를 만들지 않는다. Reviewer wheel·sdist·editable 설치는 canonical `packages/noema-core` source를 포함하거나 참조하며 별도 100% coverage·docstring과 clean install smoke로 검증한다. 외부 소비는 immutable versioned publication·exact source identity·SBOM/provenance·licensing/NOTICE·compatibility/rollback evidence 전에는 허용하지 않는다. - `writeAcquisitionPrivateFile`의 기존 대상 사전-교체 검증 read(`existingDescriptor` open)에 `O_NONBLOCK`을 추가해 fail-closed를 강화한다. 이 open은 이미 필수 filesystem capability로 `O_NONBLOCK`을 검증했지만 실제로는 사용하지 않아, 로컬 권한을 가진 행위자가 사전 `lstatSync` 정규 파일 확인과 이 open 사이에 대상 경로를 FIFO로 교체하면 writer가 나타날 때까지 무한정 블로킹해 writer lease를 계속 점유할 수 있었다. `O_NONBLOCK`은 정규 파일에는 영향이 없고, FIFO에서는 open이 즉시 반환되어 이어지는 descriptor 타입 검증이 그대로 fail-closed로 거부한다. 회귀 테스트(`test/acquisition-private-output-existing-target-nonblocking.test.ts`)와 기존 open-flags 계약 테스트 갱신으로 고정했다. - `readStableFile`의 close-후 재검증 단계(`afterClosePath` lookup 실패)와 `writeAcquisitionPrivateFile`의 cleanup-시점 `O_NONBLOCK` 소실 분기에 대한 fail-closed 회귀 테스트를 추가해 `scripts/lib/acquisition-data-room-integrity.mjs`/`scripts/lib/acquisition-private-output.mjs`의 100% coverage 게이트를 복구한다. 동작 변화는 없다. -- Noema reviewer의 strict changed-file evidence를 historical 12-file prefix에서 canonical 80-file CodeGraph scope와 일치시켰다. 13–80 file PR은 선택된 모든 current-head file context를 유지하고 81개 이상은 기존처럼 실패-폐쇄하며, local CodeGraph fallback의 `HOME`·`TEMP`·`TMP`·`TMPDIR`은 ambient host path를 상속하지 않고 실행마다 새 private temporary directory로 격리한다. +- Noema reviewer의 strict changed-file evidence를 historical 12-file prefix에서 canonical 80-file CodeGraph scope와 일치시켰다. 13–80 file PR은 선택된 모든 current-head file context를 유지하고 81개 이상은 기존처럼 실패-폐쇄하며, local CodeGraph fallback의 `HOME`·`TEMP`·`TMPDIR`은 ambient host path를 상속하지 않고 실행마다 새 private temporary directory로 격리한다. - Workflow / Task Execution은 untrusted DAG를 execution/plan identity에 결합한 detached immutable snapshot으로 승인하고, validated array bounds 안에서만 task/dependency/state evidence를 읽는다. runnable 선택은 cross-execution·foreign·duplicate·non-canonical evidence, admitted concurrency를 초과한 running state, 성공하지 않은 prerequisite 뒤에 존재하는 causally impossible executed state를 실패-폐쇄하며, 선택 결과는 reservation이나 side-effect authority가 아닌 후보임을 명시한다. Agent Runtime lifecycle·State & Checkpoint·Workflow admission은 null·throwing accessor·revoked proxy 같은 malformed runtime input의 임의 JavaScript 예외를 각 bounded-context domain error로 정규화한다. - State & Checkpoint admission은 accepted/replay 결과와 내부 checkpoint를 모두 caller-owned alias에서 분리한 frozen snapshot으로 반환한다. TypeScript `readonly`만으로는 막을 수 없는 JavaScript 런타임 alias mutation이 승인된 checkpoint authority나 `accepted`/`replay` 분류를 사후 변경하지 못하도록 실패-폐쇄한다. - Noema의 필수 PR 워크플로 `ci`, `reviewer-ci`, `patch-validator-image`를 부동 `ubuntu-latest` 대신 명시적 `ubuntu-24.04` GitHub-hosted runner에 고정하고, 인용 여부와 무관하게 `ubuntu-latest` 회귀를 탐지하는 계약 테스트를 추가해 pre-checkout runner-assignment stall의 repository-owned selector 원인을 제거한다. 중앙 `Security Scan`의 runner/control-plane 권한은 별도 `.github` owner 경계에 유지한다. From c4dc70f28c51f05118be73a05b8d6fd20227a2a4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:14:30 +0900 Subject: [PATCH 11/14] fix: restore historical changelog context --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1643c167c..143842f0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ - Protected #693 normalizes reader acquisition on the shared 65,536-byte external JSON response reader used by GitHub OIDC discovery, JWKS, and GitHub API responses at exact source `c23a2bcf5e79eea5f095fb3516e28397899c87c9`. If an already locked or otherwise non-stream-readable response body makes `response.body.getReader()` throw synchronously, Noema fails closed with the path-specific stable `GitHub OIDC discovery response body could not be read`, `GitHub OIDC JWKS response body could not be read`, or `GitHub API response body could not be read` diagnostic instead of misclassifying that transport failure as malformed JSON. Existing 65,536-byte ceiling, 10-second absolute deadline, fixed retained buffer, best-effort cancellation, fatal UTF-8, duplicate-key and JSON admission, and reader-lock cleanup after successful acquisition remain unchanged. OIDC/GitHub identity, provider/model routing, destination/outbound policy, credential authority, quarantine/security authority, release/deployment authority, and foreign-domain truth remain with their existing owners; protected source is not an immutable release, production deployment, recovery rehearsal, or deployed p95/heap evidence. PR #693. - Protected #691 normalizes reader acquisition on the read-only private-vulnerability-reporting audit at exact source `65e0d3dd3c4060ba0057ba13cf6c9ea23b03373d`. If an already locked or otherwise non-stream-readable GitHub response body makes `response.body.getReader()` throw synchronously, Noema fails closed with the stable `GitHub private vulnerability reporting response body could not be read.` diagnostic. Existing 16 KiB response ceiling, JSON media-type gate, fatal UTF-8, duplicate-key and JSON admission, best-effort oversize cancellation, and reader-lock cleanup after successful acquisition remain unchanged. GitHub private-vulnerability-reporting setting, security, outbound, credential, release/deployment, and foreign-domain authority remain with their existing owners; protected source is not an immutable release, production deployment, live private-vulnerability-reporting enablement or notification staffing, recovery rehearsal, or deployed p95/heap evidence. PR #691. - Protected #689 normalizes reader acquisition on the public `/exchange` bounded JSON request body at exact source `b838c352a7cd0f7f58a905857537a3a9675a56f2`. If an already locked or otherwise non-stream-readable body makes `request.body.getReader()` throw synchronously, Noema returns the established `400` / `ERR_VALIDATION_INPUT` / `unreadable` contract before credential egress. Existing 8,192-byte ceiling, 10-second absolute deadline, media-type and JSON admission, best-effort cancellation, and reader-lock cleanup after successful acquisition remain unchanged. Provider/model routing, destination/outbound policy, credential authority, quarantine/security authority, release/deployment authority, and foreign-domain truth remain with their existing owners; protected source is not an immutable release, production deployment, recovery rehearsal, or deployed p95/heap evidence. PR #689. -- Protected #687 normalizes reader acquisition on the distributed `/exchange` private Durable Object rate-limit transport. If an already locked/non-stream-readable 256-byte internal request makes `request.body.getReader()` throw synchronously, it returns the established `400 malformed_json` contract before storage authority; a locked 4,096-byte decision response fails closed with the stable `rate-limit Durable Object decision body could not be read` diagnostic. Existing fixed retained buffers, byte ceilings, best-effort cancellation, reader-lock release after successful acquisition, fatal UTF-8·duplicate-key·JSON admission, and bucket/identity/Durable Object authority remain unchanged. Provider/model routing, destination/outbound policy, credential authority, quarantine/security authority, release/deployment authority, and foreign-domain truth remain with their existing owners; this protected source is not an immutable release or deployed recovery/p95/heap evidence. PR #687. +- Protected #687 normalizes reader acquisition on the distributed `/exchange` private Durable Object rate-limit transport. If an already locked/non-stream-readable 256-byte internal request makes `request.body.getReader()` throw synchronously, it returns the established `400 malformed_json` contract before storage authority; a locked 4,096-byte decision response fails closed with the stable `rate-limit Durable Object decision body could not be read` diagnostic. Existing fixed retained buffers, byte ceilings, best-effort cancellation, reader-lock release after successful acquisition, fatal UTF-8·duplicate-key·JSON admission, and bucket/identity/Durable Object authority remain unchanged. Provider/model routing, destination/outbound policy, credential authority, quarantine/security authority, release/deployment, and foreign-domain truth remain with their existing owners; this protected source is not an immutable release or deployed recovery/p95/heap evidence. PR #687. - Protected #685 normalizes reader acquisition on Noema's OIDC replay guard bounded transport. If an already locked/non-stream-readable 4,096-byte decision response makes `response.body.getReader()` throw synchronously, the reader now fails closed with the stable `OIDC replay guard decision body could not be read` diagnostic; a locked 512-byte internal claim request returns the established `400 malformed_json` contract before Durable Object storage authority. Existing fixed retained buffers, byte ceilings, best-effort cancellation, reader-lock release after successful acquisition, fatal UTF-8·duplicate-key·JSON admission, and replay/storage authority remain unchanged. OIDC/GitHub identity, provider/model routing, destination/outbound policy, credential, quarantine/security, release/deployment, and foreign-domain authority remain with their existing owners; this protected source is not an immutable release or deployed recovery/p95/heap evidence. PR #685. - Protected #683 normalizes reader acquisition on the 1 MiB bounded Cloudflare production control-plane deploy/status/recovery response transport. If a locked Cloudflare control-plane response body makes `body.getReader()` throw synchronously, the reader now fails closed with the stable `${operation} response body is not stream-readable` diagnostic instead of leaking the raw stream exception; the existing fixed retained buffer, byte ceiling, timeout, cancellation-liveness, reader-lock, fatal UTF-8/JSON and provider-error semantics remain unchanged. This repair does not transfer Cloudflare/provider authority, destination/outbound policy, credential authority, quarantine/security authority, release/deployment authority or foreign domain truth into Noema, and protected source is not an immutable release, controlled production recovery rehearsal or deployed p95/heap evidence. PR #683. - Protected #681 keeps the authenticated Distroless Debian 13 CodeGraph sandbox and existing Trivy MEDIUM/HIGH/CRITICAL fail-closed scan while repairing the reviewed glibc substrate at `2.41-12+deb13u4`. The shared preparation contract uses authenticated Debian snapshot `20260711T202405Z`, admits only the exact Debian 12 and Debian 13 automatic archive primary keys needed for that signed historical transition, verifies `InRelease`→`Packages.xz`→exact package digests, and accepts the derived local immutable image ID only after the same Trivy gate. This reviewer-isolation integration does not transfer quarantine/security verdict, provider/model routing, outbound authority, release/deployment authority, or foreign domain truth into Noema, and the ephemeral CI image is not an immutable release. PR #681. @@ -54,7 +54,7 @@ - `noema-core` provider-neutral Shared Kernel을 추가하여 이미 해석된 PydanticAI `Model`과 역할별 prompt/schema만 받아 Agent를 구성한다. 문자열 model identifier와 provider discovery·credential·routing·retry·failover는 Shared Kernel 밖에 두고 `Agent(..., retries=0)`으로 repository-local model-attempt authority를 만들지 않는다. Reviewer wheel·sdist·editable 설치는 canonical `packages/noema-core` source를 포함하거나 참조하며 별도 100% coverage·docstring과 clean install smoke로 검증한다. 외부 소비는 immutable versioned publication·exact source identity·SBOM/provenance·licensing/NOTICE·compatibility/rollback evidence 전에는 허용하지 않는다. - `writeAcquisitionPrivateFile`의 기존 대상 사전-교체 검증 read(`existingDescriptor` open)에 `O_NONBLOCK`을 추가해 fail-closed를 강화한다. 이 open은 이미 필수 filesystem capability로 `O_NONBLOCK`을 검증했지만 실제로는 사용하지 않아, 로컬 권한을 가진 행위자가 사전 `lstatSync` 정규 파일 확인과 이 open 사이에 대상 경로를 FIFO로 교체하면 writer가 나타날 때까지 무한정 블로킹해 writer lease를 계속 점유할 수 있었다. `O_NONBLOCK`은 정규 파일에는 영향이 없고, FIFO에서는 open이 즉시 반환되어 이어지는 descriptor 타입 검증이 그대로 fail-closed로 거부한다. 회귀 테스트(`test/acquisition-private-output-existing-target-nonblocking.test.ts`)와 기존 open-flags 계약 테스트 갱신으로 고정했다. - `readStableFile`의 close-후 재검증 단계(`afterClosePath` lookup 실패)와 `writeAcquisitionPrivateFile`의 cleanup-시점 `O_NONBLOCK` 소실 분기에 대한 fail-closed 회귀 테스트를 추가해 `scripts/lib/acquisition-data-room-integrity.mjs`/`scripts/lib/acquisition-private-output.mjs`의 100% coverage 게이트를 복구한다. 동작 변화는 없다. -- Noema reviewer의 strict changed-file evidence를 historical 12-file prefix에서 canonical 80-file CodeGraph scope와 일치시켰다. 13–80 file PR은 선택된 모든 current-head file context를 유지하고 81개 이상은 기존처럼 실패-폐쇄하며, local CodeGraph fallback의 `HOME`·`TEMP`·`TMPDIR`은 ambient host path를 상속하지 않고 실행마다 새 private temporary directory로 격리한다. +- Noema reviewer의 strict changed-file evidence를 historical 12-file prefix에서 canonical 80-file CodeGraph scope와 일치시켰다. 13–80 file PR은 선택된 모든 current-head file context를 유지하고 81개 이상은 기존처럼 실패-폐쇄하며, local CodeGraph fallback의 `HOME`·`TEMP`·`TMP`·`TMPDIR`은 ambient host path를 상속하지 않고 실행마다 새 private temporary directory로 격리한다. - Workflow / Task Execution은 untrusted DAG를 execution/plan identity에 결합한 detached immutable snapshot으로 승인하고, validated array bounds 안에서만 task/dependency/state evidence를 읽는다. runnable 선택은 cross-execution·foreign·duplicate·non-canonical evidence, admitted concurrency를 초과한 running state, 성공하지 않은 prerequisite 뒤에 존재하는 causally impossible executed state를 실패-폐쇄하며, 선택 결과는 reservation이나 side-effect authority가 아닌 후보임을 명시한다. Agent Runtime lifecycle·State & Checkpoint·Workflow admission은 null·throwing accessor·revoked proxy 같은 malformed runtime input의 임의 JavaScript 예외를 각 bounded-context domain error로 정규화한다. - State & Checkpoint admission은 accepted/replay 결과와 내부 checkpoint를 모두 caller-owned alias에서 분리한 frozen snapshot으로 반환한다. TypeScript `readonly`만으로는 막을 수 없는 JavaScript 런타임 alias mutation이 승인된 checkpoint authority나 `accepted`/`replay` 분류를 사후 변경하지 못하도록 실패-폐쇄한다. - Noema의 필수 PR 워크플로 `ci`, `reviewer-ci`, `patch-validator-image`를 부동 `ubuntu-latest` 대신 명시적 `ubuntu-24.04` GitHub-hosted runner에 고정하고, 인용 여부와 무관하게 `ubuntu-latest` 회귀를 탐지하는 계약 테스트를 추가해 pre-checkout runner-assignment stall의 repository-owned selector 원인을 제거한다. 중앙 `Security Scan`의 runner/control-plane 권한은 별도 `.github` owner 경계에 유지한다. From 8ea6a470da20d0932cf69aa7cfe932aa1f82121f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:18:05 +0900 Subject: [PATCH 12/14] fix: restore #687 authority wording --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 143842f0b..fb0849e33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ - Protected #693 normalizes reader acquisition on the shared 65,536-byte external JSON response reader used by GitHub OIDC discovery, JWKS, and GitHub API responses at exact source `c23a2bcf5e79eea5f095fb3516e28397899c87c9`. If an already locked or otherwise non-stream-readable response body makes `response.body.getReader()` throw synchronously, Noema fails closed with the path-specific stable `GitHub OIDC discovery response body could not be read`, `GitHub OIDC JWKS response body could not be read`, or `GitHub API response body could not be read` diagnostic instead of misclassifying that transport failure as malformed JSON. Existing 65,536-byte ceiling, 10-second absolute deadline, fixed retained buffer, best-effort cancellation, fatal UTF-8, duplicate-key and JSON admission, and reader-lock cleanup after successful acquisition remain unchanged. OIDC/GitHub identity, provider/model routing, destination/outbound policy, credential authority, quarantine/security authority, release/deployment authority, and foreign-domain truth remain with their existing owners; protected source is not an immutable release, production deployment, recovery rehearsal, or deployed p95/heap evidence. PR #693. - Protected #691 normalizes reader acquisition on the read-only private-vulnerability-reporting audit at exact source `65e0d3dd3c4060ba0057ba13cf6c9ea23b03373d`. If an already locked or otherwise non-stream-readable GitHub response body makes `response.body.getReader()` throw synchronously, Noema fails closed with the stable `GitHub private vulnerability reporting response body could not be read.` diagnostic. Existing 16 KiB response ceiling, JSON media-type gate, fatal UTF-8, duplicate-key and JSON admission, best-effort oversize cancellation, and reader-lock cleanup after successful acquisition remain unchanged. GitHub private-vulnerability-reporting setting, security, outbound, credential, release/deployment, and foreign-domain authority remain with their existing owners; protected source is not an immutable release, production deployment, live private-vulnerability-reporting enablement or notification staffing, recovery rehearsal, or deployed p95/heap evidence. PR #691. - Protected #689 normalizes reader acquisition on the public `/exchange` bounded JSON request body at exact source `b838c352a7cd0f7f58a905857537a3a9675a56f2`. If an already locked or otherwise non-stream-readable body makes `request.body.getReader()` throw synchronously, Noema returns the established `400` / `ERR_VALIDATION_INPUT` / `unreadable` contract before credential egress. Existing 8,192-byte ceiling, 10-second absolute deadline, media-type and JSON admission, best-effort cancellation, and reader-lock cleanup after successful acquisition remain unchanged. Provider/model routing, destination/outbound policy, credential authority, quarantine/security authority, release/deployment authority, and foreign-domain truth remain with their existing owners; protected source is not an immutable release, production deployment, recovery rehearsal, or deployed p95/heap evidence. PR #689. -- Protected #687 normalizes reader acquisition on the distributed `/exchange` private Durable Object rate-limit transport. If an already locked/non-stream-readable 256-byte internal request makes `request.body.getReader()` throw synchronously, it returns the established `400 malformed_json` contract before storage authority; a locked 4,096-byte decision response fails closed with the stable `rate-limit Durable Object decision body could not be read` diagnostic. Existing fixed retained buffers, byte ceilings, best-effort cancellation, reader-lock release after successful acquisition, fatal UTF-8·duplicate-key·JSON admission, and bucket/identity/Durable Object authority remain unchanged. Provider/model routing, destination/outbound policy, credential authority, quarantine/security authority, release/deployment, and foreign-domain truth remain with their existing owners; this protected source is not an immutable release or deployed recovery/p95/heap evidence. PR #687. +- Protected #687 normalizes reader acquisition on the distributed `/exchange` private Durable Object rate-limit transport. If an already locked/non-stream-readable 256-byte internal request makes `request.body.getReader()` throw synchronously, it returns the established `400 malformed_json` contract before storage authority; a locked 4,096-byte decision response fails closed with the stable `rate-limit Durable Object decision body could not be read` diagnostic. Existing fixed retained buffers, byte ceilings, best-effort cancellation, reader-lock release after successful acquisition, fatal UTF-8·duplicate-key·JSON admission, and bucket/identity/Durable Object authority remain unchanged. Provider/model routing, destination/outbound policy, credential authority, quarantine/security authority, release/deployment authority, and foreign-domain truth remain with their existing owners; this protected source is not an immutable release or deployed recovery/p95/heap evidence. PR #687. - Protected #685 normalizes reader acquisition on Noema's OIDC replay guard bounded transport. If an already locked/non-stream-readable 4,096-byte decision response makes `response.body.getReader()` throw synchronously, the reader now fails closed with the stable `OIDC replay guard decision body could not be read` diagnostic; a locked 512-byte internal claim request returns the established `400 malformed_json` contract before Durable Object storage authority. Existing fixed retained buffers, byte ceilings, best-effort cancellation, reader-lock release after successful acquisition, fatal UTF-8·duplicate-key·JSON admission, and replay/storage authority remain unchanged. OIDC/GitHub identity, provider/model routing, destination/outbound policy, credential, quarantine/security, release/deployment, and foreign-domain authority remain with their existing owners; this protected source is not an immutable release or deployed recovery/p95/heap evidence. PR #685. - Protected #683 normalizes reader acquisition on the 1 MiB bounded Cloudflare production control-plane deploy/status/recovery response transport. If a locked Cloudflare control-plane response body makes `body.getReader()` throw synchronously, the reader now fails closed with the stable `${operation} response body is not stream-readable` diagnostic instead of leaking the raw stream exception; the existing fixed retained buffer, byte ceiling, timeout, cancellation-liveness, reader-lock, fatal UTF-8/JSON and provider-error semantics remain unchanged. This repair does not transfer Cloudflare/provider authority, destination/outbound policy, credential authority, quarantine/security authority, release/deployment authority or foreign domain truth into Noema, and protected source is not an immutable release, controlled production recovery rehearsal or deployed p95/heap evidence. PR #683. - Protected #681 keeps the authenticated Distroless Debian 13 CodeGraph sandbox and existing Trivy MEDIUM/HIGH/CRITICAL fail-closed scan while repairing the reviewed glibc substrate at `2.41-12+deb13u4`. The shared preparation contract uses authenticated Debian snapshot `20260711T202405Z`, admits only the exact Debian 12 and Debian 13 automatic archive primary keys needed for that signed historical transition, verifies `InRelease`→`Packages.xz`→exact package digests, and accepts the derived local immutable image ID only after the same Trivy gate. This reviewer-isolation integration does not transfer quarantine/security verdict, provider/model routing, outbound authority, release/deployment authority, or foreign domain truth into Noema, and the ephemeral CI image is not an immutable release. PR #681. From 089af44b33eb88c957ec9fe4ff24379c801b1e0e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:20:57 +0900 Subject: [PATCH 13/14] test: prove #704 authority must be section scoped --- ...-current-lifecycle-media-authority.test.ts | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/procedural-current-lifecycle-media-authority.test.ts b/test/procedural-current-lifecycle-media-authority.test.ts index 9cd7390d4..68686b9d8 100644 --- a/test/procedural-current-lifecycle-media-authority.test.ts +++ b/test/procedural-current-lifecycle-media-authority.test.ts @@ -2,7 +2,29 @@ import { readFileSync } from "node:fs"; import { describe, expect, it } from "vitest"; +const REQUIRED_704_CHANGELOG_FRAGMENTS = [ + "Protected #704", + "42b15e865bdf88fde622c3bba2c0b123770d18be", + "e8c2002e5af8fa5611880091dab81916bb716c35", + "application/json with optional `charset=utf-8` parameter", + "invalid_workflow_state_response", + "best-effort cleanup", +] as const; + +function hasProtected704ChangelogAuthority(changelog: string): boolean { + return REQUIRED_704_CHANGELOG_FRAGMENTS.every((fragment) => changelog.includes(fragment)); +} + describe("protected procedural current-lifecycle media documentation authority", () => { + it("rejects authority fragments that are only present in a neighboring changelog entry", () => { + const relocatedAuthority = [ + "- Protected #704 exact `42b15e865bdf88fde622c3bba2c0b123770d18be`.", + "- Protected #702 exact `2b31805eb2b81b6078fefe1ebcce8007b6ca5169`, integrated by GitHub-verified normal merge `e8c2002e5af8fa5611880091dab81916bb716c35`, requires application/json with optional `charset=utf-8` parameter and preserves invalid_workflow_state_response with best-effort cleanup.", + ].join("\n"); + + expect(hasProtected704ChangelogAuthority(relocatedAuthority)).toBe(false); + }); + it("records protected #704 without promoting Workflow / Task or production authority", () => { const baseline = readFileSync("docs/product-technical-gap-baseline.md", "utf8"); const changelog = readFileSync("CHANGELOG.md", "utf8"); From 164c5a86dd40f047c459f430cfa2c658a0b2017a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:23:50 +0900 Subject: [PATCH 14/14] test: scope #704 documentation authority checks --- ...-current-lifecycle-media-authority.test.ts | 79 ++++++++++++++----- 1 file changed, 59 insertions(+), 20 deletions(-) diff --git a/test/procedural-current-lifecycle-media-authority.test.ts b/test/procedural-current-lifecycle-media-authority.test.ts index 68686b9d8..3ae1e4d7a 100644 --- a/test/procedural-current-lifecycle-media-authority.test.ts +++ b/test/procedural-current-lifecycle-media-authority.test.ts @@ -2,6 +2,10 @@ import { readFileSync } from "node:fs"; import { describe, expect, it } from "vitest"; +const CHANGELOG_704_MARKER = "- Protected #704 "; +const BASELINE_704_HEADING = + "## Protected procedural current-lifecycle media admission — merged PR #704"; + const REQUIRED_704_CHANGELOG_FRAGMENTS = [ "Protected #704", "42b15e865bdf88fde622c3bba2c0b123770d18be", @@ -11,41 +15,76 @@ const REQUIRED_704_CHANGELOG_FRAGMENTS = [ "best-effort cleanup", ] as const; +const REQUIRED_704_BASELINE_FRAGMENTS = [ + "merged PR #704 exact `42b15e865bdf88fde622c3bba2c0b123770d18be`", + "GitHub-verified normal merge `e8c2002e5af8fa5611880091dab81916bb716c35`", + "application/json with optional `charset=utf-8` parameter", + "stable `invalid_workflow_state_response`", + "best-effort cleanup", + "immutable release", +] as const; + +function extractChangelog704Entry(changelog: string): string { + const start = changelog.indexOf(CHANGELOG_704_MARKER); + if (start < 0) { + return ""; + } + const nextEntry = changelog.indexOf("\n- ", start + CHANGELOG_704_MARKER.length); + return changelog.slice(start, nextEntry < 0 ? changelog.length : nextEntry); +} + +function extractBaseline704Section(baseline: string): string { + const start = baseline.indexOf(BASELINE_704_HEADING); + if (start < 0) { + return ""; + } + const nextSection = baseline.indexOf("\n## ", start + BASELINE_704_HEADING.length); + return baseline.slice(start, nextSection < 0 ? baseline.length : nextSection); +} + function hasProtected704ChangelogAuthority(changelog: string): boolean { - return REQUIRED_704_CHANGELOG_FRAGMENTS.every((fragment) => changelog.includes(fragment)); + const entry = extractChangelog704Entry(changelog); + return REQUIRED_704_CHANGELOG_FRAGMENTS.every((fragment) => entry.includes(fragment)); +} + +function hasProtected704BaselineAuthority(baseline: string): boolean { + const section = extractBaseline704Section(baseline); + return REQUIRED_704_BASELINE_FRAGMENTS.every((fragment) => section.includes(fragment)); } describe("protected procedural current-lifecycle media documentation authority", () => { - it("rejects authority fragments that are only present in a neighboring changelog entry", () => { - const relocatedAuthority = [ + it("rejects authority fragments that are only present in neighboring documentation", () => { + const relocatedChangelogAuthority = [ "- Protected #704 exact `42b15e865bdf88fde622c3bba2c0b123770d18be`.", "- Protected #702 exact `2b31805eb2b81b6078fefe1ebcce8007b6ca5169`, integrated by GitHub-verified normal merge `e8c2002e5af8fa5611880091dab81916bb716c35`, requires application/json with optional `charset=utf-8` parameter and preserves invalid_workflow_state_response with best-effort cleanup.", ].join("\n"); + const relocatedBaselineAuthority = [ + `${BASELINE_704_HEADING}\n\nProtected history includes merged PR #704 exact \`42b15e865bdf88fde622c3bba2c0b123770d18be\`.`, + "## Protected neighboring authority", + "GitHub-verified normal merge `e8c2002e5af8fa5611880091dab81916bb716c35` uses application/json with optional `charset=utf-8` parameter, stable `invalid_workflow_state_response`, best-effort cleanup, and remains separate from immutable release evidence.", + ].join("\n\n"); - expect(hasProtected704ChangelogAuthority(relocatedAuthority)).toBe(false); + expect(hasProtected704ChangelogAuthority(relocatedChangelogAuthority)).toBe(false); + expect(hasProtected704BaselineAuthority(relocatedBaselineAuthority)).toBe(false); }); it("records protected #704 without promoting Workflow / Task or production authority", () => { const baseline = readFileSync("docs/product-technical-gap-baseline.md", "utf8"); const changelog = readFileSync("CHANGELOG.md", "utf8"); const source = readFileSync("src/agent-runtime/procedural-current-lifecycle.ts", "utf8"); + const changelog704 = extractChangelog704Entry(changelog); + const baseline704 = extractBaseline704Section(baseline); + + expect(changelog704).not.toBe(""); + for (const fragment of REQUIRED_704_CHANGELOG_FRAGMENTS) { + expect(changelog704).toContain(fragment); + } - expect(changelog).toContain("Protected #704"); - expect(changelog).toContain("42b15e865bdf88fde622c3bba2c0b123770d18be"); - expect(changelog).toContain("e8c2002e5af8fa5611880091dab81916bb716c35"); - expect(changelog).toContain("application/json with optional `charset=utf-8` parameter"); - expect(changelog).toContain("invalid_workflow_state_response"); - expect(changelog).toContain("best-effort cleanup"); - - expect(baseline).toContain( - "merged PR #704 exact `42b15e865bdf88fde622c3bba2c0b123770d18be`", - ); - expect(baseline).toContain("GitHub-verified normal merge `e8c2002e5af8fa5611880091dab81916bb716c35`"); - expect(baseline).toContain("application/json with optional `charset=utf-8` parameter"); - expect(baseline).toContain("stable `invalid_workflow_state_response`"); - expect(baseline).toContain("best-effort cleanup"); - expect(baseline).toContain("immutable release"); - expect(baseline).not.toContain("#704 transfers Workflow / Task lifecycle authority to Agent Runtime"); + expect(baseline704).not.toBe(""); + for (const fragment of REQUIRED_704_BASELINE_FRAGMENTS) { + expect(baseline704).toContain(fragment); + } + expect(baseline704).not.toContain("#704 transfers Workflow / Task lifecycle authority to Agent Runtime"); expect(source).toContain("function isJsonMediaType(value: string | null): boolean"); expect(source).toContain("Noema current workflow-state response used an unsupported media type");