Relay (X23, X27): the intake key is its own tier (upload and file drops only, RELAY_INTAKE_COMPAT=0 closes it);
a run task needs an Ed25519 signature by the Mac run key over {to, nonce, body sha256, flags} (RELAY_RUN_PUB,
401 without) and an HMAC tag with the target's machine secret that the agent verifies before anything runs;
results and registration are bound to the machine the secret proves (403 on a forged from).
X24: every client and Mac tool sends x-relay-token as a header to /api/relay?fn=; the path token stays for the
phone page only. X25: the agent arms the logon task only for a restart a task asked for and disarms on start
and exit. X26: 30-day retention with blob deletion, feed capped at 100, the dl base as RELAY_DL_BASE held by the
agent, never in a body. X28: GET inbox never acks (POST inbox does), RELAY-REBOOT on its own line and only with a
reboot flag, 120/min and 10 failed auths/min per IP, no username or folder on register, WSL sudo scoped to
apt-get and dpkg with SETENV, no password on a command line. X29: the intake key reaches curl through -K in
upload.sh and both upload-log.bat; tools/ci/curl-header-check.sh fails the class. G14: TZ=UTC in ship-app.mjs
and publish-jobs.sh; tools/ci/commit-tz-check.sh fails the class; history-rewrite.md names the .old-2026-10-05
files as the values in the history. The handler moved to relay/lib/handler.mjs with injected sql and blobs
(relay/lib/blob.mjs holds @vercel/blob) so relay/test/handler.test.mjs drives it without a database:
47 tests across 6 suites, all green.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
18 lines
1.1 KiB
JavaScript
18 lines
1.1 KiB
JavaScript
// Igneum relay: one function, dispatched on ?fn=. Reached as /api/relay?fn=<fn> with x-relay-token (the Mac tools
|
|
// and the PC clients) or x-igneum-key (the relay key; the intake key for uploads only), and through the rewrite
|
|
// /r/<token>/api/<fn> from the phone's page. The contract and the whole handler live in ../lib/handler.mjs so
|
|
// relay/test/handler.test.mjs drives it with a fake database and fake blobs (5 October 2026, night: X23 to X28).
|
|
import { neon, authed } from '../lib/relay.mjs';
|
|
import { storeBuffer, clientUploadToken, deleteBlobs } from '../lib/blob.mjs';
|
|
import { makeHandler } from '../lib/handler.mjs';
|
|
|
|
const json = (res, status, obj) => { res.status(status).setHeader('Content-Type', 'application/json; charset=utf-8'); res.end(JSON.stringify(obj)); };
|
|
const state = {};
|
|
let inner = null;
|
|
|
|
export default async function handler(req, res) {
|
|
let sql;
|
|
try { sql = neon(); } catch (e) { res.setHeader('Cache-Control', 'no-store'); return json(res, 500, { ok: false, error: e.message }); }
|
|
if (!inner) inner = makeHandler({ sql, blob: { storeBuffer, clientUploadToken, deleteBlobs }, authed, json, state });
|
|
return inner(req, res);
|
|
}
|