diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a7a578f3..62df3e95a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,16 @@ Compatibility is documented in release notes, not encoded in the version string. ### Added +- A tokenless `queue_start` now files a **start request** the operator confirms + in the BLUESKY queue panel, instead of dead-ending in a refusal. Deployed + web terminals never hold the scan launch token by design; the agent stages + and queues, the request appears in the queue panel beside the queue it would + drain, and the human's *Confirm start* click — the panel's own token-gated + start — is what arms it. Dismissing the request is always available and + starts nothing. Skill and error-message guidance across the scan stack now + explains this posture so agents hand the start to the human instead of + chasing the token in configuration. + - An archiver read that comes back empty now says why: the response carries a coverage verdict — the window predates or postdates the archive, the channel was never recorded, or the window holds a genuine gap — with the archive's @@ -156,6 +166,13 @@ Compatibility is documented in release notes, not encoded in the version string. ### Changed +- Deployed agents can no longer reconfigure their own harness: the Claude Code + CLI's bundled harness-configuration skills (`update-config`, + `keybindings-help`, `fewer-permission-prompts`) are switched off in every + rendered project, and the `setup-mode` skill (which can patch config.yml) + left the operator preset's default roster — it stays in the artifact catalog + for admin profiles to opt into. Rebuilt control-assistant projects will + report preset staleness once; that is the intended signal. - **Log out** moved into the web terminal's display menu, alongside **Settings** — the two now sit side by side under a line naming the signed-in user. The separate user chip in the header is gone, leaving search and the diff --git a/docs/source/how-to/bluesky/queue.rst b/docs/source/how-to/bluesky/queue.rst index cc3d1fd3a..c5b4991c2 100644 --- a/docs/source/how-to/bluesky/queue.rst +++ b/docs/source/how-to/bluesky/queue.rst @@ -66,12 +66,13 @@ One queue, three ways to drive it .. code-block:: text - POST /queue/items add the current draft revision - POST /queue/start start draining (needs the launch token) - POST /queue/stop stop after the running item - POST /queue/abort abort the running plan — never gated - GET /queue what is queued and running - GET /runs recent runs; /runs//data for the numbers + POST /queue/items add the current draft revision + POST /queue/start start draining (needs the launch token) + POST /queue/start-request ask a token holder to start — arms nothing + POST /queue/stop stop after the running item + POST /queue/abort abort the running plan — never gated + GET /queue what is queued and running + GET /runs recent runs; /runs//data for the numbers Every refusal comes back with a ``detail`` object of the form ``{"code": ..., "detail": ...}`` — a stable code for software to @@ -115,6 +116,9 @@ quirks worth knowing: - The launch token — this hands work straight to a moving machine. * - Start the queue - The launch token. + * - Ask for a start (file a start request) + - Nothing — the request arms nothing. Confirming it *is* the + token-gated start, done from the queue panel. * - Stop the queue / abort the running plan - Nothing. Ever. Anywhere. * - Withdraw a pending stop @@ -126,6 +130,14 @@ quirks worth knowing: anything, even on an idle queue. Its halts and its read tools are never taken away. + In a deployed control room the agent's environment never holds the launch + token at all — the token lives with the operator panels. The agent's + ``queue_start`` then files a **start request**: it appears in the BLUESKY + queue panel beside the queue it would drain, with *Confirm start* and + *Dismiss* controls. Confirming fires the panel's own token-carrying start; + dismissing starts nothing. Either way, the human's click is the arming + decision. + .. dropdown:: When something is refused :color: info :icon: alert @@ -138,7 +150,13 @@ quirks worth knowing: for a repeat. ``launch_token_required`` - The operation was armed and the deployment is not. Nothing was started. + The operation was armed and the caller held no valid token. Nothing was + started. (An agent asking for a plain start never hits this — it files a + start request for the panel instead.) + + ``queue_empty`` + A start was requested with nothing queued, so there was nothing a + confirmation could run. Stage and add a plan first. ``browse_only_connector`` This deployment cannot execute scans at all — it is pointed at the diff --git a/docs/source/how-to/bluesky/run-first-scan.rst b/docs/source/how-to/bluesky/run-first-scan.rst index f008a023c..dad3c97f1 100644 --- a/docs/source/how-to/bluesky/run-first-scan.rst +++ b/docs/source/how-to/bluesky/run-first-scan.rst @@ -108,8 +108,10 @@ token, no switch can disable them: process with its own copy of the devices. That is why the queue survives restarts of everything around it. - **Start queue** is checked against a **launch token** the deployment - holds. For the agent, starting is additionally switched off entirely - whenever the project's control-system writes are disabled. + holds. In deployed control rooms the agent never holds it — asking the + agent to start a scan gets you a **start request** to confirm in the + queue panel. For the agent, starting is additionally switched off + entirely whenever the project's control-system writes are disabled. .. dropdown:: First-run hiccups :color: info diff --git a/src/osprey/cli/build_injectors.py b/src/osprey/cli/build_injectors.py index c43d3f909..1469d01e5 100644 --- a/src/osprey/cli/build_injectors.py +++ b/src/osprey/cli/build_injectors.py @@ -519,7 +519,9 @@ def _inject_bluesky(bluesky: BlueskyConfig, project_path: Path) -> None: logger.info(" ✓ Injected Bluesky scan bridge (port %d)", bluesky.port) logger.info( " Token: `osprey deploy up` writes BLUESKY_LAUNCH_TOKEN to .env; " - "the `bluesky` MCP server's queue tools read it automatically." + "a host-run agent's queue tools read it automatically. Deployed web " + "terminals never receive it — their agents file a start request the " + "operator confirms in the BLUESKY queue panel." ) logger.info( " Images: `osprey deploy up` builds the bluesky-bridge image locally " diff --git a/src/osprey/deployment/web_terminals/env_production.py b/src/osprey/deployment/web_terminals/env_production.py index 6a6600fda..d2ca8c30a 100644 --- a/src/osprey/deployment/web_terminals/env_production.py +++ b/src/osprey/deployment/web_terminals/env_production.py @@ -185,10 +185,16 @@ def _build_env_production_subset( :mod:`osprey.deployment.container_lifecycle`, minted per deploy under those fixed names). Neither kind is anything a web terminal presents to anyone: the containers that need a service token read the deploy ``.env`` - the main compose file hands them, and nothing in a web terminal reads one - at all. This is the security spec for this function: a var absent from the - enumerated list above can never appear in the returned dict, regardless of - what the input ``.env`` contains. + the main compose file hands them. The one web-terminal consumer that + WOULD read a service token if present — the bluesky MCP server's + ``${BLUESKY_LAUNCH_TOKEN:-}`` — is tokenless here on purpose: an agent + container must never hold a write-arming bearer credential (any Bash or + Python it runs could read it and arm the queue with no approval), so its + ``queue_start`` files a panel start request and the operator's panels + sidecar, which does receive the token, answers it. This is the security + spec for this function: a var absent from the enumerated list above can + never appear in the returned dict, regardless of what the input ``.env`` + contains. :param config: Raw deploy config (facility fields merged in — see ``modules.web_terminals.image_source`` in :func:`ensure_env_production`). diff --git a/src/osprey/interfaces/bluesky_panels/panels/bluesky/index.html b/src/osprey/interfaces/bluesky_panels/panels/bluesky/index.html index 8e20551ee..60c4652aa 100644 --- a/src/osprey/interfaces/bluesky_panels/panels/bluesky/index.html +++ b/src/osprey/interfaces/bluesky_panels/panels/bluesky/index.html @@ -241,6 +241,22 @@

Queue

+ + +