Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -1211,6 +1211,21 @@ replaced a standalone `biorouter-headless` binary and its Linux tarball, both de
operator-pinned-off extension and its ordinary path needs none. ⚠ Not a security change:
nothing that was refused becomes permitted. The availability flag is sampled ONCE per roster
and threaded, so a roster can never half-believe a person is reachable.
- **Stop and steering answer to the reach gate on a keyless daemon** (SD-11). `/agent/cancel`,
`/interrupt` and the two `/agent/continuation/*` routes take the proof on a daemon that holds
a key, and on one that holds none gate through `authorize_agent_control` — the *same call*
`/agent/stop` makes — via `reply.rs::authorize_turn_control`. Tightening that gate tightens
who may press Stop in a browser. A keyless steer is recorded unstamped (never `UserDirect`),
and a subagent's tab stays refused. ⚠ Keyless behaviour can only be tested in its own binary
(the digest is a process-global `OnceLock`): `cargo test -p biorouter-server --test
turn_control_no_user_key`.
⚠ **The CLI reads the refusal's shape, not its status.** `biorouter session cancel` / `attach`
/ `send` cannot ask a daemon whether it holds a key, so they send without the proof and ask the
person for the key only on turn control's **empty** 403 — the keyed `Unproven` arm; every
keyless refusal carries a sentence and is printed instead (`key_verdict` in
`commands/session_watch.rs`). A sentence added to `Unproven`, or an empty keyless refusal,
breaks the terminal silently — one never prompts on the desktop's daemon, the other prompts a
`serve` user for a key that does not exist. Pinned from both sides.
- **Proof of a person is checked at the resolution choke point, not at one route.** Every door
that answers a parked decision — the HTTP route, an Agent Drafter app's WebSocket, ACP, the
CLI prompt, the TUI modal, an ancestor agent's relay — passes a `DecisionAuthority` into
Expand Down
6 changes: 3 additions & 3 deletions crates/biorouter-cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,7 @@ enum SessionCommand {
no_wait: bool,
#[arg(
long,
help = "Read the daemon's raw user-action key from the first line of stdin instead of prompting on the controlling terminal"
help = "For a daemon started with a user-action key: read the raw key from the first line of stdin, instead of being asked for it on the terminal once the daemon wants it"
)]
user_action_key_stdin: bool,
},
Expand Down Expand Up @@ -699,7 +699,7 @@ enum SessionCommand {
read_only: bool,
#[arg(
long,
help = "Read the daemon's raw user-action key from the first line of stdin instead of prompting on the controlling terminal"
help = "For a daemon started with a user-action key: read the raw key from the first line of stdin, instead of being asked for it on the terminal once the daemon wants it"
)]
user_action_key_stdin: bool,
},
Expand All @@ -709,7 +709,7 @@ enum SessionCommand {
session_id: String,
#[arg(
long,
help = "Read the daemon's raw user-action key from the first line of stdin instead of prompting on the controlling terminal"
help = "For a daemon started with a user-action key: read the raw key from the first line of stdin, instead of being asked for it on the terminal once the daemon wants it"
)]
user_action_key_stdin: bool,
},
Expand Down
Loading
Loading