# Build verification — CAPTURE-HOSTED-APPLY-KN-b round 1 **Verdict:** pass **Frozen spec:** `docs/CAPTURE-HOSTED-APPLY-FREEZE.md` (`frozen: true`, review_stamp `pass`, digest `sha256:6db36223…`) **Diff scope:** Knowtation `feat/flow-capture-live` — NEW `hub/gateway/capture-approve-hosted.mjs`, `lib/flow/flow-capture-hosted-apply.mjs`, `test/capture-hosted-apply-kn-b.test.mjs`; MOD `hub/bridge/flow-capture-routes.mjs` (apply-approved + GET flows list/get), `hub/gateway/server.mjs` (hook wiring + proxies), `docs/PROPOSAL-LIFECYCLE.md` (Wave 2 note) **Reviewer posture:** independent verifier subagent (fresh session, not the build session; Grok 4.5 high — both Claude thinking-high slugs were API-limited at review time); not redesign ### Evidence | type | sha256 | ref | notes | | --- | --- | --- | --- | | test_output | `7671a00ded680291437bebd40560eae5b898792016a30d316c5a4a6c80ab3eee` | `node --test test/capture-hosted-apply-kn-b.test.mjs` | **15/15** pass (7 suites), exit 0 | | test_output | `1287a1325477e39b1da462a724decf8f2fcdaec5834cf9611c0c3e7985d40696` | `node --test test/flow-capture-live-kn-b.test.mjs` | **13/13** pass, exit 0 | ### Checklist | # | Check | Evidence | | --- | --- | --- | | V1 | Frozen deliverables exist | Hook module + merge helper; `applyApprovedCaptureProposalFromCanister`; bridge apply-approved + GET flows list/get; gateway import/call/proxies; lifecycle note; seven-tier test file | | V2 (CHA-C1) | Gateway hook per freeze | Separate module; merges `capture_index_applied` / `capture_apply` / `capture_apply_error`+`_code`; null for non-capture; approve HTTP status preserved; `console.error` on failure | | V2 (CHA-C2) | Bridge apply-approved | Behind `requireBridgeAuth` + vault context + canister headers; helper steps 1–8 (fetch → 400 non-capture → 409 non-approved → shared precheck refusal passthrough, no store mutate → `applyCaptureProposal` → blob persist via `withExternalProtocolBlobSync` → payload with promote/merge/dismiss markers) | | V2 (CHA-C3/C10) | No precheck fork; body intact | Same `precheckApprovedCaptureProposal` + `applyCaptureProposal` as self-hosted `hub/server.mjs`; blob hydrate before precheck; normalize passes canister `body` through intact | | V2 (CHA-C4) | T5 refuse-all unchanged | `lib/hub-proposal-personal-self-apply.mjs` untouched; no capture fingerprint admission; `SELF_APPLY_NOT_ADMITTED` regression green | | V2 (CHA-C5) | Route ordering | Bridge GETs after `flows/candidates`; gateway GETs after projection/external-grants/candidates, before canister catch-all — no route stealing | | V2 (CHA-C6) | Lifecycle doc | Wave 2 subsection: T5 refuse-all; Hub-complete approve applies; propose-only clarified; no hosted media apply claim | | V2 (CHA-C7/C11) | Hard stops + honesty | No `FLOW_CAPTURE_*` env/posture flip; no approve of `prop-1785500300353491755`; no atomic approve+apply claim; ops re-apply route exists | | V3 | Seven-tier matrix (§CHA.4) | unit/integration/e2e/stress/data-integrity/performance/security — **15/15**; real behavior assertions, e2e boots live gateway + mock bridge/canister | | V4 | No scope creep | No T5 change; no Scooling product code; capture run path untouched | | V5 | No silent deletion | Existing observe/list/propose/dismiss routes retained; apply-approved and GET flows added beside them | | V6 | Governance truthful | ROADMAP/HANDOVER claimed BUILT — BV pending before this review; DONE only after this pass | | V7 | No secrets / unsafe defaults | Security tier asserts no secrets in `capture_apply` payload; envs default off | | V8 | Claims match evidence | Test digests above; prior KN-b T5 suite still green | ### Findings None. ### Honest summary Hosted Hub-complete capture apply landed as frozen: after an admin/evaluator approve on the hosted gateway, `maybeApplyHostedCaptureAfterApprove` calls the bridge `apply-approved` route, which runs the same precheck/apply pair as self-hosted Hub approve and persists `hub_flow_store.json` via blob sync; hosted `GET api/v1/flows` (+ `:id`) makes the promoted Flow observable. Hosted approve commits before the hook, so an apply failure surfaces honestly as `capture_index_applied: false` with an ops re-apply path. T5 personal self-apply stays refuse-all (SD-23); no posture/env flip; `prop-1785500300353491755` untouched.