theseus-site/plug-ins/index.html

288 lines
18 KiB
HTML
Raw Normal View History

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>theseus.x — Plug-ins</title>
<meta name="description" content="Silent Mode's first-party plug-ins for Theseus Navigator: the Aegis wallet and the Ariadne's Thread system-wide resolver. Current signed versions, hashes, and how they update.">
<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="theseus.x">
<meta property="og:title" content="theseus.x — Plug-ins">
<meta property="og:description" content="First-party plug-ins for Theseus: Aegis wallet and Ariadne's Thread. Signed, verified on the device.">
<meta property="og:url" content="https://theseus.x/plug-ins/">
<style>
:root{
--bg:#0b0e14; --panel:#141a24; --panel2:#18202c; --line:rgba(255,255,255,.09);
--ink:#e7eaf1; --mut:#8b98a9; --dim:#5e6678; --acid:#d6ff3d; --ok:#4fd1a5;
}
*{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:900px;margin:0 auto;padding:0 1.2rem}
.topnav{position:fixed;top:0;left:0;right:0;z-index:20;display:flex;gap:2px;align-items:center;flex-wrap:wrap;
padding:10px 1.2rem;background:rgba(11,14,20,.88);backdrop-filter:blur(10px)}
.topnav .brand{font-weight:600;color:var(--ink);text-decoration:none;margin-right:14px;font-size:15px;letter-spacing:.2px;display:flex;align-items:center;gap:8px}
.topnav .brand .g{color:var(--acid)}
.topnav .brand svg{width:20px;height:20px}
.topnav a{color:var(--mut);text-decoration:none;padding:6px 12px;border-radius:8px;font-size:14px;
display:inline-flex;align-items:center;gap:6px}
.topnav a:hover{color:var(--ink);background:var(--panel)}
.topnav a.here{color:var(--acid);background:rgba(214,255,61,.08)}
.topnav a .g{color:var(--acid)}
.topnav a svg.tabicon{width:15px;height:15px;flex:none}
/* Mobile hamburger — matches the home-page pattern. */
.topnav .menu{display:none}
@media (max-width:720px){
.topnav{flex-wrap:nowrap;padding:10px 1rem}
.topnav .brand{margin-right:0}
.topnav > a:not(.brand){display:none}
.topnav .menu{display:block;margin-left:auto;position:relative}
.topnav .menu > summary{list-style:none;cursor:pointer;padding:8px 10px;
border-radius:8px;color:var(--mut);display:inline-flex;align-items:center;gap:6px}
.topnav .menu > summary::-webkit-details-marker{display:none}
.topnav .menu > summary svg{width:22px;height:22px;display:block}
.topnav .menu > summary:hover,
.topnav .menu[open] > summary{color:var(--ink);background:var(--panel)}
.topnav .menu .menu-panel{position:absolute;top:calc(100% + 6px);right:0;
background:var(--bg);border:1px solid var(--line);border-radius:12px;
padding:6px;min-width:220px;display:flex;flex-direction:column;gap:2px;
box-shadow:0 10px 32px rgba(0,0,0,.55)}
.topnav .menu .menu-panel a{padding:10px 14px;border-radius:8px;font-size:14.5px;
color:var(--mut);text-decoration:none;display:flex;align-items:center;gap:8px}
.topnav .menu .menu-panel a:hover{color:var(--ink);background:var(--panel)}
}
.topnav a.get{margin-left:auto;background:rgba(214,255,61,.10);color:var(--acid);font-weight:500}
.topnav a.get:hover{background:rgba(214,255,61,.18)}
/* Adaptive edge nav: full-width panel at left edge on wide,
icon rail on medium, bottom bar with icons on mobile. */
:root{--sn-w:200px;--tn-h:52px}
body{padding-top:var(--tn-h)}
.sidenav{position:fixed;top:var(--tn-h);left:0;bottom:0;width:var(--sn-w);z-index:15;
background:transparent;padding:56px 12px 22px 18px;
overflow-y:auto;transition:width .15s ease;pointer-events:none}
.sidenav a{display:flex;align-items:center;gap:14px;color:var(--mut);text-decoration:none;
padding:9px 12px;border-radius:10px;
font-size:14.5px;font-weight:500;opacity:.35;pointer-events:auto;
transition:opacity .12s,color .12s,background .12s,backdrop-filter .12s}
.sidenav a .ic{flex:none;width:22px;font-size:18px;line-height:1;text-align:center;
display:none;justify-content:center;align-items:center}
.sidenav a .lb{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sidenav a:hover{opacity:1;color:var(--ink);background:rgba(11,14,20,.72);backdrop-filter:blur(8px)}
.sidenav a.active{opacity:.85;color:var(--acid)}
.sidenav a.active:hover{opacity:1}
@media (max-width:1180px){
:root{--sn-w:64px}
.sidenav{padding:22px 6px}
.sidenav .lbl{display:none}
.sidenav a{justify-content:center;padding:12px 4px;gap:0}
.sidenav a .ic{display:inline-flex}
.sidenav a .lb{display:none}
}
@media (max-width:720px){
:root{--sn-w:0px}
body{padding-left:0;padding-bottom:64px}
.sidenav{top:auto;bottom:0;left:0;right:0;width:100%;height:auto;
padding:4px 4px;flex-direction:row;background:rgba(11,14,20,.52);
display:flex;justify-content:space-around;overflow-x:auto}
.sidenav .lbl{display:none}
.sidenav a{flex:1;min-width:56px;padding:10px 6px;justify-content:center;gap:0}
.sidenav a .ic{display:inline-flex}
.sidenav a .lb{display:none}
}
header.hero{text-align:center;padding:3.5rem 1.2rem 1rem}
h1{font-size:clamp(1.8rem,4.5vw,2.4rem);margin:.6rem 0 .3rem;letter-spacing:-.3px}
h1 .g{color:var(--acid)}
.tag{color:var(--mut);font-size:1.02rem;max-width:640px;margin:0 auto}
section{padding:2rem 0;border-top:1px solid var(--line);margin-top:1.6rem;scroll-margin-top:72px}
section:first-of-type{border-top:none;margin-top:1rem}
h2{font-size:1.35rem;margin:0 0 .5rem}
.lede{color:var(--mut);margin:0 0 1.2rem;max-width:720px}
code{background:#0e131b;border:1px solid var(--line);border-radius:6px;padding:1px 6px;font-family:ui-monospace,monospace;font-size:13px}
.ext{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:20px 22px;margin:1rem 0}
.ext h3{margin:0 0 .3rem;font-size:1.15rem;display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.ext h3 .icon{font-size:1.4rem;display:inline-flex;align-items:center;line-height:1}
.ext h3 .icon img{width:26px;height:26px;display:block}
.ext .cur{color:var(--acid);font-size:12px;font-weight:600;letter-spacing:.14em;text-transform:uppercase}
.ext .desc{color:var(--mut);font-size:14px;margin:.3rem 0 .8rem}
.ext .verifybox{margin-top:.9rem;padding-top:.8rem;border-top:1px solid var(--line);font-size:11.5px;color:var(--dim)}
.ext .verifybox .lbl{color:var(--mut);font-size:12px;margin-bottom:6px}
.ext .h{display:flex;gap:8px;flex-wrap:wrap;align-items:baseline;margin-top:4px}
.ext .h b{color:var(--mut);font-weight:600;min-width:90px}
.ext .h code{font-family:ui-monospace,monospace;font-size:10.5px;color:#c9d4e3;word-break:break-all;background:transparent;border:none;padding:0}
.ext .meta{color:var(--dim);font-size:12.5px;margin-top:.4rem}
.btns{display:flex;gap:8px;flex-wrap:wrap;margin-top:.8rem}
.btn{display:inline-block;padding:.45rem .9rem;border-radius:9px;background:var(--acid);color:#0b0e14;font-weight:650;text-decoration:none;font-size:14px}
.btn.ghost{background:transparent;color:var(--ink);border:1px solid var(--line)}
.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:1.4rem 0}
.note b{color:var(--ink)}
footer{color:var(--dim);font-size:12.5px;margin:3rem 0 2rem;text-align:center}
footer a{color:var(--mut)}
</style>
</head>
<body>
<nav class="topnav">
<a class="brand" href="../">
<svg viewBox="0 0 64 64" aria-hidden="true">
<rect width="64" height="64" rx="12" fill="#0b0e14"/>
<path d="M32 6 L38 32 L26 32 Z" fill="#e04e4e"/>
<path d="M38 32 L32 58 L26 32 Z" fill="#d6ff3d"/>
<path d="M6 32 L32 27 L58 32 L32 37 Z" fill="#d6ff3d" opacity=".55"/>
<circle cx="32" cy="32" r="3" fill="#0b0e14"/>
</svg>
<span>Theseus<span class="g">.X</span></span>
</a>
<a class="here" href="./">Plug-ins</a>
<a href="../extensions/">Extensions</a>
<a href="../dev/">Developers</a>
<a href="//sirius.x/" title="Register a BCNR name"><svg class="tabicon" viewBox="0 0 64 64" aria-hidden="true"><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><span>Sirius<span class="g">.X</span></span></a>
<a class="get" href="../#download">Get Theseus</a>
<details class="menu">
<summary aria-label="Open menu">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M4 7h16M4 12h16M4 17h16"/></svg>
</summary>
<div class="menu-panel">
<a href="./">Plug-ins</a>
<a href="../extensions/">Extensions</a>
<a href="../dev/">Developers</a>
<a href="//sirius.x/">Sirius.X</a>
</div>
</details>
</nav>
<aside class="sidenav" aria-label="On this page">
<a href="#aegis-section" title="Aegis wallet" ><span class="ic" aria-hidden="true"><svg viewBox="0 0 32 32" fill="none" width="20" height="20"><polygon points="16,2 28,9 28,23 16,30 4,23 4,9" fill="#0a0a0d" stroke="#D6FF3D" stroke-width="1.6" stroke-linejoin="round"/><circle cx="16" cy="16" r="4.5" fill="none" stroke="#D6FF3D" stroke-width="1.4"/><circle cx="16" cy="16" r="1.6" fill="#D6FF3D"/></svg></span><span class="lb">Aegis wallet</span></a>
<a href="#ariadne-section" title="Ariadne's Thread" ><span class="ic" aria-hidden="true">🧵</span><span class="lb">Ariadne's Thread</span></a>
<a href="#line" title="Plug-ins vs extensions"><span class="ic" aria-hidden="true">🧩</span><span class="lb">Plug-ins vs extensions</span></a>
</aside>
<header class="hero">
<h1>Theseus <span class="g">Plug-ins</span></h1>
<p class="tag">Silent Mode's own components that ship inside Theseus and appear under
<b>Settings › Plug-ins</b>: the wallet and the system-wide resolver. Community-made
add-ons live on the separate <a href="../extensions/">Extensions</a> page.</p>
</header>
<div class="wrap">
<section id="aegis-section">
<h2>Aegis — the wallet</h2>
<p class="lede">Multi-chain wallet derived from your Theseus vault (BCH, BTC, TRX, ETH, SOL, SC, DGB) with a
dApp bridge for the pages you visit. Bundled with every Theseus build and updated over a signed channel
between releases; the panel's own <i>Stage → Restart</i> flow applies an update without reinstalling Theseus.</p>
<div class="ext" id="aegis" data-channel="../extensions/aegis/updates.json">
<h3><span class="icon" style="font-size:0;line-height:0"><svg viewBox="0 0 32 32" fill="none" width="26" height="26" style="vertical-align:-6px"><polygon points="16,2 28,9 28,23 16,30 4,23 4,9" fill="#0a0a0d" stroke="#D6FF3D" stroke-width="1.6" stroke-linejoin="round"/><circle cx="16" cy="16" r="4.5" fill="none" stroke="#D6FF3D" stroke-width="1.4"/><circle cx="16" cy="16" r="1.6" fill="#D6FF3D"/></svg></span> Aegis <span class="cur" style="margin-left:auto">current <span data-live="version">0.6.31</span></span></h3>
<div class="desc">Vault-derived keys, per-chain accounts, imported keys, message signing, dApp permissions per site.</div>
<div class="meta">Plug-in · Settings › Plug-ins · <span data-live="count">signed versions on the channel</span></div>
<div class="verifybox">
<div class="lbl">Signed update manifest — Ed25519 by the Silent Mode operator, SHA-256 verified before install</div>
<div class="h"><b>updates.json</b><code><a href="../extensions/aegis/updates.json">theseus.x/extensions/aegis/updates.json</a></code></div>
<div class="h"><b>Tarball</b><code><a data-live="url" href="../extensions/aegis/">…</a></code></div>
<div class="h"><b>sha256</b><code data-live="sha256">—</code></div>
</div>
</div>
</section>
<section id="ariadne-section">
<h2>Ariadne's Thread — the system-wide resolver</h2>
<p class="lede">Makes BCDN names resolve for <em>every</em> program on the machine, not only Theseus: a local
DNS resolver plus gateway, installed by Theseus's setup by default (opt-out) and switchable from
<b>Settings › Plug-ins</b>. The same resolver ships standalone for Windows and as Ariadne for Android.</p>
<div class="ext" id="ariadne">
<h3><span class="icon"><img src="../assets/thread.svg" alt="" aria-hidden="true"></span> Ariadne's Thread <span class="cur" style="margin-left:auto">current <span data-live="resolver-version">0.1.3</span></span></h3>
<div class="desc">Windows service: answers A/AAAA for registered names, forwards everything else to your upstream
resolver, serves Sia-hosted content through a local gateway with a machine-local CA. Answers MX/TXT/NS from
owner-signed DNS records.</div>
<div class="meta">Plug-in · Settings › Plug-ins · Turn on / off · Install / Update / Uninstall from inside Theseus</div>
<div class="btns">
<a class="btn" href="https://dl.silentmode.st/latest/AriadneResolver-Setup.exe">Windows installer</a>
<a class="btn ghost" href="https://dl.silentmode.st/latest/ariadne.apk">Ariadne for Android (APK) · v<span data-live="android-version">0.19</span></a>
</div>
<div class="verifybox">
<div class="lbl">Hashes from the releases manifest — verify before running</div>
<div class="h"><b>Installer</b><code data-live="resolver-sha">—</code></div>
<div class="h"><b>APK</b><code data-live="android-sha">—</code></div>
<div class="h"><b>Manifest</b><code><a href="https://dl.silentmode.st/releases-manifest.json">dl.silentmode.st/releases-manifest.json</a></code></div>
</div>
</div>
</section>
<section id="line">
<h2>Where the line is</h2>
<p class="lede">Plug-ins are first-party: Silent Mode builds them, signs them with the operator key, and Theseus treats
them as part of itself (own Settings section, own update flow). Extensions are everyone else's: published by
any BCDN name holder, signed with that name's wallet, listed on <a href="../extensions/">theseus.x/extensions</a>
and installed from <b>Settings › Extensions</b>. Both are verified on your device before a byte runs.</p>
<div class="note"><b>Want to build one?</b> Start on the <a href="../extensions/#build">Extensions page</a> — the same add-on
format powers both, and publishing takes a name and a signature, nothing else.</div>
</section>
<footer>
Silent Mode · <a href="https://code.silentmode.st/silentmode/theseus/src/branch/master/TheseusNavigator/docs/ADDON-UPDATES.md">how signed updates work</a>
</footer>
</div>
<script>
(async () => {
const set = (k, f) => document.querySelectorAll('[data-live="' + k + '"]').forEach(f);
const cmp = (a, b) => { const x = String(a).split(".").map(Number), y = String(b).split(".").map(Number); for (let i = 0; i < Math.max(x.length, y.length); i++) { const d = (x[i] || 0) - (y[i] || 0); if (d) return d; } return 0; };
try {
const r = await fetch("../extensions/aegis/updates.json", { cache: "no-store" });
if (r.ok) {
const m = await r.json(); const list = (m.addons || []).slice().sort((x, y) => cmp(y.version, x.version)); const top = list[0];
if (top) {
set("version", (el) => { el.textContent = top.version; });
set("sha256", (el) => { el.textContent = top.sha256 || "—"; });
set("url", (el) => { el.href = top.url; el.textContent = String(top.url).split("/").pop(); });
set("count", (el) => { el.textContent = list.length + " signed version" + (list.length === 1 ? "" : "s") + " on the channel"; });
}
}
} catch {}
try {
const r = await fetch("https://dl.silentmode.st/releases-manifest.json", { cache: "no-store" });
if (r.ok) {
const m = await r.json(); const g = (id) => (m.releases || []).find((x) => x.id === id);
const res = g("ariadne-resolver"), an = g("ariadne-android");
if (res) { set("resolver-version", (el) => { el.textContent = res.version; }); const f = Object.keys(res.files || {})[0]; set("resolver-sha", (el) => { el.textContent = f ? res.files[f] : "—"; }); }
if (an) { set("android-version", (el) => { el.textContent = an.version; }); const f = Object.keys(an.files || {})[0]; set("android-sha", (el) => { el.textContent = f ? an.files[f] : "—"; }); }
}
} catch {}
})();
// Sidenav scroll-spy: highlight the section currently in view.
// Uses scroll-position tracking so short sections at the end of the page
// still activate their link when the reader scrolls to them.
(() => {
const links = document.querySelectorAll(".sidenav a[href^='#']");
if (!links.length) return;
const entries = [];
links.forEach((a) => { const el = document.querySelector(a.getAttribute("href")); if (el) entries.push({ el, link: a }); });
if (!entries.length) return;
const setActive = (link) => { links.forEach((l) => l.classList.remove("active")); link.classList.add("active"); };
const update = () => {
const doc = document.documentElement;
const scrollBottom = window.scrollY + window.innerHeight;
if (scrollBottom >= (doc.scrollHeight - 4)) { setActive(entries[entries.length - 1].link); return; }
const line = window.scrollY + window.innerHeight * 0.35;
let active = entries[0].link;
for (const e of entries) {
if (e.el.getBoundingClientRect().top + window.scrollY <= line) active = e.link;
else break;
}
setActive(active);
};
window.addEventListener("scroll", update, { passive: true });
window.addEventListener("resize", update);
update();
})();
</script>
</body>
</html>