Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
1f2465a
docs(dispatch): design least-privilege continuation broker
seonghobae Sep 30, 2026
70e5a16
test+feat(dispatch): define closed continuation contract
seonghobae Sep 30, 2026
4d9b040
test+feat(dispatch): add exactly-once continuation state
seonghobae Sep 30, 2026
9509527
docs(dispatch): record exactly-once state completion
seonghobae Sep 30, 2026
700c7fa
test+feat(dispatch): bind live PR and fixed central event
seonghobae Sep 30, 2026
35d5bfe
docs(dispatch): record Task 3 completion
seonghobae Sep 30, 2026
f55b412
test+feat(dispatch): issue signed continuation receipts
seonghobae Sep 30, 2026
6f7b7dc
docs(dispatch): record Task 4 completion
seonghobae Sep 30, 2026
d47d840
fix(security): update patch-validator Node runtime
seonghobae Sep 30, 2026
c618677
docs: record patch-validator security RCA
seonghobae Sep 30, 2026
df3c8e3
test+feat(dispatch): expose versioned continuation broker
seonghobae Sep 30, 2026
17b80d8
docs(dispatch): publish broker contracts and release gates
seonghobae Sep 30, 2026
c87db11
fix(dispatch): serialize retries and preserve terminal evidence
seonghobae Sep 30, 2026
08d501c
docs: integrate concurrent patch validator repair
seonghobae Sep 30, 2026
abea8f3
merge: integrate continuation broker and patch-validator repair
seonghobae Sep 30, 2026
09610da
test(dispatch): close continuation coverage gaps
seonghobae Sep 30, 2026
f7bcee6
test(dispatch): cover integrated broker boundaries
seonghobae Sep 30, 2026
ad610e0
merge: integrate #737 Undici evidence into #736
seonghobae Sep 30, 2026
fb360d3
test(dispatch): expose review boundary gaps
seonghobae Sep 30, 2026
2209882
fix(dispatch): preserve pre-effect retry authority
seonghobae Sep 30, 2026
5c6d2f8
docs(dispatch): specify shared payload contract
seonghobae Sep 30, 2026
e8e1532
test(dispatch): reproduce review contract gaps
seonghobae Sep 30, 2026
a6ad725
fix(dispatch): harden pre-effect recovery
seonghobae Sep 30, 2026
44b0678
merge: integrate concurrent #736 review repair
seonghobae Sep 30, 2026
c87d001
test(dispatch): cover exact expiry recovery paths
seonghobae Sep 30, 2026
c66fb9a
test(dispatch): cover fresh reserve after expiry
seonghobae Sep 30, 2026
7965976
fix(dispatch): reserve after expired authority cleanup
seonghobae Sep 30, 2026
4271510
docs(gap): record exact-expiry reservation recovery
seonghobae Sep 30, 2026
b1dddb7
docs(changelog): record expiry recovery repair
seonghobae Sep 30, 2026
5d8aff6
fix(dispatch): narrow retained state before reuse
seonghobae Sep 30, 2026
8f46eb3
test(dispatch): remove fixed OIDC expiry time bomb
seonghobae Sep 30, 2026
1de7255
docs(changelog): cover all expiry fixtures
seonghobae Sep 30, 2026
20fd1aa
fix(api): document continuation configuration failures
seonghobae Sep 30, 2026
1bd5fce
fix(api): validate overlapping 503 error contracts
seonghobae Sep 30, 2026
2a4488c
test(dispatch): reproduce post-commit pre-effect expiry
seonghobae Sep 30, 2026
350a366
fix(dispatch): recover proven pre-effect expiry
seonghobae Sep 30, 2026
8156891
docs(dispatch): bind pre-effect retry evidence
seonghobae Sep 30, 2026
7487485
fix(dispatch): attribute boundary failures to requested route
seonghobae Oct 1, 2026
b637890
merge: integrate gateway endpoint authority prerequisite
seonghobae Oct 1, 2026
a5d65a4
merge: advance patch-validator prerequisite evidence
seonghobae Oct 1, 2026
9e8bd9b
docs(gap): reconcile continuation merge evidence
seonghobae Oct 1, 2026
dbe22c0
merge: advance current patch-validator prerequisite
seonghobae Oct 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
- 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
- Review repair for Proposed #736 makes the continuation boundary's error and recovery contracts executable: the OpenAPI route now declares its 10-second body-read deadline and `408`; every `401` includes the Bearer challenge and stable hint; retained denied/indeterminate replays preserve `502`/`503` plus exact-replay evidence; and the overlapping generic/signed 503 shapes use `anyOf` with a representative payload validation rather than a vacuous `oneOf`. The central App credential is prepared before the durable pre-dispatch commit and checked against its exact GitHub `expires_at` immediately before commit and send; pre-effect preparation/commit failures abort the reservation; and a crash-stranded reservation expires only at the exact retained OIDC `exp` through a Durable Object alarm. Reservation creation and commit transactionally reject expired authority even when alarm delivery is late; expired retained reservations are deleted and treated as absent in the same transaction, allowing replacement only when the newly presented OIDC expiry remains live. Calendar-relative continuation state and Worker tests remove the fixed-2027 expiry time bomb. Legacy v1 terminal evidence remains replayable, and legacy reservations without exact expiry fail closed. If the prepared central token expires after the indeterminate commit but before the HTTP request starts, a typed no-effect result releases only the exact matching indeterminate receipt and preserves retry authority; transport ambiguity after a request begins remains terminal indeterminate. The adapter and receipt digest share one canonical dispatch body, and dispatch response mapping uses the contract owner. No arbitrary TTL, retry threshold, provider/model policy, or second-dispatch fallback is introduced. Hosted exact-head gates, ordinary merge, immutable release, deployment recovery evidence, and the downstream consumer pin remain required.
- exact-head patch-validator image scan에서 차단된 embedded `undici@7.29.0`의 GHSA-rfgv-xxqx-mfg5/GHSA-w293-vg96-wgc3를 source에서 제거한다. 공식 SHA-256으로 인증한 Node.js 24.21.0 source(`process.versions.undici === 7.29.1`)와 그 배포판에 포함된 Node.js 24.21.0/npm 11.19.0 개발 도구 체인으로 repository-owned runtime·GitHub Actions exact-version 계약을 함께 올리고, 새 `process.versions`의 nghttp2/V8/SQLite/zlib identity를 exact applicability 계약에 재결합한다. 기존 `strict-allow-scripts=true`와 schema v3 lockfile change control을 보존하고 scanner ignore·waiver·severity 완화는 추가하지 않으며 raw scan, exact image/source binding, strict receipt verifier와 fail-closed 동작을 유지한다.
- Proposed #736 adds `POST /v1/continuation-dispatches`, binding a closed request to exact OIDC workflow/source identity, fresh PR state, retry-independent logical-effect idempotency, pre-dispatch signed indeterminate evidence, fixed central event mapping, and an RFC 8785/Ed25519 credential-free receipt. Exact replay returns retained evidence before another live read, retry-attempt digest drift fails closed without a second dispatch, and stalled bodies have a 10-second absolute deadline. It never returns GitHub credentials. Protected integration, immutable Noema release with its key-id-to-SPKI artifact/digest, and the later `ContextualWisdomLab/.github#2540` exact-head consumer revalidation remain required.
- PR #737의 patch-validator static-runtime receipt verifier가 `process.versions.node`뿐 아니라 bundled Undici를 reviewed fixed version `7.29.1`로 exact-match한다. 서로 내부적으로 일치하더라도 Undici `7.29.0` inventory/component/PURL/raw scan evidence는 fail closed하며, simplified verifier fixtures도 실제 Node 24.21.0 runtime identity에 맞춘다. Source/test GREEN은 새 exact-head hosted image/SBOM/provenance/scanner, 독립 승인, ordinary merge, immutable release를 대신하지 않는다.
- `packages/noema-core/README.md`의 `build_agent` 서명을 코드와 ADR-0014에 맞춘다. caller-visible `retries=3` 표기를 제거하고, 이 경계의 model-attempt retry는 `Agent(..., retries=0)`으로 고정되며 orchestration retry/failover는 contextual-orchestrator 소유임을 명시한다. 구현·ADR 상태·provider 정책은 바꾸지 않는다.
- PR #724 makes private-vulnerability-reporting setting receipts a fail-closed strict-release prerequisite without turning setting evidence into release or deployment truth. The consumer validates bounded stable/no-follow receipt files with fatal UTF-8 and duplicate-key rejection, canonical repository/source/timestamp identity, bounded future skew and freshness, and explicit `PASS + enabled:true + failures:[]`; all observations are validated before ordering and the newest observation wins even when it is FAIL, so a historical PASS cannot mask later contradictory evidence. Protected CD recollects the setting in the same job from the exact immutable-release commit through a repository-scoped `Metadata: read` GitHub App capability, moves the short-lived bearer into an owner-only capability file, unsets the raw bootstrap value before Node execution, feeds the same-run receipt into `release:verify:strict`, and retains the receipt with deployment evidence. The ordinary pre-tag source gate remains `release:verify`; bare pre-publication `release:verify:strict` without a fresh matching receipt is not an authorized procedure. External reporter visibility, staffing/notification, benign private-case handling, immutable-release publication, deployment, KPI and acquisition authority remain independent evidence classes.
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ The Cloudflare Worker exposes three intentionally distinct HTTP surfaces:
| `GET` | `/health` | Process liveness only |
| `GET` / `HEAD` | `/ready` | Runtime readiness without reflecting secrets |
| `POST` | `/exchange` | Exchange an authorized GitHub Actions OIDC bearer for short-lived repository capability |
| `POST` | `/v1/continuation-dispatches` | Emit one exact Noema/Strix continuation and return a credential-free signed receipt |

