Scaffold the EFS SDK monorepo#1
Conversation
pnpm + Turborepo + Changesets workspace with two packages: - @efs-project/sdk — TypeScript SDK (tsup dual ESM/CJS, viem-native, vitest) - @efs-project/solidity — compile-in Solidity library (Foundry, ships .sol source) Includes the ADR system (mirrored from contracts, lighter — ADR-0001 layout, 0002 viem-only, 0003 compile-in Solidity), top-level docs (README, CONTRIBUTING, AGENTS.md), CI, and scaffolded public API shapes reflecting the planning design (identity seam, static-vs-dynamic refs). TS build/typecheck/test/lint verified green; Solidity is CI-verified (forge not local). Best-practice review applied (changeset config, publishConfig, forge-std CI install, .nvmrc/engines). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
- Rename npm scope @efs-project/* -> @efs/* (scope confirmed unpublished;
GitHub org stays efs-project). Pending `npm org create efs` before publish.
- ADR system: cut the contracts-inherited Etched/Durable/Ephemeral "permanence
framing" section + the cargo-culted `Permanence:` template field (validation
flagged as residual freeze-rigor); fold the one real point (published npm API
is the only near-permanent surface) into Discipline.
- Add the missing procedural bits agents need: next-number mechanic, an
ADR-worthiness threshold ("a choice with alternatives worth preserving"), and
a worked boundary example (vault design -> SDK ADR slice).
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Establishes the three-layer doc model so nothing duplicates: specs (how it works now) vs ADRs (why we chose it) vs planning vault (cross-cutting design). Seeds specs/overview.md (the SDK model at a glance) and wires it into AGENTS.md as start-here reading. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c8e5a19b20
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- BLOCKER fix: .github/workflows/ci.yml still used @efs-project/sdk (the rename grep missed .yml) — would have failed every CI run. Now @efs/sdk. - Add release.yml using npm Trusted Publishing (OIDC) — no stored NPM_TOKEN, provenance automatic. ADR-0004 records the decision (OIDC over long-lived token) + the one-time per-package trusted-publisher setup. - Mark docs/api row "(later)"; bump recommended-next ADR numbers. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7994df5334
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- Solidity job failed: `forge install --no-commit` flag was removed in current Foundry. Clone forge-std (test-only dep) via git instead — version-stable. - Changeset job failed: no changeset on the PR. Add an empty changeset (the designed no-release escape hatch) for the scaffold. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
- CI: minimal `permissions: contents: read`, cancel-in-progress concurrency, `timeout-minutes` on all jobs, pin forge-std to v1.9.4 (no master drift). - Release: pin global npm to @11; explicit `publishConfig.provenance: true` on both packages (belt-and-suspenders around the changesets/pnpm publish path). - ADR-0004 reconciled with the explicit-provenance choice. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
forge fmt --check was the last red CI job. Reformatted EFSLib/EFSWriter to Foundry style (verified locally with forge 1.7.1), simplified the stub signatures to unnamed params/returns so there are no unused-variable warnings, and removed the unreachable emit in _efsPinFile. Build + test pass locally. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: eadb898eab
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- P1: release workflow ran `pnpm build` (turbo) which builds @efs/solidity via `forge build`, but never installs Foundry → release job would fail on main. Scope the release build to @efs/sdk only; the Solidity package publishes .sol source and needs no build artifact (CI compile-checks it per-PR). - P2: remove the hardcoded `version = '0.0.0'` export — it would go stale after the first Changesets bump. Re-add derived from the manifest when implementing. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
… deployer
The SDK ships a maintained chainId -> {addresses, schema UIDs} registry and
resolves EFS by chain (with a custom-deployment override). It deploys nothing;
integration tests fork a registry chain (anvil --fork-url) like the contracts
repo, rather than reimplementing EFS's CREATE3/proxy deploy. Reflected in the
overview spec.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
- DX-7/ENG-14: lower Solidity pragma floor ^0.8.28 -> ^0.8.26 so the library is compilable alongside the contracts repo (pinned 0.8.26). Real compat bug. - DX-11: fix wrong ADR pointer in index.ts (cited ADR-0004 = OIDC publishing for the error model; now points at "Recommended next"). - DX-10: repoint READMEs from the private planning vault to the public in-repo docs/specs/overview.md as the primary "how it works" reference. Larger API-shape findings (resume/onProgress in pinFile, fetch+verify, resolvedBy, branded UIDs, pagination iterator, deployments codegen) tracked for the beta-slice spec. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d1e88d32fa
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
First functional-slice plan for @efs/sdk: write/read real files with the API shapes frozen correctly before publish. Grounded in the freeze-branch contracts (contentHash now lives as a lens-scoped PROPERTY string; no chain deployed but a local fork exists) and two review passes. Adversarial review caught: (1) the spec/scaffold drifted to a FLAT API but the validated design is NAMESPACED (efs.fs.write) — realigned, surfaced as Decision F; (2) content verification is trust-relative not absolute (attacker can attest a contentHash under their own lens) — honest semantics baked in; (3) honest click count (~3 with metadata, not 2); richer WriteReceipt/preview; per-step idempotent resume; pinned local-fork artifact boundary; declared the large-file/update/delete seams. Decisions A/C/D/E/F surfaced for James. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…pping - P1: the "Changeset present" gate would block Changesets' own Version Packages PR (it consumes the changeset files). Skip the gate for head_ref changeset-release/main so the version PR can pass and publish. - P2: `pnpm test` / `pnpm --filter @efs/solidity test` failed on a clean checkout (forge-std absent, lib/ gitignored). Add a `setup` script + prebuild/pretest hooks that bootstrap forge-std, and DRY the CI solidity job to run the package scripts so CI and a contributor's local run are identical. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…odule Decision A closed after two expert passes: contentHash is a bare SHA-256 digest (lowercase hex, sha256sum-identical); the PROPERTY key is the algorithm tag — no multihash/CID/keccak (its future-proofing is illusory; the IPFS-CID rationale is false). Built it (it's pure, chain-independent): - src/content/hash.ts: hashContent() + trust-relative verifyContent() (matches-author/mismatch/no-claim; no-claim != success; malformed claim guarded) - tests against known SHA-256 vectors; exported from index.ts - ADR-0006 + docs/specs/content-hash.md (incl. fetch-safety: lens-scoped mirrors, size-cap streaming, ignore transport Content-Type) - updated beta-slice (Decision A done) + overview + ADR index (next: 0007/0008) Verified by subagent (impl correct, vectors confirmed, cross-docs consistent: GO). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 39653f6167
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
changesets/action with `publish: pnpm release` would publish the unpublished 0.0.0 scaffold packages on the first no-changeset main run — premature, and the @efs org doesn't exist yet. Drop the `publish:` input so the action only manages the Version Packages PR and never publishes. Re-enable at launch with a one-line `with: { publish: pnpm release }` (documented inline + in ADR-0004). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…rors Realign to the namespaced client (Decision F): efs.fs.* / efs.lenses.* / efs.eas.* / efs.raw.*. Built the foundational, chain-independent layers: - eas/: viem-native EAS layer (vendored ABIs, SchemaEncoder, attest/multiAttest builders, UID re-derivation) — no ethers/eas-sdk (ADR-0002). 15 tests. - lenses/: opaque Lens, lens()/identity()/resolveLens; throws MaxLensesExceeded rather than truncating (review S2); ENS resolution; MAX_LENSES=20. - chain/: deployments registry + resolveDeployment + construct-time integrity gate (checks view/router bytecode, review S1) (ADR-0005). - errors/: typed EfsError tree (NotImplemented/LensRequired/MaxLensesExceeded/ SchemaMismatch/DeploymentNotFound). - types/: branded DataUID, DataRef vs PathRef, WriteReceipt/ReadResult/EfsFile. - fs.* verbs are NotImplemented stubs with their final signatures. format script now runs `biome check --write` (organizes imports too, matching CI). tsc/test(24)/build/lint all green. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Integration review (GO) flagged two: - B1/B2: fs.* stubs were async-typed but threw synchronously — `.catch()`/ `.rejects`/`for await` would misbehave. Make them reject / throw-on-iterate so the async contract is locked before fs.* is implemented; tests use `.rejects`. - S1: assertDeploymentIntegrity only checks bytecode presence — softened the doc to say so (sanity gate, not "is the right EFS contract"); the real trust gate (schema-UID match) is noted as landing with the read layer. EAS layer, lenses, deployments, errors all verified by the review. tsc/test(24)/ build/lint green. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5e92a8d0f0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
The quickstart still used the pre-F flat API (efs.read/efs.pinFile); the client is namespaced (efs.fs.read/write/fetch). Updated to the accurate shape — read returns a ref + resolvedBy, fetch gets verified bytes — and added a status note that fs.* verbs are the target shape (currently NotImplemented). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 145e590697
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ex P2) buildAttest/buildMultiAttest returned no tx-level `value`, so a non-zero per-attestation resolver value would revert (no ETH sent). Compute and include `value` on the ContractCall: buildAttest forwards data.value; buildMultiAttest sums every entry across all requests. Added tests (26 total). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
From the 3-agent foundation review. The additive-now/breaking-later items: - Type-level write gating: createEfsClient overloads return EfsReadClient (no write verbs) without a walletClient, EfsClient with one (viem's read/write split). Runtime WalletRequired backstop. - EfsError -> viem-BaseError-grade: shortMessage, open-union `code`, cause, walk(). Added WalletRequired/CursorInvalid/PartialBatchFailure. - Named, exported option/return types (ReadOptions/ListOptions/FetchOptions/ WriteOptions) — no inline literals; param renamed `as` -> `lens`. - Pagination seam: Page<T> + EfsList<T> (AsyncIterable + .page()). - Batch seam: efs.batch() + BatchReceipt/OperationResult/WriteMechanism; fs.write documented as sugar over it. - Wallet-agnostic seam (your point): EfsReader/EfsWriter aliases instead of raw viem types in the public config, so widening to an ethers adapter later is non-breaking. viem-core stays; any wallet already works via EIP-1193. - FileStat (was Stat), branded steps[].uid, dropped root `export *`. Deferred (additive, non-breaking later): full graph/props/lists/sorts namespace skeleton — designed in a dedicated pass. tsc/test(27)/build/lint green. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4017c175b9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Renamed the read option `as` -> `lens` in the hardening batch; the README
quickstart still showed `{ as: ... }`. Fixed.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…ide)
Per the standards research (docs/specs/standards.md): the SDK's public boundary
is now the durable standard, not a library.
- createEfsClient accepts the standard form `{ provider: EIP1193Provider, chain,
account? }` and wraps it with viem's custom() transport internally; viem clients
`{ publicClient, walletClient? }` stay as a convenience form. Both normalize to
viem inside. Write-gating preserved (account/walletClient presence → write client).
- Any wallet works (all are EIP-1193 providers); swapping/adding a client library
never breaks a consumer. Dropped the EfsReader/EfsWriter placeholder aliases.
- Folded the standards into the ADRs: ADR-0009 (boundary implemented), ADR-0008
(instantiation), ADR-0007 (error model = classifier over viem BaseError + RPC
codes 4001/4100/4902). README quickstart leads with the provider form.
tsc/test(28)/build/lint/attw all green.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3443be823c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
The wrapper documented emitting EfsFilePinned but the stub just returned the UID, so inheritors of the happy-path base would miss every pin once pinFile is implemented. Restored capture -> emit -> return. EFSLib.pinFile still reverts so the emit is unreachable today (harmless warning), but the correct shape is now locked for the implementation. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Adds docs/specs/future-proofing.md synthesizing a second research sweep beyond the core EIP table: SDK engineering (wevm stack), storage/durability, indexing & history-expiry, security/clear-signing, gas/tx-lifecycle, L2/interop, key- management, the Ethereum roadmap, and metadata. Three load-bearing constraints: (1) history expires (EIP-4444) -> reads are index-first; (2) calldata costs/caps (EIP-7623/7825) -> chunked, hash-on-chain-bytes-off-chain writes; (3) a hash is integrity not availability -> pair fast+permanent mirrors. Extends standards.md with the new EIPs/ERCs (7730/7623/7825/4444/7745/Multicall3/RIP-7212/etc.). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
A mid-conversation compaction caused the first synthesis to omit two agents' output. Audited all 10 pass-2 agent transcripts against the doc and recovered: - completeness-sweep agent (the "what are we missing" pass): ride-EAS-directly (no Final attestation ERC; 7512/5851/8273 off-target WATCH), ERC-8048/8049 onchain key-value metadata as the closest PROPERTY mirror, ERC-2098 compact signatures, EAS-native expirationTime/revocable/refUID for revocation, abi. encode-not-encodePacked. New section 9 + standards.md rows. - security agent: transaction-simulation seam (Tenderly/Blockaid -> fs.preview, pluggable, no baked keys). - indexing agent: ship a reference subgraph/Envio/Ponder schema as docs. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Adversarially-verified 6-dimension review (docs/reviews/2026-06-11). Applies the before-freeze surface locks; defers the additive/open items. TS surface (A1-A12): DataRef gains chainId + resolvedBy (multi-chain identity + fetch-can-verify); CallStatus + status/partialFailure/txHashes on receipts (EIP-5792 600 partial-write); WriteEstimate usd-range; branded ContentHash; OperationResult.error: EfsError + kind + txHash; stat() non-nullable discriminated FileStat; TransportName union; VerificationStatus malformed-claim; WriteMechanism 'sequential'; DirEntry for fs.list; PreviewOptions seam; drop unexported PathRef. Solidity (B1-B4): event EfsFilePinned -> EFSFilePinned w/ indexed path; pinFile PinOpts overload (EAS-native expirationTime/revocable/refUID); _efsMkdir + readAs/lens-stack parity wrappers; must-not-hash-paths + active-pin NatSpec. Docs (C/D): reconcile sdk-architecture.md drift (efs.eas casing, SCHEMAS.REDIRECT, lens singular, receipt field names); EAS EIP-712 domain via getDomainSeparator(); ERC-2098 TS-scoped; SSTORE2/EIP-7825 + payable-resolver notes. Reverse the bundled-index-provider framing in future-proofing.md per review section F. Gate: typecheck/build/test/lint green across @efs/sdk + @efs/solidity. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…tooling) Productive work that doesn't depend on the contracts schema freeze, so the freeze unblocks only the thin attestation glue. Fetch/verify/mirror engine (src/mirror/, ADR-0010): zero-dep transport resolver (ipfs/ar/https/data full; web3:// parsed, resolution seam'd), fetchVerified with sequential gateway failover, per-attempt timeout, hard size cap, nosniff, and an SSRF guard (v4/v6 incl. IPv4-mapped). Verify-before-trust against the bare-SHA-256 contentHash (ADR-0006); bytes returned even on mismatch, never executed. Error classifier (ADR-0007, errors.ts): classifyError() maps viem BaseError / ContractFunctionRevertedError + EIP-1193 (4001/4100/4200/4900/4901) + JSON-RPC -32xxx to typed EfsError codes; idempotent; cause-preserving. Tooling/supply-chain (future-proofing §1/§4): pinned exact dep versions (11; viem peer left ranged), size-limit budget (6.45/8 kB), Knip dead-export check, --ignore-scripts in CI. Test infra: mock EIP-1193 provider + createEfsClient boundary tests, prool fork harness (env-gated). 75 tests pass, 1 skipped. Gate green: typecheck/build/test/lint/size across @efs/sdk + @efs/solidity. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
CI caught 11 noNonNullAssertion violations in test/mirror.test.ts that a stale turbo lint cache hid locally. Rather than weaken null-safety repo-wide (the rule stays enforced in src/, where the mirror engine handles untrusted bytes), add a biome override that exempts only test files, where expect(arr[0]!.x) is idiomatic. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 449c286907
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
The guard only matched the dotted tail (::ffff:127.0.0.1), but new URL()/Node canonicalize it to the two-hextet hex form (::ffff:7f00:1), so an attacker- chosen mirror like http://[::ffff:127.0.0.1]/ slipped past checkSsrf and could reach loopback/private services. embeddedMappedIpv4() now decodes both the dotted and hex tails and re-checks the embedded IPv4 against the v4 blocklist. Regression test covers loopback/metadata/private mapped forms + a public one. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 78a6a6cc08
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
fetchOne used redirect:'follow', so a public mirror could 30x to http://127.0.0.1/... and fetch would follow it without re-running checkSsrf — bypassing the private-host block. Switched to redirect:'manual' with a manual hop loop that re-checks every Location against the SSRF guard (and rejects non-http(s) schemes), capped at 5 hops. Browser opaque-redirects fall back to a follow fetch (the browser enforces SSRF/CORS itself). Regression tests: a 30x to loopback is blocked and never fetched; a 30x to a public host is followed. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a0c0d83143
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
P1: URL.hostname preserves a trailing dot, so http://localhost./ and http://metadata.google.internal./ slipped past the literal internal-host checks even though DNS treats the FQDN form as the same host. checkSsrf now strips trailing dot(s) from the host (and allowlist entries) before any comparison. P2: the inline data: branch returned decoded bytes without checking maxBytes, so a giant data: URI from untrusted metadata bypassed the size cap. fetchVerified now rejects inline payloads over maxBytes (recorded as an attempt, fails over). Regression tests for both. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 59253c1cf7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…e bomb Proactive adversarial hardening pass on the mirror module (the SDK's untrusted- input boundary), from a 6-category red-team enumeration validated against actual Node 20/undici behavior — getting ahead of the SSRF/size bypass classes rather than fielding them one at a time. - IPv6 SSRF: replaced the ::ffff:-only regex with a byte-level IPv6 expander + prefix checks. Now blocks IPv4-compatible (::7f00:1), IPv4-translated (::ffff:0:..), NAT64 (64:ff9b::/96), 6to4 (2002::/16 embedded v4), plus site-local (fec0::/10) and Teredo (2001::/32). One canonical byte check covers all textual variants (compressed/expanded/case/leading-zero). - Decompression bomb: fetchOne now sends accept-encoding: identity and rejects any non-identity Content-Encoding BEFORE reading the body, so undici never pumps a gzip/br/zstd inflate (also neutralizes the chained-encoding CVE-2026-22036 in undici 7.16 regardless of runtime version). - data: decode bomb: resolveData rejects by *encoded* length before decoding, so an oversized data: URI can't force a large allocation pre-cap. - Confirmed-safe (lock-in tests, no code change): alternate IPv4 literal encodings (octal/decimal/hex/dword/part-collapse) — Node's URL parser canonicalizes them before checkSsrf runs. Known gap still open: DNS rebinding (public name -> private A record) needs connect-time IP pinning (a Node/undici dispatcher) — its own deliberate pass. Tests: 84 (36 mirror), gate green. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2fa8bf9f9e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…s (P2) ipfs://cid/%2e%2e/admin (and the arweave equivalent) string-concatenated into new URL, which normalizes .. AND %2e%2e (WHATWG decodes percent-encoded dots during dot-segment removal), escaping /ipfs/<cid>/ to an arbitrary path on the trusted gateway. Now: validate CID (alphanumeric) / Arweave txid (base64url) shape at parse, and buildGatewayUrl asserts the post-normalization pathname still begins with the content-address namespace, rejecting otherwise. Legit subpaths preserved. Regression tests for literal + %2e-encoded traversal. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: db195ad73a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
The startsWith(nsPath) guard from db195ad accepted a sibling sharing the CID prefix: ipfs://bafy/../bafyadmin normalizes to /ipfs/bafyadmin, which startsWith /ipfs/bafy. Now require pathname === nsPath or startsWith nsPath+'/' so only the exact namespace (or a child under it) is allowed. Regression test added. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…s (ADR-0011) Absorbs two merged contracts features as additive surface; fs.* bodies stay NotImplemented stubs pending the schema freeze, shapes locked now. On-chain directory filter (contracts ADR-0048): - ListOptions gains optional excludes (def-UID or human label) + minWeights; non-empty routes fs.list to the filtered view, empty = unfiltered. - Vendor the EFSFileView view ABI (first view-layer ABI; was EAS-only): getDirectoryPageFiltered + unfiltered siblings, transcribed from deployedContracts.ts. - Pure read helpers (src/reads/directory.ts): shouldUseFilteredQuery, reconcileMinWeights (all-zero default avoids the length-mismatch revert), validateDirectoryQuery (fails fast on the 20-attester / 8-exclude / maxItems caps) + InvalidDirectoryQuery. 18 tests. - No default excludes; SAFETY_EXCLUDES=['system','nsfw'] exported for opt-in. Folder Overviews: - fs.overview(path) -> discriminated OverviewResult (none|markdown|binary| too-large), exact-path resolve; fs.setOverview(container, markdown) (system TAG before placement). Convention constants OVERVIEW_NAME, MAX_RENDER_BYTES. No new schema/contract/reserved key. Deployments reconciled to contracts source-of-truth: drop phantom redirect schema + aliasResolver contract; add real blob/sortInfo/naming schemas + fileView/edgeResolver/sortOverlay/schemaNameIndex/listReader contracts. Add 'InvalidArgument' error code. Fix stale ADR-0011->ADR-0010 transport refs. Gate green: lint/typecheck/test(102)/build across @efs/sdk + @efs/solidity. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
… surface The ADR-0011 additions (first view-layer ABI + directory-filter helpers + Overview types) grew the gzipped ESM bundle from 6.45 -> 8.15 kB, past the 8 kB budget. size-limit guards regressions, not deliberate surface growth — raise to 10 kB (~25% headroom per our bundle doctrine). Revisit subpath-splitting the ABIs if bundle size later becomes a real constraint. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 310ef5f138
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…s (P2 x2) P2 (transport): the data: text-path size guard measured UTF-16 string length, so a payload within the char cap could decode past it (€ = 1 char, 3 UTF-8 bytes), and resolveTransport used directly never enforced the cap. Now: pre-decode reject on a cheap lower bound (ceil(len/3) for text) to bound transient allocation, plus an authoritative exact UTF-8 byteLength cap inside resolveData itself. P2 (errors): classifyError read the numeric EIP-1193/1474 code off the OUTER error only, so a 4001/-32xxx wrapped under a viem contract/tx error fell through to generic. numericCode now walks the cause chain (cycle-guarded). Tests: UTF-8 vs UTF-16 data: cap (encoded + literal non-ASCII), nested-cause 4001->UserRejected and -32000->RpcError. Gate incl. size: 104 tests, green. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8481394982
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…k (P2) The base64 pre-decode bound counted `=` padding (and whitespace), over-estimating by up to 2 bytes — so an at-cap payload like data:;base64,aGVsbG8= (5 bytes) was falsely rejected at maxBytes=5 before the authoritative byteLength check. Strip whitespace + trailing padding first: floor(sig*3/4). Regression test: at-cap padded payload is now accepted. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f4f9bb5564
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…P2 x2) P2 (transport): non-base64 data: payloads are octets (RFC 2397), but decodeURIComponent treats %XX as UTF-8 and throws on binary like data:application/octet-stream,%ff. New decodeDataOctets decodes %XX byte-wise (literal runs as UTF-8), so binary inline mirrors hash instead of failing. P2 (eas): easAbi exported only function fragments, so viem couldn't populate ContractFunctionRevertedError.data.errorName on a real attest/multiAttest revert and the classifier's InvalidSchema->SchemaMismatch mapping never fired. Added the 22 EAS custom-error fragments (transcribed from eas-contracts EAS.sol/IEAS.sol). Tests: binary octet decode (%ff, mixed literal+octet); InvalidSchema revert decoded against the real easAbi -> SchemaMismatch. Gate incl. size: 107 tests. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fa56b1134d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
WHATWG data: processing percent-decodes the body before base64-decoding, so a producer may percent-encode base64 specials (data:...;base64,%2Fw%3D%3D == 0xff). We passed raw %XX to atob (throws) and the size estimate counted the triplets (false oversize at small caps). Now decodeURIComponent the base64 body first (ASCII; falls back to raw on malformed input), then estimate + decode. Regression test: %2Fw%3D%3D -> 0xff, incl. at maxBytes=1. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Initial scaffold of the EFS SDK monorepo, set up from best-practice research + multiple expert-subagent review passes.
What's here
@efs/sdk— TypeScript SDK (tsup dual ESM/CJS, viem-native, vitest)@efs/solidity— compile-in Solidity library (Foundry, ships.solsource)Verified
build(dual ESM/CJS + types),typecheck,test(2 passing),lint— all green.forge build/test/fmt, CI-verified.Notes for review
@efs(org needs claiming on npm before first publish; one-line revert to@efs-projectif taken).NotImplemented) — this is structure + decisions, not implementation.sdk-architecture.md); ADRs here implement slices of it.🤖 Generated with Claude Code