📚

Sirius.X docs

How the pieces fit together: the TLD registry, name registration, records that tell the resolver where a site lives, the resolver itself, and how anyone can verify anything against the chain.

The TLD registry

Every BCNR name lives under a top-level domain whose certificate is itself a first-class token on the Bitcoin Cash chain — an NFT with the TLD label as its commitment, paying dust to a dedicated TLD-registry beacon. That certificate is the on-chain proof the TLD exists, and once enforcement ships, it is what makes any second-level name under it valid to conforming resolvers.

Fourteen public TLDs on chipnet today (2026-08-29): bch p2p bit nav test x asm neo gt sc sia dex cex nt. The current list and per-TLD categories are at silentmode.st/tlds/.

Why per-TLD certs, not a single list. Without a registry, anyone could quietly declare a TLD against the same beacon by minting a name under it. That leaves resolvers in silent disagreement. Per-TLD certificates make the TLD set itself something the chain records, so every resolver sees the same list — and TLDs become ownable assets that can carry policy, fees, and governance of their own.

Register a name — end to end

The buyer's certificate mints straight to a wallet they control, in one transaction that also publishes the initial records and pays the beacon. Nobody including the operator can take the name back — the covenant work in progress adds an expiry / reclaim clock but does not change who controls the key.

  1. Search a label across every TLD. The registrar fans out to every TLD in the registry in parallel and shows available / taken per row. Available names appear first.
  2. Create or connect a wallet. Built-in browser wallet (PBKDF2 → AES-GCM in localStorage) or WizardConnect to Cashonize / Paytaca — both mint to the buyer's own key.
  3. Confirm the price. Miner fee + beacon dust + certificate dust + service fee. Chipnet placeholder is 10,000 sat; real pricing is a mainnet decision.
  4. The certificate lands in your wallet. The name resolves the moment the transaction confirms. Records can be set or changed later — only your key can sign a UPD.

Private & co-sign TLDs

A TLD owner decides who may register names under it, and the decision is enforced by every resolver, not just by the shop. Three switches live in the TLD's on-chain records (a TUPD signed by the owner's key):

RecordWho can registerHow it is enforced
hidden: 1 (switched off) Only the owner, from the dashboard. Off the public list. Co-sign rule (below).
policy: "cosign" Anyone, but every registration needs the owner's approval. Co-sign rule (below).
policy: "frozen" Nobody, owner included. Resolvers drop every new registration.

The co-sign rule

A registration under a cosign or hidden TLD is only recognised when the same transaction also carries the TLD's own certificate — the TLD NFT goes in as an input and comes back out to its owner. Only the owner's key can spend that NFT, so its presence is a signature nobody can forge, and nothing is consumed: the certificate returns in the same transaction. Every conforming client (gateway, Theseus, Ariadne desktop and mobile) applies the rule when it builds its index, judging each registration against the TLD policy in force at that block, so switching a TLD off later never invalidates names registered while it was open.

  1. Owner registering under a private TLD. Open the TLD in the dashboard, type a label, register. The certificate is added from your own wallet; you pay only the platform share of the name price.
  2. Anyone registering under a co-sign TLD. The normal register flow builds the full transaction with the owner's certificate as its last input, you sign your part, and the request waits in the gateway's approval queue (POST /api/cosign). Nothing leaves your wallet until the owner acts; requests expire after 7 days.
  3. Owner approving. Dashboard → the TLD → Pending approvals. Approve signs the certificate input and broadcasts; Decline removes the request. The wallet refuses to sign any request that would not return the certificate to you.
Why not a covenant? A covenant-gated mint is the mainnet plan for fee enforcement; the co-sign rule needs no new script, works today with plain P2PKH certificates, and gives the owner a human veto rather than a formula.

Buying & selling names

