# Implementation Plans

Generated by the `improve` skill on 2026-07-06, audited against commit `610a7b0`.
Each plan is self-contained: an executor with zero prior context can run it from
the plan file + the repo. Read the plan fully before starting, honor its STOP
conditions, run its drift check first, and update your row below when done.

Breaking / behavior-changing plans are flagged **⚠️** — they are intentional and
each documents the migration in its Maintenance notes (per the request, breaking
changes are allowed as long as they're marked).

## Execution order & status

| Plan | Title | Cat | Priority | Effort | Depends on | Status |
|------|-------|-----|----------|--------|------------|--------|
| 001 | Add missing `typecheck` scripts (inspect + 5 examples) | dx | P1 | S | — | DONE (partial — see note) |
| 002 | Clear the critical `shell-quote` advisory in the bundle | security/deps | P1 | S | — | DONE |
| 003 | Reject cross-origin WebSocket upgrades ⚠️ | security | P1 | S | — | DONE |
| 004 | Stop git argument injection via `ref`/`hash` | security/bug | P1 | S | — | DONE |
| 005 | Don't cache a rejected RPC `setup()` promise | bug | P1 | S | — | DONE |
| 006 | Bound `SharedState.syncIds` (memory leak) | bug | P1 | S | — | DONE |
| 007 | Behavioral tests for the auth/OTP trust boundary | tests | P1 | S | — | DONE |
| 008 | Cap hub terminal buffer + reject restart-after-terminate | bug | P2 | S | — | DONE |
| 009 | Fix two server-side streaming lifecycle leaks | bug | P2 | S-M | — | TODO |
| 010 | Initialize client shared state once across trust flips | bug | P2 | S | — | DONE |
| 011 | Don't leak/drop when WS client posts on a closing socket | bug | P2 | S | — | DONE |
| 012 | Atomic, non-throwing `createStorage` writes | bug | P2 | M | — | DONE |
| 013 | De-duplicate git parse helpers into `node/git.ts` | tech-debt | P2 | S | 004 | TODO |
| 014 | Parallelize the `git:show` static dump | perf | P2 | S-M | 004, 013 | TODO |
| 015 | Expire + bound the persisted trusted-token store | security | P2 | S | 007 (shared test) | TODO |
| 016 | Harden code-server: loopback bind + folder guard ⚠️ | security | P2 | M | 003 (mitigates cookie) | TODO |
| 017 | Make `allowArbitraryCommands` govern preset overrides ⚠️ | security | P2 | M | — | TODO |
| 018 | Persist a Turbo cache in CI (e2e job) | dx | P3 | S | — | TODO |
| 019 | RPC round-trip tests for the inspect plugin | tests | P3 | S | 001 (compl.) | TODO |
| 020 | Docs pages for the 15 plugin `DP_*` diagnostics | docs | P3 | M | — | TODO |
| 021 | Document `@devframes/plugin-messages` | docs | P3 | S | — | TODO |
| 022 | Memoize git commit-log rows | perf | P3 | M | — | DONE |
| 023 | Single-pass MessagesView filtering | perf | P3 | M | — | TODO |
| 024 | Batch stream-replay into one frame | perf | P3 | M | 009 | TODO |
| 025 | Cache falsy RPC results (presence check) | bug | P3 | S | — | DONE |
| 026 | Clear dev/docs-only dependency advisories | deps | P3 | S | 002 | TODO |
| 027 | Spike: `@devframes/next` host-integration package | direction | P3 | M | — | DONE (shipped `@devframes/next`, experimental — see `docs/helpers/next.md`; hub + next-runtime-snapshot examples adopt it) |
| 029 | Bring `@devframes/plugin-git` to the host baseline | direction/dx | P3 | S-M | — | TODO |
| 030 | Spike: server-side auth enforcement ⚠️ | security | P2 | L | 003, 007, 015 | DONE |
| 031 | Agent-native MCP wave (bridges, core surface, connector) | direction | P2 | L | — | IN PROGRESS (phases 1–3 implemented on PR #145; DONE at merge) |

Status values: TODO | IN PROGRESS | DONE | BLOCKED (one-line reason) | REJECTED (one-line rationale).

## Recommended sequencing

1. **First wave (P1, mostly non-breaking, quick, clean verification):** 001, 002,
   003, 004, 005, 006, 007. Do **001 early** (it makes the inspect plugin + examples
   actually typecheck, catching regressions from later work). **003** is the single
   highest-leverage security fix and is the prerequisite mitigation for the
   code-server cookie disclosure (016) and the auth-enforcement spike (030).
2. **Second wave (P2):** 008–017. Note the git chain: **004 → 013 → 014** all touch
   `show.ts`/`log.ts`, so land them in that order. 015 shares `state.test.ts` with 007.
3. **Third wave (P3 polish + docs + direction):** 018–029. 024 depends on 009.
4. **Design spike:** 030 (auth enforcement) after 003/007/015 — it only makes
   enforcement *possible and tested*, off by default; turning it on is a separate
   breaking follow-up.

## Dependency notes

- **013 depends on 004**, **014 depends on 004 + 013** — same git files
  (`show.ts`, `log.ts`); serialize to avoid collisions.
- **024 depends on 009** — both edit the streaming `subscribe` handler.
- **015 coordinates with 007** — both live in `node/auth/__tests__/state.test.ts`.
- **016's** cookie-disclosure residue is mitigated by **003** (origin check) and
  fully addressed by **030** (auth); 016 itself ships the bind + folder hardening.
- **026 depends on 002** — 002 clears the one runtime-shipped critical; 026 mops
  up the dev/docs-only advisories.
- **019 / 001** — 001 hit a STOP condition on the inspect plugin itself (see
  below) and did **not** add its `typecheck` script; 019's verification should
  run `tsc --noEmit` directly in `plugins/inspect` instead.

## Execution notes

- **001 shipped for 4 of the 6 in-scope packages** (`files-inspector`,
  `streaming-chat`, `next-runtime-snapshot`, `minimal-vite-devframe-hub`),
  fixing the small in-scope type errors each surfaced (a missing `*.css` /
  `virtual:uno.css` ambient shim, a superfluous `async` on a schema-typed RPC
  handler whose framework type requires a synchronous return, a missing
  destructure default matching a valibot `v.optional(..., default)`, a bad
  `as never[]` cast in `plugins/inspect/src/rpc/functions/invoke.ts` — the
  last one *is* an in-scope inspect-plugin fix and was kept even though the
  plugin's own script was not added, below).
- **`plugins/inspect` did not get the script** (STOP condition): its
  `tsconfig.json` is the only one in the repo with `composite: true`, which
  makes `tsc --noEmit` reject otherwise-valid cross-package imports (`devframe/
  utils/*`, `devframe/adapters/cli`, etc.) with TS6307 "file not listed in the
  file list of project" errors — a tsconfig fix, which this plan's Scope marks
  out-of-bounds. The plugin also has a few genuine SPA-composable type bugs
  (`src/spa/composables/{history,rpc}.ts`) independent of that flag. Follow-up:
  a small dedicated plan to drop `composite` (auditing why it was set — see
  `6bbe9d2`, it looks like copy-paste from a template, unused elsewhere) and
  then fix the remaining composable bugs.
- **`minimal-next-devframe-hub` did not get the script** (STOP condition):
  `packages/hub/src/node/host-terminals.ts` types its child-process `env` as
  `NodeJS.ProcessEnv`; Next.js's own ambient types (`next/types/global.d.ts`)
  augment `ProcessEnv` to require a literal-typed `NODE_ENV`, so the plain
  `{ COLORS, FORCE_COLOR, ...env }` object hub builds no longer satisfies it
  **once a Next.js app is in the program** (`packages/hub` typechecks clean on
  its own). Fixing this means loosening `host-terminals.ts`'s env type in
  `packages/hub` — out of scope here. Follow-up: type that field as
  `Record<string, string | undefined>` (or similar) in `packages/hub`.
- **CI guard added**: `scripts/verify-typecheck-coverage.ts` (wired into
  `pnpm typecheck`, and therefore into CI) now fails if any workspace package
  has a `tsconfig.json` but no `typecheck` script, with the two exceptions
  above declared explicitly (and flagged stale the moment they're fixed) —
  closing plan 001's original "Maintenance notes" follow-up so the gap this
  plan fixed can't quietly reopen.

## Findings considered and deferred / rejected

- **Hub-bridge type import (TECH-DEBT-02)** — terminals + code-server each
  duck-type `ctx.terminals` with local interfaces (`manager.ts:60-82`,
  `supervisor.ts:44-64`). Importing the canonical types from `@devframes/hub/types`
  would remove the drift risk, but a `import type` still makes the plugins' emitted
  `.d.ts` reference `@devframes/hub`, adding a type-resolution dependency the
  plugins **deliberately avoid** (they must typecheck standalone without hub). Net
  negative; **deferred** unless the maintainer accepts a type-only hub peer.
- **h3 pinned to a release candidate (DEPS-02)** — `pnpm-workspace.yaml:53` pins
  `h3: 2.0.1-rc.22` on the critical host path. This looks intentional (exact RC
  pin). No plan; **watch** for h3 GA and bump behind a `mountStaticHandler`/upgrade
  characterization test then.
- **serve-static per-request `stat` fan-out (PERF-05)** — `serve-static.ts:61-95`
  does up to ~5 `stat`s per request with no cache. For a dev tool this is
  acceptable, and a resolution cache risks serving stale files on rename/delete
  (MED risk for marginal gain). **Rejected** as not worth the staleness risk.
- **Shared-state RPC read/write not trust-gated (SEC-06)** —
  `node/rpc-shared-state.ts:94-130` exposes get/set/patch with no trust check.
  This is a real exposure but its root cause is the origin/auth gap; **folded into
  plan 003** (origin check) as the immediate mitigation and plan 030 (per-key
  client-writable opt-in + trust) as the durable fix. No standalone plan.
- **Auth token carried in the WS URL query** — `ws-client.ts:32-34` appends
  `?devframe_auth_token=…`. WS URLs aren't sent as `Referer` and this is
  loopback, so impact is low; noted for awareness, not planned.

## Audit coverage note

Audited across all nine categories (correctness, security, performance, tests,
tech-debt/architecture, dependencies, DX, docs, direction) over `packages/*`,
`plugins/*`, and the build/CI tooling. **Not deeply audited:** the plugins' SPA
render layers for DOM-XSS from untrusted repo content (flagged by the security
pass as a worthwhile dedicated follow-up — e.g. `plugins/git/src/client/**` diff/
commit views), `packages/nuxt`, `storybook/`, and the Playwright e2e specs
line-by-line.
