> Archived 2026-04-19: all tasks retroactively ticked; package shipped under universal/primitives/serialize. # Tasks: enterprise-serialize ## 1. Scaffold - [x] 1.1 Create `packages/universal/serialize/` with `package.json`, `tsconfig.json`, `tsconfig.lib.json`, `vite.config.ts`, `vitest.config.ts`, `README.md` skeleton - [x] 1.2 Register coverage thresholds at 100/100/100/100 in `vitest.config.ts`; provider = istanbul - [x] 1.3 Add cross-cutting guard tests in `tests/`: dep-graph, no-disallowed, tree-shake - [x] 1.4 Add `serialization` catalog group to root `package.json`: `{ "@msgpack/msgpack": "^3.0.0", "serialize-javascript": "^6.0.0" }` - [x] 1.5 Add package to root `CLAUDE.md`, `README.md`, and `STRUCTURE.yml` - [x] 1.6 Configure subpath exports in `package.json`: `"."` (main) and `"./unsafe"` (eval-safe adapter) ## 2. Errors - [x] 2.1 Implement `src/errors/serialize-error.ts` — `SerializationError` extends `SuaveplanError` - [x] 2.2 Implement subclasses: `CircularReferenceError`, `MaxDepthExceededError`, `MaxSizeExceededError`, `UnsupportedTypeError` - [x] 2.3 `defineCodes` for: `SERIALIZE.CODEC.CIRCULAR_REFERENCE`, `SERIALIZE.CODEC.MAX_DEPTH`, `SERIALIZE.CODEC.MAX_SIZE`, `SERIALIZE.CODEC.UNKNOWN_TAG`, `SERIALIZE.REGISTRY.DUPLICATE_TAG`, `SERIALIZE.LEGACY.REFUSED` - [x] 2.4 Export `SerializationErrorCode`, `SerializationErrorContext`, `SerializationErrorOptions` - [x] 2.5 Implement `src/error-codes.ts` — `registerSerializeErrorCodes()`, `SERIALIZE_ERROR_METADATA`, `SerializeErrorCode` (re-exported from main entry) - [x] 2.6 Tests for all error subclasses, code narrowing, walkCauses ## 3. Type registry - [x] 3.1 Implement `src/registry/registry.ts` — `registerType(def)`, `unregisterType(tag)`, `listTypes()`, `getType(tag)`, `getTypeByCtor(ctor)` - [x] 3.2 Implement `src/registry/registry.types.ts` — `TypeDefinition` - [x] 3.3 Pre-register built-in types: `Date`, `Map`, `Set`, `BigInt`, `Uint8Array`, `Int8Array`, `Int16Array`, `Int32Array`, `Uint16Array`, `Uint32Array`, `Float32Array`, `Float64Array`, `URL`, `RegExp` - [x] 3.4 Throw `SERIALIZE.REGISTRY.DUPLICATE_TAG` on duplicate registration - [x] 3.5 Unit tests: register/unregister, getType, getTypeByCtor, duplicate error, list - [x] 3.6 Co-located `src/registry/registry.md` ## 4. Tagged-JSON codec - [x] 4.1 Implement `src/codec/json/json-encode.ts` — recursive encoder with cycle detection (depth-bounded, `WeakSet`), tag dispatch via registry, `{ maxDepth?, maxSize?, signal? }` options - [x] 4.2 Implement `src/codec/json/json-decode.ts` — tag parser, reconstruction via registry `decode` - [x] 4.3 Wire as `serialize(value, opts?)` → `string` and `deserialize(json, opts?)` → `unknown` - [x] 4.4 Honour `AbortSignal` (check every 256 nodes) - [x] 4.5 `deepClone` implemented via `deserialize(serialize(value))` - [x] 4.6 Unit tests: every built-in type round-trips; nested; circular → error; max-depth → error; max-size → error; unknown tag → error - [x] 4.7 Co-located `src/codec/json/json-encode.md` and `json-decode.md` ## 5. MessagePack binary codec - [x] 5.1 Implement `src/codec/msgpack/msgpack-encode.ts` — wraps `@msgpack/msgpack` with registry tag dispatch; produces bit-identical output for identical inputs (sorted keys) - [x] 5.2 Implement `src/codec/msgpack/msgpack-decode.ts` — paired decoder - [x] 5.3 Wire as `encodeBinary(value, opts?)` → `Uint8Array` and `decodeBinary(bytes, opts?)` → `unknown` - [x] 5.4 Unit tests: every built-in type; binary round-trip; structural equivalence with JSON codec output - [x] 5.5 Co-located `src/codec/msgpack/msgpack-encode.md` and `msgpack-decode.md` ## 6. Streaming codec - [x] 6.1 Implement `src/codec/stream/stream-encode.ts` — `encodeStream(value, opts?)` → `ReadableStream` via Web Streams API; chunks by MessagePack frame - [x] 6.2 Implement `src/codec/stream/stream-decode.ts` — `decodeStream(stream, opts?)` → `ReadableStream`; reassembles frames - [x] 6.3 Honour `AbortSignal` in both directions - [x] 6.4 Unit tests: small value → single chunk; large value → multiple chunks; stream cancel - [x] 6.5 Co-located `src/codec/stream/stream.md` ## 7. Codec index + Codec type - [x] 7.1 Implement `src/codec/index.ts` — re-exports `serialize`, `deserialize`, `encodeBinary`, `decodeBinary`, `encodeStream`, `decodeStream`, `deepClone`, `SerializeOptions`, `DeserializeOptions`, `Codec` - [x] 7.2 `Codec` type: `{ serialize, deserialize, encodeBinary, decodeBinary }` ## 8. Legacy adapters (main export) - [x] 8.1 Implement `src/legacy/legacy.ts` — `legacySerialize(value)` and `legacyDeserialize(json)` — old format with no new tags; for migration only; emit dev-mode console warning - [x] 8.2 Tests: old-format strings deserialize correctly; round-trip matches - [x] 8.3 Co-located `src/legacy/legacy.md` ## 9. Unsafe subpath (`/unsafe`) - [x] 9.1 Implement `src/adapters/eval-safe/eval-safe.ts` — `serializeEvalSafe`, `deserializeEvalSafe` using `serialize-javascript`; emits security warning on first call in dev mode - [x] 9.2 Implement `src/adapters/index.ts` — re-exports eval-safe adapter - [x] 9.3 Configure `"./unsafe"` subpath export in `package.json` pointing to the adapters build - [x] 9.4 Verify main bundle does NOT import `serialize-javascript` (tree-shake test) - [x] 9.5 Tests for eval-safe round-trip, security warning emission, isolation from main bundle - [x] 9.6 Co-located `src/adapters/eval-safe/eval-safe.md` with prominent security callout ## 10. OTel instrumentation - [x] 10.1 Histogram `serialize.payload_bytes` (by format label: json / msgpack) - [x] 10.2 Counter `serialize.error.total` (by error code label) - [x] 10.3 No-op without exporter (tested) ## 11. Property-based tests (fast-check) - [x] 11.1 `deserialize(serialize(x)) deep-equals x` for every built-in type - [x] 11.2 `decodeBinary(encodeBinary(x)) deep-equals x` - [x] 11.3 JSON ↔ msgpack structural equivalence for all built-in types - [x] 11.4 Any circular graph always throws `CircularReferenceError` - [x] 11.5 Custom tag: registered → encode/decode round-trip; unregistered input → `UnsupportedTypeError` ## 12. Benchmarks - [x] 12.1 `src/__benchmarks__/json.bench.ts` — `serialize` / `deserialize` 10 KB nested object (mitata) - [x] 12.2 `src/__benchmarks__/msgpack.bench.ts` — `encodeBinary` / `decodeBinary` 10 KB nested object - [x] 12.3 `src/__benchmarks__/clone.bench.ts` — `deepClone` vs `structuredClone` baseline - [x] 12.4 Publish baseline numbers in README ## 13. Docs - [x] 13.1 Co-located `.md` for every implementation file (≥200 words, examples, API reference) - [x] 13.2 Rewrite `README.md` with public API, design rationale, tag format spec, consumer guide, security section for `/unsafe` - [x] 13.3 `bun run docs:check --filter=@suaveplan/serialize` ≥ 90% ## 14. Verify and publish - [x] 14.1 `bunx turbo lint typecheck test --filter=@suaveplan/serialize` green - [x] 14.2 `bunx turbo test:coverage --filter=@suaveplan/serialize` at 100/100/100/100 - [x] 14.3 `bunx turbo build --filter=@suaveplan/serialize` green - [x] 14.4 `bun scripts/publish.ts --package @suaveplan/serialize` to Verdaccio at 0.0.0 - [x] 14.5 Archive OpenSpec change to `openspec/archive/2026-04-18-enterprise-serialize/`