GET /wake?since=<stamp> is public (the apps hold no token) and rate limited (30 a minute per IP). It holds up to
45 s, re-reading the stamp every 2 s, and answers {stamp, at, added, changed, held_ms} the moment the stored stamp
differs from since, else the unchanged stamp at the deadline. POST /r/<token>/wake {stamp, added} (the relay's
auth, also x-relay-token or x-igneum-key on /wake) records a stamp; one row per stamp in relay_wake, created by the
first POST. maxDuration 60 s for api/wake.mjs in vercel.json. api/relay.mjs is untouched.
The handler lives in lib/wake.mjs with its dependencies injected; relay/test/wake.test.mjs drives it with a fake
database, a fake clock and a fake sleep (the hold, the change, the deadline, the rate limit, the hold cap, auth, a
database error). CI's site job runs it with the other relay tests.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
One notice at a time, the most important first (app/igneum-app/ui/app.js, Notices; pure, unit tested):
0 update installing, urgent or failed 1 job failed 2 clock 3 job running
4 update available, downloading, ready, waiting for permission, manual 5 job done 6 updated
Lower notices wait their turn. Every notice has a close control; closing hides that notice's key until the
state moves on (a new status, version or job id).
States and their rules:
update available "Igneum Miner X is available." Install now, Later. Key update:X:pending.
update downloading "Downloading Igneum Miner X: 43%." (no percent when unknown), progress bar; same key as
available and checking, so Later hides the whole download until it is ready.
update checking "Checking Igneum Miner X." (the engine's staging step).
update ready "Igneum Miner X is ready. It installs by itself at a quiet moment." (auto on) or just
"... is ready." Install now, Later. Key update:X:ready.
update waiting Windows, nobody answered the administrator prompt: "... is waiting for permission. It
installs the next time someone is at this PC. Mining continues."
update manual "... is downloaded. Open it and drag the app over the old one." Open the download.
update installing "Installing Igneum Miner X. The app restarts itself. Mining continues until then."
(on a Mac, where the engine quits at once: "The app restarts itself in a moment.")
Also while the engine says "installing now" after Install now.
update urgent the engine's consensus-deadline text, ember, downloading percent when it downloads.
update failed "The update to X failed." plus one line of cause and Try again; rolled back:
"Igneum Miner X did not stay up and was rolled back." A dev build with no manifest
configured shows nothing (Settings still says it).
updated "Updated to Igneum Miner X from Y." Gone 60 s after the new version started.
job running "Job: <title> running, N min. <Stage>." with the last RESULT line underneath.
job done "Job: <title> done after N min. Report uploaded." Gone after 5 minutes.
job failed "Job: <title> failed after N min, exit C. Report not uploaded." plus the first error
line (BUILD FAILED / error / failed / panic among the result lines, else the summary).
Stays until closed. Timeout and aborted are "hit its time cap" and "was stopped".
clock as before: the engine's words, Sync clock, the manual hint; on the setup screens only
(the node card carries it on the dashboard). Jobs show on the dashboard only.
Layout: the strip reserves no height while empty; when a notice appears or goes, main's top moves once with a
150 ms transition (none under prefers-reduced-motion). Existing tokens only, nothing newer than 2022 CSS.
Screenshots: ?update=<state> as before, ?job=running|done|failed added (packaging/ota/README.md).
Test: node --test app/igneum-app/ui/notices.test.mjs (ordering, dismissed keys, wording, the 5-minute and
60-second timers); added to the CI site job. Built once with cargo (include_str) and checked against the
ui-mock scenarios and a scratch engine instance (IGNEUM_APP_DATA in a temp dir, fake worker).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
GitHub Actions workflow (.github/workflows/ci.yml) on push and pull_request with three jobs on the free runners:
igneum-pow `cargo test --release` and the igneum-census build; the two Python simulators' --quick modes under a
120-second timeout; the site build, an internal link check of site/*.html (tools/ci/link-check.mjs) and a gh-free
identity grep of the public export list (tools/ci/identity-check.sh over tools/ci/forbidden-strings.txt: machine
names, LAN and overlay addresses, home paths, local time zones, the log-intake key pattern; never a key or a name).
The node fork is too big for CI today and the workflow says so.
sim/finality_v2.py --quick is now a genuine smoke run (one day or hour per scenario, one partition and one eclipse
setting): 149 s at nice 19 on a loaded Mac, was 745 s. sim/difficulty/sim.py gains --quick (up50 and warmup-hard,
kaspa and igneum controllers, 36 s). One bench-log time-zone label reworded so the identity grep passes.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>