Files
tech-log-frontend/docs/superpowers/specs/2026-08-01-runtime-integrity-refactor-design.md

172 lines
7.7 KiB
Markdown

# 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.