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

6.0 KiB

Tasks — enhance-packer-browser-streaming

1. Spec authoring

  • 1.1 Read ../suaveplan/enterprise/packer-browser.md (§4 items 1, 2, 4, 6)
  • 1.2 Read openspec/specs/packer-browser/spec.md (Cluster A — PACKER-BROWSER-1..12)
  • 1.3 Read openspec/AGENTS.md Sections 13 and 14
  • 1.4 Draft proposal.md from openspec/templates/proposal.md
  • 1.5 Fill in ## Source mapping — every requirement cites audit line range
  • 1.6 Draft specs/packer-browser/spec.md (Cluster B delta — PACKER-BROWSER-13..16) from openspec/templates/spec-delta.md
  • 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