6.8 KiB
6.8 KiB
Tasks — Serialize proto-guard + structured-clone surface
Every checkbox MUST reflect work actually done in this change. Do not retroactively tick boxes for work that was already in main when this change opened.
0. Pre-flight (non-negotiable)
- 0.1 Confirm clean working tree (
git statusreports nothing) and no in-flight worktrees with uncommitted work (git worktree listthengit statusin each) - 0.2 If any worktrees exist under
.claude/worktrees/, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (git worktree remove) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - 0.3 Confirm the package set in
MANIFEST.mdmatchesfind packages -maxdepth 3 -name package.jsoncount. Drift here means a prior change archived without regenerating the manifest.
Audit Note (2026-05-02)
Minimal progress — DEFERRED, do not archive.
packages/data/serialize/src/has nosecurity/directory. Thecodec/directory exists but contains nostructured-clone/module.grep -rln "stripPrototypePolluters\|deepClone\|proto-guard\|structured-clone" packages/data/serialize/src/returns zero hits.bunx turbo lint typecheck test --filter=@suaveplan/serializeis GREEN — but neitherproto-guardnorstructured-cloneships.- All 44 tasks remain: register
STRUCTURED_CLONE.UNAVAILABLE+PROTO_GUARD.FORBIDDEN_KEYcodes, portstripPrototypePollutersandcloneAndStrip, portdeepClone, JSON-decoder option wiring, OTel span event, subpath exports, sibling.mds, root-barrel re-exports, conformance tests for both new modules.
1. Spec authoring
- 1.1 Read
../suaveplan/packages/universal/serialize/src/security/proto-guard.tsend-to-end - 1.2 Read
../suaveplan/packages/universal/serialize/src/codec/structured-clone/structured-clone.tsend-to-end - 1.3 Read
openspec/specs/serialize/spec.md - 1.4 Read
openspec/AGENTS.mdSections 13 and 14 - 1.5 Draft
proposal.mdfromopenspec/templates/proposal.md - 1.6 Fill in
## Source mappingtable — every requirement cites a line range OR appears in the "no source line" table with justification - 1.7 Draft
specs/serialize/spec.mdfromopenspec/templates/spec-delta.md - 1.8 Every requirement in the spec delta carries a
**Verified by:**line naming concreteit(...)titles
2. Implementation
- 2.1 Register error codes
STRUCTURED_CLONE.UNAVAILABLE,PROTO_GUARD.FORBIDDEN_KEYinsrc/error-codes.ts - 2.2 Create
src/security/proto-guard/feature module withproto-guard.ts,proto-guard.types.ts,proto-guard.schemas.ts,proto-guard.md,index.ts - 2.3 Implement
stripPrototypePolluters(value, options?)(in-place mutation; recursion across plain objects and arrays only) - 2.4 Implement
cloneAndStrip<T>(value, options?)(delegates todeepClonethenstripPrototypePolluters) - 2.5 Create
src/codec/structured-clone/feature module withstructured-clone.ts,structured-clone.md,index.ts - 2.6 Implement
deepClone<T>(value)overglobalThis.structuredClonewithSerializationErrorfallback - 2.7 Add subpath exports
./security/proto-guardand./codec/structured-clonetopackage.json::exports - 2.8 Re-export
deepCloneandstripPrototypePollutersfrom the root barrelsrc/index.ts - 2.9 Extend
src/codec/json/json-decode.tswithstripPrototypePolluters?: booleanoption (defaultfalse); whentrue, run post-pass after the existing reviver guard - 2.10 Wire OTel span event
serialize.proto-guard.stripwithkeysRemoved: numberattribute
3. Tests
- 3.1 Unit tests at
src/security/proto-guard/proto-guard.test.ts— recursion, non-traversal into class instances / Map / Set / Date / Uint8Array, in-place mutation,cloneAndStrippreserves input - 3.2 Spec-conformance tests at
src/security/proto-guard/proto-guard.spec-conformance.test.ts—allowDangerousKeys: trueno-ops; OTel span event emitted with correctkeysRemovedcount via real in-memoryTracerProvider - 3.3 Unit tests at
src/codec/structured-clone/structured-clone.test.ts— round-trip primitives / objects / arrays / Map / Set / Date / Uint8Array;deepClone(undefined)returnsundefined - 3.4 Spec-conformance tests at
src/codec/structured-clone/structured-clone.spec-conformance.test.ts—SerializationErrorwithSTRUCTURED_CLONE.UNAVAILABLEthrown whenglobalThis.structuredCloneisundefined; subpath import resolves - 3.5 Spec-conformance test in
src/codec/json/json-decode.spec-conformance.test.tscoveringstripPrototypePolluters: truepost-pass behaviour - 3.6 Every
it(...)carries{ timeout: 5000 }
4. Documentation
- 4.1
src/security/proto-guard/proto-guard.md— sibling doc (≥200 words, basic + advanced, full API) - 4.2
src/codec/structured-clone/structured-clone.md— sibling doc (≥200 words, basic + advanced, full API, documentSTRUCTURED_CLONE.UNAVAILABLEruntime requirement) - 4.3 README links both
.mdfiles under## Modules - 4.4 Update
CLAUDE.md@suaveplan/serializeentry to mentionstripPrototypePollutersanddeepClone
5. Pre-archive verification (the 5-gate triple)
- 5.1
bun run check— Biome 0 errors / 0 warnings / 0 info across the whole monorepo - 5.2
bunx turbo lint typecheck test --filter=@suaveplan/serialize— green - 5.3
bunx turbo test:coverage --filter=@suaveplan/serialize— 100/100/100/100 - 5.4
bun scripts/openspec-conformance.ts @suaveplan/serialize— exit 0, noerrorfindings - 5.5
bunx turbo build --filter=@suaveplan/serialize— green - 5.6
bunx turbo test --filter=...@suaveplan/serialize— every dependent (network-plugin-protocol, network-websockets, network-plugin-webrtc, slsa, audit-logging, etl) passes
6. Pre-archive 7-row checklist (AGENTS.md Section 13)
- 6.1 Generics threaded;
expectTypeOfassertions oncloneAndStrip<T>return type - 6.2 Zod schemas wired at every declared boundary (proto-guard options)
- 6.3 Both error codes (
STRUCTURED_CLONE.UNAVAILABLE,PROTO_GUARD.FORBIDDEN_KEY) thrown by at least one production path - 6.4
allowDangerousKeysstrict mode tested both on and off - 6.5 OTel span event emitted from production paths and asserted with a real in-memory
TracerProvider - 6.6 Lifecycle dedup — N/A (stateless helpers)
- 6.7 No retroactive tick — every box above reflects work done in this change
7. Archive
- 7.1 Fold spec delta into
openspec/specs/serialize/spec.md - 7.2 Move
openspec/changes/serialize-proto-guard/→openspec/archive/<yyyy-mm-dd>-serialize-proto-guard/ - 7.3 Refresh
MANIFEST.mdif dep set changed (no expected change)