diff --git a/docs/superpowers/specs/2026-08-01-runtime-integrity-refactor-design.md b/docs/superpowers/specs/2026-08-01-runtime-integrity-refactor-design.md new file mode 100644 index 0000000..855dbd1 --- /dev/null +++ b/docs/superpowers/specs/2026-08-01-runtime-integrity-refactor-design.md @@ -0,0 +1,171 @@ +# Runtime Integrity Refactor Design + +## Purpose + +Apply the repository-wide refactoring review without discarding the current +uncommitted implementation snapshot. The program closes release and boot +fail-open paths first, then makes runtime ownership explicit, and finally +consolidates tooling and large adapter modules. + +## Chosen approach + +Use a phased compatibility migration. + +- Rejected: a big-bang V2-only rewrite. It removes legacy code quickly but + combines artifact, boot, HTTP, cache, and worker changes into one unsafe + release. +- Rejected: patch only the currently failing verifier. It makes one gate green + while leaving cross-version boot acceptance, schema drift, and duplicate + execution contracts intact. +- Chosen: introduce explicit V1/V2 discriminated contracts, route every writer + and reader through them, migrate production execution onto one registry, and + remove legacy bridges only after each vertical is covered by tests. + +## Program boundaries + +The work is split into independently testable sub-projects. + +1. Release artifact integrity + - One executable schema for release, runtime-config, and build artifacts. + - Version-specific token projection. + - Real build-to-verification integration coverage. +2. Boot protocol integrity + - Exact supported version selection. + - V1/V1 and V2/V2 pairing only. + - Mandatory V2 contract-set verification and HTTP(S) endpoint policy. +3. Scope-owned server state and HTTP contract execution + - A scope generation owns QueryClient, mutations, optimistic state, and + cross-context resources. + - The composed external-contract registry is the only executable HTTP + registry. +4. Optional runtime and Service Worker lifecycle + - Generation-fenced start/stop. + - Nonce-based activation/reset acknowledgements. + - Bounded install streams and one verified rollback revision. +5. Quality infrastructure + - Typed subprocess results, bounded CI steps, generated artifact schemas, + one authoritative architecture analyzer, and representative coverage. +6. Adapter hardening and decomposition + - Shared bounded-body and worker-RPC primitives. + - IndexedDB singleflight. + - Route-policy closure, invalidation tuple identity, and focused extraction + from the largest adapter runtimes. + +## Release artifact architecture + +`scripts/contracts/release-artifacts.ts` owns Zod schemas for Release Manifest +V1/V2, Runtime Config V1/V2, and Build Manifest V1. Writers parse before writing; +readers parse before comparing. JSON Schema files are generated views and never +an independent source of truth. + +`projectReleaseTokens(document)` maps a parsed artifact into comparison tokens. +V1 projects the legacy API contract version. V2 projects +`contractSet.setDigest` as `contractSetDigest` and never requires the removed +scalar. Token comparison receives projected values, not arbitrary records. + +## Boot protocol architecture + +The version selector accepts only `"1"` and `"2.0"`. Parsing preserves the +versioned shape through manifest loading: + +```ts +type BootProtocol = + | { kind: "V1"; config: RuntimeConfigV1; manifest: ReleaseManifestV1 } + | { kind: "V2"; config: RuntimeConfigV2; manifest: ReleaseManifestV2 }; +``` + +Mixed pairs fail before application composition. V2 requires a contract set and +verifies it exactly once. Endpoint protocols are `http:` or `https:` in local +and development, and `https:` elsewhere. + +## Scope and execution ownership + +A `ScopeGenerationBundle` owns every resource capable of retaining account data: +QueryClient, mutation admission, optimistic layers, cross-context invalidation, +and optional closers. Transition order is fixed: + +1. publish FENCED and render only the transition surface; +2. close query and mutation admission; +3. abort in-flight work and roll back optimistic layers; +4. detach providers and close scoped transports; +5. clear and dispose the old QueryClient; +6. construct and mount a new bundle; +7. publish READY. + +Mandatory cleanup failure remains terminal/FENCED. It never publishes READY. + +The composed contract-contribution registry becomes the only HTTP operation +registry. Feature gateways resolve installed operations and map executor +outcomes; they do not carry parallel schemas or retry definitions. + +## Optional runtime and worker lifecycle + +Optional hosts use explicit lifecycle states plus a generation token. Every +continuation after an await verifies that generation. Stop closes admission, +waits for pending startup to settle, and disposes children in reverse order. + +Service Worker activation and reset messages are discriminated by kind and +carry source build, target build, nonce, and a typed result. Activation calls +`skipWaiting()` only after every controlled client acknowledges the same nonce. +Install owns a deadline AbortController, reads at most declared bytes plus one, +aborts siblings on first failure, and atomically records current and previous +verified asset digests. + +## Tooling and schema policy + +Subprocesses return `SUCCESS`, `EXPECTED_DIAGNOSTIC`, `TOOL_FAILURE`, `SIGNAL`, +or `TIMEOUT`. Negative fixtures must match expected diagnostic identifiers; +arbitrary non-zero exits are failures. CI gates have per-step timeouts and are +generated or structurally checked against `config/ci/gates.json`. + +The TypeScript-aware custom source analyzer becomes authoritative unless a +dependency-cruiser version with TypeScript 7 support is selected. A zero-module +analysis is always a gate failure. Concrete adapter-to-adapter dependencies are +replaced by injected ports or explicitly named shared infrastructure. + +## Error handling + +- Artifact or boot schema mismatches use stable, version-specific failure codes. +- Unknown future versions fail closed and do not fall back to V1. +- Mandatory scope cleanup and worker protocol failures remain terminal. +- Transport readers return closed failure unions; `UNKNOWN` is not a success + fallback. +- Tool invocation failures are never accepted as expected fixture rejection. + +## Testing strategy + +Every behavior change follows red-green-refactor. Required matrices include: + +- Release V1/V2 success plus field, digest, package, and schema tampering. +- Boot V1/V1 and V2/V2 success; mixed and future versions fail. +- Synchronous old-data hiding, late completion fencing, and cleanup failure. +- Old-page/new-worker activation, partial acknowledgement, reset results, and + install deadline/body limits. +- Process spawn error, null status, signal, timeout, and expected diagnostic. +- IndexedDB concurrent open, worker RPC crash/abort, and composite-key collision. + +Repository-wide verification includes types, lint, unit/component/integration, +browser capability tests where supported, build, release verification, schema +round-trip, architecture analysis, and diff hygiene. + +## Delivery order and compatibility + +Release artifact integrity and boot protocol integrity ship first and retain a +read-only V1 window. Scope ownership and HTTP registry consolidation ship next. +Optional runtime, quality infrastructure, and adapter decomposition follow as +separate reviewable changes. Public facades remain stable during internal file +splits; removal of legacy exports occurs only after static usage checks reach +zero. + +## Acceptance criteria + +- A clean V2 build passes release verification; every supported tamper fails. +- No accepted V2 boot bypasses contract-set verification. +- FENCED renders no previous-account data and late work cannot mutate a new + generation. +- Selected optional capabilities have a concrete host or fail composition. +- Negative quality fixtures cannot pass because a tool crashed or timed out. +- Checked-in JSON schemas exactly match executable schemas. +- Architecture analysis covers a non-zero complete module graph. +- No source file contains an actual NUL byte, and all final verification gates + report their real status.