docs(design): how libID would integrate with ENS - #7
Open
SupremaLex wants to merge 6 commits into
Open
Conversation
A proposal, not a spec: it defines no identifiers and nothing here is built. The finding that shapes it is that we would not be issuing subnames, we would be projecting state that already exists. `resolveHandle` answers the question an ENS resolver asks, so a name needs no registry entry, no NFT and no storage -- it is a view. That costs one resolver contract on mainnet, one stateless read-only gateway, and nothing at all on the write path, and it means a rename or a wallet move follows the binding with no ENS transaction. The namespace is the DNS domain we already own, imported on-chain. Gasless DNSSEC cannot serve subnames, and a `.eth` name would add an annual renewal whose expiry takes every name below it. The import is written out: DNSSEC as a precondition, the `_ens` TXT record, every argument of `proveAndClaimWithResolver`, and the dependency that follows -- the ENS name follows the DNS domain, so a later valid proof overwrites the owner. Resolution is three steps, and the address comes from the third: the revert carries the endpoint, the gateway returns a signed blob, and a second `eth_call` turns it into an address. Supporting ENS is not enough for a wallet; it needs ENSIP-10, ERC-3668 and ENSIP-11 together. Cross-chain needs no invention: ENSIP-11 coin types say which chain's `IdentityNames` to read, and answering only for chains that hold a binding makes wrong-chain delivery impossible rather than unlikely. The chain is a label of the hierarchy; it may be omitted, and then the coin type decides. What several chains do cost is freshness, which is ordered within a chain and not across them -- with handle recycling that can put two people under one name, and the gateway is the only component positioned to notice. Handle mapping is specified rather than described. ENSIP-15 is not UTS-46, and on our lowercase ASCII exactly two of its rules can fire: an underscore only at the start of a label, and no hyphen at both the third and fourth characters. The transform follows from them -- GitHub unchanged, X through an injective `_` to `-` substitution which loses only a doubled underscore at those two positions, Gmail split at its dots once the platform label implies the domain, and an id-derived name behind an `_id` marker for everything that refuses. Workspace is expressible and deliberately not exposed, because a resolving name would publish where someone works. The gateway signs, and that is the model rather than a stage toward something else. The cost is accepted and stated: a compromised signing key can answer with any address. Three keys are kept apart -- the DNS credentials that own the namespace, the owner key that sets the resolver, and the signer that lives on the gateway. Also records where the boundary runs -- everything before the gateway call belongs to the client, everything after belongs to us -- and what is deliberately not proposed, namely minting subnames as NFTs, which would create a second source of truth able to disagree with the binding. Assisted-by: Claude Opus 5 Signed-off-by: SupremaLex <georglutsenko@gmail.com>
…t encode The draft promised totality through an id-derived name, `<idNode as 64 hex characters>._id.handles.link`. Sixty-four characters is one past the DNS label ceiling of RFC 1035, so no client can encode it — ethers' `dnsEncode` refuses above 63. The property it was there to hold never held, and the accounts it was meant to rescue had no name at all. Those accounts are Google addresses outside gmail.com, which is not a corner: one of the five bindings on eden today is `green.baneling@fuel.sh`. So the Workspace form this document already described is enabled rather than reserved. Six labels with a marker in the middle is closer to a machine string than to a name, and it discloses an employer — both were reasons to withhold it, and neither survives the alternative being no name. The privacy consequence is kept, moved to where it belongs: whether a Workspace name is minted by default is a decision for the binding flow, and it is recorded as open. What still has no name is stated plainly instead of being covered by a fallback: an address holding `_` or `+`. Both are legal as proved, neither is legal in a label, and no substitution is reversible — unlike X, where `_` maps to `-` because X forbids `-`, a Google address may hold both. Assisted-by: Claude Opus 5 Signed-off-by: SupremaLex <georglutsenko@gmail.com>
The gateway signs for the resolver address it is configured to serve, not
the {sender} in the path: through the batch gateway the two agree, but a
resolver announcing ERC-7996 is called directly and the universal resolver
raises the lookup again under its own address. CORS goes on every response
because viem runs the batch gateway in the page and fetches the gateway
cross-origin. ENSv2's DNS TLD resolver consults the v1 registry first, so
the import and the resolver survive v2 unchanged.
Assisted-by: Claude Fable 5.1
Signed-off-by: xgreenx <xgreenx9999@gmail.com>
… only method
The gateway in usernames-indexer#5 compares {sender} to its configured
resolver and answers a terminal 400 on mismatch; the digest never uses it.
Say so, instead of "logged and not parsed strictly". The resolver's urls
carry {data} and the deployment workflow refuses a template without it, so
ERC-3668's POST form never occurs; drop the OPTIONS clause that promised it.
Assisted-by: Claude Fable 5.1
Signed-off-by: xgreenx <xgreenx9999@gmail.com>
… no RPC Aligns the backend section with usernames-indexer#7: answers come from the indexed model, chains are whatever indexers have written into the store, and the gateway takes no per-chain configuration. Assisted-by: Claude Fable 5.1 Signed-off-by: xgreenx <xgreenx9999@gmail.com>
…d, and never decodes them The backend block said "no database" and decoded the coin type, which is not what usernames-indexer#7 does: the gateway reads the Postgres mirror the indexer keeps, matches a coin type forward against the chains the store holds, and answers null for a label that names another chain. Assisted-by: Claude Fable 5.1 Signed-off-by: xgreenx <xgreenx9999@gmail.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.
A design proposal for projecting
IdentityNamesbindings into ENS, so a name inan X bio resolves in a wallet that has never heard of libID. Nothing here is
built, and it defines no
ASM-*/SP-*/REQ-*identifiers — the parts carryingtrust assumptions would graduate into
specs/if this is approved.The load-bearing finding
We would not be issuing subnames. We would be projecting state that already
exists:
resolveHandle(platformId, handle)already answers the question an ENSresolver asks. So a name needs no registry entry, no NFT, no mint and no storage
of its own — it is a view.
The cost is one small resolver contract on mainnet, one stateless read-only
gateway, and nothing on the write path:
IdentityNamesis untouched. A renameor a wallet move then follows the binding with no ENS transaction at all.
Coinbase runs the same shape for eleven million
*.cb.idnames.What the document decides
handles.link, the DNS domain we already own, importedon-chain via
DNSRegistrar..ethis rejected: an annual renewal whose expirywould kill every name beneath it. Gasless DNSSEC (ENSIP-17) cannot serve
subnames at all.
<handle>.<platform>[.<chain>].handles.link. The chain is alabel of the hierarchy; omitting it means "answer by the caller's coin type".
answering only for chains that hold a binding makes wrong-chain delivery
impossible rather than unlikely.
lowercase ASCII exactly two of its rules can fire. GitHub passes unchanged, X
goes through an injective
_→-substitution that loses only a doubledunderscore at the third and fourth characters, Gmail splits at its dots, and an
_id-marked name derived fromidNodecovers everything that refuses.something else. The cost is stated: a compromised signing key can answer with
any address. Three keys are kept apart — the DNS credentials that own the
namespace, the owner key that sets the resolver, and the signer on the gateway
host.
Two things worth reading closely
Resolution is three steps and the address comes from the third. The revert
carries the endpoint, the gateway returns a signed blob, and a second
eth_callinto the resolver's callback turns it into an address. Both calls are
eth_call;no transaction, no gas.
The ENS name follows the DNS domain. A later valid DNSSEC proof overwrites
the owner, so whoever holds the registrar account and the DNSSEC keys holds the
namespace. Section 0 writes out the import: the
_ensTXT record and everyargument of
proveAndClaimWithResolver.Still open
Gateway policy when chains disagree; whether
_→-is surfaced in our own UI;and name depth, which is the first thing to measure after the import because
depth is decided by the client rather than by the specification.