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

7.7 KiB

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:

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.