5.7 KiB
5.7 KiB
Tasks: enterprise-browser-packer-browser
Change ID: enterprise-browser-packer-browser
Package: @suaveplan/packer-browser
Target path: browser/storage/packer-browser
Prerequisite packages on Verdaccio: @suaveplan/packer, @suaveplan/crypto, @suaveplan/events, @suaveplan/error, @suaveplan/logger
0. Pre-flight (non-negotiable)
- 0.1 Confirm clean working tree (
git statusreports nothing) and no in-flight worktrees with uncommitted work (git worktree listthengit statusin each) - 0.2 If any worktrees exist under
.claude/worktrees/, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (git worktree remove) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - 0.3 Confirm the package set in
MANIFEST.mdmatchesfind packages -maxdepth 3 -name package.jsoncount. Drift here means a prior change archived without regenerating the manifest.
1. Scaffold
- Create directory tree per
proposal.md. package.jsonv0.0.0,"sideEffects": false.dependencies:@suaveplan/packer workspace:^,@suaveplan/crypto workspace:^,@suaveplan/events workspace:^,@suaveplan/error workspace:^,@suaveplan/types workspace:^,@suaveplan/logger workspace:^,@suaveplan/schema-registry workspace:^,zod catalog:forms,@opentelemetry/api catalog:observability,tslib catalog:builddevDependencies:vitest catalog:testing,@vitest/coverage-istanbul catalog:testing,@playwright/test catalog:testing,@suaveplan/testing workspace:^- Subpath exports:
".","./manager","./service-worker","./utils","./singleton"
tsconfig.json,vitest.config.ts(pool: forks,fileParallelism: false).
2. Error codes
PACKED_RESOURCE_NOT_FOUND,SW_REGISTRATION_FAILED,PACKED_ARCHIVE_SIGNATURE_INVALID.registerPackerBrowserErrorCodes()— call eagerly insrc/index.ts.
3. Types (src/types/types/)
PackedResource { path: string; mimeType: string; size: number; blob: Blob }.PackedResourceType = 'image' | 'audio' | 'font' | 'video' | 'other'.ManagerOptions,SwOptions,SwCacheStatus,PackedResourceManagerMetrics.- Write
types.md.
4. Cache module (src/manager/cache/)
cache.ts— LRU blob cache:get(path),set(path, blob),evict(),clear(),metrics().- Configurable
maxEntriesandmaxBytes; eviction on exceed. - Write
cache.test.ts(CRUD, LRU eviction order, byte-limit eviction). Writecache.md.
5. Loader module (src/manager/loader/)
loader.ts— fetch archive URL, decode via@suaveplan/packer, verify manifest signature whenmanifestSignatureprovided.- On invalid signature throw
PACKED_ARCHIVE_SIGNATURE_INVALIDvia@suaveplan/cryptoed25519 verify. - Write
loader.test.ts(fetch success, decode, signature valid, signature invalid). Writeloader.md.
6. Manager module (src/manager/manager/)
manager.ts— LRU orchestrator composingcache.ts+loader.ts.fetch(assetPath): Promise<Blob>— cache hit fast path; cache miss → loader → cache insert.release(assetPath),clear(),getMetrics(): PackedResourceManagerMetrics.- Wire OTel counters:
packer.resource_fetch_total,packer.cache_hits_total,packer.cache_miss_total; histogrampacker.decode_ms. - Write
manager.test.ts(fetch hit, fetch miss, release, clear, metrics). Writemanager.md.
7. createPackedResourceManager factory (src/manager/)
index.tsre-exportingcreatePackedResourceManager(options: ManagerOptions): PackedResourceManager.- Factory validates options with Zod; throws typed error on invalid config.
8. Service Worker (src/service-worker/service-worker/)
service-worker.ts—ServiceWorkerGlobalScopehandler: intercept fetch, match against packed archive cache, respond or pass through.- Write
service-worker.test.tsvia aServiceWorkerGlobalScopeshim (novi.stubGlobal). - Write
service-worker.md.
9. SW utilities (src/utils/register-service-worker/)
register-service-worker.ts—registerPackedResourceServiceWorker(options?),unregisterPackedResourceServiceWorker(),clearServiceWorkerCache(),getServiceWorkerCacheStatus().- Throw
SW_REGISTRATION_FAILEDon registration failure. - Write
register-service-worker.test.ts. Writeregister-service-worker.md.
10. Singleton subpath (src/singleton/)
index.ts—export const packedResourceManager = createPackedResourceManager(defaultOptions)for backward compat.
11. Integration test (tests/integration.test.ts)
- Fetch multiple assets from a packed archive.
- Verify LRU eviction under quota pressure.
- Verify signature rejection path.
12. Playwright E2E (e2e/packer-browser.spec.ts)
- Chromium, Firefox, WebKit browser contexts.
- Assert SW intercepts packed asset requests and serves blobs.
- Assert SW cache invalidation after
clearServiceWorkerCache().
13. Docs + verify
- Write
.mdper module (≥200 words, API reference, examples). - Write
README.mdwith subpath table, manifest-verification guide, SW setup. bunx turbo lint typecheck test --filter=@suaveplan/packer-browser— green.bunx turbo test:coverage— 100%.- No
@ts-expect-errorinsrc/or tests. Novi.stubGlobal. - Playwright E2E green on Chromium, WebKit, Firefox.
bun scripts/publish.ts --package @suaveplan/packer-browser.- Archive to
openspec/archive/2026-04-24-enterprise-browser-packer-browser/.