The service behind prometheus.x � standalone .x site that accepts app listings, scans binaries, and attaches signed scan reports.
Find a file
Local Dev 72f7d41902 prometheus: signed listings — BIP-137 publisher sign, SQLite index
POST /api/listing accepts a JSON body with the manifest fields, a
reference to a signed scan report from /api/upload, and a BIP-137
signature. Before the row lands in SQLite the service verifies three
things:

  1. the attached scan_report was signed by this service, is for the
     exact (hash, size) the listing claims, and the verdict is clean —
     a publisher cannot swap in a different file's clean report;

  2. the publisher's signature recovers to a valid cashaddress, and
     that address matches the on-chain owner of the publisher's BNS
     name (gateway /api/name/<name>) — recovery alone is never enough
     per [[recovery-is-not-verification]];

  3. the usual shape checks: category in the allow-list, sha256 is 64
     hex, download URL is http(s), slug matches [a-z0-9-]{1..64}, body
     under 1 MiB.

GET /api/listings and GET /api/listings/<publisher>/<slug> are read-only
endpoints the browse milestone will render from.

MOCK_BNS_OWNER=<cashaddr> short-circuits the gateway call for local
testing without a chipnet gateway reachable — same pattern as MOCK_SCAN.

Dependencies:
- @bitauth/libauth, for the secp256k1 primitives behind BIP-137 recovery
  and the cashaddress encoder. Same primitive Argus's registrar uses, so
  signatures from Argus-compatible wallets verify unchanged.
- node:sqlite (ships with Node 22+) for the listings DB — one file next
  to the service, WAL journaling, no native build step. engines bumped
  to ">=22".

Lifted service/lib/sign-message.js from Argus so Prometheus does not
have to pull the resolver's whole dependency tree in for one verifier.
Removed its NETWORK import; the default address prefix comes from
BNS_NETWORK=chipnet|mainnet instead.

INTERIM: no APS1 record on chain yet. The signed row IS the listing;
when APS1 is defined cross-session the service will add an on-chain
publish step that points at the same signed manifest. The browse and
admin milestones can proceed against this DB in the meantime.

scripts/test-listing-roundtrip.mjs drives the whole flow end-to-end
with a deterministic test key, so a sanity check is a two-command
sequence: start the server with MOCK_SCAN=clean + MOCK_BNS_OWNER=<the
test address>, then run the script. Negative paths (fake scan report,
bad category, duplicate slug) also verified by hand.
2026-10-08 01:48:12 +02:00
public prometheus: scaffold the standalone service — pages, routing, static assets 2026-10-05 22:22:47 +02:00
scripts prometheus: signed listings — BIP-137 publisher sign, SQLite index 2026-10-08 01:48:12 +02:00
service prometheus: signed listings — BIP-137 publisher sign, SQLite index 2026-10-08 01:48:12 +02:00
.gitignore prometheus: upload + ClamAV scan + signed scan reports 2026-10-05 22:41:55 +02:00
package-lock.json prometheus: signed listings — BIP-137 publisher sign, SQLite index 2026-10-08 01:48:12 +02:00
package.json prometheus: signed listings — BIP-137 publisher sign, SQLite index 2026-10-08 01:48:12 +02:00
README.md prometheus: scaffold the standalone service — pages, routing, static assets 2026-10-05 22:22:47 +02:00

Prometheus

The service behind prometheus.x — a standalone website that accepts app listings, scans the binaries, generates APS1 records for publishers to sign, and serves the browse pages.

The architecture decisions and the reasoning behind them live at _coordination/sessions/prometheus-x-architecture.md. Read that before touching the code; it answers the questions this directory otherwise invites ("why isn't this on Sia?", "why isn't the admin on another subdomain?", "why Node?").

service/     Node HTTP server, templates, scanner, storage, payments
public/      Static assets served under /static/
content/     Prose content in a form the templates render into pages

Run it locally

cd Prometheus
npm install          # none yet; placeholder for when deps show up
node service/server.js

Opens on http://127.0.0.1:3700 by default. Override with PORT=xxxx.

Layout

The server is one node:http listener behind a trivial map-based router. Pages are plain functions that return {title, description, body} and layout() wraps them in the common document shell. Static files under public/ are served directly.

There's no framework and no templating engine on purpose — a site this small does not earn a dependency surface, and the response-rendering path is short enough to read at a glance.