Initial commit

This commit is contained in:
Local Dev 2026-09-12 00:07:25 +02:00
commit cc4e36d7fb
14 changed files with 1781 additions and 0 deletions

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
# Generated git-mirror artifacts served from sirius.x/repo/.
# Regenerated on each publish; the source of truth is the working repo itself.
repo/silent-mode.bundle
repo/silent-mode.git/

8
assets/favicon.svg Normal file
View file

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<!-- sirius.x — brightest-star favicon. Rounded dark square + 4-point sparkle
in the Silent Mode acid green so it reads clearly at 16x16 tab-icon size
while staying legible against both light and dark browser chromes. -->
<rect width="64" height="64" rx="12" fill="#0b0e14"/>
<path d="M32 4 L36.4 27.6 L60 32 L36.4 36.4 L32 60 L27.6 36.4 L4 32 L27.6 27.6 Z"
fill="#d6ff3d"/>
</svg>

After

Width:  |  Height:  |  Size: 473 B

8
assets/logo.svg Normal file
View file

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 64" role="img" aria-label="sirius.x">
<path d="M32 12 L35.3 30.7 L54 34 L35.3 37.3 L32 56 L28.7 37.3 L10 34 L28.7 30.7 Z"
fill="#d6ff3d"/>
<text x="72" y="42" font-family="system-ui, -apple-system, Segoe UI, Roboto, sans-serif"
font-size="28" font-weight="600" fill="#e7eaf1" letter-spacing=".5">
sirius<tspan fill="#d6ff3d">.x</tspan>
</text>
</svg>

After

Width:  |  Height:  |  Size: 434 B

9
brand/avatar.svg Normal file
View file

@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" role="img" aria-label="sirius.x avatar">
<!-- Square profile-picture avatar. Full-bleed dark background, single star
centered and enlarged so it reads at 24px in a social feed. Corners are
square (not rounded) so the platform can apply its own mask (Twitter,
Discord, Nostr, etc. all round-mask avatars themselves). -->
<rect width="512" height="512" fill="#0b0e14"/>
<path d="M256 40 L288.4 220 L468 256 L288.4 292 L256 472 L223.6 292 L44 256 L223.6 220 Z"
fill="#d6ff3d"/>
</svg>

After

Width:  |  Height:  |  Size: 579 B

34
brand/banner.svg Normal file
View file

@ -0,0 +1,34 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 630" role="img" aria-label="sirius.x banner">
<!-- 1200x630 = the OpenGraph / Twitter Card canonical size. Left half is the
wordmark + tagline; right half is a large decorative star that survives
aggressive cropping (Facebook, Slack and Discord all crop differently). -->
<defs>
<radialGradient id="glow" cx="70%" cy="50%" r="55%">
<stop offset="0%" stop-color="#16202e"/>
<stop offset="100%" stop-color="#0b0e14"/>
</radialGradient>
</defs>
<rect width="1200" height="630" fill="url(#glow)"/>
<!-- decorative giant star, right side -->
<g opacity="0.95">
<path d="M900 90 L950 300 L1160 315 L950 330 L900 540 L850 330 L640 315 L850 300 Z"
fill="#d6ff3d"/>
</g>
<!-- wordmark, left column -->
<g transform="translate(80, 250)">
<text font-family="system-ui, -apple-system, Segoe UI, Roboto, sans-serif"
font-size="110" font-weight="700" fill="#e7eaf1" letter-spacing="-1">
sirius<tspan fill="#d6ff3d">.x</tspan>
</text>
<text y="70" font-family="system-ui, -apple-system, Segoe UI, Roboto, sans-serif"
font-size="30" font-weight="400" fill="#8b98a9">
The home for names on Bitcoin Cash.
</text>
<text y="115" font-family="system-ui, -apple-system, Segoe UI, Roboto, sans-serif"
font-size="18" font-weight="500" fill="#5e6678" letter-spacing="1.5">
REGISTER · RESOLVE · VERIFY
</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

5
brand/favicon.svg Normal file
View file

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<rect width="64" height="64" rx="12" fill="#0b0e14"/>
<path d="M32 4 L36.4 27.6 L60 32 L36.4 36.4 L32 60 L27.6 36.4 L4 32 L27.6 27.6 Z"
fill="#d6ff3d"/>
</svg>

After

Width:  |  Height:  |  Size: 233 B

225
brand/index.html Normal file
View file