Any name can be sold to anyone, in one transaction, with no escrow. The seller is paid exactly when the certificate moves — or not at all.

  1. Seller lists. Dashboard → the name → Sell, set a price. Your wallet signs a partial transaction — your certificate as input 0, the price to you as output 0 — with SIGHASH_SINGLE | ANYONECANPAY. That signature says "whoever completes this pays me this much"; it constrains nothing else. The gateway stores it and shows it on the market after checking the signature, the on-chain owner and that the certificate is still unspent.
  2. Buyer completes. Verify the offer locally, add your coins, add the certificate output to your own token address plus a registry update so every resolver learns the new owner, sign your inputs, broadcast. The seller's signature is already in place.
  3. Seller cancels. Cancelling removes the offer from the market and moves the certificate once (a no-op update, a few cents), so the signed offer can never be completed afterwards.
Trust model. The gateway is a bulletin board. A forged or stale listing fails the buyer's local check or the broadcast; a buyer can never pay without receiving the certificate in the same transaction, and a seller can never lose the certificate without being paid. Endpoints: GET /api/market, GET /api/market/<name>, POST /api/market (a signed listing), DELETE /api/market/<name> (owner-signed BNS-MARKET1 <name> <ts>).

Releasing a name

An owner can give a name back. Dashboard → name → Transfer → Release this name publishes a REL transaction that destroys the name's certificate. The name stops resolving at once, and from the block after the release confirms anyone can register it again — as a new name, with a new certificate. Nothing of the old registration carries over, and nothing is refunded.

  • It cannot be undone. The dashboard asks you to type the name before it signs.
  • One block of quiet. A registration made in the same block as the release, or while the release is still unconfirmed, is void. Everyone sees a confirmed release before anyone can claim the name.
  • Take it off the market first. A listed name has to be unlisted before it can be released.
  • Hosted files stay where they are. A release does not delete a site's files; a later owner only serves them again by pointing a record at that folder.
Clients must be current. A resolver older than the release rule ignores REL and keeps showing the name as registered. The gateway, the Sirius.X site and the resolver library carry the rule; GET /api/name/<name> reports released_at for a released name.

Flagged names

A resolver can subscribe to a blocklist: a public, on-chain list of names reported as dangerous. It is advice, not a chain rule. A flagged name stays registered and its owner keeps the certificate; a resolver that subscribes warns you before showing the site, and one that does not shows it as before.

  • The default list is sirius-blocklist.x, and it is empty. The mechanism ships ahead of need so that the first real report takes a transaction, not a software update.
  • Six reasons, nothing else: phishing, impersonation, malware, scam-financial, csam, stolen. No "offensive", no "illegal": only harms with a victim you can point to.
  • Every flag names its report. A flag without a report on chain is ignored by every resolver, and anyone can read the report by its transaction id.
  • You can continue anyway. The gateway's warning page offers a way through, per name. The one exception is csam, which it refuses.
Check it yourself. GET /api/blocklist lists the subscribed lists and every current flag; GET /api/name/<name> adds blocked, block_reason and block_report_txid for a flagged name. The list is an ordinary address: only transactions spent from it count, so nobody can add an entry by paying it.

Records & hosting

A registered name carries a small JSON records object. Every record is optional and multiple can coexist. Priority order the gateway uses: h (inline HTML) → s3 (Sia bucket key) → ip (host header served by an IP) → u (redirect).

RecordMeaningTypical use
hInline HTML in the OP_RETURN payload itselfTiny sites, a profile, a link hub
s3A Sia bucket key (with auto-index for directory-style)Multi-file sites, permanent hosting
ipAn IPv4 address + optional tls fingerprintYour own server, apps behind an IP
uRedirect URLShort-form redirects to any web host
tlsSHA-256 fingerprint of the leaf cert served at ipChain-pinned TLS trust, no OS root store needed
np, nrNostr pubkey + relay listHermes / NIP-17 messaging bound to the name
elSpace-separated electrum server listOn-chain-updatable resolver bootstrap

Subdomains inherit from their parent with a slight priority tweak: for a subdomain query, ip beats s3 (Host-header semantics). Full rule is in Argus/src/lib/record-picker.js.

