Theseus soft-mode UX: 'Open with...' modal on collision, per-name/per-TLD overrides, live per-tab switcher in the site-info popover, and a Naming section in Settings for policy + reset. Backed by an on-chain root TLD certificate (tlds.bch) that resolver-web.js discovers via fetchBcnrTlds()/isBcnrNativeTld(). Companion pieces: - Argus/src/indexer/ELECTRUM-SOURCE-README.md — the featherweight VPS variant (no BCHN node, no Fulcrum) now live as bns-indexer.service. - Argus/DESIGN-root-tld-cert.md — clarified: NOT a governance workflow, just ordinary key management (single wallet MVP -> 2-of-3 multisig). List gates registration / surgical NRPT / soft-mode classifier — never resolution. - ROADMAP-IDEAS.md — recorded SiaGit/GitHub.sia + user-friendly Sia UI ideas. Full spec: Argus/DESIGN-collision-modes.md (already tracked).
127 lines
5.5 KiB
Markdown
127 lines
5.5 KiB
Markdown
# 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.
|
|
|
|
**Key management, not governance.** The TLD list is a **rarely-changed activation
|
|
list** (the "constitution"), not a workflow with continuous decisions. After
|
|
launch, a new TLD gets added occasionally — quarterly, maybe. So the cert needs
|
|
ordinary key hygiene, not a standing governance body:
|
|
|
|
- **MVP / chipnet:** single operator wallet is fine.
|
|
- **Real deployment:** **2-of-3 multisig** (operator + backup keys) for bus-factor
|
|
and key-loss protection. Not "decentralized governance" — just multiple
|
|
keyholders to protect one occasionally-updated list.
|
|
|
|
Note the strict scope: the TLD cert has **no editorial power** — it doesn't
|
|
decide what names may exist within a TLD (that's permissionless), doesn't take
|
|
names away from existing owners, and doesn't moderate content. **Moderation is a
|
|
different concern**, about *sites* not TLDs, continuous rather than occasional
|
|
— that's where Athenae Politeia + paid members earn their keep (see
|
|
`ROADMAP-IDEAS.md §4`). Keep the two systems separate.
|
|
|
|
## What this unlocks — and what it does NOT
|
|
|
|
**The root cert does NOT gate resolution.** The resolver stays TLD-agnostic —
|
|
any registered name under any TLD resolves. The activated list has three real
|
|
consumers:
|
|
|
|
1. **Registrar** (`register.html`) — the TLD dropdown for buyers is limited to
|
|
activated TLDs. Storefront quality bar; keeps stray experimental TLDs out of
|
|
the buying UI. Names *already* registered under unlisted TLDs still resolve.
|
|
2. **Surgical-mode routing** (`install.ps1 -Mode nrpt`) — the installer reads
|
|
the root cert and writes one NRPT rule per activated TLD. Adding a TLD
|
|
on-chain + re-running the installer picks it up (no code change). Users who
|
|
want any-TLD system-wide routing pick **Full mode** instead.
|
|
3. **Collision-mode classifier** (soft "Open with…" prompt) — clients use it as
|
|
a hint: "is this TLD BCNR-native → probably not a collision, don't prompt."
|
|
A TLD not on the list falls through to normal collision handling; the list
|
|
is a *preemption* aid, not a filter.
|
|
|
|
The resolver never consults the list. Registration and resolution are separate
|
|
concerns; permissionless resolution + curated activation is deliberate.
|
|
|
|
## 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`.
|