5.3 KiB
OpenSpec Change: enterprise-browser-packer-browser
- Change ID: enterprise-browser-packer-browser
- Package:
@suaveplan/packer-browser - Category: browser
- Target path:
browser/storage/packer-browser - Status: IN PROGRESS
- Date: 2026-04-24
- Reference spec:
/mnt/s/web/suaveplan/enterprise/packer-browser.md
Summary
Deliver @suaveplan/packer-browser on the genesis branch at enterprise quality. The package provides the browser-side runtime for @suaveplan/packer packed media archives: a Service Worker interceptor, a PackedResourceManager with fetch + LRU cache, signed-manifest verification via @suaveplan/crypto, and SW lifecycle utilities. React hooks (usePackedResource etc.) move to a separate @suaveplan/react-packer companion. No react runtime dep in this package.
Current-state audit (genesis)
Fresh build — does not exist on genesis yet.
Available workspace deps on genesis
| Package | Role |
|---|---|
@suaveplan/packer (workspace:^) |
Pack/unpack, archive format, manifest |
@suaveplan/crypto (workspace:^) |
Signed-manifest verification |
@suaveplan/events (workspace:^) |
Resource lifecycle events |
@suaveplan/error (workspace:^) |
Typed errors |
@suaveplan/types (workspace:^) |
LoggerLike |
@suaveplan/logger (workspace:^) |
Structured logging in SW + manager |
@suaveplan/schema-registry (workspace:^) |
Manifest schema registration |
zod (catalog:forms) |
Manifest Zod schema |
@opentelemetry/api (catalog:observability) |
Fetch/cache/decode metrics |
tslib (catalog:build) |
Runtime helpers |
No react in runtime deps.
Dev: vitest, @vitest/coverage-istanbul, @playwright/test, @suaveplan/testing.
Preserved public API surface
// Manager (no React dep)
class PackedResourceManager {
fetch(assetPath: string): Promise<Blob>
release(assetPath: string): void
getMetrics(): PackedResourceManagerMetrics
clear(): void
}
function createPackedResourceManager(options: ManagerOptions): PackedResourceManager
// Singleton (backward compat at ./singleton subpath)
// import { packedResourceManager } from '@suaveplan/packer-browser/singleton'
// SW utilities
function registerPackedResourceServiceWorker(options?: SwOptions): Promise<ServiceWorkerRegistration>
function unregisterPackedResourceServiceWorker(): Promise<boolean>
function clearServiceWorkerCache(): Promise<void>
function getServiceWorkerCacheStatus(): Promise<SwCacheStatus>
// Types
interface PackedResource { path: string; mimeType: string; size: number; blob: Blob }
type PackedResourceType = 'image' | 'audio' | 'font' | 'video' | 'other'
Subpath exports: ./manager, ./service-worker, ./utils, ./singleton.
New additions for genesis
1. React hooks removed → @suaveplan/react-packer
usePackedResource, usePackedImage, usePackedFont, usePackedVideo, usePackedAudio all move to a companion package. This package has zero React runtime dep.
2. Signed-manifest verification
PackedResourceManager accepts manifestSignature in ManagerOptions. Before trusting packed resources, verifies signature with @suaveplan/crypto ed25519; throws PACKED_ARCHIVE_SIGNATURE_INVALID on failure.
3. Split PackedResourceManager
Into manager.ts (orchestration, LRU accounting), cache.ts (blob cache, hit/miss, eviction), loader.ts (fetch + decode + verify) — each ≤300 lines.
4. Service worker unit test
service-worker/service-worker.ts unit-tested via a ServiceWorkerGlobalScope shim; no coverage gap.
5. createPackedResourceManager factory
Replaces module-singleton; explicit factory. Singleton available at ./singleton backward-compat subpath.
6. Error codes
PACKED_RESOURCE_NOT_FOUND, SW_REGISTRATION_FAILED, PACKED_ARCHIVE_SIGNATURE_INVALID.
7. OTel metrics
Counter packer.resource_fetch_total, counter packer.cache_hits_total, counter packer.cache_miss_total, histogram packer.decode_ms.
File layout
browser/storage/packer-browser/
package.json
tsconfig.json
vitest.config.ts
src/
index.ts
error-codes.ts
manager/
manager/ (manager.ts — LRU orchestrator, manager.test.ts, manager.md)
cache/ (cache.ts — blob cache, cache.test.ts, cache.md)
loader/ (loader.ts — fetch + decode + manifest verify, loader.test.ts, loader.md)
service-worker/
service-worker/
service-worker.ts
service-worker.md
service-worker.test.ts (real SW scope shim)
index.ts
utils/
register-service-worker/
register-service-worker.ts
register-service-worker.md
register-service-worker.test.ts
index.ts
singleton/
index.ts (re-exports packedResourceManager singleton)
types/
types/
types.ts
types.md
index.ts
tests/
integration.test.ts
e2e/
packer-browser.spec.ts (Chromium/Firefox/WebKit SW interception)
Impact
Downstream: any browser app consuming packed media archives; @suaveplan/react-packer (new companion).
Breaking changes: usePackedResource hooks removed from this package (relocated to companion).
Prerequisites: @suaveplan/packer, @suaveplan/crypto, @suaveplan/events, @suaveplan/error, @suaveplan/logger on Verdaccio.