Download docs/CONSOLE.md from Lawless1987/covenant: direct link, hf CLI and curl.
- Browser
- Download file 6.59 kB
-
https://huggingface.co/Lawless1987/covenant/resolve/main/docs/CONSOLE.md
- Command line
-
hf download hf://Lawless1987/covenant/docs/CONSOLE.md
-
curl -L -o CONSOLE.md https://huggingface.co/Lawless1987/covenant/resolve/main/docs/CONSOLE.md
The console
AP_CONSOLE.bat β one page instead of fifteen .bat files.
AP_CONSOLE.bat read-only. It looks. It cannot touch anything.
AP_CONSOLE.bat --armed the buttons and the transaction panel work.
It opens http://127.0.0.1:5199/ and stops when you close the window.
What it shows
The three claims (M38). Disk source hash, how many nodes answer, how many of those are running that source, the heights, and whether they converge. This is the thing that was invisible for days: a machine can run a source from last week while every restart reports success. The console names the node that disagrees rather than averaging it away.
Per node. Version, source hash and line count, height, peers, pending
transactions, judge identity, alignment, available memory against the judge's
own footprint, anomaly kinds with counts, and the node's full warning list.
Flags for source β disk, degraded, crisis mode, judge keyless,
judge insecure, quorum not diverse, own genesis.
The watchdog's pulse, in seconds, against the 60-second bound the watchdog
itself states β and the last few ALERT lines. A missing log reads as
UNKNOWN, never as age zero.
Height comes from /health. The console never polls /chain: that route
is rate-limited to 20 reads per 60 seconds per node (M11), and a page
refreshing every 2.5 seconds would exhaust it and make a converged network look
split β an observability feature that changes what it observes (M47).
What it can do, when armed
Every action is a name in a fixed allowlist, mapped to a script that is already in this folder. Nothing from a request ever reaches a shell, an argument list, or a path. An ops console that can run an arbitrary string is a remote shell with a nicer font.
Each action declares what it costs you, and the page draws that difference:
gates verify config3 portdiag ports |
reads only β safe to click while thinking |
dashboard |
writes a file in this folder; touches no running process |
restart aclfix |
changes state β red, and asks before it runs |
sweep |
long run β 30 to 45 minutes against the live nodes |
An interface that draws "run the twelve gates, which change nothing" and "stop all three production nodes" as the same button teaches its reader to click without reading. That is M34 arriving through the front door instead of through a permanently-firing alert.
Transact. From-node, to-node, amount, memo, and mine. The signing happens
in the server process using the node's own verified helpers. The key is read at
the moment of signing, used, and dropped: never logged, never in a response,
never in the page. /api/state is asserted key-free by the suite, armed and
unarmed.
The panel states the cost in plain sight because it is not small: the ethics judge runs inside the submit call and judging is sequential under the chain lock. A warm verdict is ~12.8 s, a cold model load is ~39.9 s, the timeout is 91.3 s per judge, and a verdict costs roughly 512 J against the 13.6 J it takes to mine the block that carries it (B4).
If /alignment cannot be read, the console refuses the transaction rather
than substituting a plausible benefit_score. A guess there is either refused
by the governor's drift band or drags the band, and neither is visible.
Four rules that are structural, not configurable
- Loopback only.
BIND_HOSTis127.0.0.1;main()refuses to start if anything changed it, and every request is checked again at the handler. There is no environment variable that moves it. This console can restart nodes and sign transactions; a console that can do that must not be one env var away from the network. Putting it on a phone is a different program with an auth story, and it should be built as one rather than reached by flipping a string here. - Actions are a fixed allowlist, never a command string.
- Actions are off until
COVENANT_APP_ACTIONS=1exactly. No other value arms them and no value relaxes anything else β the same shape asCOVENANT_FORCE_NO_SANDBOX(P4/P10) andCOVENANT_REQUIRE_JUDGE_DIVERSITY(B2). Nothing in this system turns a control off from the environment. Arming lives in the console window; closing it disarms. - The signing key never leaves the process.
It also describes itself, because P15 counted the long-lived processes on this
machine and found the fourth one β the model server, since removed (2026-09-07) β reporting nothing. This is the
fifth. It prints its own source hash and line count at boot (P11) and writes a
line to logs/app.log at least every 60 seconds even when nothing changes,
and states that bound in its own banner, so a longer gap is readable as
death rather than calm (P16).
Proof
test_covenant_app.py β 51 checks. It starts three stub nodes on the real
production ports and runs the real unmodified covenant_app.py against them as
a subprocess, twice: once read-only, once armed.
python test_covenant_app.py
What it actually proves, rather than asserts:
- the console does not answer on this machine's non-loopback address
- every guard is mutation-tested (M31): the test flips the actions gate ON and requires the allowlist to keep refusing a name outside it, then flips it back and requires the refusal to return
COVENANT_APP_ACTIONSset totrue,0,yesor empty does not arm it β each checked by starting the console that way and asking it- a node running a different source is named (M38); a height split is reported as a split; a node that stops answering is reported down with its error kind
/chainis never touched β the stubs count every hit and the count is zero/api/statecarries no key material, armed or not- traversal and near-miss action names are refused:
../verify_bundle.py,/etc/passwd,GATES,gates,gates;rm -rf /,gates%00 - a missing watchdog log reports
age=None, notage=0 - the page loads nothing from anywhere, and says so in a CSP header
- an unreadable
/alignmentrefuses the transaction instead of guessing
The suite races gates β not sweep β for its concurrency check, because
run_local_sweep.py is a 30-to-45-minute job against the live nodes. A test
with a side effect on production is not a test.
If the production ports are busy the suite reports UNKNOWN and exits 2. It does not fall back to different ports and call that a pass.