Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,102 @@
# `loader`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
`loader.ts` is the fetch → verify → unpack → Blob-URL pipeline for
packed resources. It is the only place in the package that issues a
network request, the only place that runs `Unpacker.unpack`, and the
only place that allocates a Blob URL. Splitting it out from
`PackedResourceManager` keeps every concern testable in isolation —
fetch retry, signature failure, abort propagation, and OTel histogram
emission can each be exercised without instantiating a cache.
## Features
- `fetch` routed through `@suaveplan/retry`'s `withRetry` with a
single-attempt default policy; callers opt in to retry by passing
`retryConfig`.
- `AbortSignal` honoured at every yield point — pre-fetch, post-fetch,
post-buffer, post-verify, and pre-unpack.
- Optional Ed25519 signature verification when `verifyKey` is supplied
and the response carries an `X-Archive-Signature` header.
- OTel emission: increments `packed_resource_fetch_total` on every
attempt; records `packed_resource_decode_ms` on every successful
pipeline run.
- Typed error surface: every failure produces `PackerBrowserError`
with a `PACKER_BROWSER.*` code and an i18n-resolved message.
- Injectable `fetch` for tests — no `vi.mock` required.
## Usage: Basic
```ts
import {
createPackerBrowserObservability,
PackedResourceLoader,
resolveRuntime,
} from "@suaveplan/packer-browser";
const loader = new PackedResourceLoader({
runtime: resolveRuntime(),
observability: createPackerBrowserObservability(),
});
const { url, metadata } = await loader.load("/banner.packed");
img.src = url;
```
## Usage: Advanced
```ts
import { createConstantBackoff } from "@suaveplan/retry";
import { PackedResourceLoader } from "@suaveplan/packer-browser";
const controller = new AbortController();
const loader = new PackedResourceLoader({
runtime: resolveRuntime(),
observability,
fetch: async (url) => recordedFetch(url),
});
const out = await loader.load("/banner.packed", {
verifyKey: trustAnchorPublicKey,
signal: controller.signal,
retryConfig: {
maxAttempts: 3,
delay: createConstantBackoff({ delay: 250 }),
},
});
```
## API Reference
- `new PackedResourceLoader(opts: PackedResourceLoaderOptions)`.
- `loader.load(url: string, opts?: PackedResourceLoadOptions):
Promise<LoadedResource>`.
- Throws `RESOURCE_NOT_FOUND` for non-2xx.
- Throws `ARCHIVE_SIGNATURE_INVALID` for a non-verifying signature
when `verifyKey` is supplied.
- Throws `LOAD_FAILED` when `Unpacker.unpack` rejects.
- Throws `ABORTED` when the supplied signal fires.
- `PackedResourceLoadOptions`:
- `verifyChecksum?: boolean` — default `false`.
- `verifyKey?: Uint8Array` — optional Ed25519 public key.
- `signal?: AbortSignal` — checked at every yield.
- `retryConfig?: RetryConfig` — default: single attempt.
- `messageResolver?: MessageResolver` — overrides the constructor's
resolver for this call.
## Implementation Notes
Cluster A's loader treats every fetched payload as a raw `PackedData`
whose metadata is reconstructed from the bytes; signature verification
covers the **archive transport** layer, while integrity verification
is delegated to the `Unpacker` and currently skipped
(`verifyIntegrity: false`) because Cluster A archives do not carry the
BLAKE3 integrity bundle. Cluster B introduces the formal manifest
decoder and re-enables integrity. The `X-Archive-Signature` header
contract is unchanged across clusters — switching to a separate
signature manifest is a Cluster B concern only.