You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 4fd4fe4
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: docs/w3bs-net.md
+15Lines changed: 15 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -38,3 +38,18 @@ W3BS is an independent Moshpit instance: W3BS names, owner ids and DNS writes st
38
38
A configured Moshpit resolver maps the W3BS realm `label.namespace.w3bs.org` to this instance, querying its resolve and records APIs. It does not treat bare `label.namespace` on the primary network as the same ownership. Active instance records are authoritative within that explicitly configured realm, including over public parking answers; inactive local names cannot be revived through primary-network fallback. A name with no custom address records goes to the W3BS gateway so its existing HTTPS destination can redirect there. Custom AAAA or CNAME records override the gateway address; TXT/MX coexist with its default address. DNS changes publish immediately in the instance; cached resolver/browser answers still follow TTL.
39
39
40
40
DNS answers and HTTPS certificates are separate rollout gates. Standard browser access to every new `*.namespace.w3bs.org` requires public DNS and a publicly trusted certificate for that suffix. A generic `*.w3bs.org` certificate does not cover two labels. The primary Moshpit CA intentionally refuses public TLDs and must not be changed to mint arbitrary `.org` certificates to work around missing registrar credentials. Resolver routing is not evidence that public DNS or HTTPS is ready. Preserve that distinction when reporting a new name live.
41
+
42
+
### URL redirects
43
+
44
+
At `/net/records`, each active name you own has a URL redirect form. Enter a complete HTTPS URL (including a path), choose **301 permanent** or **302 temporary**, then save. Existing registration destinations appear here as 302 redirects. Saving/removing gives inline feedback without refreshing the page. A 301 can be remembered by browsers; use 302 while testing.
`DELETE` at that same endpoint removes the destination. Only the local owner of an active name in an active namespace can change it. Redirect changes update the resolver record and publish a federation activation event. Redirects and AAAA/CNAME records are mutually exclusive, since those records route visitors away from the gateway. TXT/MX records can coexist. Redirects require working gateway DNS and HTTPS; setting a URL does not provision a public certificate or change registrar DNS.
card.append(el('h3','URL redirect'),el('p','Send visitors to a complete HTTPS URL, including its path. Choose 301 for a permanent move or 302 for a temporary destination. Browsers may remember permanent redirects. AAAA/CNAME records must be removed to use the redirect gateway. The hostname must resolve to the gateway and have a valid HTTPS certificate.',{className:'net-help'}),summary,redirectForm,message);
@@ -54,7 +54,29 @@ export function createNetRecords(db) {
54
54
}
55
55
return{
56
56
asyncowned(ownerId){
57
-
returndb.all('SELECT n.label,n.tld,n.status,n.target,t.status AS namespace_status FROM net_names n JOIN net_tlds t ON t.tld=n.tld WHERE n.owner_id=? ORDER BY n.tld,n.label',[ownerId]);
57
+
returndb.all('SELECT n.label,n.tld,n.status,n.target,t.status AS namespace_status,COALESCE(r.status,302) AS redirect_status FROM net_names n JOIN net_tlds t ON t.tld=n.tld LEFT JOIN net_url_redirects r ON r.tld=n.tld AND r.label=n.label WHERE n.owner_id=? ORDER BY n.tld,n.label',[ownerId]);
thrownewW3bsError('REDIRECT_DNS_CONFLICT','Remove AAAA or CNAME records first so this name uses the W3BS redirect gateway.',409);
74
+
awaittx.run('UPDATE net_names SET target=? WHERE tld=? AND label=?',[target,tld,label]);
75
+
if(target)awaittx.run('INSERT INTO net_url_redirects(tld,label,status) VALUES(?,?,?) ON CONFLICT(tld,label) DO UPDATE SET status=excluded.status',[tld,label,status]);
76
+
elseawaittx.run('DELETE FROM net_url_redirects WHERE tld=? AND label=?',[tld,label]);
77
+
awaitannounceRedirect(tx,name,target,target ? status : 302,ownerId);
78
+
return{ target,redirectStatus: target ? status : 302};
79
+
});
58
80
},
59
81
asynclist(name){
60
82
const[tld,label]=parts(name);
@@ -65,6 +87,8 @@ export function createNetRecords(db) {
65
87
constrecord=normalizeNetRecord(input,name);
66
88
returntransaction(asynctx=>{
67
89
const[tld,label]=awaitauthorize(tx,name,ownerId);
90
+
if(['AAAA','CNAME'].includes(record.type)&&(awaittx.get('SELECT target FROM net_names WHERE tld=? AND label=?',[tld,label]))?.target)
91
+
thrownewW3bsError('REDIRECT_DNS_CONFLICT','Remove the URL redirect first before pointing this name at another server.',409);
Copy file name to clipboardExpand all lines: src/net-routes.mjs
+25-4Lines changed: 25 additions & 4 deletions
Original file line number
Diff line number
Diff line change
@@ -417,7 +417,10 @@ export function createNet({
417
417
`<section class="page-head compact"><div class="eyebrow">W3BS NET · ${e(record.status)}</div><h1>${e(name)}</h1><p>This local W3BS record is not active, so the federation backfill is not used for it.</p><a class="button" href="https://w3bs.org/net">W3BS Net</a></section>`,
res.type('html').send(shell('DNS Records · W3BS Net','Publish DNS records on names you own in this Moshpit instance.','/net',`
484
-
<section class="page-head compact"><div class="eyebrow">W3BS NET · MOSHPIT INSTANCE</div><h1>DNS <em>records.</em></h1>
485
-
<p>Real records on the names you hold: AAAA for IPv6, CNAME to another hostname, MX for mail and TXT for verification. Changes publish to this W3BS instance immediately; existing resolver caches follow the record’s TTL.</p>
500
+
<section class="page-head compact"><div class="eyebrow">W3BS NET · MOSHPIT INSTANCE</div><h1>DNS & <em>redirects.</em></h1>
501
+
<p>Send a name to any HTTPS URL with a 301 permanent or 302 temporary URL redirect. Or publish DNS records on the names you hold: AAAA for IPv6, CNAME to another hostname, MX for mail and TXT for verification. Changes publish to this W3BS instance immediately; existing resolver caches follow the record’s TTL.</p>
486
502
<p class="net-help">W3BS is a separate Moshpit instance. Your names and records belong here; imported primary-network records remain read-only backfill. The public gateway name is <code>name.namespace.w3bs.org</code>.</p>
${user ? `<section class="net-block"><form id="net-dns-filter" role="search"><label for="dns-filter">Filter your names</label><input id="dns-filter" name="q" placeholder="dumb.fuck, fuck, dumb.*" autocomplete="off"><button class="button" type="submit">Filter</button></form><p id="dns-status" class="net-status" role="status" aria-live="polite">Loading your names…</p><div id="dns-names"></div></section><script type="module" src="/assets/net-records.js"></script>` : `<section class="net-block"><p>Sign in to publish records on names you own in W3BS.</p><a class="button primary" href="/login?next=%2Fnet%2Frecords">Sign in →</a></section>`}
489
505
<section class="net-block"><h2>Publish from a script</h2><p>Use the existing W3BS OAuth bearer from <code>w3bs login</code>. Primary-network API keys do not grant W3BS ownership.</p><pre>POST /api/net/v1/names/blue.example/records
constrow=awaitdb.get('SELECT * FROM net_names WHERE tld = ? AND label = ?',[tld,label]);
537
+
constrow=awaitdb.get('SELECT n.*, COALESCE(r.status,302) AS redirect_status FROM net_names n LEFT JOIN net_url_redirects r ON r.tld=n.tld AND r.label=n.label WHERE n.tld = ? AND n.label = ?',[tld,label]);
528
538
if(!row)return{error: 'not_found'};
529
539
if(status==='active'){
530
540
constnamespace=awaitdb.get('SELECT status FROM net_tlds WHERE tld = ?',[tld]);
0 commit comments