The service behind prometheus.x � standalone .x site that accepts app listings, scans binaries, and attaches signed scan reports.
Find a file
Local Dev cb1589cf36 prometheus: admin panel — login, listings, 3-mode toggle, audit log
/admin is wallet-gated. The configured ADMIN_PUBLISHER is a BNS name;
only the on-chain owner of that name can sign in. The sign-in flow is
BIP-137 (same primitive publishers use): the login page shows a fresh
one-shot challenge, the admin signs it in their wallet, pastes the
signature, and the service verifies that it recovers to the current
on-chain owner. Session is a 24-hour ed25519-signed cookie minted by
the service key.

Pages:
  /admin             dashboard — totals, mode state, recent listings + audit
  /admin/login       BIP-137 challenge sign-in
  /admin/listings    all listings, with a Withdraw button per row
  /admin/modes       global + per-category publish-mode toggle
  /admin/audit       the hash-chained audit log

The three publish modes exist as toggles:
  `append`     — any valid listing goes in (launch default)
  `scan-first` — infected uploads are rejected before they land
  `review`     — clean listings wait for human approval
Global mode is the fallback; a per-category override takes precedence
when set. The toggle persists; the review-queue enforcement lands in a
later milestone (the enforcement sketch is in modes.js's header).

Audit log:
  Every admin action (login, set_mode, clear_mode, withdraw_listing) is
  an append-only row with a sha256 chain over the previous row's hash.
  The chain does not prevent edits; it makes retroactive ones loud —
  row N's `prev_hash` disagreeing with row N-1's `this_hash` is the
  tamper signal.

Withdrawal:
  Soft — `withdrawn_at` on the listing row. Browse hides withdrawn
  listings (already the case) and the detail page returns 404 for them.
  Nothing in the chain is undone; this is Prometheus's own view only.

Session design:
  Cookie is `prom_admin=<payload b64url>.<signature b64url>`, signed with
  the ed25519 service key, HttpOnly, SameSite=Strict, Path=/admin,
  24-hour expiry. Reconfiguring ADMIN_PUBLISHER invalidates in-flight
  sessions by name mismatch. Challenges live in a 10-min TTL map and
  are tied to a specific name so one admin's challenge cannot authenticate
  another.

Added:
  service/admin.js         route handlers + dispatch
  service/admin-pages.js   HTML templates for the four pages
  service/admin-session.js challenge + cookie mint/verify + readSession
  service/audit.js         hash-chained append helper
  service/modes.js         publish-mode read/write with override semantics
  schema: settings + audit tables

scripts/test-admin-roundtrip.mjs drives the whole flow (unauth redirect
→ challenge scrape → sign → login → dashboard → set mode → audit
inspection) with the same deterministic test key the listing-roundtrip
script uses. Withdraw-flow spot-check: create a listing, log in as
admin, withdraw it, confirm browse hides it and the detail page returns
404. All seven checks pass.
2026-10-08 21:35:48 +02:00
public prometheus: scaffold the standalone service — pages, routing, static assets 2026-10-05 22:22:47 +02:00
scripts prometheus: admin panel — login, listings, 3-mode toggle, audit log 2026-10-08 21:35:48 +02:00
service prometheus: admin panel — login, listings, 3-mode toggle, audit log 2026-10-08 21:35:48 +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.