The public contract is published as [`openapi.json`](./openapi.json), with narrative details in [`docs/api-spec.md`](./docs/api-spec.md).

Expand Down
4 changes: 2 additions & 2 deletions docs/PRD.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Noema is an evidence-producing credential and maintenance control plane. Its run

### 4.1 Credential exchange

The Cloudflare Worker exposes `/health`, `/ready`, and `/exchange`.
The Cloudflare Worker exposes `/health`, `/ready`, `/exchange`, and the Proposed `/v1/continuation-dispatches` broker. The broker performs one fixed central continuation without returning `Contents: write` capability: it binds exact workflow/source/PR evidence, retains terminal idempotency state, and returns only a credential-free signed receipt. Immutable Noema release must precede the `ContextualWisdomLab/.github#2540` consumer pin.

The observed protected branch point uses `ALLOWED_WORKFLOW_REF_PREFIX` as one **exact full workflow ref** despite the legacy variable name and pairs it with immutable `ALLOWED_WORKFLOW_SHA` trust. Cryptographic OIDC verification validates issuer, audience, repository identity, exact workflow ref, the immutable `job_workflow_sha` workflow-source identity, token time semantics, and replay requirements before GitHub App token exchange. `wrangler.toml` pins the trusted central `.github` workflow source commit; that dependency remains read-only from the Noema writer and any future central movement requires an explicit Noema roll-forward plus fresh evidence.

