feat: CAP-Tree v0.3 HTTP binding — content-addressed object host#45
Open
twilson63 wants to merge 4 commits into
Open
feat: CAP-Tree v0.3 HTTP binding — content-addressed object host#45twilson63 wants to merge 4 commits into
twilson63 wants to merge 4 commits into
Conversation
Real root cause of the proxy 502s (UND_ERR_INVALID_ARG): the code passed an npm-undici `Agent` as the `dispatcher` to Node's **built-in** global `fetch`. Built-in fetch validates the dispatcher against its own bundled undici's Dispatcher class; an Agent from the npm `undici` package is a different class when the two undici versions differ, so it is rejected with UND_ERR_INVALID_ARG — before any lookup/connector code runs. That is why #42 (lookup forms) and #43 (connector override) both failed with the exact same error, and why it worked locally (local Node's bundled undici matches npm undici 6.26). Fix: call undici's own `fetch` (imported from the same package as Agent), so dispatcher and fetch are guaranteed the same version. SSRF validation and connector IP-pinning are unchanged. Verified locally end-to-end (undici fetch + pinned dispatcher + full response body read): https/http public hosts return 200; SSRF targets remain blocked. tsc + build clean; proxy.test.ts 52/52. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Makes ZenBin a conformant CAP-Tree v0.3 host alongside the existing v0.2 pages API (nothing migrated). Implements the PRD in plan-prd.md. - Vendor cap-tree-core (twilson63/cap-tree core/, MIT) into src/vendor/cap-tree-core; add DOM to tsconfig lib for WebCrypto types. All canonicalization/hashing/verification comes from the library. - Storage (src/storage/capTreeDb.ts): objects, tree-index, refs LMDB environments; immutable content-addressed objects; atomic refs-chain head advance via transactionSync (fork-safe). config.capTree.maxObjectBytes. - ObjectService (src/services/objectService.ts): host-side validation (HB § 5) — envelope + structural checks, genesis owner match, parent resolution, verifyRootChain for non-genesis/merge roots, refs target + owner checks + chain extension. Merge roots are NOT policy-policed. - Routes: POST/GET /v1/objects (signed publish / open retrieve, immutable cache), /v1/trees reads (refs, refs/history, roots, roots/history, resolve), /v1/reviews query, /.well-known/cap-tree.json discovery. Objects consume page quota 1:1 via reserve/release. - Errors: 13 CAP-Tree codes; 422 bodies carry errors[]; 409 carries currentSeq/currentHash recovery info. - Tests: cap-tree-objects (vectors round-trip byte-exact, idempotency, tamper/parent/owner rejections, oversize, policy-violating merge accepted), cap-tree-refs (chain enforcement, conflict/gap → 409, non-owner → 403, history), cap-tree-reads (roots/history/resolve/ reviews/discovery), cap-tree-lifecycle (build → publish → clone → verify via API-only resolver). setup.ts cleans the new content-addressed envs so fixed-hash objects don't leak across files. All § 8 acceptance criteria pass: 429/429 tests green, tsc --noEmit and production build clean, v0.2 suite unchanged. No new runtime dependency beyond the vendored cap-tree-core. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Status → Implemented (a39d5f7). New § 11 records sequencing/acceptance completion (re-verified: 429/429 tests, typecheck clean), deviations (vendored cap-tree-core, dedicated capTreeDb.ts), and open items (stretch goals, npm swap, post-deploy conformance). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rash-heal
- Swap the vendored cap-tree-core copy for the published npm package
(cap-tree-core@0.3.0) and delete src/vendor/cap-tree-core — one
implementation, no drift.
- rootHistory now accepts a cursor so next_cursor is actually consumable;
GET /v1/trees/{treeId}/roots/{hash}/history takes ?cursor=.
- publishRefs heals the extend-then-store crash window: re-publishing a
refs object that is already the chain head but unstored succeeds and
stores it instead of 409ing against itself.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Makes ZenBin the first conformant CAP-Tree v0.3 host — content-addressed object storage, tree read endpoints, refs-chain enforcement, and discovery — alongside (not replacing) the existing v0.2 pages API. Implements the PRD in
plan-prd.md(spec: https://github.com/twilson63/cap-tree).cap-tree-core(src/vendor/cap-tree-core/, MIT, source-commit header) — all canonicalization/hashing/verification comes from the reference library; swap to npm oncecap-tree-core@0.3.0is published.src/storage/capTreeDb.ts): objects / tree-index / refs LMDB environments; immutable content-addressed objects; atomic refs-chain head advance (fork-safe).ObjectService: envelope + structural checks, genesis owner match, parent resolution,verifyRootChainfor non-genesis/merge roots, refs target + owner checks + chain extension. Merge roots are not policy-policed.POST/GET /v1/objects(signed publish / open retrieve, immutable cache),/v1/treesreads (refs, refs/history, roots, roots/history, resolve),/v1/reviewsquery,/.well-known/cap-tree.jsondiscovery. Objects consume page quota 1:1.errors[]; 409 carriescurrentSeq/currentHashrecovery info.fetchso the dispatcher version matches) and the PRD progress update.Test plan
cap-tree-objects,cap-tree-refs,cap-tree-reads,cap-tree-lifecycletsc --noEmitclean🤖 Generated with Claude Code