Skip to content

Spec: agent-identity package (INFT re-encryption + ENS gateway + primary names) #11

@fritzschoff

Description

@fritzschoff

Status: approved design, ready for implementation plan
Closes: #9 (plan A), #10 (plans A and B)
Source of truth: docs/superpowers/specs/2026-04-28-agent-identity-package-design.md (1,154 lines, full spec — committed in 8bdaafd)

This issue is the GitHub-side backup of the unified design that supersedes #9 and #10. The full document is too large for a single issue body (66.7k chars > 65.5k limit), so the canonical text lives in the repo. Below: an executive summary so reviewers can read at-a-glance and follow the file links for any section.


Goal

Three workstreams, designed and shipped as one package because they cross-link strongly: the INFT's encryption state is exposed via ENS, the ENS gateway's authority story mirrors the INFT oracle's, and primary names tie all wallets in the system into a single legible identity surface.

Workstream What it ships Maps to
W1 — ERC-7857 INFT oracle INFT memory blob is re-encrypted to the new owner on every authorized transfer; verifier matches 0G's reference byte layout; oracle is a Vercel function we run #9 plan A
W2 — Dynamic CCIP-Read ENS resolver *.agentlab.eth text records become EIP-3668 offchain queries served live from a signed Vercel gateway; ENSIP-10 wildcard means every new agent gets ENS records for free; kills the hourly heartbeat tax #10 plan A
W3 — Reverse + ENSIP-19 primary names Every wallet we own (agent EOA, pricewatch deployer, KeeperHub Turnkey, validator) gets a primary name on Sepolia + Base Sepolia #10 plan B

Trust anchors (W1 + W2 share posture). Both the INFT oracle (W1) and the CCIP-Read gateway (W2) are EOA-signing services. The INFT verifier checks the oracle's signature on-chain; the ENS offchain resolver checks the gateway's signature on-chain via the standard OffchainLookup callback. Same posture as 0G's reference verifier deploy script (Verifier(0x0000…0000, VerifierType.TEE) — its on-chain attestation contract is unset and a // TODO: verify TEE's signature comment sits in the verifier path) and cb.id / uni.eth (CCIP-Read trusted gateway flavor). Hardware-attested swap-in path is identical for both: replace the EOA, the contract config tracks the new pubkey, callers see no API change.

Locked decisions (from brainstorming)

Q Decision Rationale
W1-Q1 oracle posture (b′) track 0G's reference verifier byte-for-byte; ship the missing oracle counterpart 0G's hosted TEE oracle does not exist on Galileo today (the placeholder repo 0gfoundation/0g-inft-oracle-server-ts is empty). The reference contract verifier itself is EOA-signature-based — we ship the matching oracle plus the on-chain attestation check the reference left as // TODO.
W1-Q2 raw transferFrom Allow it, flip memoryReencrypted[tokenId] = false, emit MemoryStaled Keeps marketplace compatibility; UI shows red "memory stale" badge — feature, not bug
W1-Q3 bidder accessibility sig Bidder pre-signs an EIP-712 Delegation(tokenId, oracle, expiresAt) at bid time; oracle acts as receiver-proxy in the proof's accessibility signature No live coordination at accept time
W2-Q5 gateway flavor (α) trusted gateway (β) storage proofs deferred; resolver designed for swap-in by replacing only the verifier body

Architecture summary

W1 (INFT oracle)

  • AgentINFTVerifier.sol (new) — implements 0G's IERC7857DataVerifier, byte-for-byte proof layout from the reference, plus on-chain check of the oracle attestation tail.
  • AgentINFT.sol (rewrite) — adds transferWithProof(to, tokenId, proof), delegation table, memoryReencrypted stale flag, EIP-712 delegation forwarding for AgentBids.
  • AgentBids.sol (rewrite) — Bid struct gets delegation expiry; placeBid forwards delegation sig (single tx for bidder); acceptBid threads proof to transferWithProof.
  • AgentMerger.sol (rewrite) — recordMerge takes proofs for both source tokens; uses setDelegationByOwner since MERGER is a contract with no key.
  • Oracle server at app/api/inft/oracle/{seal-blob,prepare-transfer,confirm-transfer,prepare-merge,confirm-merge,reveal,key}/route.ts. Two-phase commit: prepare-transfer builds proof but does NOT rotate Redis key; confirm-transfer verifies tx receipt then rotates.
  • AES-128-GCM blob encryption + ECIES-secp256k1 key wrap to receiver pubkey (recovered from delegation sig). Per-token KEK derived from INFT_ORACLE_PK via HKDF.