Expand Down Expand Up @@ -120,7 +120,7 @@ Procedural graph ownership follows existing CWL boundaries. Any released cross-s

| ID | Requirement |
| --- | --- |
| FR-001 | `/health`, `/ready`, and `/exchange` retain distinct liveness, readiness, and credential-exchange semantics. |
| FR-001 | `/health`, `/ready`, `/exchange`, and `/v1/continuation-dispatches` retain distinct liveness, readiness, credential-exchange, and fixed-continuation semantics. |
| FR-002 | Validate OIDC issuer, audience, repository/organization, the configured exact full workflow ref, and immutable configured workflow-source SHA before credential minting. |
| FR-003 | Treat workflow-ref/SHA configuration as exact authority and fail closed on absent, malformed, mismatched, stale, or non-canonical trust identity; do not promote a central source movement without explicit Noema roll-forward evidence. |
| FR-004 | Restrict credential-bearing GitHub/OIDC requests by reviewed origin, path, method, redirect, timeout, and bounded body/response behavior. |
Expand Down
17 changes: 12 additions & 5 deletions docs/TRD.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,29 @@ src/runtime-entrypoint.ts
├─ replay protection → NoemaOidcReplayGuard
└─ src/index.ts
├─ /health
└─ /exchange core OIDC + GitHub App protocol
├─ /exchange core OIDC + GitHub App protocol
└─ /v1/continuation-dispatches → live PR ACL → SQLite idempotency → fixed dispatch → Ed25519 receipt
```

자세한 구현과 route ownership은 `ARCHITECTURE.md`, `docs/api-spec.md`를 따릅니다.

### 2.1 `/exchange` inbound body deadline
### 2.1 Continuation dispatch broker

`POST /v1/continuation-dispatches`는 exact-URL, bearer envelope, distributed rate limit, workflow trust, OIDC verification/replay 계층을 재사용한다. Transport retry metadata를 제외한 logical-effect identity로 `NOEMA_CONTINUATION_DISPATCH_STATE`의 SQLite owner를 고르되 complete request digest는 retry attempt를 포함한다. Exact replay는 live PR 재조회보다 먼저 retained receipt를 반환하며, fresh reservation만 live PR을 검증한다. denied/indeterminate replay는 최초 결과와 동일한 `502`/`503` 상태를 유지하고 exact-replay header를 반환한다. Central App credential은 외부 effect가 없는 준비 단계에서 먼저 발급하고 opaque capability 내부에 GitHub `expires_at`을 보존한다. Capability는 durable commit 직전과 fixed event 전송 직전에 정확한 만료를 검사하며, exact dispatch body digest에 결속된 signed `indeterminate` evidence만 durable commit한다. 준비 또는 commit 실패는 best-effort reservation abort 뒤 실패-폐쇄하며 dispatch를 수행하지 않는다. Commit 이후에는 준비된 sender만 fixed event를 전송하고, 204/denial 뒤 같은 receipt authority를 accepted/denied로만 강화한다. 준비/commit 사이 crash로 남은 `reserved` record는 임의 TTL이 아니라 retained OIDC `exp`의 정확한 시각에 Durable Object alarm으로만 회수한다. Alarm 지연을 권위 연장으로 바꾸지 않도록 reservation 생성과 commit transaction 모두 `exp`를 재검사한다. 기존 v1 terminal record는 그대로 replay하고 exact expiry가 없는 legacy reserved record는 fail closed한다. Terminal record는 alarm이 삭제하지 않는다. 따라서 post-effect finalization failure나 crash는 두 번째 dispatch authority를 만들지 않는다. 별도 central App은 fixed `ContextualWisdomLab/.github` event만 호출하고 응답에는 GitHub credential이 없다.

Required bindings: `CONTINUATION_DISPATCH_GITHUB_APP_ID`, `CONTINUATION_DISPATCH_GITHUB_APP_PRIVATE_KEY_PEM`, `CONTINUATION_DISPATCH_GITHUB_APP_INSTALLATION_ID`, `CONTINUATION_RECEIPT_SIGNING_PRIVATE_KEY_PEM`, `CONTINUATION_RECEIPT_SIGNING_KEY_ID`, `NOEMA_CONTINUATION_DISPATCH_STATE`.

### 2.2 `/exchange` inbound body deadline
Comment thread
coderabbitai[bot] marked this conversation as resolved.

`POST /exchange`의 JSON body는 UTF-8 wire bytes 기준 최대 **8,192 bytes**이고, body read가 시작된 뒤 전체 stream은 **10,000 ms의 절대 wall-clock deadline** 안에 완료되어야 합니다. 작은 chunk를 반복해서 보내더라도 deadline은 재설정되지 않습니다. 제한시간을 넘긴 incomplete stream은 best-effort로 취소하고 **HTTP 408**의 Noema 표준 JSON error envelope로 실패-폐쇄하며, 이 경계는 distributed rate-limit delegation, OIDC/JWKS 검증, GitHub App private-key 사용과 GitHub API 호출보다 앞에서 적용됩니다.

배포 acceptance는 기존 unauthenticated 401 contract와 별도로 `scripts/smoke-readiness.sh`의 stalled-body deployment smoke가 실제 408/JSON error response를 관찰해야 합니다. Executable proof는 `test/exchange-body-read-deadline.test.ts`, `test/smoke-readiness.test.ts`, `test/smoke-readiness-endpoint-safety.test.ts`, OpenAPI contract와 `docs/api-spec.md`를 함께 사용합니다.

### 2.2 External Claude plugin admission
### 2.3 External Claude plugin admission

Tool / Capability Boundary의 로컬 포트 `src/tool-capability/external-extension-admission.ts`는 Claude community plugin 서술자를 exact repository/commit/path/digest와 독립적으로 pin된 AppGuardrail·격리 영수증에 결합한다. 가변 브랜치/태그, 로컬 경로, 마켓플레이스/카탈로그 불일치, 공급자 키, 광역 GitHub 권한, 미선언 셸/파일/네트워크/비밀/MCP, 다른 제품 승인, 만료·롤백, 카탈로그 drift, 관측 내용의 정책 승격, 제품 런타임 플러그인 래퍼는 실패-폐쇄한다. 이 포트는 HTTP API가 아니며 `/exchange` 권한을 바꾸지 않는다. `context-graph-contracts` 불변 계약이 나오기 전에는 로컬 ACL/테스트 더블이다.

### 2.3 Durable external-extension lifecycle evidence
### 2.4 Durable external-extension lifecycle evidence

Protected source includes `DurableExternalExtensionLifecycleRepository` under the Tool Capability / State / Checkpoint boundary. A lifecycle stream is keyed by the canonical `external_extension_id` plus exact upstream repository/commit/path, artifact SHA-256, and marketplace-entry SHA-256. The implementation stores an append-only versioned event chain, a transition-ID idempotency index, and a compact current `head` projection in Durable Object storage; it does not reuse the bounded Workflow / Task observability ledger as canonical lifecycle history.

Expand All @@ -52,7 +59,7 @@ Exact duplicate transition replay is returned only after immutable request/event

Corrupt/truncated audit evidence is not repaired by the application path. Full recovery procedure, restore constraints, rollback semantics, future compaction constraints, and actual Durable Object recovery rehearsal requirements are defined in `docs/external-extension-lifecycle-recovery.md`. ADR 0015 remains `Proposed` while real-backend performance/recovery, immutable owner-issued activation evidence, release and deployment acceptance remain incomplete.

### 2.4 Protected procedural graph advisory runtime
### 2.5 Protected procedural graph advisory runtime

Protected source includes four library-only Agent Runtime modules: `procedural-input.ts`, `procedural-graph.ts`, `procedural-evolution.ts`, and `procedural-execution.ts`. The admission path snapshots exact-key plain records and dense bounded arrays through data descriptors, rejects accessors/proxies/extra authority-shaped fields, applies canonical execution identity and bounded procedural identity rules, canonicalizes graph ordering, and computes SHA-256 graph and structure identities under an explicit serialized byte ceiling. These digests are local content identities, not signatures or a released cross-language wire standard.

Expand Down
Loading
Loading