Free edits — signed off-chain records

The on-chain records above (h, s3, ip, u, tls, np, el) cost a chain transaction to change and are capped at 200 bytes of OP_RETURN. For DNS-style records (A / AAAA / MX / TXT / CNAME / NS) and any records you edit often, Sirius.X uses a companion mechanism: a signed off-chain manifest that costs nothing per change and has no size cap.

The chain says who owns the name. A signed blob says what the records are. Resolvers verify both. No third party is trusted for records: the manifest is signed by the same key that holds the on-chain NFT certificate, so an operator (or Sia farmer, or anyone else in the middle) can't rewrite records without breaking the signature.

ConcernWhere it livesCost per change
Who owns the nameBitcoin Cash chain (NFT certificate)1 tx to transfer
Where the site livesChain record: s3, ip, u, h1 tx per change
DNS records, meta, TXT churn, etc.Sia at <s3-bucket>/_records.jsonfree

How the manifest is verified

  1. Resolver reads the name's chain record, follows records.s3 to the Sia bucket, fetches _records.json.
  2. Signature check — recovers the signing pubkey from the manifest's sig field, derives the CashAddress, compares to the current NFT-holder address from the chain. Mismatch = reject.
  3. Replay check — the manifest carries a monotonic seq number. Resolvers cache the highest seen and reject anything less-or-equal. An old signed blob can't be re-served.
  4. Fall-back — if the manifest is missing, invalid, or its signature doesn't match, the resolver silently falls back to the on-chain records. Signed records never override a name; they extend it.

The manifest shape

{
  "v":    1,
  "name": "bitcoin.cash",
  "seq":  42,
  "updated_at": "2026-09-15T00:00:00Z",
  "dns": {
    "A":     ["1.2.3.4"],
    "AAAA":  ["2001:db8::1"],
    "MX":    [{"pref": 10, "host": "mail.example.com"}],
    "TXT":   ["v=spf1 include:_spf.silentmode.st -all"],
    "CNAME": null,
    "NS":    []
  },
  "sig":  "<BCH message signature over sha256(canonical bytes)>"
}

Canonicalisation: sorted keys, no whitespace, null fields omitted. The signable bytes are the manifest with the sig field removed. Full spec: DESIGN-signed-records-manifest.md — signable byte order, seq-monotonicity rules, threat model, v2 roadmap.

Endpoints

MethodPathEffect
GET/api/records/<name>Fetches the raw signed manifest from the name's Sia bucket. Public, cacheable.
POST/api/records/<name>Accepts a signed manifest, verifies against the on-chain owner + seq monotonicity, uploads to Sia.
GET/api/dns/<name>Resolver read. Fetches the manifest, verifies the signature against the on-chain owner and rejects rollback of the seq, then returns only the verified dns block. Callers can trust the response without doing their own signature or chain lookups. 30-second cache hint.

The distinction between /api/records/<name> and /api/dns/<name> is deliberate: the former is transparent (raw manifest as uploaded, including the signature so clients can re-verify), the latter is opinionated (only the verified DNS records, with the gateway having done the sig + seq work). Bridges and shims should use /api/dns/; wallets and tools that want to see the full signed blob should use /api/records/.

A name needs records.s3 set on chain first — without a storage pointer, the manifest has nowhere to live. Portal and CLI both refuse to publish a manifest until s3 is present.

Threat model at a glance. Operator tampers → sig check fails, resolver falls back to chain records. Replay of an old blob → seq check fails. Owner's key compromised → same as chain-side compromise; move the name to a new key. Sia object deleted → name still resolves via chain records, DNS records disappear until republished. Hostile gateway can refuse writes but cannot forge them; users can PUT directly to Sia with their own credentials to bypass.

Host your name

The end-to-end recipe for putting a static site under a BCNR name. Chipnet today, mainnet later — the shape is the same. Three ways to host, most people combine two of them (Sia + VPS mirror) so the site keeps serving if either mirror goes down.

