theseus/dev/probe-site.mjs
Local Dev 7898e78ff4 Initial commit — Silent Mode baseline (2026-07-29)
Snapshot of the decentralized-web stack at the point of the resolver+Theseus
rebuild deploy. Includes:

- Argus (BNS engine + resolver daemon + Sia gateway)
- AriadneResolver (Windows Inno installer bundle + Android APK sources +
  Firefox extension)
- TheseusNavigator (Electron browser)
- site/ (silentmode.st content, deployed to Sia at bns/silentmode/)
- design docs, roadmap, protocol spec

Secrets excluded via .gitignore: Argus/sia-s3.json, Argus/wallets.json,
Argus/ca/*.key,*.crt. Build outputs, node_modules, and bundled runtimes
also excluded.

Shipped hashes on dl.silentmode.st at this commit:
  AriadneResolver-Setup-0.1.0.exe    5bcb216eef31ea28ed767e4134ab74bd5ac69dfbd365fd249e9e6938e55c986a
  TheseusNavigator-Setup-0.0.1.exe   7c735e88bad2da3347145adba3016c8f626a18b8422289c8c6ba471972e2952b
  TheseusNavigator-0.0.1-portable.exe 008fd84445babeabb401b2bca40ea9466b24b0e6d6c85104da7640c5c5c84521
  ariadne-v0.2.apk                   635c8f04d44ef855a8390b9eeddb8cd2d50622e81cc4e5004e8daffc1bb0425c
2026-07-29 13:54:34 +02:00

65 lines
3 KiB
JavaScript

// Dev harness — exercise Theseus's `s3` content path (serveBns) WITHOUT Electron.
// Faithfully replicates what the browser triggers for a Sia site: resolve the
// name, fetch the index through the public gateway exactly as serveBns does,
// strip the gateway's <base>, then fetch every referenced same-origin asset the
// same way and report which load. This is the headless version of manual test
// #2 (Sia-via-gateway rendering).
//
// Usage: node dev/probe-site.mjs <name> e.g. coinspectrum.deviant.bch
import WebSocket from "ws";
import { resolveName } from "../../Argus/src/lib/resolver-web.js";
const GATEWAY = "https://navigate.st"; // must match main.js
const host = (process.argv[2] || "coinspectrum.deviant.bch").toLowerCase();
// mirror of serveBns's s3 fetch for one request path
async function gw(reqPath) {
const r = await fetch(`${GATEWAY}/bns/${host}${reqPath}`);
const ct = r.headers.get("content-type") || "";
const buf = Buffer.from(await r.arrayBuffer());
return { status: r.status, ct, buf };
}
const stripBase = (html) => html.replace(/<base\s+href="\/bns\/[^"]*">/i, "");
// same-origin STATIC asset refs a browser would request from bns://host/.
// Strip <script>/<style> bodies first so we don't match template literals or
// URLs built at runtime (those need a real render to verify — see selftest.js).
function assetPaths(html) {
const stripped = html
.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, "")
.replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, "");
const out = new Set();
const re = /(?:href|src)\s*=\s*["']([^"']+)["']/gi;
let m;
while ((m = re.exec(stripped))) {
const u = m[1].trim();
if (!u || u.startsWith("#") || u.startsWith("data:") || u.startsWith("mailto:")) continue;
if (/^[a-z]+:\/\//i.test(u) || u.startsWith("//")) continue; // external
if (u.includes("${") || u.includes("{{")) continue; // runtime-built
out.add(u.startsWith("/") ? u : "/" + u.replace(/^\.?\//, ""));
}
return [...out];
}
console.log(`\n=== probe ${host} ===`);
const entry = await resolveName(host, { WebSocket });
if (!entry) { console.log("NXDOMAIN — not registered"); process.exit(1); }
console.log("records:", JSON.stringify(entry.records));
if (!entry.records.s3) { console.log("(not an s3 site — this harness targets s3)"); process.exit(0); }
const idx = await gw("/");
const wasBase = /<base\s+href="\/bns\//i.test(idx.buf.toString("utf8"));
const html = stripBase(idx.buf.toString("utf8"));
console.log(`index: HTTP ${idx.status} ${idx.ct} base-injected-by-gateway=${wasBase} (stripped)`);
const assets = assetPaths(html);
console.log(`\nassets referenced: ${assets.length}`);
let fail = 0;
for (const p of assets) {
const a = await gw(p);
const ok = a.status >= 200 && a.status < 300;
if (!ok) fail++;
console.log(` ${ok ? "OK " : "FAIL"} ${String(a.status).padEnd(3)} ${a.ct.split(";")[0].padEnd(24)} ${p}`);
}
console.log(`\nresult: ${assets.length - fail}/${assets.length} assets loaded, ${fail} failed`);
process.exit(fail ? 2 : 0);