You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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
*.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
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.
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.
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:
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.
Off-chain integration scripts — test-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).
KeeperHub workflow tests — for each new workflow: valid input, idempotent re-trigger, invalid input.
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)
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).
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 in8bdaafd)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.
*.agentlab.ethtext 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 taxTrust 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
OffchainLookupcallback. 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 signaturecomment sits in the verifier path) andcb.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)
0gfoundation/0g-inft-oracle-server-tsis 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.transferFrommemoryReencrypted[tokenId] = false, emitMemoryStaledDelegation(tokenId, oracle, expiresAt)at bid time; oracle acts as receiver-proxy in the proof's accessibility signatureArchitecture summary
W1 (INFT oracle)
AgentINFTVerifier.sol(new) — implements 0G'sIERC7857DataVerifier, byte-for-byte proof layout from the reference, plus on-chain check of the oracle attestation tail.AgentINFT.sol(rewrite) — addstransferWithProof(to, tokenId, proof), delegation table,memoryReencryptedstale flag, EIP-712 delegation forwarding forAgentBids.AgentBids.sol(rewrite) —Bidstruct gets delegation expiry;placeBidforwards delegation sig (single tx for bidder);acceptBidthreads proof totransferWithProof.AgentMerger.sol(rewrite) —recordMergetakes proofs for both source tokens; usessetDelegationByOwnersince MERGER is a contract with no key.app/api/inft/oracle/{seal-blob,prepare-transfer,confirm-transfer,prepare-merge,confirm-merge,reveal,key}/route.ts. Two-phase commit:prepare-transferbuilds proof but does NOT rotate Redis key;confirm-transferverifies tx receipt then rotates.INFT_ORACLE_PKvia HKDF.W2 (CCIP-Read resolver)
OffchainResolver.sol(new) — implementsIExtendedResolver.resolve(name, data)revertingOffchainLookup;resolveWithProof(response, extraData)ecrecovers the gateway sig.app/api/ens-gateway/[sender]/[data].json/route.ts. Decodes ABI calldata, computes record value, signs withINFT_GATEWAY_PK, returns. Records served:agent-card,description,url,current-price-tieroutstanding-bids,compliance-status,tvl,inft-tradeable(W1 cross-link),avatarlast-seen-at,memory-rotations(W1 cross-link)reputation-summary(5-min cache), ENSIP-25 multichain*.agentlab.ethand every nested*.*.agentlab.eth.W3 (primary names)
addrresolution handled dynamically by W2 gateway — no on-chain forward records to write.KeeperHub orchestration
Heartbeat(existing)last-seen-atfrom Redis liveReputationCache(existing)reputation-summaryon-the-flySwap(existing)/api/a2a/jobspaid quoteENSPrimaryNameSetterENSAvatarSyncavatartext record toeip155:.../erc721:.../<tokenId>GatewayCacheInvalidator/cache/invalidatefor affected keysOnboardAgentMigration
New deploys (all on Sepolia unless noted):
IdentityRegistryV2-b(V2-a'sinftfield is one-shot and already bound; V2-b mirrorsagentId=1registration). Other downstream contracts (Reputation, Credit, IPO, SLA) keep using V2-a — reputation continuity preserved by coincidence (same numeric agentId).AgentINFTVerifierAgentINFT(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: verifyagentlab.ethownership before any contract deploy.Old INFT (
0x245217…84EB6) and its plaintext memory blob are abandoned; new mint on the new contract creates a fresh encryptedtokenId=1.Test plan
Three layers, dependency-ordered:
AgentINFTVerifier.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).test-inft-oracle-e2e.ts,test-ens-gateway-e2e.ts,test-primary-names-e2e.ts. Each must printALL GREEN(mirrors the existingscripts/zg-prod-lib-test.tsposture, included in this commit).Out-of-scope (tracked, none unresolved)
clone(),authorizeUsage()Next: implementation plan via the
superpowers:writing-plansskill, broken into phased milestones (W1 first because W2 cross-links into INFT state, W3 last because it can run in parallel with anything).