Pattern A — Sia only

Simplest. Site lives on the Sia storage network, name's s3 record points at the bucket key, gateways (navigate.st, silentmode.st, any BCNR-aware browser) fetch it on demand. Same pattern silentmode.bch uses.

# From a checkout with sia-s3.json credentials:
node Argus/src/lib/sia-upload.js ./my-site bns/myname/

# Set the chain record (once). Note the trailing slash — enables auto-index
# so /myname/ serves myname/index.html and /myname/about/ serves .../about/index.html.
node Argus/src/update.js myname.x '{"s3":"bns/myname/"}'

Bucket-path convention: bns/<label>/ (no TLD; the label is unique enough within our Sia namespace and keeps game.x + game.bch from colliding). Files update by re-running sia-upload; the chain record only changes when the bucket path does.

Pattern B — Your own server (VPS + ip)

Point the name at an IP; every request goes directly to your box. Add a tls record with the SHA-256 of the leaf certificate so browsers verify the connection against the chain instead of the OS trust store.

# On your VPS: nginx serves your site over TLS. Then, on chain:
node Argus/src/update.js myname.x '{"ip":"1.2.3.4","tls":"<sha256-of-leaf-cert>"}'

Pattern C — Dual host (Sia primary, VPS mirror)

What Sirius.X itself uses. Sia is the chain-authoritative source (survives if the VPS is down); the VPS serves the same content on silentmode.st/<path> for users without a BCNR resolver installed. On the VPS side, extend the nginx vhost serving silentmode.st with a new location block that aliases straight from disk:

location /myname-x/ {
    alias /opt/silent-mode/site-myname-x/;
    index index.html;
    try_files $uri $uri/ =404;
}

Then rsync / scp your site tree to silentmode:/opt/silent-mode/site-myname-x/ and reload nginx. This gives you two URLs for the same content: https://silentmode.st/myname-x/ (VPS-direct) and the chain-authoritative https://myname.x/ via any BCNR resolver.

The dual-host recipe, end to end

