argus/DESIGN-root-tld-cert.md

106 lines
4.3 KiB
Markdown
Raw Normal View History

# Root TLD certificate (BCNR's IANA-root)
**Status: ✅ deployed on chipnet (2026-07-30).**
The authoritative list of BCNR-native TLDs — the "IANA root" for BCNR — lives
in a single on-chain certificate. Clients read it to know which TLDs BCNR
considers its own, which is what makes multi-TLD support and collision
detection work without hardcoded lists.
## The name
**`tlds.bch`** — registered on chipnet (see the wallet's index). One record:
- **`tlds`** (string) — space-separated list of TLD suffixes, lowercase,
`[a-z0-9-]{1,16}` each. Bootstrap set (2026-07-30):
`"bch p2p deviant nav sia dgb nt sm lm"`.
Chosen shape:
- **Space-separated string, not JSON.** Fits the 200-byte OP_RETURN payload
comfortably, mirrors the existing `el` electrum-server-list record
(`electrum.silentmode.bch`), avoids escaping in on-chain payloads.
- **One well-known name at the well-known TLD (`.bch`).** No chicken-and-egg —
a client that only knows `.bch` can still resolve `tlds.bch` and learn the
rest. This is the sole hardcoded name; the rest are on-chain.
## Client API (`resolver-web.js`)
```js
import { ROOT_TLD_NAME, BOOTSTRAP_TLDS,
fetchBcnrTlds, getBcnrTlds, parseTldsRecord,
isBcnrNativeTld } from "./resolver-web.js";
// One-shot: connect, read the on-chain list, return it
const tlds = await fetchBcnrTlds({ WebSocket, electrum: [...] });
// Or reuse an already-built index (no extra round-trip)
const tlds = getBcnrTlds(index);
// Classify a TLD
isBcnrNativeTld(tlds, "p2p") // -> true
isBcnrNativeTld(tlds, "de") // -> false
```
Fallbacks: unpublished / unreachable / empty → `BOOTSTRAP_TLDS = ["bch"]`.
Callers should treat the list as **live but cacheable** (short TTL, e.g. one
hour) — every consumer already has a name-index cache, so add the TLD read to
the same warm path.
## How to update the list
Adding a TLD is one on-chain UPDATE (proves ownership by moving the certificate):
```js
import { loadWallet } from "./src/lib/wallet.js";
import { updateName } from "./src/lib/bns.js";
const w = await loadWallet();
await updateName(w, "tlds.bch", {
tlds: "bch p2p deviant nav sia dgb nt sm lm bit test x silentmode",
});
```
Once the tx confirms and resolver indexes refresh (typically < 60 s), every
client picks up the new TLD without a software update or reinstall. The
certificate is held by the operator wallet on chipnet — for a real deployment
this needs to be a multisig, a covenant, or a governance body (Athenae council,
see `ROADMAP-IDEAS.md §4`) so the root isn't controlled by a single key.
## What this unlocks
1. **Multi-TLD resolution** (already live) — `bnsd` and Theseus accept any
`<label>.<tld>`. The root cert is the "which TLDs count as ours" answer.
2. **Collision detection** for the soft "Open with…" prompt — a client can
preempt the prompt on `.com` (not BCNR-native, only ICANN could have it)
without hardcoding an ICANN-TLD allowlist.
3. **Surgical-mode routing** (`install.ps1 -Mode nrpt`) — the installer can
read the root cert and write one NRPT rule per activated TLD; adding a TLD
on-chain later triggers a re-sync, not a reinstall. (📐 to build.)
4. **Registrar hygiene** — a permissionless registrar (see `ROADMAP-IDEAS.md §3`)
must sell names only under activated TLDs; the root cert is the check.
## Not in scope here
- **Per-TLD registry designation** (which chain / operator backs each TLD, à la
the `.bit` on BCH vs Namecoin question). The current record is flat; if we
need per-TLD metadata, upgrade the record to `tlds` = space-separated tokens
of shape `<tld>|<registry>|…`, mirroring `el`'s `url|ip` shape. Or move to a
Sia-hosted manifest referenced by hash in the record (unlocks arbitrary
metadata without OP_RETURN size worries).
- **Root cert key ownership.** For real use the key holding `tlds.bch` must be
more than one operator's hot wallet — see the governance discussion in
`ROADMAP-IDEAS.md §4`.
## Test / verify
Any BNS resolver (local Fulcrum, VPS BNS indexer, public electrum) reads it:
```js
import WebSocket from "ws";
import { fetchBcnrTlds } from "./src/lib/resolver-web.js";
console.log(await fetchBcnrTlds({
WebSocket, electrum: [{ url: "ws://127.0.0.1:50003" }],
}));
// -> ["bch","p2p","deviant","nav","sia","dgb","nt","sm","lm"]
```
Registration tx (2026-07-30): `f5a34ec7b995541f2f9b10f85d30b29cc76ebf75960e794a9001a68b16f6b3e9`.