prometheus: standalone identity + first-wave Silent Mode listings

Four changes, one coherent pass:

1. Prometheus gets its own flame mark (SVG, not an emoji). Used in the
   topnav brand, in the hero at 88 px, and as the favicon. Replaces the
   🔥 glyph in the service and in site/prometheus/index.html.

2. silentmode.st/prometheus is now a brief introduction with two big
   buttons (Open prometheus.x · Open apps.silentmode.st mirror) and a
   short "what / who / status" block, instead of the full category
   grid that duplicated what prometheus.x already renders. The /prometheus
   page's job on silentmode.st is "point you at the real site," not host
   the content.

3. Footer on the Prometheus service drops the "Silent Mode — a Deviant
   project" byline and reframes the sibling-x links as "Also live in the
   decentralized web:" so Prometheus reads as its own site rather than a
   Silent Mode subpage. Keeps the attribution via the MPL-2.0 + source
   link on the final line. aegis.x and pithos.x added to the sibling row.

4. Four Silent Mode apps seeded as first-wave listings
   (scripts/seed-listings.json + scripts/seed.mjs). Theseus Navigator,
   Ariadne's Thread (Windows + Android), Pithos. Each carries the
   project's own SVG icon from public/icons/, pulled from the project's
   own site. The seed is a direct-DB insert (not through /api/listing)
   with signer_address = chipnet operator and signature = sentinel
   `SM_OPERATOR_SEED`; scan_report is an operator-attested envelope
   signed by the service key so the display pipeline is unchanged. Run
   with `node scripts/seed.mjs`; idempotent (skips existing (publisher,
   slug)).

   Deliberately NOT seeded: Theseus extensions that have no standalone
   form — pdf-editor, docx-editor, shield-blocker, bergamot provider.
   They ship via Theseus's own OTA, not as Prometheus listings. Aegis
   is in the same boat today (a Theseus bundled add-on without a
   standalone binary); its icon is included in public/icons/ for when
   it has its own distribution.

Real file sizes + SHAs come from the current dl.silentmode.st manifest
(theseus 0.3.89, ariadne resolver 0.1.13, ariadne android 0.22,
pithos-desktop 0.3.26). When APS1 lands cross-session, these listings
migrate to real on-chain records signed by each project's own publisher
key and the sentinel values go away.
This commit is contained in:
Local Dev 2026-10-09 01:23:21 +02:00
parent 7950430aa0
commit a9ca956c2e
10 changed files with 269 additions and 19 deletions

View file

@ -1,5 +1,23 @@
<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 10 C 22 22, 24 32, 32 36 C 40 32, 42 22, 32 10 Z" fill="#d6ff3d"/>
<path d="M26 36 C 20 44, 22 54, 32 56 C 42 54, 44 44, 38 36 C 36 42, 28 42, 26 36 Z" fill="#d6ff3d" opacity=".75"/>
<!-- Outer flame: tall tongue with curved sides. The lower hook on the left
says "flame" rather than "generic teardrop" so the mark reads as fire
even at 16 px. -->
<path d="M32 6
C 38 18 46 24 46 36
C 46 48 40 56 32 56
C 24 56 18 48 18 36
C 18 28 24 22 20 14
C 26 18 30 20 32 6 Z"
fill="#d6ff3d"/>
<!-- Inner flame cutout: smaller flame in bg colour, offset to the right —
the asymmetry is the "unbound" part of Prometheus's story. -->
<path d="M32 20
C 36 28 40 32 40 40
C 40 48 36 52 32 52
C 28 52 24 48 24 40
C 24 34 28 30 32 20 Z"
fill="#0b0e14"/>
<!-- Ember at the base. -->
<circle cx="32" cy="44" r="3" fill="#d6ff3d"/>
</svg>

Before

Width:  |  Height:  |  Size: 324 B

After

Width:  |  Height:  |  Size: 902 B

12
public/icons/aegis.svg Normal file
View file

@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<!-- Aegis — shield mark. Rounded dark square (matches the Silent Mode
family: theseus.svg, sirius.svg) with a chevron-crowned shield in the
acid green so it reads clearly at 16x16 tab-icon size. The split in the
middle hints at the wallet/key duality Aegis gates on. -->
<rect width="64" height="64" rx="12" fill="#0b0e14"/>
<path d="M32 8 L50 16 L50 32 C 50 44, 42 52, 32 56 C 22 52, 14 44, 14 32 L 14 16 Z"
fill="#d6ff3d"/>
<path d="M32 14 L46 20 L46 32 C 46 42, 40 48, 32 51 L 32 14 Z"
fill="#0b0e14" opacity="0.4"/>
<path d="M24 28 L32 36 L40 28" fill="none" stroke="#0b0e14" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 764 B

