Wiki · Architecture & Decisions
ADR-0008 — Human presence is required to go live
How to read this page
Three ways to read this page. Precise is the document itself, exactly as it is written in the repository. Plain and Clear were written for this website to help you meet that document — they are about it. They are not it, and they are not evidence.
This is the design record of the part of the estate whose job is to stop the rest of it claiming more than it has measured. It runs to architecture notes, numbered decision records, phase plans, and the results written after each phase ran.
It is for anyone curious how a decision was actually reached — what was considered, what was refused, and what the refusal cost. The decision records are the most durable part: each names one choice, the alternatives, and the consequence accepted in exchange. The failure-modes page is worth the detour, because it states each refusal as something you could go and test rather than as a promise.
Read the architecture page first. It opens by declaring itself part design and part built, which sets the tone for the whole section. Then the first decision record, then whichever phase interests you — read as a pair, the plan and the results page written afterwards, including the phases where a premise turned out to be wrong and the receipt says so.
What it is not: a description of running software, and not a complete record. Three documents from this area were withheld from publication, because they describe private infrastructure or the operator declined them; they are listed as withheld rather than quietly dropped, so you can see that they exist.
Your browser cannot switch reading levels, so the document itself is shown.
Precise — the source document
This is the document. Rendered from the repository at the commit above, with nothing rewritten for the web. A gate re-renders it on every deploy and fails the build if a single byte differs.
- Status: PROPOSED — NOT ADOPTED. This document is not in force.
- Date: 2026-07-27
- Deciders: Michael (has not yet ruled) — drafted by Claude under Phase 9 step 3.3
- Amends: nothing yet. It proposes a contract for
viewer/golive_guard.cjsinUNI.Minecraft(branchgen2-runtime) and forFAILURE-MODES.mdF31.
An ADR is a contract, and a contract amendment is S5 — the operator's, never an agent's. This
was drafted by Claude on 2026-07-27 during Phase 9 step 3.3 so that there is something concrete to
rule on. Until Michael adopts it, the code it describes is already built and already refusing,
which is the safe direction: the door is shut and nothing can open it.
Context
FAILURE-MODES.md declares:
F31 | go-live is requested by an agent | refuse — it is typed by a human | falsifier: any agent path reaches go-live
Measured on 2026-07-27, before this step, the repository had six code paths that reach
StartStream, and between them two string comparisons:
| path | guard, before |
|---|---|
command_center.cjs /api/golive |
confirm === "CONFIRM" — on unauthenticated loopback |
studio.cjs golive CONFIRM |
arg === "CONFIRM" — on argv |
command_center.cjs /api/broadcast_test |
nothing, and public by owner directive |
obs_golive.cjs |
nothing |
obs_streamtest.cjs |
nothing |
obs_ctl.cjs |
nothing — and its request type comes from argv, so a search for the word StartStream cannot even see it |
A seventh was found while building the gate: obs_req.cjs sends an arbitrary
{requestType, requestData} read from a JSON file named on argv. It contains the word
StartStream nowhere and is a complete path to air.
curl -X POST 127.0.0.1:8098/api/golive -d '{"confirm":"CONFIRM"}' is one line. Four of the seven
paths did not ask for even that.
Decision
Go-live requires a human-presence token, and every path to air passes one chokepoint.
viewer/golive_guard.cjs is the only function in this repository that may say yes. It refuses
unless a token exists that is:
- present — absence is refusal, never a default-allow;
- fresh — minted within 120 seconds, because it attests presence a moment ago and nothing longer;
- interactive — minted by a desktop session, which excludes service sessions, scheduled tasks, remote shells and every script in this repository;
- single-use — a nonce, spent on actuation, so a token cannot be replayed.
Refusal throws rather than returning. A refusal you can assign to a variable is a refusal you can ignore, and that is precisely how five of the seven paths came to have no guard at all.
The typed CONFIRM is kept on both paths that had it. It stops a slip of the hand. It is no
longer the thing standing between an agent and the air.
Claim level: presence_evident. NOT unforgeable.
This wording appears in the module, in every grant the guard issues, in the gate output, and in the operator-facing prover. It is not a caveat in a design document.
What it buys: no headless agent, service-session process, scheduled task, remote shell, CI job, or script in this repository can go live.
What it does not buy: an agent already running inside the operator's live desktop session, with read access to the token, can replay it before it expires.
And the harder limit, stated because it is the real one: OBS WebSocket listens on
127.0.0.1:4455 with no authentication — obs_ctl.cjs's own header says so. Every path
guarded here is a path through this repository. Four lines of Node that never import the guard
reach the same actuator directly. F31 binds this codebase's paths to air. It does not bind the
box.
Closing that means enabling authentication on the OBS WebSocket server. That is a change to the
operator's studio configuration — S2, "any write to a host" — and is his.
What is NOT decided here, and is the reason this needs a ruling
The minting side does not exist. The plan names the intended mechanism: a token minted by the
interactive-session WPF widget (the HUD). It is not built, and building it is what opens the
door — S6, "go-live, in any form".
So the current state is: every path to air refuses, and there is no way to make one allow. For a guard, that is the correct resting state. It also means go-live is currently closed, by construction, until Michael rules this ADR and the mint is built to match it.
Consequences
- Go-live cannot happen until the mint exists. Deliberate. The door is not open by default and never was meant to be.
viewer/verify_golive_refuses_agents.cjsdiscoversStartStreamcall sites from the filesystem and fails if any is unguarded, so an eighth path fails the gate on the day it is added rather than the day it is used. It also requires every OBS forwarder to be classified in a table a human has to read — internal builders are distinguished from externally-driven ones by declaration, not by a hidden regex.viewer/prove_golive_refuses_me.cjsis the operator's probe: an agent trying to go live down every path, refusing every time, exiting non-zero if any gets through.- Presence tokens are machine-local and git-ignored. Committing one would make a live claim that a human is at this desk into a shared secret.
The question this ADR is asking
- Is
presence_evidentan acceptable claim level for opening a public broadcast, given it is explicitly not unforgeable against an agent inside the operator's own session? - Should OBS WebSocket authentication be enabled, which is the only thing that would make the guard bind the box rather than the codebase?
- Who mints, and from where — the WPF HUD as planned, or another interactive surface?
Until these are answered, the guard refuses everything, and that is not a failure state.
sha256 acd0afaab24d14a0 — of the original file, so what was ingested stays checkable.
Plain — written for this website, not the source document
Read the status line first: this record is proposed and not adopted, and it says of itself that it is not in force. It was drafted so that the operator has something concrete to rule on, and he has not yet ruled. Amending a contract is his, never an agent's.
What it proposes is that going live — putting a broadcast on air — requires evidence that a human is present at the desk, and that every path to air passes one chokepoint. The token it asks for must exist, be freshly minted, come from an interactive desktop session, and be usable once. Absence is refusal, never a quiet default to yes.
The record is unusually honest about what this does not buy. It calls its own claim level presence-evident and says outright it is not unforgeable. A process already inside the operator's own live session could replay the token. And the deeper limit is that the broadcast software's own control socket has no authentication at all, so the guard binds this codebase's paths, not the machine.
The minting side does not exist yet, so nothing can currently be allowed.
Plain · written 2026-08-01 by claude-opus-5 · not yet checked by a person · about the document whose sha256 is acd0afaab24d14a0
Clear — written for this website, not the source document
Nothing here is decided, though it is written as a decision record. The status line says proposed and not adopted, and the text repeats that the document is not in force. It was drafted by an agent during a remediation step so that the operator would have something concrete to rule on; amending a contract is his call. The record notes that while it waits, the code it describes is already built and already refusing — the door is shut and nothing can open it.
The context is a declared failure mode: if an agent requests going live, the system should refuse, because going live is meant to be typed by a human. Measured before this work, the record found several code paths that could reach the broadcast start command, and between all of them only two string comparisons. Most asked for nothing at all. One was found only while the gate was being built, because it takes its request from a file named on the command line and never contains the relevant word.
The proposal is that going live requires a human-presence token and that every path to air passes one chokepoint, a single guard that is the only function permitted to say yes. The token must be present, since absence is refusal rather than a default to allow. Fresh, because it attests presence a moment ago and nothing longer. Interactive, minted by a desktop session, which excludes service sessions, scheduled tasks, remote shells and every script in the repository. And single-use, so it cannot be replayed. Refusal throws rather than returning a value, because a refusal you can assign to a variable is a refusal you can ignore — which the record says is how most paths came to have no guard at all. The typed confirmation word is kept where it existed, but only against a slip of the hand.
The most important section limits the claim. The record names its own level as presence-evident and states that it is not unforgeable, and says this wording appears in the module, in every grant, in the gate output and in the operator's prover. What it buys: no headless agent, service process, scheduled task, remote shell, continuous-integration job or script in the repository can go live. What it does not buy: something already running inside the operator's live desktop session, able to read the token, could replay it before it expires. And the harder limit is that the broadcast software's control socket listens locally with no authentication, so a few lines of code that never import the guard reach the same actuator. The guard binds this codebase's paths to air; it does not bind the machine. Closing that is a change to his own studio configuration, and is his.
The record is equally plain that the minting side does not exist. The intended mechanism is named as a planned interactive widget, and building it is what would open the door. So the present state is that every path refuses and there is no way to make one allow. That is correct for a guard: going live is closed by construction until the record is ruled on and a mint is built.
It closes with three questions for the operator. Whether presence-evident is an acceptable claim level for opening a public broadcast. Whether authentication should be enabled on the broadcast control socket, which is the only thing that would make the guard bind the machine. And who mints a token, and from where.
Clear · written 2026-08-01 by claude-opus-5 · not yet checked by a person · about the document whose sha256 is acd0afaab24d14a0