This is the exact sequence Sirius.X itself uses on every publish. The chain record stays constant; only file contents change, so no per-publish UPD is needed.

  1. Edit locally. Site source lives at site-myname-x/ in your working repo. Any static generator works (or plain HTML) — the deploy is content-agnostic.
  2. Push VPS mirror (fast path). Serves at silentmode.st/myname-x/ within seconds. Users without a BCNR resolver hit this route.
    scp -r site-myname-x/* silentmode:/opt/silent-mode/site-myname-x/
  3. Push Sia mirror (durable copy). Serves at sirius.x/ via any BCNR gateway. Survives VPS outage.
    node Argus/src/lib/sia-upload.js site-myname-x/ bns/myname/
  4. Verify both. curl -so /dev/null -w "%{http_code}\n" https://silentmode.st/myname-x/ and curl -so /dev/null -w "%{http_code}\n" https://silentmode.st/bns/myname.x/ — both should return 200.

Auto-backup: one command, both mirrors

Wrap the two commands into a script so every publish reaches both mirrors without extra thought. This is exactly what a two-liner deploy hook looks like:

# scripts/deploy-myname-x.sh
#!/usr/bin/env bash
set -eu
SRC="$(dirname "$0")/../site-myname-x"
VPS_DEST="silentmode:/opt/silent-mode/site-myname-x/"
SIA_BUCKET="bns/myname/"

echo "→ VPS mirror"
scp -qr "$SRC"/. "$VPS_DEST"

echo "→ Sia mirror"
node "$(dirname "$0")/../Argus/src/lib/sia-upload.js" "$SRC" "$SIA_BUCKET"

echo "✓ deployed; verifying"
for url in "https://silentmode.st/myname-x/" "https://silentmode.st/bns/myname.x/"; do
  code=$(curl -so /dev/null -w '%{http_code}' "$url")
  printf '  %s → %s\n' "$url" "$code"
done

Wire it into git: chmod +x scripts/deploy-myname-x.sh, add a .git/hooks/post-commit that runs it if the site subtree changed, or invoke manually. Sia uploads that fail (network hiccup, quota) leave the VPS mirror ahead until the next run — same failure mode as any staged deploy.

Automate the reverse — VPS → Sia periodic backup

If your primary publish path is straight-to-VPS (nginx-direct, no Sia step per publish), a cron job can pull the VPS state and push to Sia on a schedule:

# /etc/cron.d/sirius-x-sia-backup (on the operator's VPS)
17 * * * * root  cd /opt/silent-mode && node Argus/src/lib/sia-upload.js \
    /opt/silent-mode/site-myname-x/ bns/myname/ >/var/log/sia-backup.log 2>&1

Runs hourly at :17 (offset from the top of the hour so it doesn't collide with everyone else's cron traffic). The tradeoff: up to an hour of drift between VPS and Sia after a publish — usually fine, since the chain record still resolves correctly either way and BCNR gateways cache Sia content.

Which mirror is authoritative? The one your chain record points at. If s3 is set, gateways fetch from Sia; the VPS mirror is just a convenience URL. If only ip is set, gateways fetch from the VPS; Sia is just backup. If BOTH are set, gateways pick per the priority in the "Records" section (subdomain-aware; see record-picker.js). Set both for durability, but be deliberate about which is primary.

Verify records changed correctly

node --input-type=module -e "
import { loadWallet } from './Argus/src/lib/wallet.js';
import { resolveName } from './Argus/src/lib/bns.js';
const w = await loadWallet('main');
console.log(await resolveName(w.provider, 'myname.x'));
process.exit(0);"
Credentials. Sia upload needs Argus/sia-s3.json. VPS deploy needs SSH to the operator's box. Neither is in the repo — a session that isn't run by the operator will need those handed over out-of-band. Full command reference is in INSTRUCTIONS.md, especially §5 (Sia storage) and §6 (deploy).

Resolver / gateway

Three paths, same chain data. Anyone can pick.

  1. Local — Ariadne Resolver. A system-wide resolver that intercepts BCNR TLDs and answers them from the chain. Any browser you already use starts opening .bch URLs directly. Installs a local root CA for TLS. Download →
  2. In-browser — Theseus Navigator. A Chromium build with the resolver baked in, plus an on-chain TLS trust anchor. No OS trust-store install; nothing modified globally. Download →
  3. Public gateway — navigate.st. For anyone without the resolver installed: https://navigate.st/bns/<name>/ proxies through a hosted resolver. Same content, fewer guarantees — trust the gateway to fetch honestly, or run one of the first two. Pages served through the gateway run in a sealed browser view with no cookies, no local storage and no credential APIs — see Relay sandbox below.

Public relay sandbox

If you host a BCDN site, visitors can reach it two ways: natively through Theseus or Ariadne (the site loads under its own real origin, everything works), or through navigate.st/bns/<name>/ — the public relay. The relay is convenient but it is a shared origin: every BCDN site relayed through it would, in a naive setup, see every other BCDN site's cookies, local storage, passkeys and in-flight tokens. That is the risk the sandbox closes.

How isolation works

Every HTML response under /bns/ carries a Content-Security-Policy: sandbox … directive. The browser assigns the document a unique opaque origin that is not navigate.st and is not shared with any other document — not even another tab loading the exact same URL. Two different BCDN sites get two different opaque origins; two tabs of the same BCDN site also get two different opaque origins. Tenants cannot see or touch each other, by browser enforcement.

The exact tokens the gateway grants:

Content-Security-Policy: sandbox allow-scripts allow-forms allow-popups
  allow-popups-to-escape-sandbox allow-top-navigation-by-user-activation
  allow-modals allow-downloads

Notably absent: allow-same-origin. Adding it would hand the document back its navigate.st origin and defeat the whole mechanism; the gateway will never set it.

What works, what fails

CapabilityStatusNotes
Inline scripts, forms, popupsworksOrdinary content browsing is intact
Downloads, modals, user-click top-navworksFile saves and alert()/confirm() work
fetch() to upstream APIsworksOpaque origin sends Origin: null; CORS-aware backends must allow it
WebCrypto SubtleCryptoworksSigning / encrypting in memory is fine; you just can't persist keys
localStorage / sessionStorageSecurityErrorOpaque origins can't persist state
IndexedDBSecurityErrorSame reason
document.cookie read/writeSecurityErrorServer-sent Set-Cookie is also discarded
WebAuthn / passkeysfailsrp.id check rejects opaque origin
navigator.credentials.*failsCredential Management API gated the same way
Service workersrejectedOpaque origin can't own a worker scope — no offline mode
document.requestStorageAccess()not grantedallow-storage-access-by-user-activation is not set

Sign-in without browser storage

Durable browser-persistent sign-in is off through the relay — no amount of code on your page can defeat the sandbox. These four patterns do work, in increasing order of durability:

  1. In-memory session. Hold the auth token in a JS variable for the lifetime of the page view. Lost on reload. Fine for one-off operations like signing a single transaction.
  2. window.name as a per-tab store. Readable and writable even on opaque origins; survives reload within the same tab, lost on tab close. Good for "stay signed in across refreshes" during a single browsing session.
  3. Theseus ID popup — silent SSO. Click "Sign in with Theseus ID" → open a popup to id.theseus.x (this escapes the sandbox because the gateway grants allow-popups-to-escape-sandbox). The popup runs on its own real origin, carries its own long-lived session cookie, and posts an auth token back with window.opener.postMessage(…). On a repeat visit the popup opens and closes in a flash; the user sees nothing. Needs a user gesture (click) to defeat popup blockers. On id.theseus.x this requires response_mode=web_message — the gateway can wire this in when a tenant asks for it.
  4. Wallet-signed challenge. Have your page emit a nonce for the user's BCH wallet to sign; your server verifies against a known address. Browser extensions (including Aegis in Theseus) inject on any origin, so this works even in a sandboxed document. The identity is the wallet, not a stored credential — nothing to persist.
Honest default: if your site needs real sign-in UX (remember-me, passkeys, offline mode), tell visitors to install Theseus. There is no gateway-side UI nudging them — the sealed view is invisible until a page tries to touch storage or credentials, at which point the browser silently rejects. Communicating that to visitors is up to the site; the operator-facing explanation lives at navigate.st/about.

What the gateway injects into HTML

Just a <base href> to make relative URLs resolve, a rewrite of cross-BCDN links so they stay on the relay instead of hitting ICANN NXDOMAIN, and an .html stripper for prettier URL bars. No visible chrome: no chip, no banner, no sign-in nudge. Relayed sites render exactly like the native article. Earlier drops shipped a persistent chip and a dormant password-focus nudge; both were retired because they leaked into native-client renders in some paths and branded tenant sites in a way that read as noise.

Headers you can rely on

Alongside the sandbox directive, every /bns/ HTML response carries:

Permissions-Policy: camera=(), microphone=(), geolocation=(),
  payment=(), usb=(), bluetooth=(), accelerometer=(), gyroscope=(),
  magnetometer=(), autoplay=(), interest-cohort=(), browsing-topics=(),
  publickey-credentials-get=(), publickey-credentials-create=(),
  identity-credentials-get=()
Referrer-Policy: no-referrer
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN

Camera, microphone, location, payment, Bluetooth, USB and advertising-topic APIs are all denied as a defense-in-depth layer on top of the sandbox. If your site needs any of these, Theseus is where it will work.

Operator-visible metadata. The gateway is a convenience tier, not the trustless one. The operator can see which BCDN sites you request (not the content — the resolver fetches that itself over pinned HTTPS). The gateway keeps no request logs; whether to trust that is a choice. For trustless resolution install Theseus; for IP-level privacy use Tor.

Pricing (mainnet)

On mainnet the covenant enforces USD-denominated floors, tiered by TLD label length. This is what keeps someone from land-grabbing every ICANN TLD in one afternoon. TLD registration is one-time — a TLD is closer to a domain purchase than a lease.

Label lengthFloor (USD)Notes
1 char100,000Effectively unique; ENS-like scarcity
2 char50,000The .ai / .io tier
3 char15,000Order of magnitude below ICANN's $185k application floor
4 char5,000Floor for short but reasonable TLDs
5–8 char1,000Bulk-registerable but not spam
9+ char250Descriptive TLDs, low economic gravity

On name registration under a TLD, the TLD's owner collects a share (fee_bps, default 5%, cap 50%). Chain-enforced when the TLD's policy is covenant; honour-system otherwise. Name registration is yearly and priced separately.

The TLD owner also sets what names under it sell for and whether the TLD is on or off, straight from the portal: a price record (flat USD per name, replaces the length tiers for every buyer) and a hidden record (1 makes it a private TLD: off the public list, nobody but the owner can register names under it — the owner still can from the portal, paying only the platform share — until it is switched back on). Both ride the same signed TUPD, so every client reads them from the chain; the owner keeps 90% of each sale.

Tracker & mirrors

A tracker publishes signed snapshots of the TLD registry to Sia and Nostr so downstream clients don't have to walk the chain themselves. The chain is authoritative; the tracker is speed. Every snapshot carries a root hash anyone can recompute locally — a lying mirror is caught by any recipient who bothers to check.

A conforming client falls through: (1) fetch snapshot from a mirror, (2) verify root, (3) if suspicious, walk the beacon and rebuild. All three yield the same list for any given block height.

Verify anything

You do not have to trust that sirius.x, silentmode.st, or navigate.st are serving honest content. Every name's certificate is on chain; every record is a signed on-chain payload; every host is checkable independently.

Confirm a specific name on chain

node --input-type=module -e "
import { loadWallet } from './Argus/src/lib/wallet.js';
import { resolveName } from './Argus/src/lib/bns.js';
const w = await loadWallet('main');
console.log(await resolveName(w.provider, 'sirius.x'));
process.exit(0);"

Fetch the operator-signed TLD snapshot from Nostr

Kind / d-tag
30078 / bns-tld-list
Pubkey (x-only, hex)
f2c925194c531c7c398017e35b2396df64a61a613aa5fadebdf1f4990f2267f4
Relays
wss://nos.lol · wss://relay.damus.io

Reach any site via more than one route

Same content should be served from at least two independent paths:

  • Direct BCNR: https://<name>/ (requires local resolver + CA)
  • Public gateway: https://navigate.st/bns/<name>/
  • silentmode.st mirror: https://silentmode.st/bns/<name>/
  • Direct from Sia (content-addressed) via the name's s3 record

Operator runbook

These docs describe what. The how — exact bash commands to register TLDs, mint names, update records, and deploy — is INSTRUCTIONS.md. Three ways to read it, in order of "how much do I already have installed":

  1. Just read it in the browser Served straight from the docs directory: /sirius-x/docs/INSTRUCTIONS.md. Plain text; every browser renders it.
  2. Clone the git remote git clone https://silentmode.st/sirius-x/repo/silent-mode.git — dumb-HTTP, no auth. Get the whole tree, browse offline, run the scripts.
  3. Browse the Forgejo mirror Repo lives at code.silentmode.st/silentmode/sirius on the Silent Mode Hephaestus forge. Rendered runbook: docs/INSTRUCTIONS.md. Clone: git clone https://code.silentmode.st/silentmode/sirius.git — public, no auth.

The runbook covers CLI name registration, TLD-registry seeding, record updates, Sia upload, VPS deploy, tests, and the historically-costly gotchas.