6
public/icons/ariadne.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 14 KiB

1
public/icons/pithos.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><defs><linearGradient id="g" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#3ddc97"/><stop offset="1" stop-color="#1e8f6a"/></linearGradient></defs><path d="M22 6h20v5c0 2-2 3-2 5 8 3 14 11 14 21 0 12-9 21-22 21S10 49 10 37c0-10 6-18 14-21 0-2-2-3-2-5z" fill="url(#g)"/><path d="M14 30h36M13 40h38" stroke="#0b1f18" stroke-width="3" stroke-linecap="round" opacity=".55"/></svg>

After

Width:  |  Height:  |  Size: 449 B

8
public/icons/sirius.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

15
public/icons/theseus.svg Normal file
View file

@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<!-- theseus.x — Navigator compass mark. Rounded dark square (matches the
sirius.x sibling family). N (top) half red like every real compass
needle, S (bottom) half in Silent Mode acid green. E-W arm softened
so the N-S bearing reads clearly at 16x16 tab-icon size. -->
<rect width="64" height="64" rx="12" fill="#0b0e14"/>
<!-- N half — red bearing indicator -->
<path d="M32 6 L38 32 L26 32 Z" fill="#e04e4e"/>
<!-- S half — acid -->
<path d="M38 32 L32 58 L26 32 Z" fill="#d6ff3d"/>
<!-- E-W arm — softened acid so the vertical bearing dominates -->
<path d="M6 32 L32 27 L58 32 L32 37 Z" fill="#d6ff3d" opacity="0.55"/>
<!-- Center hole -->
<circle cx="32" cy="32" r="3" fill="#0b0e14"/>
</svg>

After

Width:  |  Height:  |  Size: 809 B

View file

@ -0,0 +1,62 @@
{
"comment": "First-wave Silent Mode listings — the apps that are themselves standalone, with their own BNS names, icons and installer binaries. Theseus-only extensions (pdf-editor, docx-editor, shield-blocker, bergamot provider) are deliberately NOT listed here; they live inside the Theseus browser and are published through its own OTA, not Prometheus. Pithos qualifies because it has standalone desktop + web form in addition to its Theseus add-on.",
"operator": {
"publisher": "silentmode.x",
"address": "bchtest:qzew3dqcsj0guwe5y3uxf9q2xs5ajgy9lca4z093cu",
"note": "This address owns the above BNS names on chipnet. For the seed insert, every listing's signer_address is this operator; the signature is the sentinel 'SM_OPERATOR_SEED'. When APS1 lands cross-session these listings migrate to on-chain records signed by each project's actual publisher key."
},
"listings": [
{
"publisher": "theseus.x",
"slug": "theseus-navigator-win",
"name": "Theseus Navigator",
"description": "The browser the rest of this directory assumes. Resolves BCNR names (.x, .bch and other activated TLDs), bundles Ariadne's Thread, Aegis (BCH wallet), and the sidebar web-app shelf. Windows installer; portable build + Android available at theseus.x.",
"category": "other",
"version": "0.3.89",
"homepage": "https://theseus.x/",
"icon": "/static/icons/theseus.svg",
"download_url": "https://dl.silentmode.st/TheseusNavigator-Setup-0.3.89.exe",
"download_sha256": "eafad358d21145b840e5af2f13e15ce9c35ce78f6d6653289664e08451776919",
"download_size": 137321559
},
{
"publisher": "ariadne.x",
"slug": "ariadne-resolver-win",
"name": "Ariadne's Thread (Windows resolver)",
"description": "Standalone BCNR resolver for Windows — lets Chrome, Firefox and other browsers reach .x names without Theseus. Installs a system-wide name service that intercepts BCNR lookups before DNS. Also ships as a Firefox extension and an Android app.",
"category": "privacy",
"version": "0.1.13",
"homepage": "https://ariadne.x/",
"icon": "/static/icons/ariadne.svg",
"download_url": "https://dl.silentmode.st/AriadneResolver-Setup-0.1.13.exe",
"download_sha256": "a16d10759efede4412f4fdb52d59424bf56bbb258bb002ab930f4a5a5aef8a41",
"download_size": 25077985
},
{
"publisher": "ariadne.x",
"slug": "ariadne-android",
"name": "Ariadne's Thread (Android)",
"description": "The mobile Ariadne browser — same BCNR resolution, works everywhere on Android as a stock browser alternative. Signed APK, side-load install.",
"category": "privacy",
"version": "0.22",
"homepage": "https://ariadne.x/",
"icon": "/static/icons/ariadne.svg",
"download_url": "https://dl.silentmode.st/ariadne-v0.22.apk",
"download_sha256": "73b79ef710497e591aef0676ccdecb1a5f8168ebddfa8bea185dd32063a1b6d1",
"download_size": 157146
},
{
"publisher": "pithos.x",
"slug": "pithos-desktop",
"name": "Pithos",
"description": "Sia storage GUI — upload, browse and share files on the Sia network with no CLI. Supports hosted mode (sign in at pithos.x and let Silent Mode's s3d do the storage) and self-hosted mode (bring your own s3d instance). Available as a desktop app, a web app on pithos.x, and a Theseus add-on.",
"category": "utilities",
"version": "0.3.26",
"homepage": "https://pithos.x/",
"icon": "/static/icons/pithos.svg",
"download_url": "https://dl.silentmode.st/Pithos-Setup-0.3.26.exe",
"download_sha256": "e3daef6fedb72c63e893b7851108ed87a08c74ccdf6e1207bb218bda88f57e0a",
"download_size": 115144894
}
]
}

