Files
tech-log-frontend/docs/superpowers/plans/2026-08-01-http-worker-adapter-remediation.md
T

159 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# HTTP Worker and Adapter Remediation Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Remove duplicate HTTP authorities, harden Service Worker activation bounds and identity, and decompose large browser adapters only after shared golden behavior is locked.
**Architecture:** Installed contract contributions are the HTTP source of truth and expose provider-neutral typed outcomes. Worker protocol V2 exchanges a canonical full-identity digest. Browser adapter facades remain stable while shared persisted schemas and cohesive internal modules are extracted.
**Tech Stack:** TypeScript 7, Fetch API, Service Worker API, IndexedDB, OPFS, React 19, Vitest 4, Playwright.
## Global Constraints
- Contract and application layers never import concrete adapter outcome types.
- Production exports accept only `BoundQuery` and `BoundMutation` after migration.
- Runtime timeout is a global ceiling applied over descriptor deadlines.
- Worker marker reads are bounded even without `Content-Length` and cancel oversized/non-terminating streams.
- Public adapter facades and product-default optional capability selection remain unchanged.
- Extraction follows characterization tests; file length alone does not justify a split.
---
### Task 1: Installed HTTP contract as single source of truth
**Files:**
- Modify: `src/features/reference-feature/contracts/reference-feature-contract.ts`
- Modify: `src/features/reference-feature/contracts/reference-schemas.ts`
- Modify: `src/contracts/external-contract-runtime.ts`
- Modify: `src/contracts/api-operations.ts`
- Modify: `src/contracts/rest-profiles.ts`
- Modify: `src/contracts/schema-registry.ts`
- Modify: `src/features/installed-feature-contracts.ts`
- Modify: `src/bootstrap/runtime-adapters.ts`
- Modify: `tests/features/reference-feature/reference-contract.test.ts`
- Modify: `tests/runtime-schema/http-schema.test.ts`
- Modify: `tests/integration/http-execution-contract.test.ts`
- Modify: `tests/unit/http-execution-v3.test.ts`
- [ ] Add parity tests showing method/path/validators/retry/effect/deadline/byte bounds come from one contribution; `createdAt` accepts omitted or RFC3339 datetime and rejects arbitrary strings.
- [ ] Run focused tests and confirm RED on duplicated descriptors and permissive date schema.
- [ ] Make the installed contribution authoritative; generate temporary legacy views from it and migrate all production callers before deleting the legacy registries/codecs.
- [ ] Apply `REQUEST_TIMEOUT_MS` as `min(runtimeCeiling, descriptorDeadline)` without replacing shorter descriptor deadlines.
- [ ] Keep the deadline authoritative through response admission and body reads: a deadline-owned abort after headers must still return `TRANSPORT_FAILURE / TIMEOUT`, perform one attempt, and never enter retry sleep instead of being masked as `RESPONSE_STREAM_FAILURE`.
- [ ] Treat credential resolution as a credential-only patch boundary: reject attempts to inject or overwrite `Idempotency-Key` (including case variants) or transport/query authority, and cover hostile patches in the executor regression table.
- [ ] Prove diagnostic privacy against the full runtime seam with non-empty identity references; assertions over an empty diagnostic projection do not count as evidence that intent/key/query identity is absent.
- [ ] Re-run focused tests, prove `rg` has zero production callers of removed registries, and commit with `git commit -m "refactor: consolidate installed HTTP contracts"`.
### Task 2: Provider-neutral typed operation outcomes
**Files:**
- Create: `src/contracts/operation-outcome.ts`
- Create: `src/application/ports/contract-operation-executor.ts`
- Modify: `src/features/reference-feature/adapters/reference-http-gateway.ts`
- Modify: `src/bootstrap/runtime-adapters.ts`
- Modify: `src/adapters/http/http-execution-v3.ts`
- Modify: `tests/features/reference-feature/reference-contract.test.ts`
- Modify: `tests/unit/runtime-adapters.test.ts`
- [ ] Add compile/runtime tests that unknown operation IDs and mismatched input/output types fail, and that the feature gateway has no import from `src/adapters/http`.
- [ ] Run focused tests/typecheck and confirm RED because the port is `operationId: string`, `input: unknown`, and concrete `HttpExecutionOutcome` leaks inward.
- [ ] Derive `InstalledOperationMap` from installed contracts, expose generic `execute<K extends keyof Map>(operationId: K, input: Map[K]["input"], context)` and map HTTP outcomes to provider-neutral contract outcomes at the adapter boundary.
- [ ] Re-run tests, typecheck, and architecture; commit with `git commit -m "refactor: type installed contract operations"`.
### Task 3: Bound-only server-state exports
**Files:**
- Modify: `src/presentation/adapters/query/application-query.ts`
- Modify: `src/presentation/adapters/query/index.ts`
- Modify: `src/features/reference-feature/presentation/use-reference-feature.ts`
- Create: `tests/helpers/legacy-application-query-harness.tsx`
- Modify: `tests/component/application-query.test.tsx`
- [ ] Add type tests that production hooks reject raw query keys and raw mutation executors while bound definitions still compile.
- [ ] Run typecheck and confirm current overloads accept raw forms.
- [ ] Move legacy raw harness behavior under `tests/helpers`; remove `LegacyMutationOptions` and the raw query union from production exports; migrate feature callers to `bindQuery`/bound mutations.
- [ ] Run focused component tests and typecheck; commit with `git commit -m "refactor: expose bound server-state hooks only"`.
### Task 4: Bounded Service Worker marker reader
**Files:**
- Create: `src/adapters/service-worker/bounded-worker-response.ts`
- Modify: `src/adapters/service-worker/service-worker-lifecycle.ts`
- Modify: `tests/unit/service-worker-runtime.test.ts`
- [ ] Add tests for oversized declared length, headerless oversized chunks, invalid UTF-8, malformed JSON, and a non-terminating stream. Assert reader cancellation and bounded completion.
- [ ] Run `corepack pnpm exec vitest run tests/unit/service-worker-runtime.test.ts` and confirm RED because lifecycle calls `response.text()`.
- [ ] Implement realm-safe stream reads up to `maxBytes + 1`, fatal `TextDecoder`, explicit cancellation, and strict marker parsing. Never call `Response.text()` for protocol data.
- [ ] Re-run tests and commit with `git commit -m "fix: bound Service Worker activation markers"`.
### Task 5: Service Worker protocol V2 full identity
**Files:**
- Modify: `src/contracts/service-worker.ts`
- Modify: `src/adapters/service-worker/service-worker-protocol.ts`
- Modify: `src/adapters/service-worker/service-worker-entry.ts`
- Modify: `src/adapters/service-worker/service-worker-lifecycle.ts`
- Modify: `src/adapters/service-worker/service-worker-page-controller.ts`
- Modify: `src/bootstrap/register-service-worker.ts`
- Modify: `scripts/generate-build-manifest.ts`
- Modify: `tests/unit/service-worker-runtime.test.ts`
- Modify: `tests/unit/service-worker-build-input.test.ts`
- [ ] Add a tuple-mutation table for protocol/cache schema/build/release/contract/static set; each mutation must change the digest and reject activation. Add a valid ACTIVE fixture build that recomputes static set digest from asset entries.
- [ ] Run focused tests and confirm RED because protocol V1 compares partial fields.
- [ ] Set `SERVICE_WORKER_PROTOCOL_VERSION = 2`, define canonical sorted identity serialization, compute SHA-256 over every identity field, and exchange/validate the digest on every page-worker message.
- [ ] Keep default capability selection `null`; use ACTIVE only in the explicit fixture build.
- [ ] Re-run focused tests and the supported fixture build; commit with `git commit -m "fix: bind Service Worker activation to full identity"`.
### Task 6: Shared IndexedDB persisted-row schema
**Files:**
- Create: `src/adapters/storage/indexeddb/indexeddb-persisted-schema.ts`
- Modify: `src/adapters/storage/indexeddb/indexeddb-types.ts`
- Modify: `src/adapters/storage/indexeddb/indexeddb-runtime.ts`
- Modify: `src/adapters/storage/indexeddb/indexeddb-maintenance.ts`
- Create: `tests/fixtures/indexeddb/persisted-rows.ts`
- Modify: `tests/unit/indexeddb-runtime.test.ts`
- Modify: `tests/unit/indexeddb-maintenance.test.ts`
- [ ] Before extraction, run the same accepted/rejected record, receipt, retention, and budget golden rows through runtime and maintenance and assert identical verdicts.
- [ ] Confirm RED on at least one drift fixture using the duplicate current guards.
- [ ] Move persisted types/guards into the shared module; runtime and maintenance import it without behavior changes.
- [ ] Re-run both large suites and commit with `git commit -m "refactor: share IndexedDB persisted schemas"`.
### Task 7: Cohesive browser adapter decomposition
**Files:**
- Modify: `src/adapters/storage/opfs/opfs-worker-runtime.ts`
- Create: `src/adapters/storage/opfs/opfs-worker-bootstrap.ts`
- Create: `src/adapters/storage/opfs/opfs-worker-message-host.ts`
- Create: `src/adapters/storage/opfs/opfs-worker-core.ts`
- Create: `src/adapters/storage/opfs/opfs-worker-lock.ts`
- Create: `src/adapters/storage/opfs/opfs-physical-io.ts`
- Modify: `src/adapters/cache-storage/public-response-cache-adapter.ts`
- Create: `src/adapters/cache-storage/public-cache-manifest.ts`
- Create: `src/adapters/cache-storage/cache-lock.ts`
- Modify: `src/adapters/browser-files/download-delivery-adapter.ts`
- Create: `src/adapters/browser-files/download-browser-managed.ts`
- Create: `src/adapters/browser-files/download-picker-stream.ts`
- Create: `src/adapters/browser-files/download-object-url.ts`
- Modify: `tests/unit/opfs-worker-runtime.test.ts`
- Modify: `tests/unit/public-response-cache.test.ts`
- Modify: `tests/unit/browser-file-download.test.ts`
- [ ] Add golden facade tests for all success/failure/cancellation/lock-loss branches before moving code; snapshot externally observable operation order and error kinds.
- [ ] Run the three focused suites and capture GREEN characterization evidence.
- [ ] Extract OPFS bootstrap, host, core state machine, Web Lock, and physical I/O without changing public exports. Do not split the core state machine further.
- [ ] Extract public-cache manifest codec/digest and generic lock logic behind the same facade.
- [ ] Extract browser-managed, picker streaming, and object-URL download strategies behind the same delivery facade.
- [ ] Re-run the same golden suites after each extraction. Any failure is a refactor regression, not a fixture update.
- [ ] Commit each adapter independently with `refactor: decompose OPFS worker adapter`, `refactor: extract public cache internals`, and `refactor: extract download delivery strategies`.
### Task 8: HTTP/worker/adapter verification
- [ ] Run all focused tests named in Tasks 17.
- [ ] Run `corepack pnpm check:architecture`, `corepack pnpm check:types`, and `corepack pnpm lint`.
- [ ] Run `corepack pnpm test:all`.
- [ ] Run supported Service Worker, IndexedDB, OPFS, public-cache, and download Playwright capability specs.
- [ ] Run `git diff --check` and report unsupported browser gates without claiming success.