diff --git a/admin/index.html b/admin/index.html index 889c468..0014033 100644 --- a/admin/index.html +++ b/admin/index.html @@ -1,394 +1,451 @@ - - -
- - -Operator-side tools: mint new TLDs, browse the registry, verify chain health. - Sign in with the wallet the ecosystem knows as the operator; unfamiliar wallets get - read-only access to the registry.
-Chipnet-only. Keys stay in this browser tab; a mint transaction is signed - locally and broadcast direct to the electrum. Operator gate is client-side — the covenant - that enforces it on-chain is a mainnet requirement (Decentralized.DNS/DESIGN-tld-registry.md §5.2).
-——Adds a per-TLD certificate to the TLD beacon. The cert - lands in your token address. Cost is chain fees + beacon dust (~1,300 chipnet sats).
-Every TLD registered on the beacon. Operators - (signed-in) can toggle a TLD's visibility on the public /api/tlds listing — hidden TLDs stop - appearing in the name-search UIs, but on-chain registrations under them keep resolving.
-Operator-side tools: mint new TLDs, browse the registry, verify chain health. + Sign in with the wallet the ecosystem knows as the operator; unfamiliar wallets get + read-only access to the registry.
+Chipnet-only. Keys stay in this browser tab; a mint transaction is signed + locally and broadcast direct to the electrum. Operator gate is client-side — the covenant + that enforces it on-chain is a mainnet requirement (Decentralized.DNS/DESIGN-tld-registry.md §5.2).
+——Adds a per-TLD certificate to the TLD beacon. The cert + lands in your token address. Cost is chain fees + beacon dust (~1,300 chipnet sats).
+Every TLD registered on the beacon. Operators + (signed-in) can toggle a TLD's visibility on the public /api/tlds listing — hidden TLDs stop + appearing in the name-search UIs, but on-chain registrations under them keep resolving.
+Logo, wordmark, avatar, banner, favicon, and the colour palette. Every asset ships as - SVG so it stays crisp at any size and reads correctly in light and dark contexts. Free to reuse - with attribution.
-A 4-point sparkle star plus Sirius.X, with the .x TLD picked out
- in acid green. The star alone works when you have no room for the wordmark; the full lockup is
- the default choice everywhere else.
Uses currentColor, inherits from the
- surrounding text. Print, embossing, single-colour merch.
Square icons for social profiles, Nostr, GitHub, and browser tabs.
-Square profile picture. Social platforms apply - their own round mask, so corners stay hard.
-Rounded browser-tab icon. Scales down to 16×16 - cleanly; used on every Sirius.X page.
-1200×630 (OpenGraph / Twitter Card canonical). Composition survives aggressive - centre-cropping — the star and tagline both stay visible even after Facebook and Discord chop - the sides.
-Silent Mode family colours. Dark chromes are the default; acid green is the - single accent that consistently signals "this is Sirius.X".
-System font stack, so nothing needs to load and every OS renders the wordmark in - the same family the reader is used to.
-The quick brown fox
-jumps over the lazy dog · 0123456789 · Sirius.X
- -.x is a <tspan fill="#d6ff3d"> —
- don't render the whole word in acid, and don't render the star without the star's exact 4-point
- path (it's a mark, not a generic asterisk).All assets are MIT. Reuse them for third-party tools that integrate with Sirius.X - (wallets, indexers, explorers, blog posts about BCNR). Keep the star's proportions intact and - don't recolour the acid to a similar-but-different green — palette drift is what makes brands - look untrustworthy over time.
-Logo, wordmark, avatar, banner, favicon, and the colour palette. Every asset ships as + SVG so it stays crisp at any size and reads correctly in light and dark contexts. Free to reuse + with attribution.
+A 4-point sparkle star plus Sirius.X, with the .x TLD picked out
+ in acid green. The star alone works when you have no room for the wordmark; the full lockup is
+ the default choice everywhere else.
Uses currentColor, inherits from the
+ surrounding text. Print, embossing, single-colour merch.
Square icons for social profiles, Nostr, GitHub, and browser tabs.
+Square profile picture. Social platforms apply + their own round mask, so corners stay hard.
+Rounded browser-tab icon. Scales down to 16×16 + cleanly; used on every Sirius.X page.
+Silent Mode family colours. Dark chromes are the default; acid green is the + single accent that consistently signals "this is Sirius.X".
+System font stack, so nothing needs to load and every OS renders the wordmark in + the same family the reader is used to.
+The quick brown fox
+jumps over the lazy dog · 0123456789 · Sirius.X
+ +.x is a <tspan fill="#d6ff3d"> —
+ don't render the whole word in acid, and don't render the star without the star's exact 4-point
+ path (it's a mark, not a generic asterisk).All assets are MIT. Reuse them for third-party tools that integrate with Sirius.X + (wallets, indexers, explorers, blog posts about BCNR). Keep the star's proportions intact and + don't recolour the acid to a similar-but-different green — palette drift is what makes brands + look untrustworthy over time.
+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.
-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/.
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.
-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):
| Record | Who can register | How 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. |
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.
POST /api/cosign). Nothing leaves your wallet until the owner
- acts; requests expire after 7 days.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.
-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.GET /api/market,
- GET /api/market/<name>, POST /api/market (a signed listing),
- DELETE /api/market/<name> (owner-signed
- BNS-MARKET1
-<name>
-<ts>).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).
| Record | Meaning | Typical use |
|---|---|---|
h | Inline HTML in the OP_RETURN payload itself | Tiny sites, a profile, a link hub |
s3 | A Sia bucket key (with auto-index for directory-style) | Multi-file sites, permanent hosting |
ip | An IPv4 address + optional tls fingerprint | Your own server, apps behind an IP |
u | Redirect URL | Short-form redirects to any web host |
tls | SHA-256 fingerprint of the leaf cert served at ip | Chain-pinned TLS trust, no OS root store needed |
np, nr | Nostr pubkey + relay list | Hermes / NIP-17 messaging bound to the name |
el | Space-separated electrum server list | On-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.
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.
- -| Concern | Where it lives | Cost per change |
|---|---|---|
| Who owns the name | Bitcoin Cash chain (NFT certificate) | 1 tx to transfer |
| Where the site lives | Chain record: s3, ip, u, h | 1 tx per change |
| DNS records, meta, TXT churn, etc. | Sia at <s3-bucket>/_records.json | free |
records.s3 to the Sia bucket,
- fetches _records.json.sig field,
- derives the CashAddress, compares to the current NFT-holder address from the chain. Mismatch = reject.seq number. Resolvers cache the
- highest seen and reject anything less-or-equal. An old signed blob can't be re-served.{
- "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.
| Method | Path | Effect |
|---|---|---|
| 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.
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.
- -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.
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>"}'
-
- 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.
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.
-site-myname-x/ in your working repo. Any
- static generator works (or plain HTML) — the deploy is content-agnostic.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/
sirius.x/ via any BCNR gateway. Survives VPS outage.
- node Argus/src/lib/sia-upload.js site-myname-x/ bns/myname/
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.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.
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.
- -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.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);"
-
- 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).Three paths, same chain data. Anyone can pick.
-.bch URLs directly.
- Installs a local root CA for TLS.
- Download →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.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 length | Floor (USD) | Notes |
|---|---|---|
| 1 char | 100,000 | Effectively unique; ENS-like scarcity |
| 2 char | 50,000 | The .ai / .io tier |
| 3 char | 15,000 | Order of magnitude below ICANN's $185k application floor |
| 4 char | 5,000 | Floor for short but reasonable TLDs |
| 5–8 char | 1,000 | Bulk-registerable but not spam |
| 9+ char | 250 | Descriptive 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.
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.
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.
- -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);"
-
- Same content should be served from at least two independent paths:
-https://<name>/ (requires local resolver + CA)https://navigate.st/bns/<name>/https://silentmode.st/bns/<name>/s3 recordThese 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":
git clone https://silentmode.st/sirius-x/repo/silent-mode.git — dumb-HTTP,
- no auth. Get the whole tree, browse offline, run the scripts.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.
-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.
+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/.
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.
+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):
| Record | Who can register | How 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. |
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.
POST /api/cosign). Nothing leaves your wallet until the owner
+ acts; requests expire after 7 days.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.
+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.GET /api/market,
+ GET /api/market/<name>, POST /api/market (a signed listing),
+ DELETE /api/market/<name> (owner-signed
+ BNS-MARKET1
+<name>
+<ts>).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).
| Record | Meaning | Typical use |
|---|---|---|
h | Inline HTML in the OP_RETURN payload itself | Tiny sites, a profile, a link hub |
s3 | A Sia bucket key (with auto-index for directory-style) | Multi-file sites, permanent hosting |
ip | An IPv4 address + optional tls fingerprint | Your own server, apps behind an IP |
u | Redirect URL | Short-form redirects to any web host |
tls | SHA-256 fingerprint of the leaf cert served at ip | Chain-pinned TLS trust, no OS root store needed |
np, nr | Nostr pubkey + relay list | Hermes / NIP-17 messaging bound to the name |
el | Space-separated electrum server list | On-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.
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.
+ +| Concern | Where it lives | Cost per change |
|---|---|---|
| Who owns the name | Bitcoin Cash chain (NFT certificate) | 1 tx to transfer |
| Where the site lives | Chain record: s3, ip, u, h | 1 tx per change |
| DNS records, meta, TXT churn, etc. | Sia at <s3-bucket>/_records.json | free |
records.s3 to the Sia bucket,
+ fetches _records.json.sig field,
+ derives the CashAddress, compares to the current NFT-holder address from the chain. Mismatch = reject.seq number. Resolvers cache the
+ highest seen and reject anything less-or-equal. An old signed blob can't be re-served.{
+ "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.
| Method | Path | Effect |
|---|---|---|
| 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.
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.
+ +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.
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>"}'
+
+ 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.
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.
+site-myname-x/ in your working repo. Any
+ static generator works (or plain HTML) — the deploy is content-agnostic.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/
sirius.x/ via any BCNR gateway. Survives VPS outage.
+ node Argus/src/lib/sia-upload.js site-myname-x/ bns/myname/
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.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.
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.
+ +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.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);"
+
+ 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).Three paths, same chain data. Anyone can pick.
+.bch URLs directly.
+ Installs a local root CA for TLS.
+ Download →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.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 length | Floor (USD) | Notes |
|---|---|---|
| 1 char | 100,000 | Effectively unique; ENS-like scarcity |
| 2 char | 50,000 | The .ai / .io tier |
| 3 char | 15,000 | Order of magnitude below ICANN's $185k application floor |
| 4 char | 5,000 | Floor for short but reasonable TLDs |
| 5–8 char | 1,000 | Bulk-registerable but not spam |
| 9+ char | 250 | Descriptive 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.
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.
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.
+ +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);"
+
+ Same content should be served from at least two independent paths:
+https://<name>/ (requires local resolver + CA)https://navigate.st/bns/<name>/https://silentmode.st/bns/<name>/s3 recordThese 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":
git clone https://silentmode.st/sirius-x/repo/silent-mode.git — dumb-HTTP,
+ no auth. Get the whole tree, browse offline, run the scripts.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.
+