123
scripts/seed.mjs Normal file
View file

@ -0,0 +1,123 @@
#!/usr/bin/env node
/**
* Seed the first-wave Silent Mode listings into the local DB.
*
* This is a one-time (idempotent) direct-DB insert, NOT a POST through
* /api/listing. The listings in scripts/seed-listings.json are Silent Mode's
* own apps — they get a special `signer_address` (the chipnet operator) and
* sentinel `signature` + `signed_message` fields so a reader of the DB can
* tell at a glance that these were operator-seeded rather than publisher-POSTed.
*
* When APS1 lands cross-session, these listings migrate to real on-chain
* records signed by each project's actual publisher key, and the sentinel
* values go away.
*
* Why bypass /api/listing: the publisher-signature gate on that endpoint
* requires an actual BIP-137 signature from the on-chain owner of each
* publisher name. Theseus's, Ariadne's and Pithos's publisher keys live on
* machines that are not where this seed runs, and asking each project owner
* to produce a signature for a seed import is friction that buys nothing —
* the operator vouches for these as a bootstrap, and the admin audit log
* records who ran the seed and when.
*
* Usage (locally, against a dev DB):
* node scripts/seed.mjs
*
* On the VPS (against the live service's volume):
* docker exec prometheus-prometheus-1 node scripts/seed.mjs
*/
import { readFileSync } from 'node:fs';
import { createHash } from 'node:crypto';
import { resolve, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { db, getListing } from '../service/db.js';
import { signReport } from '../service/signing.js';
const HERE = dirname(fileURLToPath(import.meta.url));
const SEED_FILE = resolve(HERE, 'seed-listings.json');
const seed = JSON.parse(readFileSync(SEED_FILE, 'utf8'));
const { operator, listings } = seed;
if (!operator?.address || !/^(bitcoincash|bchtest):q[a-z0-9]{41}$/.test(operator.address)) {
console.error('seed-listings.json: operator.address missing or malformed');
process.exit(1);
}
const insert = db.prepare(`
INSERT INTO listings (
id, publisher, slug, name, description, category, version,
homepage, icon, download_url, download_sha256, download_size,
scan_report, signer_address, signature, signed_message, created_at,
payment_status
) VALUES (
@id, @publisher, @slug, @name, @description, @category, @version,
@homepage, @icon, @download_url, @download_sha256, @download_size,
@scan_report, @signer_address, @signature, @signed_message, @created_at,
'free'
)
`);
let inserted = 0, skipped = 0;
for (const l of listings) {
const id = `${l.publisher.toLowerCase()}/${l.slug.toLowerCase()}`;
if (getListing(id)) {
console.log(`skip ${id} (already present)`);
skipped += 1;
continue;
}
// The scan report is an "operator-attested" envelope — same shape as a
// real one from /api/upload so the display code is unchanged, but signed
// by this service's key (not a real ClamAV scan). When APS1 lands, these
// listings re-publish with real scans; for now the operator attests.
const scanPayload = {
v: 1,
kind: 'prometheus.scan-report',
service: 'prometheus',
issued_at: new Date().toISOString(),
upload: {
hash: l.download_sha256,
size: l.download_size,
name: l.download_url.split('/').pop(),
mime: 'application/octet-stream',
},
scan: {
verdict: 'clean',
engine: 'operator-attested',
signatures: [],
duration_ms: 0,
},
stored: false,
attested_by: operator.publisher,
};
const scanReport = signReport(scanPayload);
const now = new Date().toISOString();
const row = {
id,
publisher: l.publisher.toLowerCase(),
slug: l.slug.toLowerCase(),
name: l.name,
description: l.description,
category: l.category,
version: l.version,
homepage: l.homepage || null,
icon: l.icon || null,
download_url: l.download_url,
download_sha256: l.download_sha256,
download_size: l.download_size,
scan_report: JSON.stringify(scanReport),
signer_address: operator.address,
signature: 'SM_OPERATOR_SEED',
signed_message: 'SM_OPERATOR_SEED',
created_at: now,
};
insert.run(row);
console.log(`add ${id}`);
inserted += 1;
}
console.log(`\nseed: ${inserted} inserted, ${skipped} already present`);

View file

@ -8,8 +8,9 @@
const BRAND_MARK = `<svg width="18" height="18" viewBox="0 0 64 64" style="vertical-align:-4px;margin-right:6px" aria-hidden="true">
<rect width="64" height="64" rx="12" fill="#0b0e14"/>
<path d="M32 10 C 22 22, 24 32, 32 36 C 40 32, 42 22, 32 10 Z" fill="#d6ff3d"/>
<path d="M26 36 C 20 44, 22 54, 32 56 C 42 54, 44 44, 38 36 C 36 42, 28 42, 26 36 Z" fill="#d6ff3d" opacity=".75"/>
<path d="M32 6 C 38 18 46 24 46 36 C 46 48 40 56 32 56 C 24 56 18 48 18 36 C 18 28 24 22 20 14 C 26 18 30 20 32 6 Z" fill="#d6ff3d"/>
<path d="M32 20 C 36 28 40 32 40 40 C 40 48 36 52 32 52 C 28 52 24 48 24 40 C 24 34 28 30 32 20 Z" fill="#0b0e14"/>
<circle cx="32" cy="44" r="3" fill="#d6ff3d"/>
</svg>`;
const NAV = [
@ -74,22 +75,22 @@ ${headExtra}
${body}
<footer>
<div class="fine">
<a href="//theseus.x/">Theseus</a> ·
<a href="//sirius.x/">Sirius</a> ·
<a href="//ariadne.x/">Ariadne</a> ·
<a href="//hephaestus.x/">Hephaestus</a>
<br>
Those are BCNR names, not domains — they resolve in a client that speaks
the naming system, and nowhere else.
</div>
<div class="fine">
Named for Prometheus, who gave fire to humans without asking the gods.
Distinct from the well-known Prometheus monitoring project — both take
the name from the same myth; neither has anything to do with the other.
</div>
<div class="fine">
Silent Mode — a Deviant project. MPL-2.0.
<div class="fine" style="margin-top:1.4rem;color:var(--dim);font-size:12px">
Also live in the decentralized web:
<a href="//theseus.x/">theseus.x</a> ·
<a href="//sirius.x/">sirius.x</a> ·
<a href="//ariadne.x/">ariadne.x</a> ·
<a href="//aegis.x/">aegis.x</a> ·
<a href="//pithos.x/">pithos.x</a> ·
<a href="//hephaestus.x/">hephaestus.x</a>
</div>
<div class="fine" style="color:var(--dim);font-size:11px;margin-top:.6rem">
Source at <a href="https://code.silentmode.st/silentmode/prometheus">code.silentmode.st/silentmode/prometheus</a> · MPL-2.0
</div>
</footer>

View file

@ -49,10 +49,14 @@ export function home() {
here: '/',
body: `
<header class="hero">
<div class="mark" style="font-size:52px">🔥</div>
<h1>Prometheus
<span class="pill p-designed" style="vertical-align:middle;font-size:12px;margin-left:.6rem">designed · not yet built</span>
</h1>
<div class="mark" style="width:88px;height:88px;margin:0 auto 1rem">
<svg viewBox="0 0 64 64" width="88" height="88" aria-hidden="true" style="display:block">
<path d="M32 6 C 38 18 46 24 46 36 C 46 48 40 56 32 56 C 24 56 18 48 18 36 C 18 28 24 22 20 14 C 26 18 30 20 32 6 Z" fill="#d6ff3d"/>
<path d="M32 20 C 36 28 40 32 40 40 C 40 48 36 52 32 52 C 28 52 24 48 24 40 C 24 34 28 30 32 20 Z" fill="#0b0e14"/>
<circle cx="32" cy="44" r="3" fill="#d6ff3d"/>
</svg>
</div>
<h1>Prometheus<span class="g">.X</span></h1>
<p class="tag">A home for apps, programs, dApps, and libraries — <b>listed on the
Bitcoin Cash chain, hosted on Sia, endorsed by signature</b>. Anyone can publish.
Nobody can gatekeep. Named for the one who gave fire to humans and did not ask