W2 (CCIP-Read resolver)

  • OffchainResolver.sol (new) — implements IExtendedResolver.resolve(name, data) reverting OffchainLookup; resolveWithProof(response, extraData) ecrecovers the gateway sig.
  • Gateway at app/api/ens-gateway/[sender]/[data].json/route.ts. Decodes ABI calldata, computes record value, signs with INFT_GATEWAY_PK, returns. Records served:
    • Static (Edge Config): agent-card, description, url, current-price-tier
    • Dynamic on-chain: outstanding-bids, compliance-status, tvl, inft-tradeable (W1 cross-link), avatar
    • Dynamic Redis: last-seen-at, memory-rotations (W1 cross-link)
    • Dynamic computed: reputation-summary (5-min cache), ENSIP-25 multichain
  • Wildcard via ENSIP-10 — one resolver serves every *.agentlab.eth and every nested *.*.agentlab.eth.

W3 (primary names)

  • No new contracts. Use Sepolia + Base Sepolia ReverseRegistrar.
  • Wallets to set: agent EOA, pricewatch deployer, KeeperHub Turnkey, validator (all four get ENSIP-19 multichain primary names).
  • Forward addr resolution handled dynamically by W2 gateway — no on-chain forward records to write.

KeeperHub orchestration

Workflow Status Trigger Purpose
Heartbeat (existing) DELETE x402 paid quote webhook Replaced by W2 gateway serving last-seen-at from Redis live
ReputationCache (existing) DELETE hourly cron Replaced by W2 gateway computing reputation-summary on-the-fly
Swap (existing) keep /api/a2a/jobs paid quote Untouched
ENSPrimaryNameSetter NEW manual + onboarding W3 workhorse: ReverseRegistrar.setName cross-chain idempotent
ENSAvatarSync NEW INFT mint/transfer webhook Sets avatar text record to eip155:.../erc721:.../<tokenId>
GatewayCacheInvalidator NEW chain event firehose POSTs to gateway's /cache/invalidate for affected keys
OnboardAgent NEW dashboard button Orchestrates 6 steps (registry register → INFT seal+mint → ENS subname → avatar sync → primary names) — the demo highlight workflow

Migration

New deploys (all on Sepolia unless noted):

  • IdentityRegistryV2-b (V2-a's inft field is one-shot and already bound; V2-b mirrors agentId=1 registration). Other downstream contracts (Reputation, Credit, IPO, SLA) keep using V2-a — reputation continuity preserved by coincidence (same numeric agentId).
  • AgentINFTVerifier
  • AgentINFT (constructor: V2-b, baseURI, verifier, oracle)
  • AgentBids (constructor: newINFT, sepoliaUSDC)
  • AgentMerger (constructor: V2-b, ReputationRegistry, newINFT)
  • OffchainResolver (constructor: gatewayURLs[], INFT_GATEWAY_PK_addr)

Plus: ENS.setResolver(namehash("agentlab.eth"), OFFCHAIN_RESOLVER) from agentlab.eth owner. Pre-flight precheck: verify agentlab.eth ownership before any contract deploy.

Old INFT (0x245217…84EB6) and its plaintext memory blob are abandoned; new mint on the new contract creates a fresh encrypted tokenId=1.

Test plan

Three layers, dependency-ordered:

  1. Forge unit testsAgentINFTVerifier.t.sol (new, 7 tests), AgentINFT.t.sol (extend, 12 new), AgentBids.t.sol (extend, 5 new), AgentMerger.t.sol (extend, 3 new), OffchainResolver.t.sol (new, 7 tests).
  2. Off-chain integration scriptstest-inft-oracle-e2e.ts, test-ens-gateway-e2e.ts, test-primary-names-e2e.ts. Each must print ALL GREEN (mirrors the existing scripts/zg-prod-lib-test.ts posture, included in this commit).
  3. KeeperHub workflow tests — for each new workflow: valid input, idempotent re-trigger, invalid input.
  4. Manual UI walkthrough (Playwright MCP) covering all three workstreams.

Out-of-scope (tracked, none unresolved)

  • TEE attestation hardware (W1 oracle and W2 gateway are EOAs)
  • ERC-7857 clone(), authorizeUsage()
  • Cross-chain INFT transfers
  • W2-β storage-proof verifier (deferred)
  • Namechain migration (issue Push ENS to its limits — research + roadmap #10 plan C)
  • ENS NameWrapper / fuse-locked subnames
  • Selling subnames as NFTs in AgentBids
  • CI gating for forge tests

Next: implementation plan via the superpowers:writing-plans skill, broken into phased milestones (W1 first because W2 cross-links into INFT state, W3 last because it can run in parallel with anything).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions