prometheus/package.json

19 lines
350 B
JSON
Raw Normal View History

{
"name": "prometheus",
"version": "0.1.0",
"private": true,
"type": "module",
"description": "The service behind prometheus.x",
"license": "MPL-2.0",
"engines": {
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
"node": ">=22"
},
"scripts": {
"start": "node service/server.js"
prometheus: upload + ClamAV scan + signed scan reports POST /api/upload accepts a multipart file, spools it to a temp path while hashing to SHA-256, hands the on-disk copy to clamd via INSTREAM, keeps the file at uploads/<sha256>.bin on a clean verdict and discards it on anything else. The response carries the (hash, size, verdict) tuple signed by the service's ed25519 key — the artifact the manifest step will attach to the APS1 record later. For local dev on a box without ClamAV, MOCK_SCAN=clean|infected|error short-circuits the TCP call while still draining the bytes end-to-end. CLAMD_HOST / CLAMD_PORT / PROMETHEUS_MAX_UPLOAD_BYTES override the defaults (127.0.0.1:3310, 2 GiB). Service key lives at .keys/service.key (gitignored, 0600), generated on first start if absent. The matching public key is served at /.well-known/prometheus-service-key.json so clients can cache it per origin. ed25519 chosen over BIP-137 because the scan report is a service attestation, not a Bitcoin thing — the key never signs value, never signs for a user, never touches the chain. Canonicalisation walks the payload recursively (sorted keys at every level, no whitespace). The first draft used JSON.stringify with a keys array, which only serialises top-level keys from the array — nested objects came out as {}, so the signature verified nothing useful. /healthz pings clamd (or the mock) so monitors can tell when the scanner is down. The /submit page gets a working upload form that drives the endpoint and renders the full signed response, so the whole chain is testable in the browser as well as via curl. One dependency added: busboy. Rolling our own multipart parser was the obvious alternative; busboy is one small, maintained library with no runtime deps of its own, and multipart RFC 7578 edge cases are not places this project earns anything by rediscovering.
2026-10-05 22:41:55 +02:00
},
"dependencies": {
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
"busboy": "^1.6.0",
"@bitauth/libauth": "^3.1.0-next.8"
}
}