Files
2026-05-27 23:29:53 +01:00

72 lines
6.0 KiB
Markdown

# Tasks — enhance-packer-browser-streaming
## 1. Spec authoring
- [x] 1.1 Read `../suaveplan/enterprise/packer-browser.md` (§4 items 1, 2, 4, 6)
- [x] 1.2 Read `openspec/specs/packer-browser/spec.md` (Cluster A — PACKER-BROWSER-1..12)
- [x] 1.3 Read `openspec/AGENTS.md` Sections 13 and 14
- [x] 1.4 Draft `proposal.md` from `openspec/templates/proposal.md`
- [x] 1.5 Fill in `## Source mapping` — every requirement cites audit line range
- [x] 1.6 Draft `specs/packer-browser/spec.md` (Cluster B delta — PACKER-BROWSER-13..16) from `openspec/templates/spec-delta.md`
- [x] 1.7 Every requirement carries a `**Verified by:**` line naming concrete `it(...)` titles
## 2. Implementation
- [ ] 2.1 Add `KEY_UNAVAILABLE` to `src/error-codes.ts` (+ metadata) and matching i18n keys to `src/i18n/messages.ts`
- [ ] 2.2 Implement `src/keyring/keyring.ts` — `KeyringProvider`, `emptyKeyring()`, `MemoryKeyring`
- [ ] 2.3 Implement `src/encrypted-archive/encrypted-archive.ts` — `SP-ENC1` wire format encoder/decoder, AES-256-GCM helpers wrapping `aeadEncrypt`/`aeadDecrypt`
- [ ] 2.4 Wire `keyring` into `PackedResourceLoader.load` (decrypt step before unpack)
- [ ] 2.5 Implement `src/loader/loader-stream.ts` — `PackedResourceLoader.loadStream` async iterator yielding decoded entries as they arrive
- [ ] 2.6 Wire `PackedResourceManager.loadStream` pass-through with cache insertion
- [ ] 2.7 Implement `src/range-response/range-response.ts` — RFC 7233 §2.1 single-range parser + `Response` builder (`Content-Range`, `Accept-Ranges`, `Content-Length`, `If-Range` etag handling, 206/200/412/416)
- [ ] 2.8 Wire `serveRangeResponse` into `service-worker.ts` `fetch` handler behind `rangeThreshold` option (default 256 KiB)
- [ ] 2.9 Implement `src/content-address/content-address.ts` — `computeArchiveContentHash`, `buildContentAddressedUrl`, `cleanupOutdatedCaches`
- [ ] 2.10 Wire `cleanupOutdatedCaches` into service-worker `activate` handler when `contentAddressed` is on; recognise `legacyUrlPattern` in `fetch` handler when supplied
- [ ] 2.11 Register `PACKER_BROWSER_FLAGS.URL_CONTENT_ADDRESSED` via `flags/flags.ts` and surface from `PackedResourceManager`
- [ ] 2.12 Add 5 new exports to `src/index.ts` barrel (explicit named per §6a)
## 3. Tests
- [ ] 3.1 `src/loader/loader-stream.test.ts` — yields entries as decoded; pre-aborted signal short-circuits; mid-stream abort terminates cleanly; coexists with batch `load`; order-of-completion preserved
- [ ] 3.2 `src/manager/manager.test.ts` — manager's `loadStream` writes to cache as entries arrive (additive scenarios on the existing file; existing tests remain green)
- [ ] 3.3 `src/range-response/range-response.test.ts` — single-range 206, full 200, threshold gate, multi-range → 416, `If-Range` matching 206, `If-Range` mismatch 412, malformed range 416, `Accept-Ranges: bytes` always present
- [ ] 3.4 `src/service-worker/service-worker.test.ts` — additive: SW fetch handler emits 206 for ranged request above threshold; falls through to full body below threshold; `activate` invokes `cleanupOutdatedCaches`; legacy URL pattern still resolves when configured
- [ ] 3.5 `src/keyring/keyring.test.ts` — `emptyKeyring` rejects every keyId with `KEY_UNAVAILABLE`; `MemoryKeyring` returns ≥3 fixture keys; unknown keyId rejected
- [ ] 3.6 `src/encrypted-archive/encrypted-archive.test.ts` — round-trip AES-GCM encrypt/decrypt; magic-prefix detection; tampered ciphertext rejected; missing-key path throws `KEY_UNAVAILABLE`
- [ ] 3.7 `src/loader/loader.test.ts` — additive: loader detects encrypted prefix, decrypts via keyring, then unpacks; missing-key surfaces `KEY_UNAVAILABLE`; tampered ciphertext surfaces `LOAD_FAILED`
- [ ] 3.8 `src/content-address/content-address.test.ts` — `computeArchiveContentHash` deterministic for same entries; differs across format-version byte; `buildContentAddressedUrl` produces `/packed/<hash>.bundle.asset`; legacy form preserved when flag off; `cleanupOutdatedCaches` deletes everything not in keep list
- [ ] 3.9 `src/error-codes.test.ts` — additive: `KEY_UNAVAILABLE` present + reachable from production
- [ ] 3.10 Every `it(...)` carries `{ timeout: 5000 }` (30000 for genuinely async)
## 4. Documentation
- [ ] 4.1 Sibling `.md` for every new `.ts` (≥200 words; basic + advanced examples)
- [ ] 4.2 Update `src/loader/loader.md`, `src/manager/manager.md`, `src/service-worker/service-worker.md`, `src/error-codes.md`, `src/i18n/messages.md` to describe Cluster B additions
- [ ] 4.3 Update `README.md` if Quick Start surface changed (new exports listed)
## 5. Pre-archive verification (the 5-gate triple)
- [ ] 5.1 `bun run check` — Biome 0/0/0
- [ ] 5.2 `bunx turbo lint typecheck test --filter=@suaveplan/packer-browser` — green
- [ ] 5.3 `bunx turbo test:coverage --filter=@suaveplan/packer-browser` — 100/100/100/100
- [ ] 5.4 `bun scripts/openspec-conformance.ts @suaveplan/packer-browser` — exit 0
- [ ] 5.5 `bunx turbo build --filter=@suaveplan/packer-browser` — green
## 6. Pre-archive 9-row checklist
- [ ] 6.1 Generics threaded; `expectTypeOf` assertions on every literal-type claim
- [ ] 6.2 Zod schemas wired at every declared boundary (encrypted archive header)
- [ ] 6.3 Every error code in `error-codes.ts` thrown by ≥1 production path (incl. new `KEY_UNAVAILABLE`)
- [ ] 6.4 Strict-mode behaviors tested both on and off where applicable
- [ ] 6.5 OTel instruments emitted from production paths (existing four still wired)
- [ ] 6.6 Lifecycle dedup / in-flight Promise behaviour tested where claimed
- [ ] 6.7 AbortSignal honoured at every yield in streaming path
- [ ] 6.8 Tier purity preserved (browser-tier; no Node imports outside tests)
- [ ] 6.9 No retroactive tick — every box reflects work done in this change
## 7. Archive
- [ ] 7.1 Fold `specs/packer-browser/spec.md` into `openspec/specs/packer-browser/spec.md` (append PACKER-BROWSER-13..16, preserve 1..12)
- [ ] 7.2 Move `openspec/changes/enhance-packer-browser-streaming/` → `openspec/archive/<yyyy-mm-dd>-enhance-packer-browser-streaming/`
- [ ] 7.3 Refresh `MANIFEST.md` via `bun scripts/folder-reorg/generate-manifest.ts`