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

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.