@ -0,0 +1,225 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Brand — sirius.x</title>
<meta name="description" content="sirius.x brand kit — logo, wordmark, avatar, banner, favicon, colour palette, and usage guidance. All assets served as SVG so they stay crisp at any size.">
<link rel="icon" href="./favicon.svg" type="image/svg+xml">
<link rel="mask-icon" href="./favicon.svg" color="#d6ff3d">
<meta property="og:type" content="website">
<meta property="og:site_name" content="sirius.x">
<meta property="og:title" content="sirius.x brand kit">
<meta property="og:description" content="Logo, wordmark, avatar, banner, favicon, colour palette. All SVG, downloadable, MIT.">
<meta property="og:url" content="https://silentmode.st/sirius-x/brand/">
<meta property="og:image" content="https://silentmode.st/sirius-x/brand/banner.svg">
<meta name="twitter:card" content="summary_large_image">
<style>
:root{
--bg:#0b0e14; --panel:#141a24; --panel2:#18202c; --line:rgba(255,255,255,.09);
--ink:#e7eaf1; --mut:#8b98a9; --dim:#5e6678; --acid:#d6ff3d;
}
*{box-sizing:border-box}
body{margin:0;background:radial-gradient(1100px 560px at 50% -12%,#16202e,var(--bg));
color:var(--ink);font:16px/1.65 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;min-height:100vh}
a{color:var(--acid)}
.wrap{max-width:1040px;margin:0 auto;padding:0 1.2rem}
.topnav{position:sticky;top:0;z-index:20;display:flex;gap:2px;align-items:center;flex-wrap:wrap;
padding:10px 1.2rem;background:rgba(11,14,20,.82);backdrop-filter:blur(10px);border-bottom:1px solid var(--line)}
.topnav .brand{font-weight:600;color:var(--ink);text-decoration:none;margin-right:14px;font-size:15px;letter-spacing:.2px}
.topnav .brand .g{color:var(--acid)}
.topnav a{color:var(--mut);text-decoration:none;padding:6px 12px;border-radius:8px;font-size:14px}
.topnav a:hover{color:var(--ink);background:var(--panel)}
.topnav a.here{color:var(--acid);background:rgba(214,255,61,.08)}
.topnav a.portal{margin-left:auto;background:rgba(214,255,61,.10);color:var(--acid);font-weight:500}
.topnav a.portal:hover{background:rgba(214,255,61,.18)}
header.hero{text-align:center;padding:3.5rem 1.2rem 1rem}
.mark{font-size:44px;line-height:1}
h1{font-size:clamp(1.7rem,4.6vw,2.3rem);margin:.3rem 0 .3rem}
h1 .g{color:var(--acid)}
.tag{color:var(--mut);font-size:1.02rem;max-width:640px;margin:0 auto}
section{padding:2.2rem 0;border-top:1px solid var(--line);margin-top:2rem}
section:first-of-type{border-top:none;margin-top:1.2rem}
h2{font-size:1.35rem;margin:0 0 .35rem}
h3{font-size:1rem;margin:0 0 .3rem}
.lede{color:var(--mut);margin:0 0 1.4rem;max-width:720px}
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:14px}
.asset{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:14px 16px 16px;display:flex;flex-direction:column}
.asset .preview{background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:20px;
margin-bottom:12px;min-height:130px;display:flex;align-items:center;justify-content:center}
.asset .preview.wide{padding:0}
.asset .preview.wide img{width:100%;height:auto;display:block;border-radius:9px}
.asset .preview.avatar{padding:0}
.asset .preview.avatar img{width:104px;height:104px;display:block;border-radius:14px}
.asset .preview.favicon img{width:64px;height:64px;display:block}
.asset .preview.mono{background:#eef1f7;color:#0b0e14}
.asset h3{display:flex;align-items:center;justify-content:space-between;gap:10px}
.asset .meta{color:var(--dim);font-size:12.5px;margin:2px 0 10px;font-family:ui-monospace,monospace}
.asset .row{display:flex;gap:8px;flex-wrap:wrap;margin-top:auto}
.btn{display:inline-block;text-decoration:none;padding:6px 12px;border-radius:8px;background:transparent;
border:1px solid var(--line);color:var(--ink);font-size:12.5px;font-family:inherit;cursor:pointer}
.btn:hover{background:var(--panel2)}
.btn.acid{background:var(--acid);color:#0b0e14;border-color:var(--acid);font-weight:600}
.btn.acid:hover{filter:brightness(1.1)}
.swatches{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px;margin-top:1rem}
.sw{border:1px solid var(--line);border-radius:10px;overflow:hidden}
.sw .chip{height:70px}
.sw .info{padding:10px 12px;font-size:12.5px;font-family:ui-monospace,monospace;color:var(--mut)}
.sw .info b{color:var(--ink);display:block;font-family:inherit}
.note{background:var(--panel);border:1px solid var(--line);border-left:3px solid var(--acid);
border-radius:10px;padding:12px 15px;color:var(--mut);font-size:13.5px;margin-top:1.2rem}
.note b{color:var(--ink)}
code{background:#0e131b;border:1px solid var(--line);border-radius:6px;padding:1px 6px;font-family:ui-monospace,monospace;font-size:12.5px;word-break:break-all}
footer{border-top:1px solid var(--line);padding:2rem 0 3rem;color:var(--dim);font-size:13px;text-align:center;margin-top:2.5rem}
</style>
</head>
<body>
<nav class="topnav">
<a class="brand" href="../">⭐ <span class="g">sirius.x</span></a>
<a href="../#try">Try it</a>
<a href="../docs/">📚 Docs</a>
<a href="../theseus/">🧭 Theseus</a>
<a href="../#roadmap">Roadmap</a>
<a href="./" class="here">🎨 Brand</a>
<a href="https://silentmode.st/" rel="noopener">Silent Mode ↗</a>
<a href="../portal.html" class="portal">🔑 Sign in</a>
</nav>
<header class="hero">
<div class="mark">🎨</div>
<h1>sirius.x <span class="g">brand kit</span></h1>
<p class="tag">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.</p>
</header>
<div class="wrap">
<section>
<h2>Logo &amp; wordmark</h2>
<p class="lede">A 4-point sparkle star plus <b>sirius.x</b>, with the <code>.x</code> 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.</p>
<div class="grid">
<div class="asset">
<div class="preview"><img src="./logo.svg" alt="sirius.x logo" style="max-width:100%;height:auto"></div>
<h3>Wordmark <span class="meta">SVG · 320×64</span></h3>
<p class="lede" style="margin-bottom:.6rem">Full colour, dark backgrounds. Use this by default.</p>
<div class="row">
<a class="btn acid" href="./logo.svg" download>Download SVG</a>
<a class="btn" href="./logo.svg" target="_blank">Open</a>
</div>
</div>
<div class="asset">
<div class="preview mono" style="color:#0b0e14"><img src="./logo-mono.svg" alt="sirius.x mono" style="max-width:100%;height:auto;color:inherit"></div>
<h3>Wordmark, monochrome <span class="meta">SVG · currentColor</span></h3>
<p class="lede" style="margin-bottom:.6rem">Uses <code>currentColor</code>, inherits from the
surrounding text. Print, embossing, single-colour merch.</p>
<div class="row">
<a class="btn acid" href="./logo-mono.svg" download>Download SVG</a>
<a class="btn" href="./logo-mono.svg" target="_blank">Open</a>
</div>
</div>
</div>
</section>
<section>
<h2>Avatar &amp; favicon</h2>
<p class="lede">Square icons for social profiles, Nostr, GitHub, and browser tabs.</p>
<div class="grid">
<div class="asset">
<div class="preview avatar"><img src="./avatar.svg" alt="sirius.x avatar"></div>
<h3>Avatar <span class="meta">SVG · 512×512</span></h3>
<p class="lede" style="margin-bottom:.6rem">Square profile picture. Social platforms apply
their own round mask, so corners stay hard.</p>
<div class="row">
<a class="btn acid" href="./avatar.svg" download>Download SVG</a>
<a class="btn" href="./avatar.svg" target="_blank">Open</a>
</div>
</div>
<div class="asset">
<div class="preview favicon"><img src="./favicon.svg" alt="sirius.x favicon"></div>
<h3>Favicon <span class="meta">SVG · 64×64, 12px radius</span></h3>
<p class="lede" style="margin-bottom:.6rem">Rounded browser-tab icon. Scales down to 16×16
cleanly; used on every sirius.x page.</p>
<div class="row">
<a class="btn acid" href="./favicon.svg" download>Download SVG</a>
<a class="btn" href="./favicon.svg" target="_blank">Open</a>
</div>
</div>
</div>
</section>
<section>
<h2>Social banner</h2>
<p class="lede">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.</p>
<div class="asset">
<div class="preview wide"><img src="./banner.svg" alt="sirius.x banner"></div>
<div class="row">
<a class="btn acid" href="./banner.svg" download>Download SVG</a>
<a class="btn" href="./banner.svg" target="_blank">Open</a>
</div>
</div>
</section>
<section>
<h2>Colour palette</h2>
<p class="lede">Silent Mode family colours. Dark chromes are the default; acid green is the
single accent that consistently signals "this is sirius.x".</p>
<div class="swatches">
<div class="sw"><div class="chip" style="background:#d6ff3d"></div><div class="info"><b>Acid</b>#d6ff3d — accent, links, active nav</div></div>
<div class="sw"><div class="chip" style="background:#0b0e14"></div><div class="info"><b>Background</b>#0b0e14 — page canvas</div></div>
<div class="sw"><div class="chip" style="background:#141a24"></div><div class="info"><b>Panel</b>#141a24 — cards, elevated surfaces</div></div>
<div class="sw"><div class="chip" style="background:#18202c"></div><div class="info"><b>Panel 2</b>#18202c — nested / step items</div></div>
<div class="sw"><div class="chip" style="background:#e7eaf1"></div><div class="info"><b>Ink</b>#e7eaf1 — body text on dark</div></div>
<div class="sw"><div class="chip" style="background:#8b98a9"></div><div class="info"><b>Muted</b>#8b98a9 — secondary text</div></div>
<div class="sw"><div class="chip" style="background:#5e6678"></div><div class="info"><b>Dim</b>#5e6678 — tertiary text, dividers</div></div>
<div class="sw"><div class="chip" style="background:#4fd1a5"></div><div class="info"><b>OK</b>#4fd1a5 — success / available</div></div>
<div class="sw"><div class="chip" style="background:#f6768a"></div><div class="info"><b>Taken</b>#f6768a — errors / unavailable</div></div>
<div class="sw"><div class="chip" style="background:#ffc75f"></div><div class="info"><b>Warn</b>#ffc75f — caution, holds</div></div>
</div>
</section>
<section>
<h2>Typography</h2>
<p class="lede">System font stack, so nothing needs to load and every OS renders the wordmark in
the same family the reader is used to.</p>
<div class="asset" style="max-width:640px">
<p style="margin:0;font-family:system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
font-size:36px;font-weight:600;letter-spacing:-.5px">The quick brown fox</p>
<p style="margin:.4rem 0 0;color:var(--mut);font-family:system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
font-size:16px">jumps over the lazy dog · 0123456789 · sirius.x</p>
<div class="meta" style="margin-top:12px">system-ui, -apple-system, Segoe UI, Roboto, sans-serif</div>
</div>
<div class="note">The wordmark's <code>.x</code> is a <code>&lt;tspan fill="#d6ff3d"&gt;</code> —
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).</div>
</section>
<section>
<h2>Usage &amp; licence</h2>
<p class="lede">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.</p>
<ul style="color:var(--mut);font-size:14px;padding-left:1.2rem">
<li><b style="color:var(--ink)">Do</b> use the mark to indicate "supports sirius.x" or "hosted on sirius.x".</li>
<li><b style="color:var(--ink)">Do</b> shrink to the favicon at 16×16 — the SVG scales cleanly.</li>
<li><b style="color:var(--ink)">Don't</b> imply endorsement of a specific product without asking.</li>
<li><b style="color:var(--ink)">Don't</b> stretch, skew, or re-tint the star.</li>
</ul>
</section>
</div>
<footer>
Brand kit for sirius.x ·
<a href="../">back to sirius.x</a> ·
<a href="https://silentmode.st/">silentmode.st</a>
</footer>
</body>
</html>

10
brand/logo-mono.svg Normal file
View file

@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 64" role="img" aria-label="sirius.x (monochrome)">
<!-- Single-fill variant for print, embossing, one-colour merch. currentColor
so the SVG inherits the surrounding text colour when inlined; pass
style="color: #d6ff3d" to force the acid green. -->
<g fill="currentColor">
<path d="M32 12 L35.3 30.7 L54 34 L35.3 37.3 L32 56 L28.7 37.3 L10 34 L28.7 30.7 Z"/>
<text x="72" y="42" font-family="system-ui, -apple-system, Segoe UI, Roboto, sans-serif"
font-size="28" font-weight="600" letter-spacing=".5">sirius.x</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 623 B

8
brand/logo.svg Normal file
View file

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 64" role="img" aria-label="sirius.x">
<path d="M32 12 L35.3 30.7 L54 34 L35.3 37.3 L32 56 L28.7 37.3 L10 34 L28.7 30.7 Z"
fill="#d6ff3d"/>
<text x="72" y="42" font-family="system-ui, -apple-system, Segoe UI, Roboto, sans-serif"
font-size="28" font-weight="600" fill="#e7eaf1" letter-spacing=".5">
sirius<tspan fill="#d6ff3d">.x</tspan>
</text>
</svg>

After

Width:  |  Height:  |  Size: 434 B

363
docs/INSTRUCTIONS.md Normal file
View file

@ -0,0 +1,363 @@
# How to do things — Silent Mode runbook
Operational companion to [`SESSION-CONTEXT.md`](SESSION-CONTEXT.md). That file is
*what the product is*; this one is *how to do a thing*. Every command below was
run on 2026-07-30 and works.
All commands run from `D:\Dev\SilentMode\Argus` unless stated. Prefix with `rtk`
per project convention. **Everything is chipnet.**
> **Before you touch a `.js` in `Argus/src/lib/`, grep for it first.** Two
> sessions have written here concurrently and `registry-lifecycle.js`,
> `portfolio.js` and `ElectrumPool` were each independently rebuilt once. If a
> test file exists for a module you are about to create, implement to the test —
> the test is the contract.
---
## 1. Read the registry
```bash
node src/resolve.js # list every name, with records and category
node src/resolve.js demo.p2p # resolve one
```
Real output today (abridged):
```
silentmode.bch -> {"s3":"bns/silentmode/"}
theseus.bch -> {"h":"<h1>Theseus</h1>…"}
coinspectrum.bch-> {"ip":"195.184.247.106","p":"https://…","tls":"84e4cd…"}
demo.p2p -> {"h":"<h1>demo.p2p</h1>…"}
syskypo.de -> {"s3":"bns/syskypo.de/"}
```
Zero-dependency alternative (the resolver clients actually ship):
```bash
node --input-type=module -e "
import WebSocket from 'ws';
import { resolveName } from './src/lib/resolver-web.js';
console.log(await resolveName('silentmode.bch', { WebSocket }));
process.exit(0);"
```
---
## 2. Register a name
```bash
node src/register.js <name> <url-or-json>
```
```bash
node src/register.js mysite https://example.org # shorthand → {"u": …}
node src/register.js mysite '{"h":"<h1>Hello</h1>"}' # explicit records
node src/register.js mysite.nav '{"s3":"bns/mysite/"}' # any TLD, same command
```
Registers from the project wallet (`wallets.json`). It mints the certificate,
publishes the records and pays the beacon in **one transaction**.
Verify:
```bash
node src/resolve.js mysite.nav
```
Records can be omitted at registration and set later — see §4.
**Buyer-facing registration** (built-in wallet, pay-by-QR) goes through
`site/register.html`, not the CLI. The CLI is for operator-held names and testing.
---
## 3. Add a new TLD
**Superseded 2026-08-29.** The old "TLDs are just a convention, no registry
change needed" model is retired. The per-TLD registry
([`Decentralized.DNS/DESIGN-tld-registry.md`](Decentralized.DNS/DESIGN-tld-registry.md))
is now the source of truth: **a name REG under a TLD that has no on-chain TLD
certificate will be rejected by conforming clients once enforcement is on** (the
code is in `buildIndex({enforceTld:true})` in both `bns.js` and
`resolver-web.js`; default is still off during the mainnet migration, but the
registrar treats the on-chain list as authoritative today).
So adding a TLD is now **three steps: TREG on the beacon, UI, deploy.**
**1. Register the TLD on the TLD beacon (chipnet).**
The idempotent way — the operator wallet holds the seed for the TLD-beacon
address and the seed script skips anything already present:
```bash
cd Argus
# Edit src/seed-tld-beacon.mjs SEED_TLDS[] — append your new TLD label
node src/seed-tld-beacon.mjs
```
Or a one-off from a Node REPL if you don't want to touch the script:
```bash
node --input-type=module -e "
import { loadWallet } from './src/lib/wallet.js';
import { registerTld } from './src/lib/bns.js';
const w = await loadWallet('main');
console.log(await registerTld(w, 'newtld', {}));
process.exit(0);"
```
Either way you get `{tld, txid, category}`. The TLD certificate is minted to
the operator wallet — that address becomes the TLD's owner and can UPD the
records with `updateTld(wallet, tld, records, category)` later.
Cost: ~1,300 chipnet sats per TREG. Empty records `{}` mean "defaults apply"
per the design doc §3.
**2. Add the TLD to the registrar UI.**
The dropdown is gone. `site/sirius/register.html` now uses a `TLDS` array
(around line 275). Append your new TLD with `onchain: true`:
```js
const TLDS = [
...,
{ tld: "newtld", onchain: true },
];
```
If you registered the cert but want to *hold* the TLD without offering it in
the registrar (the `.com` pattern — cert on-chain so nobody else claims it, but
no second-level names offered), just leave it out of the `TLDS` array. The
cert stays valid on the beacon.
**3. Deploy `site/sirius/register.html` to the VPS.**
silentmode.st is nginx-served from `/opt/silent-mode/site/`, NOT Sia
(see [`DEPLOY-split-st-from-bch.md`](DEPLOY-split-st-from-bch.md)):
```bash
scp D:/Dev/SilentMode/site/sirius/register.html silentmode:/opt/silent-mode/site/sirius/register.html
```
(silentmode.bch — the Sia mirror — takes a full `sia-upload.js` of `site/`.
Only touch that if you also want the on-chain-hosted copy refreshed.)
**4. Republish the TLD snapshot (optional, updates mirrors).**
If a downstream is reading from the Sia mirror or the Nostr replaceable event
rather than doing its own chain scan, refresh the snapshot:
```bash
cd Argus
node src/publish-tld-mirror.mjs
```
Uploads `bns/tld-list.json` (floating) and `bns/tld-list-<root>.json`
(immutable content-addressed) to Sia, and publishes NIP-33 kind 30078 (d-tag
`bns-tld-list`) to the configured relays. Dry-run: `BNS_MIRROR_DRY_RUN=1`.
### The thing to think about before adding one
Under the per-TLD registry the operator's key is the countersignature gate —
so **you're the registrar** for any TLD you mint. On mainnet the covenant will
enforce a price floor and an operator-countersig for public mints
([`Decentralized.DNS/DESIGN-tld-registry.md`](Decentralized.DNS/DESIGN-tld-registry.md) §5).
On chipnet nothing enforces this; a rogue script could TREG anything under a
different key. Only the operator's key produces TLD certs that clients trust
once the enforcement rules ship.
`.bch` is special in one way only: its on-chain commitment is the **bare label**
(`silentmode`, not `silentmode.bch`) for backward compatibility. Every other TLD
stores the full `label.tld`. `normalizeName` handles this; don't hand-roll it.
### Current chipnet TLD set (2026-08-29)
Bench-checkable via `node src/seed-tld-beacon.mjs` (idempotent verify) or by
fetching the mirror at `https://s3.silentmode.st:8600/bns/tld-list.json` (403
to anon today; the Nostr replaceable event `kind:30078` `d:bns-tld-list` from
pubkey `f2c925194c531c7c398017e35b2396df64a61a613aa5fadebdf1f4990f2267f4` on
`wss://nos.lol` / `wss://relay.damus.io` is publicly readable).
Live: `bch p2p bit nav test x asm neo gt sc sia com dex cex nt` (15 total).
`.com` is **held** by the operator — cert on-chain, excluded from the public
registrar UI so nobody else can claim it.
---
## 4. Set or change records
```bash
node src/update.js <name> <url-or-json>
```
```bash
node src/update.js mysite '{"ip":"203.0.113.9"}'
node src/update.js mysite.nav '{"s3":"bns/mysite/","tls":"a1b2c3…"}'
```
Proves ownership by moving the certificate — only the holder can do it.
### Record types
| Key | Meaning | Example |
|---|---|---|
| `h` | inline HTML, stored on-chain | `{"h":"<h1>Hi</h1>"}` |
| `u` | redirect to a URL | `{"u":"https://example.org"}` |
| `ip` | IPv4 of your server | `{"ip":"203.0.113.9"}` |
| `p` | reverse-proxy upstream (address bar stays on the name) | `{"p":"https://backend.example"}` |
| `s3` | Sia object or prefix | `{"s3":"bns/mysite/"}` |
| `tls` | SHA-256 fingerprint of the name's TLS cert (hex, over DER) | `{"tls":"84e4cd…"}` |
### The 200-byte ceiling
The whole payload — `"BNS1"` + the JSON — must be **≤ 200 bytes**. For
`sirius.nav` that leaves about 161 bytes for records. An oversized payload throws
at build time rather than producing a broken registration.
Check before you commit to a long `h`:
```bash
node --input-type=module -e "
import { payloadBudget } from './src/lib/register-tx.js';
console.log('bytes free for records:', payloadBudget('sirius.nav'));
process.exit(0);"
```
`h` is for a page, a profile, a link hub. Anything real goes on Sia or a server.
---
## 5. Put a site on Sia storage
Two steps: upload the bytes, then point the name at them.
```bash
# from D:\Dev\SilentMode
node Argus/src/lib/sia-upload.js <file-or-dir> <bucket[/prefix]>
```
```bash
node Argus/src/lib/sia-upload.js D:/Dev/SilentMode/site/mysite bns/mysite
node Argus/src/lib/sia-upload.js ./page.html bns/mysite
```
Then the record — a **trailing slash means "site root"**, no slash means a single
object:
```bash
cd Argus
node src/update.js mysite '{"s3":"bns/mysite/"}' # directory → site
node src/update.js mysite '{"s3":"bns/page.html"}' # one file
```
Verify through the public gateway:
```bash
curl -s -o /dev/null -w "%{http_code}\n" https://navigate.st/bns/mysite.bch/
```
Upload the **whole directory** if the page has assets — `sia-upload.js` walks it
and preserves relative paths, which is what makes `/js/…` and `/vendor/…` resolve.
**`sia-s3.json` is a secret** (SECURITY.md rule 0). Never print it, commit it, or
copy its values into a bundle. The build refuses to emit a bundle containing them.
---
## 6. Build and deploy the site
```bash
cd Argus && node build-web.mjs # bundles
cd .. && node Argus/src/lib/sia-upload.js D:/Dev/SilentMode/site bns/silentmode
```
Two rules that will bite otherwise:
- **Run the upload from the repo root**, not from `site/`. The path is relative
to cwd and `site/Argus/...` does not exist.
- **Upload the whole `site/` directory.** `register.html` depends on `site/js/`
and `site/vendor/`; a page-only upload leaves a broken live page.
`build-web.mjs` refuses to write a bundle that contains a live secret **value**
(it reads `wallets.json`/`sia-s3.json` and greps for their contents) or a
build-machine path. Do not weaken those checks.
libauth is **one shared module behind an import map** (`site/js/libauth.js`).
Do not bundle it per-file: its WASM init uses top-level await, and a second copy
hands out `undefined` for `secp256k1` on cold load. The build verifies every
import the other bundles emit is satisfied.
Verify what is actually live:
```bash
curl -s https://navigate.st/bns/silentmode.bch/register.html | grep -c 'bns-register.js'
```
---
## 7. Tests
```bash
cd Argus
node --test test/*.test.mjs # offline; no network, no coins
```
Live scripts spend real chipnet coins and are run deliberately:
```bash
node test/chipnet-acceptance.mjs # built-in wallet, full registration
node test/chipnet-paybyqr.mjs # registrar mints to a buyer
node test/chipnet-escrow-refund.mjs # unsigned order → refund, name never minted
```
They **exit 2** when the chain is unreachable, so an environment failure is
distinguishable from a product failure. Add `--keep` to the acceptance test to
print the throwaway wallet's phrase.
---
## 8. Gotchas that have actually cost time
**Node cannot resolve some hostnames on the dev machine.** `getaddrinfo` returns
`EAI_FAIL` for `coinspectrum.duckdns.org` and the chipnet electrum hosts while
`nslookup` and c-ares resolve them fine. Symptom: uploads and live tests fail
instantly with a DNS error. Workaround is a `--require` shim that falls back to
`dns.resolve4`; the real fix is on the machine. **If a network command fails
instantly, suspect this before suspecting the code.**
**Electrum uses ports 50004/62002**, which corporate networks and some VPNs block
outright — and every configured server shares those ports, so one firewall rule
takes the whole resolver down. `REGISTRAR.selfHosted` puts your own Fulcrum on
443 first; see `Argus/OPERATIONS-electrum.md`.
**Two resolvers must stay in lockstep.** `resolver-web.js` (zero-dep, shipped in
clients) and `bns.js` (mainnet-js). Change one, change both. A disagreement is a
consensus split between clients.
**Terminology is enforced.** It is a **certificate / registration record /
title** — never an "NFT" in code, comments or UI. `NFTCapability` and `.nft` are
mainnet-js API names and stay.
**The certificate lives in a 1,000-sat UTXO.** A wallet that does not understand
CashTokens sees dust; a "sweep all funds" would destroy the name. This is why
destinations are normalised to the token-aware `z…` form.
**`h` records are HTML you are publishing permanently.** There is no edit — only
an update transaction, and the old payload stays on-chain forever.
**Never register a name you cannot spell twice.** Registration is irreversible and
there is no expiry on chipnet today, so a typo is a permanently burned name.
---
## 9. What not to do
- Do not touch `D:\Dev\NameCoin` — separate live system.
- Do not flip anything to mainnet. It is a deliberate switch (new electrum
servers, `bitcoincash:` prefix, a new beacon, real money), not a config change.
- Do not commit or print `wallets.json`, `sia-s3.json`, `ca/root-ca.key`, or any
seed phrase.
- Do not put the operator's name or email in any file (SECURITY.md rule 3).
- Do not add a TLD to the dropdown without registering a test name on it first.
- Do not weaken the build's secret scan or the LGPL licence checks.

367
docs/index.html Normal file
View file

@ -0,0 +1,367 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Docs — sirius.x</title>
<meta name="description" content="How BCNR works: the TLD registry, name registration, records, resolver, and how to verify anything against the Bitcoin Cash chain.">
<link rel="icon" href="../assets/favicon.svg" type="image/svg+xml">
<link rel="mask-icon" href="../assets/favicon.svg" color="#d6ff3d">
<meta property="og:type" content="website">
<meta property="og:site_name" content="sirius.x">
<meta property="og:title" content="sirius.x docs — how BCNR works">
<meta property="og:description" content="The TLD registry, name registration, records, resolver, mainnet pricing, and how to verify anything against the chain.">
<meta property="og:url" content="https://silentmode.st/sirius-x/docs/">
<meta property="og:image" content="https://silentmode.st/sirius-x/brand/banner.svg">
<meta name="twitter:card" content="summary">
<style>
:root{
--bg:#0b0e14; --panel:#141a24; --panel2:#18202c; --line:rgba(255,255,255,.09);
--ink:#e7eaf1; --mut:#8b98a9; --dim:#5e6678; --acid:#d6ff3d;
--ok:#4fd1a5; --warn:#ffc75f;
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{margin:0;background:radial-gradient(1100px 560px at 50% -12%,#16202e,var(--bg));
color:var(--ink);font:16px/1.65 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;min-height:100vh}
a{color:var(--acid)}
.wrap{max-width:900px;margin:0 auto;padding:0 1.2rem}
.topnav{position:sticky;top:0;z-index:20;display:flex;gap:2px;align-items:center;flex-wrap:wrap;
padding:10px 1.2rem;background:rgba(11,14,20,.82);backdrop-filter:blur(10px);border-bottom:1px solid var(--line)}
.topnav .brand{font-weight:600;color:var(--ink);text-decoration:none;margin-right:14px;font-size:15px;letter-spacing:.2px}
.topnav .brand .g{color:var(--acid)}
.topnav a{color:var(--mut);text-decoration:none;padding:6px 12px;border-radius:8px;font-size:14px}
.topnav a:hover{color:var(--ink);background:var(--panel)}
.topnav a.here{color:var(--acid);background:rgba(214,255,61,.08)}
.topnav a.portal{margin-left:auto;background:rgba(214,255,61,.10);color:var(--acid);font-weight:500}
.topnav a.portal:hover{background:rgba(214,255,61,.18)}
header.hero{text-align:center;padding:4rem 1.2rem 1rem}
.mark{font-size:52px;line-height:1}
h1{font-size:clamp(1.8rem,4.8vw,2.5rem);margin:.4rem 0 .3rem}
h1 .g{color:var(--acid)}
.tag{color:var(--mut);font-size:1.05rem;max-width:660px;margin:0 auto}
/* Layout: TOC on the left on wide screens, content on the right. */
.doc-grid{display:grid;grid-template-columns:220px 1fr;gap:32px;margin-top:1.5rem}
@media (max-width:820px){ .doc-grid{grid-template-columns:1fr} }
.toc{position:sticky;top:60px;align-self:start;background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:14px 16px;font-size:14px}
.toc h4{margin:0 0 8px;color:var(--mut);font-size:12px;text-transform:uppercase;letter-spacing:.6px;font-weight:600}
.toc a{display:block;padding:5px 8px;border-radius:6px;color:var(--mut);text-decoration:none;font-size:13.5px}
.toc a:hover{background:var(--panel2);color:var(--ink)}
section{padding:1.6rem 0 2.4rem;border-top:1px solid var(--line);margin-top:1rem}
section:first-of-type{border-top:none;margin-top:0}
h2{font-size:1.35rem;margin:0 0 .5rem}
h3{font-size:1.05rem;margin:1.4rem 0 .35rem}
.lede{color:var(--mut);margin:0 0 1rem;max-width:720px}
ol.steps{counter-reset:s;list-style:none;padding:0;margin:1.2rem 0 0;display:grid;gap:10px}
ol.steps li{counter-increment:s;display:grid;grid-template-columns:30px 1fr;gap:14px;align-items:start;
background:var(--panel2);border:1px solid var(--line);border-radius:12px;padding:13px 16px}
ol.steps li::before{content:counter(s);grid-column:1;grid-row:1;
display:grid;place-items:center;width:24px;height:24px;border-radius:50%;
background:rgba(214,255,61,.14);color:var(--acid);font-size:12.5px;font-weight:700}
ol.steps li > *{grid-column:2;min-width:0}
ol.steps b{color:var(--ink)} ol.steps span{color:var(--mut);font-size:14px}
.note{background:var(--panel);border:1px solid var(--line);border-left:3px solid var(--acid);
border-radius:10px;padding:14px 18px;color:var(--mut);font-size:14px;margin-top:1.2rem}
.note.warn{border-left-color:var(--warn)}
.note b{color:var(--ink)}
code,.mono{background:#0e131b;border:1px solid var(--line);border-radius:6px;padding:1px 6px;font-family:ui-monospace,monospace;font-size:13px;word-break:break-all}
pre{background:#0e131b;border:1px solid var(--line);border-radius:10px;padding:12px 14px;overflow-x:auto;
font-family:ui-monospace,monospace;font-size:13px;color:var(--ink);margin:1rem 0}
table.pricing{width:100%;border-collapse:collapse;margin-top:1rem;font-size:14px}
table.pricing th,table.pricing td{padding:8px 12px;text-align:left;border-bottom:1px solid var(--line)}
table.pricing th{color:var(--mut);font-weight:500;font-size:12.5px;text-transform:uppercase;letter-spacing:.4px}
table.pricing td.price{font-family:ui-monospace,monospace;color:var(--acid);font-weight:600}
.verify dt{color:var(--mut);font-size:12.5px;text-transform:uppercase;letter-spacing:.3px;margin-top:10px}
.verify dt:first-of-type{margin-top:0}
.verify dd{margin:2px 0 0;font-family:ui-monospace,monospace;font-size:12.5px;word-break:break-all;color:var(--ink)}
footer{border-top:1px solid var(--line);padding:2rem 0 3rem;color:var(--dim);font-size:13px;text-align:center;margin-top:2.5rem}
</style>
</head>
<body>
<nav class="topnav">
<a class="brand" href="../">⭐ <span class="g">sirius.x</span></a>
<a href="../#try">Try it</a>
<a href="./" class="here">📚 Docs</a>
<a href="../theseus/">🧭 Theseus</a>
<a href="../#roadmap">Roadmap</a>
<a href="../brand/">🎨 Brand</a>
<a href="https://silentmode.st/" rel="noopener">Silent Mode ↗</a>
<a href="../portal.html" class="portal">🔑 Sign in</a>
</nav>
<header class="hero">
<div class="mark">📚</div>
<h1>sirius.x <span class="g">docs</span></h1>
<p class="tag">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.</p>
</header>
<div class="wrap">
<div class="doc-grid">
<aside class="toc">
<h4>Contents</h4>
<a href="#tld-registry">TLD registry</a>
<a href="#register-name">Register a name</a>
<a href="#records">Records &amp; hosting</a>
<a href="#host">Host your name</a>
<a href="#resolver">Resolver / gateway</a>
<a href="#pricing">Pricing (mainnet)</a>
<a href="#tracker">Tracker &amp; mirrors</a>
<a href="#verify">Verify anything</a>
<a href="#runbook">Operator runbook</a>
</aside>
<div>
<section id="tld-registry">
<h2>The TLD registry</h2>
<p class="lede">Every BCNR name lives under a <b>top-level domain</b> 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.</p>
<p class="lede">Fourteen public TLDs on chipnet today (2026-08-29):
<code>bch p2p bit nav test x asm neo gt sc sia dex cex nt</code>. The current list and
per-TLD categories are at
<a href="https://silentmode.st/tlds/">silentmode.st/tlds/</a>.</p>
<div class="note"><b>Why per-TLD certs, not a single list.</b> 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.</div>
</section>
<section id="register-name">
<h2>Register a name — end to end</h2>
<p class="lede">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.</p>
<ol class="steps">
<li><b>Search a label across every TLD.</b>
<span>The registrar fans out to every TLD in the registry in parallel and shows
available / taken per row. Available names appear first.</span></li>
<li><b>Create or connect a wallet.</b>
<span>Built-in browser wallet (PBKDF2 → AES-GCM in localStorage) or WizardConnect to
Cashonize / Paytaca — both mint to the buyer's own key.</span></li>
<li><b>Confirm the price.</b>
<span>Miner fee + beacon dust + certificate dust + service fee. Chipnet placeholder
is 10,000 sat; real pricing is a mainnet decision.</span></li>
<li><b>The certificate lands in your wallet.</b>
<span>The name resolves the moment the transaction confirms. Records can be set or
changed later — only your key can sign a UPD.</span></li>
</ol>
</section>
<section id="records">
<h2>Records &amp; hosting</h2>
<p class="lede">A registered name carries a small JSON records object. Every record is
optional and multiple can coexist. Priority order the gateway uses:
<code>h</code> (inline HTML) → <code>s3</code> (Sia bucket key) → <code>ip</code>
(host header served by an IP) → <code>u</code> (redirect).</p>
<table class="pricing">
<thead><tr><th>Record</th><th>Meaning</th><th>Typical use</th></tr></thead>
<tbody>
<tr><td><code>h</code></td><td>Inline HTML in the OP_RETURN payload itself</td><td>Tiny sites, a profile, a link hub</td></tr>
<tr><td><code>s3</code></td><td>A Sia bucket key (with auto-index for directory-style)</td><td>Multi-file sites, permanent hosting</td></tr>
<tr><td><code>ip</code></td><td>An IPv4 address + optional <code>tls</code> fingerprint</td><td>Your own server, apps behind an IP</td></tr>
<tr><td><code>u</code></td><td>Redirect URL</td><td>Short-form redirects to any web host</td></tr>
<tr><td><code>tls</code></td><td>SHA-256 fingerprint of the leaf cert served at <code>ip</code></td><td>Chain-pinned TLS trust, no OS root store needed</td></tr>
<tr><td><code>np</code>, <code>nr</code></td><td>Nostr pubkey + relay list</td><td>Hermes / NIP-17 messaging bound to the name</td></tr>
<tr><td><code>el</code></td><td>Space-separated electrum server list</td><td>On-chain-updatable resolver bootstrap</td></tr>
</tbody>
</table>
<p class="lede" style="margin-top:1rem">Subdomains inherit from their parent with a slight
priority tweak: for a subdomain query, <code>ip</code> beats <code>s3</code>
(Host-header semantics). Full rule is in <code>Argus/src/lib/record-picker.js</code>.</p>
</section>
<section id="host">
<h2>Host your name</h2>
<p class="lede">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.</p>
<h3>Pattern A — Sia only</h3>
<p class="lede">Simplest. Site lives on the Sia storage network, name's <code>s3</code> record
points at the bucket key, gateways (navigate.st, silentmode.st, any BCNR-aware browser)
fetch it on demand. Same pattern <code>silentmode.bch</code> uses.</p>
<pre># 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/"}'</pre>
<p class="lede">Bucket-path convention: <code>bns/&lt;label&gt;/</code> (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.</p>
<h3>Pattern B — Your own server (VPS + <code>ip</code>)</h3>
<p class="lede">Point the name at an IP; every request goes directly to your box. Add a
<code>tls</code> record with the SHA-256 of the leaf certificate so browsers verify the
connection against the chain instead of the OS trust store.</p>
<pre># 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":"&lt;sha256-of-leaf-cert&gt;"}'</pre>
<h3>Pattern C — Dual host (Sia primary, VPS mirror)</h3>
<p class="lede">What sirius.x itself uses. Sia is the chain-authoritative source (survives
if the VPS is down); the VPS serves the same content on <code>silentmode.st/&lt;path&gt;</code>
for users without a BCNR resolver installed. On the VPS side, extend the nginx vhost
serving <code>silentmode.st</code> with a new <code>location</code> block that aliases
straight from disk:</p>
<pre>location /myname-x/ {
alias /opt/silent-mode/site-myname-x/;
index index.html;
try_files $uri $uri/ =404;
}</pre>
<p class="lede">Then rsync / scp your site tree to <code>silentmode:/opt/silent-mode/site-myname-x/</code>
and reload nginx. This gives you two URLs for the same content:
<code>https://silentmode.st/myname-x/</code> (VPS-direct) and the chain-authoritative
<code>https://myname.x/</code> via any BCNR resolver.</p>
<h3>Verify records changed correctly</h3>
<pre>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);"</pre>
<div class="note"><b>Credentials.</b> Sia upload needs <code>Argus/sia-s3.json</code>. 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
<a href="INSTRUCTIONS.md">INSTRUCTIONS.md</a>, especially §5 (Sia storage) and §6
(deploy).</div>
</section>
<section id="resolver">
<h2>Resolver / gateway</h2>
<p class="lede">Three paths, same chain data. Anyone can pick.</p>
<ol class="steps">
<li><b>Local — Ariadne Resolver.</b>
<span>A system-wide resolver that intercepts BCNR TLDs and answers them from the
chain. Any browser you already use starts opening <code>.bch</code> URLs directly.
Installs a local root CA for TLS.
<a href="../theseus/">Download →</a></span></li>
<li><b>In-browser — Theseus Navigator.</b>
<span>A Chromium build with the resolver baked in, plus an on-chain TLS trust anchor.
No OS trust-store install; nothing modified globally.
<a href="../theseus/">Download →</a></span></li>
<li><b>Public gateway — navigate.st.</b>
<span>For anyone without the resolver installed:
<code>https://navigate.st/bns/&lt;name&gt;/</code> proxies through a hosted resolver.
Same content, fewer guarantees — trust the gateway to fetch honestly, or run one of
the first two.</span></li>
</ol>
</section>
<section id="pricing">
<h2>Pricing (mainnet)</h2>
<p class="lede">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 <b>one-time</b> — a TLD is closer to a domain purchase
than a lease.</p>
<table class="pricing">
<thead><tr><th>Label length</th><th>Floor (USD)</th><th>Notes</th></tr></thead>
<tbody>
<tr><td>1 char</td><td class="price">100,000</td><td>Effectively unique; ENS-like scarcity</td></tr>
<tr><td>2 char</td><td class="price">50,000</td><td>The <code>.ai</code> / <code>.io</code> tier</td></tr>
<tr><td>3 char</td><td class="price">15,000</td><td>Order of magnitude below ICANN's $185k application floor</td></tr>
<tr><td>4 char</td><td class="price">5,000</td><td>Floor for short but reasonable TLDs</td></tr>
<tr><td>5–8 char</td><td class="price">1,000</td><td>Bulk-registerable but not spam</td></tr>
<tr><td>9+ char</td><td class="price">250</td><td>Descriptive TLDs, low economic gravity</td></tr>
</tbody>
</table>
<p class="lede" style="margin-top:1rem">On <b>name registration under a TLD</b>, the TLD's
owner collects a share (<code>fee_bps</code>, default 5%, cap 50%). Chain-enforced when
the TLD's policy is <code>covenant</code>; honour-system otherwise. Name registration is
yearly and priced separately.</p>
</section>
<section id="tracker">
<h2>Tracker &amp; mirrors</h2>
<p class="lede">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 <b>root</b> hash anyone can recompute
locally — a lying mirror is caught by any recipient who bothers to check.</p>
<p class="lede">A conforming client falls through: (1) fetch snapshot from a mirror,
(2) verify <code>root</code>, (3) if suspicious, walk the beacon and rebuild. All three
yield the same list for any given block height.</p>
</section>
<section id="verify">
<h2>Verify anything</h2>
<p class="lede">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.</p>
<h3>Confirm a specific name on chain</h3>
<pre>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);"</pre>
<h3>Fetch the operator-signed TLD snapshot from Nostr</h3>
<dl class="verify">
<dt>Kind / d-tag</dt>
<dd>30078 / bns-tld-list</dd>
<dt>Pubkey (x-only, hex)</dt>
<dd>f2c925194c531c7c398017e35b2396df64a61a613aa5fadebdf1f4990f2267f4</dd>
<dt>Relays</dt>
<dd>wss://nos.lol · wss://relay.damus.io</dd>
</dl>
<h3>Reach any site via more than one route</h3>
<p class="lede">Same content should be served from at least two independent paths:</p>
<ul style="color:var(--mut);font-size:14px;margin:.6rem 0 0;padding-left:1.2rem">
<li>Direct BCNR: <code>https://&lt;name&gt;/</code> (requires local resolver + CA)</li>
<li>Public gateway: <code>https://navigate.st/bns/&lt;name&gt;/</code></li>
<li>silentmode.st mirror: <code>https://silentmode.st/bns/&lt;name&gt;/</code></li>
<li>Direct from Sia (content-addressed) via the name's <code>s3</code> record</li>
</ul>
</section>
<section id="runbook">
<h2>Operator runbook</h2>
<p class="lede">These docs describe <i>what</i>. The <i>how</i> — exact bash commands to
register TLDs, mint names, update records, and deploy — is
<code>INSTRUCTIONS.md</code>. Three ways to read it, in order of "how much do I already
have installed":</p>
<ol class="steps">
<li><b>Just read it in the browser</b>
<span>Served straight from the docs directory:
<a href="INSTRUCTIONS.md">/sirius-x/docs/INSTRUCTIONS.md</a>. Plain text; every
browser renders it.</span></li>
<li><b>Clone the git remote</b>
<span><code>git clone https://silentmode.st/sirius-x/repo/silent-mode.git</code> — dumb-HTTP,
no auth. Get the whole tree, browse offline, run the scripts.</span></li>
<li><b>Browse the Forgejo mirror</b>
<span>Repo lives at
<a href="https://code.silentmode.st/silentmode/sirius">code.silentmode.st/silentmode/sirius</a>
on the Silent Mode Hephaestus forge. Rendered runbook:
<a href="https://code.silentmode.st/silentmode/sirius/src/branch/master/docs/INSTRUCTIONS.md">docs/INSTRUCTIONS.md</a>.
Clone: <code>git clone https://code.silentmode.st/silentmode/sirius.git</code> — public,
no auth.</span></li>
</ol>
<p class="lede">The runbook covers CLI name registration, TLD-registry seeding, record
updates, Sia upload, VPS deploy, tests, and the historically-costly gotchas.</p>
</section>
</div>
</div>
</div>
<footer>
Documentation for BCNR + the sirius.x stack ·
<a href="../">back to sirius.x</a> ·
<a href="https://silentmode.st/tlds/">TLD registry snapshot</a> ·
<a href="https://silentmode.st/sirius/register.html">register a name</a>
</footer>
</body>
</html>

260
index.html Normal file
View file

@ -0,0 +1,260 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>sirius.x — the home for names on Bitcoin Cash</title>
<meta name="description" content="sirius.x is the operator-run entry point for BCNR: register a top-level domain, register a name under one, look up records, verify anything against the chain. Backed by Sia storage, mirrored on the operator's VPS, name published on the chain.">
<!-- sirius.x branding: SVG favicon at 16/32/any size (the star + dark rounded
square scales cleanly); OpenGraph + Twitter Card so shared links preview
with the right title, description, and mark. -->
<link rel="icon" href="./assets/favicon.svg" type="image/svg+xml">
<link rel="mask-icon" href="./assets/favicon.svg" color="#d6ff3d">
<meta property="og:type" content="website">
<meta property="og:site_name" content="sirius.x">
<meta property="og:title" content="sirius.x — the home for names on Bitcoin Cash">
<meta property="og:description" content="Register a top-level domain, register a name under one, look up records, verify anything against the chain. Backed by Sia + VPS + on-chain.">
<meta property="og:url" content="https://silentmode.st/sirius-x/">
<meta property="og:image" content="https://silentmode.st/sirius-x/brand/banner.svg">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="sirius.x — the home for names on Bitcoin Cash">
<meta name="twitter:description" content="Register a TLD or a name, look up records, verify against the chain. Your keys, your names.">
<style>
:root{
--bg:#0b0e14; --panel:#141a24; --panel2:#18202c; --line:rgba(255,255,255,.09);
--ink:#e7eaf1; --mut:#8b98a9; --dim:#5e6678; --acid:#d6ff3d;
--chain:#d6ff3d; --sia:#b39ddb; --srv:#4fd1a5; --ok:#4fd1a5; --taken:#f6768a;
--warn:#ffc75f;
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{margin:0;background:radial-gradient(1100px 560px at 50% -12%,#16202e,var(--bg));
color:var(--ink);font:16px/1.65 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;min-height:100vh}
a{color:var(--acid)}
.wrap{max-width:980px;margin:0 auto;padding:0 1.2rem}
.topnav{position:sticky;top:0;z-index:20;display:flex;gap:2px;align-items:center;flex-wrap:wrap;
padding:10px 1.2rem;background:rgba(11,14,20,.82);backdrop-filter:blur(10px);
border-bottom:1px solid var(--line)}
.topnav .brand{font-weight:600;color:var(--ink);text-decoration:none;margin-right:14px;font-size:15px;letter-spacing:.2px}
.topnav .brand .g{color:var(--acid)}
.topnav a{color:var(--mut);text-decoration:none;padding:6px 12px;border-radius:8px;font-size:14px}
.topnav a:hover{color:var(--ink);background:var(--panel)}
.topnav a.here{color:var(--acid);background:rgba(214,255,61,.08)}
/* Sign-in link sits on the right so it reads as an account action, not a nav item */
.topnav a.portal{margin-left:auto;background:rgba(214,255,61,.10);color:var(--acid);font-weight:500}
.topnav a.portal:hover{background:rgba(214,255,61,.18)}
header.hero{text-align:center;padding:5rem 1.2rem 1rem}
.mark{font-size:56px;line-height:1}
h1{font-size:clamp(2rem,5.5vw,2.9rem);margin:.4rem 0 .3rem}
h1 .g{color:var(--acid)}
.tag{color:var(--mut);font-size:1.05rem;max-width:660px;margin:0 auto}
.cta{margin-top:1.8rem;display:flex;gap:10px;justify-content:center;flex-wrap:wrap}
.btn{display:inline-block;text-decoration:none;padding:11px 20px;border-radius:10px;background:#4b7bec;color:#fff;font-size:14px;border:none;cursor:pointer;font-family:inherit;transition:filter .1s}
.btn.ghost{background:transparent;border:1px solid var(--line);color:var(--ink)}
.btn.acid{background:var(--acid);color:#0b0e14;font-weight:600}
.btn:hover{filter:brightness(1.12)}
section{padding:2.6rem 0;border-top:1px solid var(--line);margin-top:2.5rem}
section:first-of-type{border-top:none;margin-top:1.5rem}
h2{font-size:1.5rem;margin:0 0 .4rem}
h3{font-size:1.1rem;margin:0 0 .35rem}
.lede{color:var(--mut);margin:0 0 1.6rem;max-width:720px}
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:14px}
.card{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:18px 20px}
.card h3{margin:0 0 .5rem;display:flex;align-items:center;gap:8px}
.card p{margin:0;color:var(--mut);font-size:14px}
.card .cta{margin-top:14px;justify-content:flex-start}
.dot{width:9px;height:9px;border-radius:50%;display:inline-block}
.d-chain{background:var(--chain)} .d-sia{background:var(--sia)} .d-srv{background:var(--srv)}
.note{background:var(--panel);border:1px solid var(--line);border-left:3px solid var(--acid);
border-radius:10px;padding:14px 18px;color:var(--mut);font-size:14px;margin-top:1.4rem}
.note.warn{border-left-color:var(--warn)}
.note b{color:var(--ink)}
code,.mono{background:#0e131b;border:1px solid var(--line);border-radius:6px;padding:1px 6px;font-family:ui-monospace,monospace;font-size:13px}
pre{background:#0e131b;border:1px solid var(--line);border-radius:10px;padding:12px 14px;overflow-x:auto;
font-family:ui-monospace,monospace;font-size:13px;color:var(--ink);margin:1rem 0}
ol.steps{counter-reset:s;list-style:none;padding:0;margin:1.2rem 0 0;display:grid;gap:10px}
ol.steps li{counter-increment:s;display:grid;grid-template-columns:30px 1fr;gap:14px;align-items:start;
background:var(--panel2);border:1px solid var(--line);border-radius:12px;padding:13px 16px}
ol.steps li::before{content:counter(s);grid-column:1;grid-row:1;
display:grid;place-items:center;width:24px;height:24px;border-radius:50%;
background:rgba(214,255,61,.14);color:var(--acid);font-size:12.5px;font-weight:700}
ol.steps li > *{grid-column:2;min-width:0}
ol.steps b{color:var(--ink)} ol.steps span{color:var(--mut);font-size:14px}
.pill{display:inline-block;font-size:11px;padding:2px 8px;border-radius:999px;background:rgba(255,255,255,.07);color:var(--dim);margin-left:8px;vertical-align:middle;font-weight:500}
.pill.soon{background:rgba(214,255,61,.13);color:var(--acid)}
.verify dt{color:var(--mut);font-size:12.5px;text-transform:uppercase;letter-spacing:.3px;margin-top:12px}
.verify dt:first-of-type{margin-top:0}
.verify dd{margin:2px 0 0;font-family:ui-monospace,monospace;font-size:12.5px;word-break:break-all;color:var(--ink)}
footer{border-top:1px solid var(--line);padding:2.4rem 0 3.5rem;color:var(--dim);font-size:13px;text-align:center;margin-top:2.5rem}
</style>
</head>
<body>
<nav class="topnav">
<a class="brand" href="./">⭐ <span class="g">sirius.x</span></a>
<a href="#try">Try it</a>
<a href="./docs/">📚 Docs</a>
<a href="./theseus/">🧭 Theseus</a>
<a href="#roadmap">Roadmap</a>
<a href="./brand/">🎨 Brand</a>
<a href="https://silentmode.st/" rel="noopener">Silent Mode ↗</a>
<a href="./portal.html" class="portal">🔑 Sign in</a>
</nav>
<header class="hero">
<div class="mark">⭐</div>
<h1>Names on the <span class="g">chain</span>.</h1>
<p class="tag">sirius.x is the entry point for BCNR — Bitcoin Cash Name Registry.
Register a top-level domain, register a name under one, look up records,
verify anything against the chain. Backed by Sia storage, mirrored on the
operator's VPS, name published on chain — this page survives if any single
mirror goes down.</p>
<div class="cta">
<a class="btn acid" href="#try">Get started</a>
<a class="btn ghost" href="#docs">Read the docs</a>
</div>
</header>
<div class="wrap">
<section id="try">
<h2>Try it</h2>
<p class="lede">Three things you can do right now. The registrar and TLD-registry UIs live at
silentmode.st today; sirius.x is the canonical home and will consolidate them here.</p>
<div class="grid">
<div class="card">
<h3><span class="dot d-chain"></span> Register a name</h3>
<p>Pick a label, search across every TLD in the registry at once, mint the name
certificate straight into your own wallet. A few cents in chain fees, no yearly renewal.</p>
<div class="cta"><a class="btn acid" href="https://silentmode.st/sirius/register.html">Search a name →</a></div>
</div>
<div class="card">
<h3><span class="dot d-chain"></span> Register a TLD</h3>
<p>Under the per-TLD registry, a TLD is itself a certificate on the chain. Public mints
are operator-gated today; propose one below.</p>
<div class="cta"><a class="btn ghost" href="#request-tld">Propose a TLD →</a></div>
</div>
<div class="card">
<h3><span class="dot d-sia"></span> Look up &amp; verify</h3>
<p>Resolve any BCNR name, compare records across mirrors, and check the TLD registry snapshot
against the chain. Everything is publicly verifiable.</p>
<div class="cta"><a class="btn ghost" href="#verify">How to verify →</a></div>
</div>
<div class="card">
<h3><span class="dot d-srv"></span> 🔑 Sign in — your names portal</h3>
<p>Import your seed phrase or connect a wallet (Cashonize / Paytaca via WizardConnect) to see
every name you own, review records, and update them. Your keys never leave your browser.</p>
<div class="cta"><a class="btn acid" href="./portal.html">Open the portal →</a></div>
</div>
<div class="card">
<h3><span class="dot d-chain"></span> 🧭 Theseus Navigator</h3>
<p>The browser that speaks BCNR natively. Open <code>hello.bch</code> in the address bar —
it just resolves. TLS verified against on-chain fingerprints, no OS trust-store install.</p>
<div class="cta"><a class="btn ghost" href="./theseus/">Download →</a></div>
</div>
</div>
</section>
<section id="docs">
<h2>Documentation</h2>
<p class="lede">The full docs — TLD registry model, record types, resolver &amp; gateway paths,
mainnet pricing, verification, and the operator runbook pointer — live on their own page so
they can grow without cluttering the landing.</p>
<div class="cta" style="justify-content:flex-start;margin-top:1rem">
<a class="btn acid" href="./docs/">📚 Open the docs →</a>
<a class="btn ghost" href="https://silentmode.st/tlds/">Current TLD list</a>
</div>
</section>
<section id="request-tld">
<h2>Propose a new TLD</h2>
<p class="lede">The per-TLD registry means minting a TLD is a real, paid action — not a namespace
land-grab. During the alpha, all TLD mints are operator-signed. To propose a TLD, get in touch
via the channels below. The design (mainnet) adds an on-chain covenant with countersignature +
tiered USD price floors: 1-char $100k, 2-char $50k, 3-char $15k, 4-char $5k, 5–8-char $1k,
9+-char $250; one-time payment (not annual). See the design doc for the full model.</p>
<div class="note warn"><b>ICANN-adjacent TLDs are not open for public mint.</b> A TLD registry is
only useful if it does not immediately collapse into an ICANN-shadow — the mainnet covenant
enforces this; on chipnet the operator's countersignature is the gate.</div>
</section>
<section id="roadmap">
<h2>What's coming</h2>
<p class="lede">sirius.x consolidates docs and registration today; three larger pieces are on the roadmap.</p>
<div class="grid">
<div class="card">
<h3>Wallet &amp; name portal <span class="pill soon">next</span></h3>
<p>Sign in with your BCNR wallet, see every name you own, edit records inline, mint or renew
from one place. Same self-custody as today — the portal never handles your keys.</p>
</div>
<div class="card">
<h3>Sirius Studio <span class="pill soon">planned</span></h3>
<p>An in-browser site editor for names you already own — the WordPress / Tilda / Wix pattern,
but the whole site persists to Sia and the name's <code>s3</code> record updates on save.
Sites live where the name says they live.</p>
</div>
<div class="card">
<h3>Decentralized git remote <span class="pill soon">MVP live</span></h3>
<p>The Silent Mode repo is served as a bare git tree over dumb-HTTP from
the VPS. Clone it with any git client, no login. Forgejo + Sia sync
for a proper decentralized backend is the next track.</p>
<pre style="margin-top:.8rem;font-size:12px">git clone https://silentmode.st/sirius-x/repo/silent-mode.git</pre>
<p style="margin-top:.5rem;font-size:12.5px">One-shot snapshot as a
downloadable git bundle (works when dumb-HTTP is blocked):</p>
<pre style="font-size:12px">curl -O https://silentmode.st/sirius-x/repo/silent-mode.bundle
git clone silent-mode.bundle silent-mode</pre>
</div>
</div>
</section>
<section id="verify">
<h2>Verify this page against the chain</h2>
<p class="lede">You do not have to trust that <code>sirius.x</code> is served by anyone specific.
The name's certificate is on the Bitcoin Cash chain; the records point to Sia; every path is
independently checkable.</p>
<h3>1. Confirm the certificate exists on chain</h3>
<pre>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);"</pre>
<h3>2. Fetch the TLD-registry snapshot from Nostr</h3>
<p class="lede">The operator-signed snapshot of the TLD list is published as a Nostr replaceable
event. Any relay carries it; the event's content field carries the current snapshot root.</p>
<dl class="verify">
<dt>Kind / d-tag</dt>
<dd>30078 / bns-tld-list</dd>
<dt>Pubkey (x-only, hex)</dt>
<dd>f2c925194c531c7c398017e35b2396df64a61a613aa5fadebdf1f4990f2267f4</dd>
<dt>Relays</dt>
<dd>wss://nos.lol · wss://relay.damus.io</dd>
</dl>
<h3>3. Reach this site via more than one route</h3>
<p class="lede">The same content should be served from at least two independent paths. If one
mirror is unavailable, the others still work. If two mirrors disagree, the on-chain record is
the tiebreaker.</p>
<ul style="color:var(--mut);font-size:14px;margin:.6rem 0 0;padding-left:1.2rem">
<li>Via any BCNR resolver: <code>https://sirius.x/</code> (requires the local root CA)</li>
<li>Via the public gateway: <code>https://navigate.st/bns/sirius.x</code></li>
<li>Via silentmode.st mirror: <code>https://silentmode.st/bns/sirius.x</code></li>
<li>Direct from Sia (content-addressed): the <code>s3</code> record on <code>sirius.x</code>
names the exact bucket key</li>
</ul>
</section>
</div>
<footer>
sirius.x — the Silent Mode name registry entry point ·
<a href="https://silentmode.st/">silentmode.st</a> ·
<a href="https://silentmode.st/tlds/">TLD registry</a> ·
<a href="https://silentmode.st/sirius/register.html">register a name</a><br>
Alpha on a test network (chipnet). You hold your own keys; verify everything against the chain.
</footer>
</body>
</html>

286
portal.html Normal file
View file

@ -0,0 +1,286 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Portal — your names on sirius.x</title>
<meta name="description" content="Sign in with your Bitcoin Cash seed phrase to see every BCNR name your wallet holds and manage records. Your keys never leave the browser.">
<link rel="icon" href="./assets/favicon.svg" type="image/svg+xml">
<link rel="mask-icon" href="./assets/favicon.svg" color="#d6ff3d">
<meta property="og:type" content="website">
<meta property="og:site_name" content="sirius.x">
<meta property="og:title" content="sirius.x portal — your BCNR names">
<meta property="og:description" content="Sign in with your seed phrase to see every name your wallet holds and manage records. Keys never leave the browser.">
<meta property="og:url" content="https://silentmode.st/sirius-x/portal.html">
<meta property="og:image" content="https://silentmode.st/sirius-x/brand/banner.svg">
<meta name="twitter:card" content="summary">
<style>
:root{
--bg:#0b0e14; --panel:#141a24; --panel2:#18202c; --line:rgba(255,255,255,.09);
--ink:#e7eaf1; --mut:#8b98a9; --dim:#5e6678; --acid:#d6ff3d;
--ok:#4fd1a5; --taken:#f6768a; --warn:#ffc75f;
}
*{box-sizing:border-box}
body{margin:0;background:radial-gradient(1100px 560px at 50% -12%,#16202e,var(--bg));
color:var(--ink);font:16px/1.65 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;min-height:100vh}
a{color:var(--acid)}
.wrap{max-width:820px;margin:0 auto;padding:0 1.2rem}
.topnav{position:sticky;top:0;z-index:20;display:flex;gap:2px;align-items:center;flex-wrap:wrap;
padding:10px 1.2rem;background:rgba(11,14,20,.82);backdrop-filter:blur(10px);border-bottom:1px solid var(--line)}
.topnav .brand{font-weight:600;color:var(--ink);text-decoration:none;margin-right:14px;font-size:15px;letter-spacing:.2px}
.topnav .brand .g{color:var(--acid)}
.topnav a{color:var(--mut);text-decoration:none;padding:6px 12px;border-radius:8px;font-size:14px}
.topnav a:hover{color:var(--ink);background:var(--panel)}
.topnav a.here{color:var(--acid);background:rgba(214,255,61,.08)}
.topnav a.portal{margin-left:auto;background:rgba(214,255,61,.10);color:var(--acid);font-weight:500}
.topnav a.portal:hover{background:rgba(214,255,61,.18)}
header.hero{text-align:center;padding:3rem 1.2rem 1rem}
.mark{font-size:44px;line-height:1}
h1{font-size:clamp(1.6rem,4.5vw,2.2rem);margin:.3rem 0 .3rem}
h1 .g{color:var(--acid)}
.tag{color:var(--mut);font-size:1rem;max-width:580px;margin:0 auto}
h2{font-size:1.25rem;margin:0 0 .4rem}
section{padding:2rem 0;border-top:1px solid var(--line);margin-top:2rem}
section:first-of-type{border-top:none;margin-top:1rem}
.card{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:20px 22px;margin-top:1rem}
label{display:block;font-size:13px;color:var(--mut);margin:14px 0 5px}
textarea,input[type=password],input[type=text]{
width:100%;padding:11px 13px;border-radius:10px;border:1px solid #ffffff22;background:#0e131b;
color:var(--ink);font-size:14px;font-family:inherit;outline:none
}
textarea{min-height:74px;resize:vertical;font-family:ui-monospace,monospace;font-size:13px}
textarea:focus,input:focus{border-color:#4b7bec}
.btn{display:inline-block;text-decoration:none;padding:10px 18px;border-radius:10px;background:#4b7bec;color:#fff;font-size:14px;border:none;cursor:pointer;font-family:inherit}
.btn.ghost{background:transparent;border:1px solid var(--line);color:var(--ink)}
.btn.acid{background:var(--acid);color:#0b0e14;font-weight:600}
.btn.small{padding:6px 12px;font-size:12.5px}
.btn:hover{filter:brightness(1.12)}
.btn:disabled{opacity:.45;cursor:not-allowed;filter:none}
.row{display:flex;gap:10px;flex-wrap:wrap;margin-top:16px;align-items:center}
.muted{color:var(--mut);font-size:13px}
.dim{color:var(--dim);font-size:12.5px}
code,.mono{background:#0e131b;border:1px solid var(--line);border-radius:6px;padding:1px 6px;font-family:ui-monospace,monospace;font-size:13px;word-break:break-all}
.badge{display:inline-block;font-size:11px;padding:2px 10px;border-radius:999px;font-weight:600}
.b-x{background:rgba(214,255,61,.14);color:var(--acid)}
.b-warn{background:rgba(255,199,95,.14);color:var(--warn)}
.err{color:var(--taken);font-size:13.5px;margin-top:10px}
.status{background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:10px 14px;font-size:13px;color:var(--mut);margin-top:12px}
.status.ok{border-left:3px solid var(--ok)}
.status.err{border-left:3px solid var(--taken);color:var(--taken)}
.hidden{display:none}
.authbox{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:14px}
.authbox .card{margin:0}
.authbox h3{margin:0 0 .3rem;font-size:1rem}
.authbox p{margin:0;color:var(--mut);font-size:13px}
.authbox .card > .cta{margin-top:14px}
.name-row{display:grid;grid-template-columns:1fr auto auto;gap:12px;align-items:center;
padding:14px 16px;background:var(--panel2);border:1px solid var(--line);border-radius:12px;margin-top:8px}
.name-row .n{font-family:ui-monospace,monospace;font-size:15px}
.name-row .rec{color:var(--mut);font-family:ui-monospace,monospace;font-size:12px;grid-column:1/-1;margin-top:6px;word-break:break-all}
.name-row .rec .k{color:var(--dim)}
footer{border-top:1px solid var(--line);padding:2rem 0 3rem;color:var(--dim);font-size:13px;text-align:center;margin-top:2.5rem}
@media (max-width:520px){
.name-row{grid-template-columns:1fr auto}
}
</style>
</head>
<body>
<nav class="topnav">
<a class="brand" href="./">⭐ <span class="g">sirius.x</span></a>
<a href="./#try">Try it</a>
<a href="./docs/">📚 Docs</a>
<a href="./theseus/">🧭 Theseus</a>
<a href="./#roadmap">Roadmap</a>
<a href="./brand/">🎨 Brand</a>
<a href="https://silentmode.st/" rel="noopener">Silent Mode ↗</a>
<a href="./portal.html" class="portal here">🔑 Sign in</a>
</nav>
<header class="hero">
<div class="mark">🔑</div>
<h1>Your <span class="g">names</span> portal</h1>
<p class="tag">Sign in with your Bitcoin Cash seed phrase or connect an external wallet to see
every BCNR name your wallet holds. Your keys never leave this browser tab.</p>
</header>
<div class="wrap">
<section id="signin">
<h2>Sign in</h2>
<p class="muted">Pick one. Nothing is transmitted — resolution is a read-only chain query,
and signing (for record edits) happens locally in the browser or in your external wallet.</p>
<div class="authbox" style="margin-top:14px">
<div class="card">
<h3>Import a seed phrase</h3>
<p>Paste your 12- or 24-word BIP-39 recovery phrase. It stays in memory only, wiped when you
close the tab or sign out.</p>
<label for="seed">Recovery phrase</label>
<textarea id="seed" placeholder="word1 word2 … word12" spellcheck="false" autocomplete="off"></textarea>
<div class="row">
<button class="btn acid" id="signin-btn">Sign in →</button>
<span class="dim">Chipnet only for now.</span>
</div>
<div id="signin-err" class="err hidden"></div>
</div>
<div class="card">
<h3>Connect an external wallet</h3>
<p>Use Cashonize 0.9+ or Paytaca via WizardConnect. The wallet signs record edits — the seed
never touches this page.</p>
<div class="row">
<button class="btn ghost" id="wc-btn" disabled>WizardConnect
<span class="badge b-warn" style="margin-left:6px">soon</span></button>
</div>
<p class="dim" style="margin-top:8px">Portal-side WizardConnect wiring is in progress; the
register.html flow already ships the WizardConnect adapter, and the portal will reuse it.</p>
</div>
</div>
<div class="status" style="margin-top:14px">
Don't have a wallet? Create one during
<a href="https://silentmode.st/sirius/register.html">name registration</a> — the recovery phrase
is generated in your browser and encrypted with your password.
</div>
</section>
<section id="me" class="hidden">
<h2>Signed in</h2>
<div class="card">
<label>Receive address</label>
<div><code id="me-addr">—</code></div>
<label style="margin-top:14px">Token address (holds your name certificates)</label>
<div><code id="me-taddr">—</code></div>
<div class="row">
<button class="btn ghost small" id="signout-btn">Sign out</button>
<span class="dim" id="me-info">—</span>
</div>
</div>
<h2 style="margin-top:2rem">Names you hold</h2>
<div class="status" id="names-status">Loading names from the chain…</div>
<div id="names-list"></div>
</section>
</div>
<footer>
Your keys, your names, your browser. ·
<a href="./">back to sirius.x</a> ·
<a href="https://silentmode.st/sirius/register.html">register a new name</a>
</footer>
<script type="importmap">
{ "imports": { "@bitauth/libauth": "https://silentmode.st/js/libauth.js" } }
</script>
<script type="module">
// The registrar bundle exports everything we need: BuiltInWallet for local
// wallet unlock, resolveName/buildIndex for chain queries, getUtxosForAddresses
// for holdings. This portal is a read-first surface; record edits (UPD) will
// come next and will piggyback on the same signing path the registrar uses.
// Cache-buster bumped whenever the bundle changes. Chrome's in-memory ES
// module map ignores Cache-Control on the .js URL for the lifetime of a tab,
// so a plain "/js/bns-register.js" import can return a stale instance days
// after deploy. A query string forces the module loader to treat this as a
// new URL and fetch fresh bytes.
import * as BNS from "https://silentmode.st/js/bns-register.js?v=20260831c";
const $ = (id) => document.getElementById(id);
const esc = (s) => String(s).replace(/[&<>"']/g, (c) => ({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"}[c]));
let wallet = null;
// ---------- sign in ----------
$("signin-btn").addEventListener("click", async () => {
const btn = $("signin-btn");
const errBox = $("signin-err");
errBox.classList.add("hidden");
const raw = $("seed").value.trim();
if (!raw) { errBox.textContent = "Enter your seed phrase to sign in."; errBox.classList.remove("hidden"); return; }
btn.disabled = true; btn.textContent = "Unlocking…";
try {
wallet = await BNS.BuiltInWallet.fromMnemonic(raw);
} catch (e) {
errBox.textContent = "Could not unlock: " + (e.message || e);
errBox.classList.remove("hidden");
btn.disabled = false; btn.textContent = "Sign in →";
return;
}
// Wipe the textarea immediately — the seed is now in the wallet object only.
$("seed").value = "";
btn.disabled = false; btn.textContent = "Sign in →";
await enterPortal();
});
$("signout-btn").addEventListener("click", () => {
wallet = null;
$("me").classList.add("hidden");
$("signin").classList.remove("hidden");
$("names-list").innerHTML = "";
$("names-status").textContent = "Loading names from the chain…";
});
async function enterPortal() {
$("signin").classList.add("hidden");
$("me").classList.remove("hidden");
$("me-addr").textContent = wallet.address;
$("me-taddr").textContent = wallet.tokenAddress;
$("me-info").textContent = "watched addresses: " + wallet.watchedAddresses.length;
await loadNames();
}
// ---------- load names ----------
// Approach: derive the scripthash for each watched address locally (the
// wallet code already knows how), send them in one POST to
// /api/holdings, and render whatever the gateway returns. Doing the
// wallet-holdings query server-side is what makes this work on browsers
// stuck behind firewalls that block chipnet electrum ports (50004,
// 50011, 62002) — the API is same-origin HTTPS on port 443, and the
// gateway can reach the full electrums the browser can't.
async function loadNames() {
const status = $("names-status");
const list = $("names-list");
list.innerHTML = "";
status.className = "status";
status.textContent = "Preparing your addresses…";
try {
const addresses = wallet.watchedAddresses;
const scripthashes = addresses.map((a) => BNS.addressToScripthash(a));
status.textContent = `Asking the gateway about ${addresses.length} addresses…`;
const r = await fetch("https://silentmode.st/api/holdings", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ scripthashes }),
});
if (!r.ok) {
const detail = await r.text().catch(() => "");
throw new Error(`API ${r.status}: ${detail.slice(0, 200)}`);
}
const { count, names: mine } = await r.json();
if (!count) {
status.className = "status";
status.textContent = "No BCNR names found for this wallet. If you just registered, wait a minute for confirmation and reload.";
return;
}
status.className = "status ok";
status.textContent = `You own ${count} name${count === 1 ? "" : "s"}.`;
for (const e of mine) {
const div = document.createElement("div");
div.className = "name-row";
const records = e.records && Object.keys(e.records).length
? Object.entries(e.records).map(([k, v]) => `<span class="k">${esc(k)}=</span>${esc(String(v).slice(0, 80))}`).join(" &nbsp;·&nbsp; ")
: '<span class="k">(no records set)</span>';
div.innerHTML =
`<div class="n">${esc(e.name)}</div>` +
'<span class="badge b-x">on chain</span>' +
`<a class="btn small ghost" href="https://silentmode.st/bns/${encodeURIComponent(e.name)}/" target="_blank" rel="noopener">view →</a>` +
`<div class="rec">${records}</div>`;
list.appendChild(div);
}
} catch (e) {
status.className = "status err";
status.textContent = "Could not load names: " + (e.message || e);
}
}
</script>
</body>
</html>

194
theseus/index.html Normal file
View file

@ -0,0 +1,194 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Theseus Navigator — the browser that speaks Bitcoin Cash names — sirius.x</title>
<meta name="description" content="Theseus Navigator is a Chromium-based browser with native .bch / BCNR name resolution built in — no OS-level daemon, no DNS shim, no root-store install. Download for Windows.">
<link rel="icon" href="../assets/favicon.svg" type="image/svg+xml">
<link rel="mask-icon" href="../assets/favicon.svg" color="#d6ff3d">
<meta property="og:type" content="website">
<meta property="og:site_name" content="sirius.x">
<meta property="og:title" content="Theseus Navigator — the browser that speaks Bitcoin Cash names">
<meta property="og:description" content="Native .bch and BCNR name resolution built into a Chromium browser. No OS-level daemon, no root-store install. Download for Windows.">
<meta property="og:url" content="https://silentmode.st/sirius-x/theseus/">
<meta property="og:image" content="https://silentmode.st/sirius-x/brand/banner.svg">
<meta name="twitter:card" content="summary">
<style>
:root{
--bg:#0b0e14; --panel:#141a24; --panel2:#18202c; --line:rgba(255,255,255,.09);
--ink:#e7eaf1; --mut:#8b98a9; --dim:#5e6678; --acid:#d6ff3d;
--chain:#d6ff3d; --sia:#b39ddb; --srv:#4fd1a5; --ok:#4fd1a5; --taken:#f6768a; --warn:#ffc75f;
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{margin:0;background:radial-gradient(1100px 560px at 50% -12%,#16202e,var(--bg));
color:var(--ink);font:16px/1.65 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;min-height:100vh}
a{color:var(--acid)}
.wrap{max-width:980px;margin:0 auto;padding:0 1.2rem}
.topnav{position:sticky;top:0;z-index:20;display:flex;gap:2px;align-items:center;flex-wrap:wrap;
padding:10px 1.2rem;background:rgba(11,14,20,.82);backdrop-filter:blur(10px);border-bottom:1px solid var(--line)}
.topnav .brand{font-weight:600;color:var(--ink);text-decoration:none;margin-right:14px;font-size:15px;letter-spacing:.2px}
.topnav .brand .g{color:var(--acid)}
.topnav a{color:var(--mut);text-decoration:none;padding:6px 12px;border-radius:8px;font-size:14px}
.topnav a:hover{color:var(--ink);background:var(--panel)}
.topnav a.here{color:var(--acid);background:rgba(214,255,61,.08)}
.topnav a.portal{margin-left:auto;background:rgba(214,255,61,.10);color:var(--acid);font-weight:500}
.topnav a.portal:hover{background:rgba(214,255,61,.18)}
header.hero{text-align:center;padding:5rem 1.2rem 1rem}
.mark{font-size:56px;line-height:1}
h1{font-size:clamp(2rem,5.5vw,2.9rem);margin:.4rem 0 .3rem}
h1 .g{color:var(--acid)}
.tag{color:var(--mut);font-size:1.05rem;max-width:660px;margin:0 auto}
.cta{margin-top:1.8rem;display:flex;gap:10px;justify-content:center;flex-wrap:wrap}
.btn{display:inline-block;text-decoration:none;padding:11px 20px;border-radius:10px;background:#4b7bec;color:#fff;font-size:14px;border:none;cursor:pointer;font-family:inherit;transition:filter .1s}
.btn.ghost{background:transparent;border:1px solid var(--line);color:var(--ink)}
.btn.acid{background:var(--acid);color:#0b0e14;font-weight:600}
.btn:hover{filter:brightness(1.12)}
section{padding:2.6rem 0;border-top:1px solid var(--line);margin-top:2.5rem}
section:first-of-type{border-top:none;margin-top:1.5rem}
h2{font-size:1.5rem;margin:0 0 .4rem}
h3{font-size:1.1rem;margin:0 0 .35rem}
.lede{color:var(--mut);margin:0 0 1.6rem;max-width:720px}
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:14px}
.card{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:18px 20px}
.card h3{margin:0 0 .4rem;display:flex;align-items:center;gap:8px}
.card p{margin:0;color:var(--mut);font-size:14px}
.card .cta{margin-top:14px;justify-content:flex-start}
.card .sub{color:var(--dim);font-size:12.5px;margin-top:10px;font-family:ui-monospace,monospace;word-break:break-all}
.dot{width:9px;height:9px;border-radius:50%;display:inline-block}
.d-chain{background:var(--chain)} .d-sia{background:var(--sia)} .d-srv{background:var(--srv)}
.note{background:var(--panel);border:1px solid var(--line);border-left:3px solid var(--acid);
border-radius:10px;padding:14px 18px;color:var(--mut);font-size:14px;margin-top:1.4rem}
.note.warn{border-left-color:var(--warn)}
.note b{color:var(--ink)}
code,.mono{background:#0e131b;border:1px solid var(--line);border-radius:6px;padding:1px 6px;font-family:ui-monospace,monospace;font-size:13px}
pre{background:#0e131b;border:1px solid var(--line);border-radius:10px;padding:12px 14px;overflow-x:auto;
font-family:ui-monospace,monospace;font-size:13px;color:var(--ink);margin:1rem 0}
ol.steps{counter-reset:s;list-style:none;padding:0;margin:1.2rem 0 0;display:grid;gap:10px}
ol.steps li{counter-increment:s;display:grid;grid-template-columns:30px 1fr;gap:14px;align-items:start;
background:var(--panel2);border:1px solid var(--line);border-radius:12px;padding:13px 16px}
ol.steps li::before{content:counter(s);grid-column:1;grid-row:1;
display:grid;place-items:center;width:24px;height:24px;border-radius:50%;
background:rgba(214,255,61,.14);color:var(--acid);font-size:12.5px;font-weight:700}
ol.steps li > *{grid-column:2;min-width:0}
ol.steps b{color:var(--ink)} ol.steps span{color:var(--mut);font-size:14px}
.pill{display:inline-block;font-size:11px;padding:2px 8px;border-radius:999px;background:rgba(214,255,61,.13);color:var(--acid);margin-left:8px;vertical-align:middle;font-weight:500}
footer{border-top:1px solid var(--line);padding:2.4rem 0 3.5rem;color:var(--dim);font-size:13px;text-align:center;margin-top:2.5rem}
</style>
</head>
<body>
<nav class="topnav">
<a class="brand" href="../">⭐ <span class="g">sirius.x</span></a>
<a href="../#try">Try it</a>
<a href="../docs/">📚 Docs</a>
<a href="./" class="here">🧭 Theseus</a>
<a href="../#roadmap">Roadmap</a>
<a href="../brand/">🎨 Brand</a>
<a href="https://silentmode.st/" rel="noopener">Silent Mode ↗</a>
<a href="../portal.html" class="portal">🔑 Sign in</a>
</nav>
<header class="hero">
<div class="mark">🧭</div>
<h1>Theseus <span class="g">Navigator</span></h1>
<p class="tag">A Chromium-based browser with native <b>.bch / BCNR</b> name resolution built in.
No OS-level daemon, no DNS shim, no root-store install. Type <code>hello.bch</code> in the
address bar and it just works.</p>
<div class="cta">
<a class="btn acid" href="#download">Download for Windows</a>
<a class="btn ghost" href="#how">How it works</a>
</div>
</header>
<div class="wrap">
<section id="download">
<h2>Download <span class="pill">v0.0.4</span></h2>
<p class="lede">Windows builds for now. The installer wires shortcuts and file associations; the
portable build is a single .exe that runs from anywhere. Ariadne Resolver is the older,
lighter option for systems where you only need name resolution without the browser.</p>
<div class="grid">
<div class="card">
<h3><span class="dot d-chain"></span> Theseus Navigator — Setup</h3>
<p>Installs with shortcuts + Start menu entry. Recommended for most users.</p>
<div class="cta"><a class="btn acid" href="https://dl.silentmode.st/TheseusNavigator-Setup-0.0.4.exe">Download Setup .exe (~97 MB)</a></div>
<div class="sub">SmartScreen may warn on first run — the binary is unsigned. Verify the SHA-256 against the checksum published on this page (below) before running.</div>
</div>
<div class="card">
<h3><span class="dot d-sia"></span> Theseus Navigator — Portable</h3>
<p>Single .exe. Nothing installed, nothing modified in the registry. Run and go.</p>
<div class="cta"><a class="btn acid" href="https://dl.silentmode.st/TheseusNavigator-0.0.4-portable.exe">Download Portable .exe (~97 MB)</a></div>
</div>
<div class="card">
<h3><span class="dot d-srv"></span> Ariadne Resolver — Setup</h3>
<p>The lighter option: a system-wide BCNR resolver (no browser). Works with any browser via
the local trust anchor. Windows installer.</p>
<div class="cta"><a class="btn ghost" href="https://dl.silentmode.st/AriadneResolver-Setup-0.1.0.exe">Download Ariadne (~25 MB)</a></div>
</div>
<div class="card">
<h3><span class="dot d-srv"></span> Ariadne Resolver — Android</h3>
<p>Android APK. Runs as a VPN service to intercept and resolve BCNR names on the device.</p>
<div class="cta"><a class="btn ghost" href="https://dl.silentmode.st/ariadne-v0.8.apk">Download APK</a></div>
</div>
</div>
</section>
<section id="how">
<h2>How Theseus works</h2>
<p class="lede">Theseus is a Chromium wrapper (Electron) with two things regular browsers don't
have: in-process BCNR name resolution, and a certificate-verify hook that trusts on-chain
TLS fingerprints instead of the OS root store for BCNR hostnames.</p>
<ol class="steps">
<li><b>Address bar accepts <code>.bch</code> / <code>.x</code> / any BCNR TLD.</b>
<span>The URL parser is short-circuited: any hostname whose TLD is in the registry is
resolved by walking the chain via the built-in <code>bns.js</code> — never through DNS.</span></li>
<li><b>Records decide how the site is served.</b>
<span><code>h</code> renders inline HTML from the OP_RETURN payload itself. <code>s3</code>
serves from a Sia bucket via the in-app gateway. <code>ip</code> connects to a server by
IP. <code>u</code> redirects. Priority is handled by the shared <code>record-picker</code>.</span></li>
<li><b>TLS verifies against on-chain fingerprints.</b>
<span>Electron's <code>setCertificateVerifyProc</code> is intercepted: for BCNR hostnames,
instead of walking the OS trust chain, the leaf's SHA-256 fingerprint is compared to the
<code>tls</code> record on chain. Matches → trusted. No <code>tls</code> record → the
browser falls back to the local root CA.</span></li>
<li><b>Provenance indicator in the URL bar.</b>
<span>A tiny badge shows whether the page came from the chain, from Sia, or from an
IP-configured server — with the NFT category shown on hover. The decentralized padlock.</span></li>
</ol>
<div class="note"><b>What Theseus is NOT.</b> Not a wallet — for that, use Deviant, Cashonize,
Paytaca, or the built-in browser wallet at
<a href="https://silentmode.st/sirius/register.html" rel="noopener">sirius/register.html</a>.
Not a hosting service — for that, register a name and point its records at any host (Sia, VPS,
your own server). Theseus just makes those names openable in a normal-feeling browser.</div>
</section>
<section id="verify">
<h2>Verify a download</h2>
<p class="lede">The binaries are unsigned (Windows will show a SmartScreen warning). Before
running, verify the SHA-256 against what the operator publishes on-chain and in the release
notes:</p>
<pre>PowerShell:
Get-FileHash TheseusNavigator-Setup-0.0.4.exe
Bash:
sha256sum TheseusNavigator-Setup-0.0.4.exe</pre>
<p class="lede">Compare the digest to the release manifest at
<a href="https://silentmode.st/releases/" rel="noopener">silentmode.st/releases/</a>.
For a stronger guarantee, sign in with the wallet and check that the release-signing key
matches the on-chain identity for <code>releases.silentmode.bch</code>.</p>
</section>
</div>
<footer>
Theseus Navigator on sirius.x ·
<a href="../">back to sirius.x</a> ·
<a href="https://silentmode.st/tools/">Silent Mode Tools</a> ·
<a href="https://silentmode.st/releases/">Release notes</a><br>
Alpha, Windows for now. macOS and Linux builds are on the roadmap.
</footer>
</body>
</html>