5.7 KiB
5.7 KiB
Tasks: packer-port
1. Scaffold
- 1.1 Create
packages/data/packer/withpackage.json(@suaveplan/packer@0.0.0),tsconfig.jsonextending@suaveplan/typescript-config/library.json,vitest.config.tsviacreateTestConfig(),README.md. - 1.2 Workspace deps:
@suaveplan/bitpacker,@suaveplan/crypto,@suaveplan/events,@suaveplan/mime,@suaveplan/error,@suaveplan/types,@suaveplan/streams,@opentelemetry/api,zod. Allworkspace:^. - 1.3 Subpath exports:
.,./chunked,./streaming,./errors.
2. Foundations
- 2.1
src/error-codes.ts—defineCodes("PACKER", [...]). SiblingPackerError. - 2.2
src/schemas/packer.schemas.ts— Zod boundary schemas forPackerOptions,ChunkedPackerOptions. Marker// schema: boundary-only. - 2.3
src/types/packer.types.ts—PackSource,PackerOptions,PackedData,ChunkedPackerOptions,ChunkMetadata,Manifest,EncryptionAlgorithm.
3. Streaming source normaliser
- 3.1 Port
src/streaming/normalize-source.tsfrom source. AcceptsUint8Array | ReadableStream<Uint8Array> | AsyncIterable<Uint8Array> | Blob. ReturnsAsyncIterable<Uint8Array>. - 3.2 Sibling
normalize-source.test.ts,normalize-source.md,normalize-source.types.ts.
4. Abstract base
- 4.1
src/abstract/abstract.ts—AbstractPackerextendingEventBus<PackerEventMap>-backed emitter. Compression (gzip vianode:zlib), AEAD wrappers, sign helpers. - 4.2 Replace source's untyped
EventEmitterwith typedEventBus<PackerEventMap>from@suaveplan/events.
5. Whole-file mode (preserves bitpacker schema)
- 5.1
src/packer/packer.ts—Packer extends AbstractPacker.pack(data, filename?): Promise<PackedData>with optional gzip + AEAD + ed25519 sign. Bitpacker schema retained. - 5.2
src/unpacker/unpacker.ts—Unpacker extends AbstractPacker.unpack(packed, key, pubKey?): Promise<{ data, metadata }>. - 5.3 Sibling tests +
.mdfor each.
6. Chunked v1 codec
- 6.1
src/chunked/codec/header.ts—encodeHeader(metadata): Uint8Array(100),parseHeader(buf): ChunkMetadatawith structural validation. Big-endian DataView reads/writes at locked offsets. - 6.2
src/chunked/codec/chunk.ts—encodeChunk({ metadata, sig, ciphertext }),parseChunk(buf)with length checks. - 6.3
src/chunked/codec/chunk.spec-conformance.test.ts— pin every byte offset againstCHUNKS-FORMAT-V1-01.
7. Chunked packer
- 7.1
src/chunked/packer/packer.ts—ChunkedPacker extends AbstractPacker.pack(source: PackSource, fileKey: EncryptKey, signKey: SignKey, opts?: ChunkedPackerOptions): AsyncIterable<{ chunkId, bytes }>. - 7.2 Pipeline:
normalizeSource → hash → aead-encrypt-stream → chop at (chunkSize - 164) → per-chunk sign → emit. - 7.3
packresolves with the assembled manifest (server-signed, fileId-addressed) at end of stream. - 7.4 Per-chunk nonce derivation:
nonce = baseNonce ⊕ chunkId-as-LE-bytes(24 B).
8. Chunked unpacker
- 8.1
src/chunked/unpacker/unpacker.ts—ChunkedUnpacker.unpack(chunks: AsyncIterable<Uint8Array>, fileKey: EncryptKey, serverPubKey: PublicKey): AsyncIterable<Uint8Array>(plaintext stream). - 8.2 Per-chunk: structural-parse → flags check → payloadLen invariants → sig-verify → aead-decrypt → emit
payloadLenplaintext bytes.
9. Chunk verifier (no decrypt)
- 9.1
src/chunked/verifier/chunk-verifier.ts—ChunkVerifier.verify(chunkBytes: Uint8Array, serverPubKey: PublicKey): VerifyResultwith{ ok: true, metadata }or{ ok: false, code: PackerErrorCode }. - 9.2 Used by mesh peers that forward chunks without holding the file decryption key.
10. Manifest
- 10.1
src/chunked/manifest/manifest.ts—buildManifest(metadata[], encryption, fileKey, signKey): Manifest,signManifest(manifest, signKey),verifyManifest(manifest, serverPubKey). - 10.2 Zod schema for manifest in
src/schemas/manifest.schema.ts.
11. Spec
- 11.1
openspec/specs/packer/spec.md—PACKER-WHOLE-01…PACKER-WHOLE-04,PACKER-CHUNK-01…PACKER-CHUNK-12,PACKER-CODES-01. Each with**Verified by:**line.
12. Conformance tests
- 12.1
src/packer/packer.spec-conformance.test.ts— whole-file pack/unpack round-trip, signed and unsigned, with and without gzip (PACKER-WHOLE-01…-04). - 12.2
src/chunked/codec/chunk.spec-conformance.test.ts— exact byte-offset pinning (PACKER-CHUNK-01v1 layout,PACKER-CHUNK-02flags=0 reject,PACKER-CHUNK-03payloadLen invariants). - 12.3
src/chunked/packer/packer.spec-conformance.test.ts— streaming pipeline end-to-end (PACKER-CHUNK-04); fixed non-final size (PACKER-CHUNK-05); short final chunk (PACKER-CHUNK-06). - 12.4
src/chunked/unpacker/unpacker.spec-conformance.test.ts— chunks-out → plaintext-in matches original (PACKER-CHUNK-07); rejects mutated chunks at sig stage (PACKER-CHUNK-08). - 12.5
src/chunked/verifier/chunk-verifier.spec-conformance.test.ts— verifies without file key (PACKER-CHUNK-09); rejects bad sig (PACKER-CHUNK-10). - 12.6
src/chunked/manifest/manifest.spec-conformance.test.ts— manifest sign + verify (PACKER-CHUNK-11); manifest matches chunk metadata (PACKER-CHUNK-12). - 12.7
src/error-codes.spec-conformance.test.ts— frozen registry,PACKER.*namespace (PACKER-CODES-01).
13. Verify
- 13.1
bunx turbo lint typecheck test --filter=@suaveplan/packergreen. - 13.2
bunx turbo test:coverage --filter=@suaveplan/packer100/100/100/100. - 13.3
bun scripts/openspec-conformance.ts @suaveplan/packerPASS. - 13.4 Sibling
.mdexists for every non-test, non-types, non-barrel.tsinsrc/.