# Roadmap — knowtation **Scope of this board.** Knowtation is the **canonical store and permission authority**. This roadmap governs **Knowtation-owned work only** — gateway authorization, canister auth, proposal lifecycle, delegation, and the vault/MCP surfaces. Cross-repo *product* sequencing (what Scooling ships, in what order) still lives on the Scooling board: `~/scooling/docs/OVERSEER-HANDOVER.md` + `~/scooling/docs/ROADMAP.md`. When the two disagree about **product order**, Scooling wins. When they disagree about **Knowtation's own security or authorization behavior**, this board wins. ## Phase Model Key | Label | Meaning | | --- | --- | | **Thinking** | Design + freeze spec before any build | | **Auto** | Mechanical implementation against frozen spec | | **Thinking → Auto** | Thinking design + test matrix, then Auto build | | **Operator + Auto** | Tier 3 operator authorization for live/staging gates; Auto for implementation | **Handover rule (SD-3):** any step marked **Thinking → Auto** is split into **`{step}a` (Thinking)** then **`{step}b` (Auto)** in `docs/OVERSEER-HANDOVER.md`. Every next-step table and paste block **must** include **`Model:`**. ## Current status (2026-08-24) | | | | --- | --- | | **Overseer Kit** | **Live** — `initialized: true`, `kit_version: 0.1.0` (verify with `ok status` before claims). | | **Product API** | `api.knowtation.store` live · MCP `https://mcp.knowtation.store/mcp` · Calendar 1D live · Hub OAuth = Google + GitHub + **Apple exchange live** | | **Apple / T15** | **KN-APPLE land + Operator T1 DONE** — [KN #295](https://github.com/aaronrene/knowtation/pull/295) `@c2a77b1`. | | **THE ONE NEXT STEP** | **Operator T2** production ingest smoke on `api.knowtation.store` (record PASS/FINDINGS in `docs/reviews/-automation-ingest-live-smoke.md`; no secrets). **Product order (Scooling):** F28b land → F26 smoke. **AIP-c** (VideoFactory wire) not started. | | **Parked** | SEC-KN-P6-ROTATE-b R4–R5 (hygiene); MuseHub F7 (AWS, parallel); BRAIN-PAIR-b; SOCIAL-OPEN-RANGE-b (F7+3G). | | **Known footprint deviation** | Intentional `MUSE-BRIDGE-WORKFLOW.md` / `muse-bridge-deploy.sh` preserve — do not "repair" by kit re-sync | ## Build queue | Phase | Model | Status | Deliverable | | --- | --- | --- | --- | | **SEC-KN-0** | **Operator** | **DONE 2026-07-26** | **Canister gateway auth secret verified SET.** Live probe on hub `rsovz-byaaa-aaaaa-qgira-cai`: `GET /vaults` without `X-Gateway-Auth` → `403 GATEWAY_AUTH_REQUIRED`. (`operator_status` does not exist on the canister.) Knowtation Netlify `knowtation-gateway`: `CANISTER_AUTH_SECRET` / `SESSION_SECRET` / `HUB_ADMIN_USER_IDS` present; `HUB_EVALUATOR_MAY_APPROVE` absent. MCP/`SESSION_SECRET` share still UNVERIFIED. | | **SEC-KN-1** | **Auto** | **DONE 2026-07-26** (code on `feat/sec-kn-1-gateway-auth-fail-closed`; **canister upgrade NOT deployed** — Tier 3) | **P1 fail-closed.** `gatewayAuthorized` empty-secret branch returns **false** (`hub/icp/src/hub/main.mo`). Health stays public 200 with loud `gateway_auth_configured` boolean. Seven-tier tests in `test/sec-kn-1-gateway-auth-fail-closed.test.mjs` (security tier diverges from legacy fail-open). Build verification **pass** (round 1). | | **SEC-KN-2** | **Auto** | **DONE 2026-07-26** (code on `feat/sec-kn-2-server-only-evaluation`; **not merged to main**) | **P2 evaluation state is server-only.** `stripClientEvaluationFields` runs on every create augment before policy/triggers/E1; E1 no longer falls back to client `evaluated_by`. Seven-tier tests in `test/sec-kn-2-server-only-evaluation.test.mjs` (security tier diverges from legacy forge-preserving augment). Build verification **pass** (round 1). | | **SEC-KN-3** | **Auto** | **DONE 2026-07-26** — code on `feat/sec-kn-3-mcp-access-role-cap`; **tip `5954c433…` is an ancestor of Muse `main`** (board "not merged" corrected 2026-08-01); GitHub `origin/main` carries the markers (first mirror `69a7673`, 2026-07-27). **EC2 MCP host now on current main** (`d48fb11c`, 2026-08-01 via SEC-KN-P6-ROTATE-b R1; R2 probe confirmed discard `401`). | **P6 agent tokens cannot inherit admin.** `resolveHostedActorRole` early-returns for `mcp_access` with `roleFromMcpAccessScopes` (never allowlist). `roleEligibleForPersonalSelfApply` rejects agent / `mcp_access` / `humanActor:false`. Seven-tier tests in `test/sec-kn-3-mcp-access-role-cap.test.mjs` (security tier diverges from legacy allowlist inheritance). Build verification **pass** (round 1). | | **SEC-KN-4a** | **Thinking** | **DONE 2026-07-26** — freeze review `pass` (round 3), D1/D2 ratified (freeze on `feat/sec-kn-4a-delegation-principal-binding-freeze`) | **P4 spec written and reviewed, not cleared.** `docs/SEC-KN-4-DELEGATION-PRINCIPAL-BINDING-FREEZE.md` (`frozen: true`) freezes R1–R9: server-only canister `created_by` (from `X-Actor-Id`, never the body, **no fallback**), `principal_ref` / `owner_ref` re-derived at apply from the **recorded author** (not the approver — §3.1), refuse-on-mismatch, `org_ref:` authority refs rejected in v0, delegation-gate check added to the ungated apply path, delegation intents stay out of self-apply. Round-1 independent review returned **blocked**: 6 findings amended in place, **2 escalated** (`security`: a fail-open author fallback I had specified; `irreversible`: the migration hook stops being idempotent, so a repeat deploy would erase the authorship column). See freeze §12 D1/D2. **Round 2** (fresh reviewer, re-derived from source) confirmed all 8 amendments **hold** and raised no remaining technical defect; it blocked on governance — the session had recorded its own ratification of D1/D2, now reverted to **UNRATIFIED** (freeze §12.1) — plus 3 cited wording fixes (R2.1/§6 vs R3 mismatch refusal; idempotency row scoped to `agent_identity` with consent duplicate-append as RR6; repeat-deploy consequence stated as "fails compatibility **or** silent reset"). The spec is **twice-reviewed and stable**. **Operator ratified D1 and D2 on 2026-07-26** (both option A: fail-closed author, one-shot hook + T4) — recorded verbatim in freeze §12.1. **Round-3** review on the fully amended artifact returned **`pass`** (C1–C8 all pass, nothing open in an escalating category, implementable with zero design decisions left open), so clearance rests on a reviewer verdict rather than the authoring session's own judgement. Its one MINOR (R3(2) "non-empty" vs R2.1's "empty after trim" for a whitespace-only value) is fixed. Mechanical gate `ok review --freeze` = pass (re-run after every amendment). **Freeze CLEARED for 4b — code build only; T1–T4 not authorized.** | | **SEC-KN-4b** | **Auto** | **DONE 2026-07-26** — BV round 2 = `pass` (code on `feat/sec-kn-4a-delegation-principal-binding-freeze`; **not merged to main**) | **P4 implementation** against the frozen spec: canister `created_by` from `X-Actor-Id` only (R1), `precheckApprovedDelegationProposal` author binding + gate + re-derive (R2–R7), `org_ref:` rejected on both refs for every kind (R5), seven-tier tests in `test/sec-kn-4-delegation-principal-binding.test.mjs` (**31/31**). BV round 1 = `findings` (4 MINOR, fixed). BV round 2 re-verified those fixes, confirmed R1–R9 match the freeze, security regression still discriminates, Motoko compile **VERIFIED** (`env -i … NO_COLOR=1 TERM=dumb dfx build --check hub`), `canister:verify-migration` exit 0, and found one new MINOR (R5 docs `:245` missing the reserved wording) which was fixed in-session before `pass`. Snapshot-diff from SEC-KN-3 tip → HEAD does **not** include `hub/gateway/server.mjs` or the RBAC assertion files (SEC-KN-3a remains pre-existing). Canister WASM upgrade is **Tier 3** (gate T1); until it installs, hosted delegation apply refuses by design (fail-closed). T1–T4 not executed. | | **SEC-KN-4c** | **Operator + Auto** | **DONE + landed 2026-08-01** — 4c-a freeze CLEARED (`docs/SEC-KN-4C-MIGRATION-HOOK-RESTORE-FREEZE.md`, review `pass`); 4c-b BV round 1 = **`pass`** (`docs/reviews/2026-08-01-sec-kn-4c-b-bv-round1-pass.md`); **operator authorized Tier 3 land 2026-08-01** — `feat/sec-kn-4c-land` fast-forwarded into Muse `main` (`4179ed46… → 2466ad64…`); suites re-run green on `main` (11/11, 31/31, verify exit 0); GitHub via muse-mirror [PR #287](https://github.com/aaronrene/knowtation/pull/287) merged `15fba5f5…` (CI green after fix-forward `760df567…`; tree hashes verified identical) | **Migration hook restored to identity** on `StableStorage` (`hub/icp/src/hub/Migration.mo:455-457`) per freeze 4C-R1–R4; verify-script contracts flipped (4C-R5); SEC-KN-4 unit assertion flipped off `TODO(SEC-KN-4c)` (4C-R6); seven-tier `test/sec-kn-4c-migration-hook-restore.test.mjs` **11/11** + SEC-KN-4 **31/31** + `canister:verify-migration` exit 0 + `dfx build --check hub` exit 0 (4C-R7). Live module hash re-read this session: `0x039360a0…` **matches frozen expected** → **no redeploy** (4C-R8; live T4 was already installed 2026-07-28). Rationale was measured, not assumed: leaving the one-shot T1 hook made repeat deploys fail `Compatibility error [M0216]`, blocking hotfixes. Freeze §8 gate T4 + R1.4 addendum discharged in source. | | **SEC-KN-3a** | **Auto** | **DONE 2026-07-26** — BV round 1 = `pass` (code on `feat/sec-kn-4a-delegation-principal-binding-freeze`; **not merged to main**) | **Stale RBAC source-shape assertions refreshed** to match post-SEC-KN-3 `resolveHostedActorRole`: single entry `jwt.verify` → reuse `bearerPayload`; return `{ role, mayApproveProposals, isMcpAccess }`; bridge fallback asserts `roleFromVerifiedAccessPayload(bearerPayload)` (not a second verify / raw parse); override section asserts `mayApplyAdminAllowlistOverride`. SEC-KN-3 security properties **not** weakened — `test/sec-kn-3-mcp-access-role-cap.test.mjs` still green. **Billing-repair decision:** do **not** gate on canister replica (suite already sets `CANISTER_URL=''`); hang was corrupt shared `data/hosted_billing.json` — fixed via call-time `KNOWTATION_BILLING_DB_PATH` / `KNOWTATION_GATEWAY_DATA_DIR` in `billing-store.mjs` + isolated temp DB in the test. RBAC trio + SEC-KN-3 + billing-repair = **82/82**. T1–T4 not executed. | | **SEC-KN-P6-VERIFY** | **Operator + Auto** | **DONE 2026-08-01** — evidence-only; outcome **B (SHARED)** → `VERIFIED-SHARED` | **P6 `SESSION_SECRET` share resolved.** Signed-token cross-acceptance probe: one gateway-signed `agent_access` JWT (minted via Phase C `POST /api/v1/auth/agent/token`) accepted by `GET /api/v1/auth/session` on **both** the Netlify gateway (`api.knowtation.store`) and the distinct EC2 MCP host (`mcp.knowtation.store`, `nginx/1.24.0` → Node, own CORS). Controls: 200 on issuer (token valid), 401 garbage-token + 401 no-auth on the MCP host (route mounted and verifying). HS256 verify succeeds iff the secret is identical → **secret is shared**. Optional sidecar: `GET /api/v1/proposals` shows `created_by` populated on the 7 newest (post-SEC-KN-4) proposals incl. `prop-1785500300353491755`. Read-only; no posture/env flip; no rotation. Evidence: `docs/reviews/2026-08-01-sec-kn-p6-verify-session-secret-share.md`; probes archived under `scripts/archive/2026-08-01-*.mjs`. | | **SEC-KN-P6-ROTATE-a** | **Thinking** | **DONE 2026-08-01** — freeze CLEARED (`docs/SEC-KN-P6-ROTATE-FREEZE.md`, freeze-review `pass`, digest `sha256:958c8add…`) on `feat/sec-kn-p6-rotate` | **D1 one signing domain** (gateway+bridge+MCP; naive MCP split rejected — README §Post-deploy #3 + cross-host agent JWTs). **D2 deploy-before-rotate:** EC2 is pre-current-main (discard asymmetry 401 vs 200); SEC-KN-3 source is on main. Dual-secret (`SESSION_SECRET` + `SESSION_SECRET_PREVIOUS`) zero-downtime runbook; wire every G10 `jwt.verify` site; drain floor **24h** unless shorter `HUB_JWT_EXPIRY` proven. No T1–T4 executed in Thinking. | | **SEC-KN-P6-ROTATE-b** | **Operator + Auto** | **R1–R3 DONE + BV pass + P0 deploy 2026-08-01; R4–R5 PARKED** (operator) | **R1 (T1):** EC2 `/opt/knowtation` ff `257ef705 → 15fba5f5` (SEC-KN-3 present), `npm ci` clean, PM2 healthy. **R2 PASS (§5.1):** non-admin `agent_access` discard of nonexistent id → **401 gateway AND MCP** (pre-deploy MCP was `200`); controls green — **live P6 elevation closed by deploy**. **R3 (P6-C1–C5):** `hub/lib/session-secret-rotation.mjs` `verifyJwtWithSecretRotation` at **all nine G10 sites**; signing/HMAC/encrypt primary-only; README §Post-deploy #4. Seven-tier `test/sec-kn-p6-session-secret-rotation.test.mjs` **30/30**; SEC-KN-3 **19/19**; BV round 1 **`pass`**. Muse `635cfdef` → main; muse-mirror **PR #288** merged `d48fb11c`. **P0 deploy:** Netlify gateway + bridge + EC2 all on `d48fb11c`, `SESSION_SECRET_PREVIOUS` unset (stable; identical to pre-rotation behavior). Evidence: `docs/reviews/2026-08-01-sec-kn-p6-rotate-b-r1-r2-deploy-probe.md`. **R4–R5 PARKED:** dual-secret env rotation (T2) is hygiene (shrink shared-secret blast radius), not incident response — unpark from `docs/OVERSEER-HANDOVER.md` PARKED runbook when a quiet ≥24h babysit window exists. May need one-time Connect GitHub re-connect after drain (§6.4). | | **SEC-KN-5** | **Auto** | **DONE 2026-07-26** — BV round 1 = `pass` (code on `feat/sec-kn-5-delegation-ttl-viewer-mint`; **not merged to main**) | **P12 + P13 delegation limits.** `readVaultDelegationPolicy` clamps `max_ttl_seconds` with `Math.min(..., MAX_TTL_SECONDS)` so a vault policy of `604800` cannot widen SD-10's 24h cap. Self-hosted `POST /api/v1/delegation/grants` is `requireRole('admin')` only (viewer/editor/evaluator cannot mint runtime bearer authority); consent propose stays viewer-inclusive. Seven-tier tests in `test/sec-kn-5-delegation-ttl-viewer-mint.test.mjs` (**19/19**) + self-hosted route assertion; combined with route file **26/26**. Security regressions vs unclamped legacy + viewer-inclusive mint. Related delegation suites **64/64**. T1–T4 not executed. | | **SEC-KN-6** | **Auto** | **DONE 2026-07-26** — BV round 1 = `pass` (code on `feat/sec-kn-6-constant-time-secret-compare`; **not merged to main**; **canister upgrade NOT deployed** — Tier 3) | **P14 constant-time secret compare.** Motoko `constantTimeTextEqual` (OR-of-XOR over every character; no early-exit `==`) used by both `gatewayAuthorized` and `operatorExportAuthorized` in `hub/icp/src/hub/main.mo`. JS mirror in `lib/gateway-authorized.mjs`. Seven-tier tests in `test/sec-kn-6-constant-time-secret-compare.test.mjs` (**18/18**) with security regression vs length-then-`==` early-exit; SEC-KN-1 suite still green (**19/19**); Motoko compile **VERIFIED**. T1–T4 not executed. | | **SEC-SEAM-1** | **Thinking → Auto** | **DONE 2026-07-27** — 1a freeze CLEARED (round 7 `pass`); **1b BV round 1 = `pass`** (code on `feat/sec-seam-1-session-bound-writes`; **not merged to main**) | **P3 session-bound learner identity.** S1 stamps `type:'session'` at all five learner mint sites; S2–S6/S10 seam classify + named refusals. Step 11 was empty admission (W3) until **FINISH-COMPLETE-APPLY-KN-b** (T5) widened Tasks/Media. T1–T4 still unexecuted for live. | | **SEC-SEAM-MEDIA-a** | **Thinking** | **DONE 2026-08-01** — freeze CLEARED (`docs/SEC-SEAM-MEDIA-FREEZE.md`, freeze-review `pass`, digest `sha256:f9c58fd3…`) on `feat/sec-seam-media-a` | **Hosted media proposal surface freeze (SM-C1–C12).** Ratified parent D2 = A / S7.6. Requires `maybeApplyHostedMediaAfterApprove` **and** `normalizeCanisterProposalForMediaPrecheck` as matching S3.1 condition in the **same** change (S3.0). Bridge propose/consent/list/get/apply-approved + blob media stores; media_attach canister note IO adapter; no posture/env flip; P6 R4–R5 stays parked. | | **SEC-SEAM-MEDIA-b** | **Auto** | **DONE + landed 2026-08-01** (`364c712a…`); **kn1 hotfix landed + Hub published 2026-08-04** ([PR #290](https://github.com/aaronrene/knowtation/pull/290) `baa41bf`) | Implement SM-C1–C12: gateway `maybeApplyHostedMediaAfterApprove` + S3.1 `normalizeCanisterProposalForMediaPrecheck` same change; bridge propose/consent/list/get/apply-approved + media blob sync; media_attach temp-stage canister note RMW + propose-time `media_pointer` stamp; OpenAPI + PROPOSAL-LIFECYCLE honesty. Seven-tier + SEC-SEAM-1 **50/50** (`test/sec-seam-media-hosted.test.mjs` + `test/sec-seam-1-session-bound-identity.test.mjs`, sha256 `2f7bf57d…`). **2026-08-04 kn1:** canister GET `liveStateIdOverride` (yaml-stage `trimEnd` false conflict) — Netlify production ready. No `MEDIA_*` / `SCOOLING_MEDIA_*` flips; no SESSION_SECRET writes; P6 R4–R5 untouched. | | **KN-b (FINISH-COMPLETE-APPLY)** | **Auto** | **DONE 2026-07-27** — BV `pass` round 2 + independent **round 3 `pass`**; landed Muse/`main` + GitHub [KN #275](https://github.com/aaronrene/knowtation/pull/275) | **T5 admission.** Persist validated `external_ref` on task/media propose; §FCA.4 Tasks/Media fingerprints; Delegation stays `SELF_APPLY_DELEGATION_REFUSED`; Flow not admitted (until FLOW-WRITE-LIVE-KN-b); E1 widened with sessionBound/author gates; Motoko pending→id path rewrite; seven-tier `test/finish-complete-apply-kn-b.test.mjs` (**16/16**). Live Tasks/Media one-click still needs P1 WASM + T1 `created_by` + Tier 3 env (§FCA.2). | | **DURABLE-AGENT-AUTH-C** | **Thinking → Auto** | **DONE 2026-07-27** — C-a freeze CLEARED; C-b BV round 2 = `pass` (22/22); **landed Muse/`main` 2026-07-28** (operator Tier 3; bridge → GitHub `muse-mirror` → `main`) | **Scoped REST agent credentials** for Trend Agent / Paperclip. Opaque `kt_agent_` + `agent_access` JWT exchange; Netlify-mounted mint/list/revoke/rotate; propose-scope REST authz; Hub UI; docs/OpenAPI. Seven-tier `test/agent-credentials-*.test.mjs`. Freeze: `docs/DURABLE-AGENT-AUTH-PHASE-C-FREEZE.md`. Consumer wiring on VideoFactory-trend-agent after Hub deploy is live. | | **FLOW-WRITE-LIVE-KN-b** | **Auto** | **DONE + landed 2026-07-29** — Muse `main` `5de83c48…` + GitHub [KN #278](https://github.com/aaronrene/knowtation/pull/278) (`f0d0450`); BV round 1 = `pass`; seven-tier **11/11** | **Admit §FWL.4 Flow fingerprints.** Persist validated `scooling.flow:` `external_ref` on flow propose for `new`\|`edit`\|`import`; widen T5 with `matchesScoolingFlowFingerprint` (exact kind, no default-to-`new`; `meta/flows/*.md`; personal scope); capture/Delegation/project/org/wrong-ref refuse; PROPOSAL-LIFECYCLE updated. No `FLOW_AUTHORING_WRITES` prod flip. Frozen: `~/scooling/docs/FLOW-WRITE-LIVE-FREEZE.md`. Product NEXT = **FLOW-WRITE-LIVE-HOSTED** (Scooling; SMOKE blocked). | | **FLOW-WRITE-LIVE-GATEWAY-PROXY** | **Auto** | **DONE + landed 2026-07-29** — BV round 1 = `pass`; seven-tier **12/12**; Muse/`main` → muse-mirror | **Gateway→bridge Flow authoring proxies.** `POST /api/v1/flows`, `…/:id/proposals`, `…/import` before canister catch-all; bridge `registerBridgeFlowRoutes` + `createFlowProposalOnCanister`. Capture/run/Delegation unchanged. Prod bridge `FLOW_AUTHORING_WRITES` on for §FWL.9. BV: `docs/reviews/2026-07-29-flow-write-live-gateway-proxy-bv-round1-pass.md`. Product NEXT = **LAB-LIVEa** (Scooling; §FWL.9 SMOKE **PASS** 2026-07-29). | | **FLOW-CAPTURE-LIVE-KN-b** | **Auto** | **DONE + landed 2026-07-30** — BV round 1 = `pass`; seven-tier **13/13**; Muse/`main` `sha256:3146d633…` → [KN #281](https://github.com/aaronrene/knowtation/pull/281) (`47fab77`) | **Wave 2 capture:** T5 non-admission regression (promote/merge/dismiss → `SELF_APPLY_NOT_ADMITTED`; no positive capture fingerprint); gateway→bridge proxies for observe/list/propose/dismiss; bridge `registerBridgeFlowCaptureRoutes` + `createCaptureProposalOnCanister`; PROPOSAL-LIFECYCLE Wave 2 note (seam + not admitted B); `FLOW_CAPTURE_*_ENABLED` stay default off. Frozen: `~/scooling/docs/FLOW-CAPTURE-LIVE-FREEZE.md` (§FCL.3 KN-b). BV: `docs/reviews/2026-07-30-flow-capture-live-kn-b-bv-round1-pass.md`. Product NEXT = **FLOW-CAPTURE-LIVEb** (Scooling Auto). | | **CAPTURE-HOSTED-APPLY-a (9-kn-a)** | **Thinking** | **DONE 2026-07-31** — freeze-review `pass` (round 2); `docs/CAPTURE-HOSTED-APPLY-FREEZE.md` (`sha256:6db36223…`) | **Hosted Hub-complete capture apply freeze:** CHA-C1–C11 — `maybeApplyHostedCaptureAfterApprove`, bridge apply-approved + shared precheck/apply, GET flows list/get exposure, T5 refuse-all kept (SD-23), no posture/env flip; `prop-1785500300353491755` stays pending. Product NEXT = **9-kn-b Auto**. | | **CAPTURE-HOSTED-APPLY-KN-b (9-kn-b)** | **Auto** | **DONE 2026-07-31** — BV round 1 = `pass` (`docs/reviews/2026-07-31-capture-hosted-apply-kn-b-bv-round1-pass.md`); seven-tier **15/15** on `feat/flow-capture-live` | CHA-C1–C11 implemented: `hub/gateway/capture-approve-hosted.mjs` hook + approve-block wiring; `lib/flow/flow-capture-hosted-apply.mjs` `applyApprovedCaptureProposalFromCanister`; bridge apply-approved + hosted `GET api/v1/flows` (+ `:id`) with blob hydrate; gateway proxies (ordered after candidates/external-grants/projection); PROPOSAL-LIFECYCLE Hub-complete note; seven-tier `test/capture-hosted-apply-kn-b.test.mjs` **15/15**; `flow-capture-live-kn-b` re-run green **13/13**. No T5 admission; no posture/env flip; `prop-1785500300353491755` untouched. Product NEXT = **9-apply re-run** (approve pending proposal via Hub tray; verify saved Flow). | | **CAPTURE-STORE-BLOB-PERSIST (9-kn-c)** | **Auto** | **DONE 2026-07-31** — landed via muse-mirror PR #284 (green CI); live-verified same day | Root cause of the 9-apply live failure (`409 FLOW_CANDIDATE_NOT_PROMOTABLE` on `prop-1785500300353491755`): Wave 2 bridge capture routes (observe / candidates / propose / dismiss in `hub/bridge/flow-capture-routes.mjs`) never hydrated/persisted the flow store through Netlify Blobs, so candidates lived only on the warm lambda's ephemeral disk and were gone by approve time. Fix wraps the three mutating routes in `withExternalProtocolBlobSync` and hydrates before the candidates read. Regression suite `test/capture-store-blob-persist.test.mjs` (11/11; pre-fix routes fail 7/11). Live-proven: post-land candidates survive observe→approve across instances. | | **CAPTURE-STORE-STALE-MERGE (9-kn-d)** | **Auto** | **DONE 2026-07-31** — landed via muse-mirror PR #285 (green CI); bridge + gateway redeployed from merge commit; suite **14/14** (pre-fix merge fails **3/14**) | Second live defect found during 9-apply re-runs: `mergeFlowStoreJson` in `hub/bridge/external-agent-blob-store.mjs` merged `tasks`/`task_loops` by id but let a **warm lambda's stale local `candidates`/`flows`/`steps`/`runs` arrays mask fresher blob records** (`...localVault` spread wins). Live evidence: approve of `prop-1785526040570098296` hit a warm lambda → hook apply refused `FLOW_CANDIDATE_NOT_PROMOTABLE`; identical CHA-C11 re-apply on a cold lambda succeeded (`flow_cap_9d65aa57`); approve of `prop-1785528026964024269` on a cold lambda auto-applied (`flow_cap_ca8f2945`), proving the CHA-C1 hook works. Fix: id/composite-key union merge for candidates (`candidate_id`), flows (`flow_id`+`version`), steps (`flow_id`+`flow_version`+`step_id`), runs (`run_id`); newest `updated` wins. Regression tiers added to `test/capture-store-blob-persist.test.mjs` (warm-stale unit + e2e). | | **SITE-FINISH-FLOW-RUN-KN-b** | **Auto** | **DONE + landed Muse `main` 2026-08-06** — BV round 1 = `pass` (`docs/reviews/2026-08-06-site-finish-flow-run-kn-b-bv-round1-pass.md`); seven-tier **10/10**; FF `feat/site-finish-flow-run-kn-b` → Muse `main` (`a33cba5c…`); Hub publish via muse-bridge this session | **Wave 3 run/consent hosted proxies (§FR.0.4):** gateway→bridge for `POST …/runs`, `…/advance`, `…/evidence`, `…/execute-automatable`, `…/submit-review`, `…/consent`, plus `GET …/runs` and `GET …/flow-runs/:run_id`; bridge `registerBridgeFlowRunRoutes` + flow-store blob sync; submit-review awaits async canister create. `FLOW_RUN_WRITES_ENABLED` / `FLOW_AUTOMATABLE_EXECUTION_ENABLED` stay default **off** until Scooling SITE-FINISH-FLOW-RUN-SMOKE. Frozen: `~/scooling/docs/SITE-FINISH-FLOW-RUN-FREEZE.md` (digest `sha256:24f10167…`; SD-29). Product SMOKE **PASS** on Scooling 2026-08-07. | | **KN-APPLE-a** | **Thinking** | **DONE 2026-08-09** — freeze CLEARED (`docs/KN-APPLE-NATIVE-HOSTED-EXCHANGE-FREEZE.md`, freeze-review `pass`, digest `sha256:4ec695738daf8e582923a6a6971d607bc5649eff35493d27dcd2de6303bd4dfa`) on `feat/kn-apple-native-hosted-exchange` | **T15 freeze.** `POST api/v1/auth/native-apple-exchange`; Apple JWKS verify; `issueToken` `provider:apple` + C7 introspect; Layer-1 `apple:`; Layer-2 HMAC stays Scooling-server-only; not Passport; not `api/v1/auth/native` PKCE; no vault-write authorize. Auto bootstrap must use `type: 'session'` gateway tip (`origin/main` lineage; Muse `main` may lag — §KNA.1 G12). | | **KN-APPLE-b** | **Auto** | **DONE 2026-08-09** — BV round 1 = `pass` (`docs/reviews/2026-08-09-kn-apple-b-bv-round1-pass.md`); seven-tier **13/13** (test_output `sha256:d419cfb2…`) | Implement D1–D9: `hub/gateway/apple-identity-token.mjs` JWKS verify; `POST api/v1/auth/native-apple-exchange`; `providers.apple`; env placeholders; docs/OpenAPI honesty; C7-compatible `issueToken` mint `provider:apple` + `type:session`. No Scooling CapabilityGate flips; no App Store; no Apple secrets in git; no live prod Apple probe. | | **KN-APPLE-land** | **Operator + Auto** | **DONE 2026-08-10** — Muse FF + audit pins → [KN #295](https://github.com/aaronrene/knowtation/pull/295) `@c2a77b1`; then T1 env | SD-21 land; SD-14 muse-mirror→main; gateway route live. | | **KN-APPLE-T1** | **Operator + Auto** | **DONE 2026-08-10** — `APPLE_CLIENT_ID=com.scooling.apple` on knowtation-gateway; live `apple:true`; Xcode SIWA capability; evidence `docs/reviews/2026-08-10-kn-apple-t1-complete.md` | Production Apple audience configured. Unlocks Scooling APPLE-4-live revisit (T1+T2+T15). | | **KN-DOCS-SYNC-a** | **Thinking** | **DONE 2026-08-17** — freeze-review **pass** | **Live Drive (then Notion) connector freeze.** Artifact `docs/KN-DOCS-SYNC-FREEZE.md`. Hub `gdrive` stays Markdown-folder import. Drive readonly OAuth + vault in Knowtation only; list/import as notes through Review-before-write; optional `sync_cursor`; Notion Hub-key (process-wide) only. No Scooling Ready flip in this tip. Source: `~/scooling/docs/CONNECT-AND-OPEN-RANGE.md`. | | **KN-DOCS-SYNC-b** | **Auto** | **DONE 2026-08-17** — BV round 1 = **`pass`** (`docs/reviews/2026-08-17-kn-docs-sync-b-bv-round1-pass.md`); seven-tier **12/12** (test_output `sha256:41713d88…`) on `feat/kn-docs-sync-b` | Implement freeze D1–D17: Drive readonly OAuth + `docs_oauth` vault; list/import → `docs-sync` proposals (no `writeNote`); optional `sync_cursor`; Notion Hub-key list/import; strong docs blob store; self-hosted + bridge + gateway routes; HUB-API/OpenAPI/PROPOSAL-LIFECYCLE honesty. Gates hard-coded **false** at ship. Folder `gdrive` unchanged. No Scooling edits. | | **KN-DOCS-SYNC-DRIVE-GATE** | **Operator + Auto** | **DONE 2026-08-17** — operator authorized “Flip Drive gate”; source `DOCS_OAUTH_GOOGLE_AUTHORIZED = true` | Live Drive OAuth gate on. Notion gate stays **false**. Env must already be set on gateway+bridge. | | **KN-WORK-PATH-LIST-a** | **Thinking** | **DONE 2026-08-18** — freeze-review **pass** (`sha256:1354ed45531fc4dac329e989727deb9f9f4eb1ed17936a5d65c83b25cb8a1506`) | **Path persist + list/get freeze.** Artifact `docs/KN-WORK-PATH-LIST-FREEZE.md`. Dedicated `learning_paths[]` in `hub_flow_store.json`; list/get REST; Review-before-write persist gated `PATH_WRITES_ENABLED` default off. No Scooling harvest. No Home bind. No Live. Source: Scooling F14 + F13 BV pass + AGENT-WORK-CHAT-HOME-BIND park. | | **KN-WORK-PATH-LIST-b** | **Auto** | **DONE + landed 2026-08-18**; write env **ON 2026-08-19** (Netlify `PATH_WRITES_ENABLED=1` gateway+bridge; T5 not admitted). BV round 1 = **`pass`**; seven-tier **44/44**; GitHub [PR #299](https://github.com/aaronrene/knowtation/pull/299) `@005d00ff` | List/get REST; gated propose/apply. Hosted `maybeApplyHostedPathAfterApprove`. Evidence: `~/scooling/docs/reviews/2026-08-19-f16-f17-path-writes-land.md`. | | **KN-AUTH-LANE-D-a** | **Thinking** | **DONE 2026-08-24** — freeze-review **pass** (rounds 1–3 findings; round 4 + `ok review --freeze` **pass**; digest `sha256:e5c48a8fa0e80a61b2fd1505d7b7a857db94c904c3107eafc51d95b62e59f972`) | **Machine lane reliability freeze.** Hub health fields; isolate `kt_agent_` from `ktn_refresh` / `gateway-auth`; no silent mass-invalidate; 503 must not 401 robots; one automation path. Artifact: `docs/KN-AUTH-LANE-D-FREEZE.md`. No Auto in this tip. No live revoke. Sibling Scooling F28 = human session reads. | | **KN-AUTH-LANE-D-b** | **Auto** | **DONE + landed 2026-08-24** — BV r1 **pass**; Muse FF → GitHub [PR #306](https://github.com/aaronrene/knowtation/pull/306) `@1d6eec39`. **Propose-path hotfix** landed same day (`getUserId` → `effectiveRequestPath`; tests **37/37**). Evidence: `docs/reviews/2026-08-24-kn-auth-lane-d-b-land.md`, `docs/reviews/2026-08-24-kn-auth-lane-d-propose-path-fix-land.md`. | | **AIP-a** | **Thinking** | **DONE 2026-08-24** — freeze-review **pass** (rounds 1–2 findings; round 3 + `ok review --freeze` + `ok check-ok --path` **pass**; digest `sha256:9fded978386543865225f5cc2bc0f04f09e777f8de96a56ef5d516c995a2793c`) | **Per-account ingest rules freeze.** Artifact `docs/AUTOMATION-INGEST-POLICY-FREEZE.md`. First-match router; `ingest:automation`; `POST api/v1/automation/ingest`; Born Free pack disabled; REST-only v1. No routes in Thinking. No Scooling edits. VideoFactory wire = AIP-c. | | **AIP-b** | **Auto** | **DONE + landed 2026-08-24** — BV r1 **pass**; seven-tier **26/26**; Muse FF → GitHub [PR #308](https://github.com/aaronrene/knowtation/pull/308) `@e9300f2`. Evidence: `docs/reviews/2026-08-24-automation-ingest-policy-b-land.md`. | Router + `POST api/v1/automation/ingest` + session CRUD + disabled Born Free pack + Research filter. No Scooling. No pack enable. Production smoke = Operator T2. No E1/T5 edits. | > **Hub UI redesign** is a **separate lane** — see [`HUB-UI-ROADMAP.md`](./HUB-UI-ROADMAP.md) + [`HUB-UI-HANDOVER.md`](./HUB-UI-HANDOVER.md). It must not alter this board's product NEXT. (HUB-DASH-IA landed 2026-07-31 via muse-mirror PR #286.) ## Definition of Done (every phase) - Deliverables match frozen spec for the phase - **Freeze review `pass`** before any **Auto** build that consumes a `frozen: true` artifact (`/freeze-review-loop` when findings) - Required seven-tier tests green locally (`.overseer/policy/test-tiers.yaml`) - **Build verification `pass`** after any **Auto** (`{step}b`) phase before status → **DONE** (`/build-verification-review`; thinking-high) - No secrets committed - Both `docs/ROADMAP.md` and `docs/OVERSEER-HANDOVER.md` updated together (SD-17) - Feature branch → commit → (push/PR per `muse+git-mirror` rules); no `main` merge without Tier 3 **Security-phase addition (SEC-*):** every SEC phase must land a **security-tier test that fails against the pre-fix code**. A fix without a regression test that would have caught the finding is not DONE. ## VCS context (this repo) | Setting | Value | | --- | --- | | Regime | muse+git-mirror | | Canonical | muse | | Git remote | origin | | Main branch | main | | Mirror branch | muse-mirror | | Muse staging | staging | | Muse main | main | | Feature branch pattern | feat/{slug} | **Hard stop:** never `git push origin main`. GitHub `main` receives changes only through a `muse-mirror → main` PR after a Tier 3 merge to Muse `main` (see `MUSE-BRIDGE-WORKFLOW.md` — the repo-specific version, not the kit template). ## Cross-references - `docs/OVERSEER-HANDOVER.md` — living relay; paste NEXT SESSION into fresh chats - `docs/SEC-KN-4-DELEGATION-PRINCIPAL-BINDING-FREEZE.md` — frozen P4 spec (ground truth for SEC-KN-4b) - `docs/CROSS-REPO-COORDINATION.md` — Standing Decisions (ADR) log and decision authority tiers - `.overseer/policy/tiers.yaml` — machine-readable Tier 1/2/3 authority table - `.overseer/policy/model-labels.yaml` — allowed Model labels for roadmap + handover - `~/scooling/docs/PRE-BUILD-SECURITY-AUDIT-FINDINGS-PASS2.md` — the audit driving the SEC queue - `~/scooling/docs/OVERSEER-HANDOVER.md` — cross-repo product order