P3-1: releasing a console start lock marks it released through its own
descriptor and removes the path only while it is still that file; a
released lock put back by a racing clear is cleared by the next start or
stop.
P3-2: org definitions reports unknown-organization only when the
organization file itself is missing; another missing file names the
operation.
P3-3: the path cut also covers a path after ':' or inside backticks.
1. Stale bus host lock refusals from bus status, start, stop and restart
name mosaic bus recover ORG.
2. org definitions: unknown org, unknown or malformed name and bad id give
one refusal or usage line, no stack trace, no host path.
3. Pack, board and workflow refusals print their hint as template save does;
tested with the real CliError transport shape.
4. console start and stop clear a console/start.lock whose named supervisor
(pid and start time) is gone; a live or unnamed holder refuses.
5. Template save keeps free text verbatim and writes no placeholders; the
preview lists each field that mentions an org-specific name.
6. A request the shim never sent (no socket, connect refused) exits 5 and
the CLI reports bus-not-running with the start and recover line.
7. autonomy-precondition carries the check that failed, including on the
hire paths.
8. Saving under an existing template name refuses template-exists with a
next step; refusal table entry added, channel-proof pins moved.
D2 security re-check P1 (agent-guard). mosaic bus start|stop|restart and
mosaic console start (with or without --dev-local-owner), stop and restart
refuse inside an agent run with refuseInsideAgent's refusal (exit 3), as
bus recover does. The check reads the given environment and this process's
own, so a sanitized io.env does not hide a marker; bus recover and console
restart now check both too. consoleStart refuses for every Console. Status
verbs stay open. No new marker list and no new human gate.
The Console's Restart bus runs org-bus.mjs in the Console process; its new
host goes through the guarded CLI entry with the Console's own environment.
Restart Console relaunches under the supervisor without the CLI.
The agent-run refusal on a dev-local-owner start now checks the starting
process's own environment as well as the environment given for the
Console, so a caller cannot pass a clean env to get past it.
The start lock now names its holder (pid and start time). A detached
start that times out and kills its supervisor's process group clears the
lock only when it names that supervisor and the supervisor is gone, so a
forced kill no longer blocks every later start.
Build review P2: the supervisor ignores a lost reply pipe and keeps
supervising. Security P2: a stop signal during start is held until the
start settles, and the CLI's start timeout signals the supervisor's
process group. Security P1 (part): console start --dev-local-owner
refuses inside an agent run. Tests cover review, confirm and reverse on
the org autonomy route; TOOLS.md and the webui README are corrected.
A --dev-local-owner Console's organization pages read writable:false because
the per-org options had no autonomy writer and the route fell back to the
request transport, which org options never set. The org options now carry an
autonomy writer on the organization's console transport, fenced to the four
owner autonomy verbs. The route prefers it and keeps requestWrite otherwise.
mosaic console start --dev-local-owner --detach now runs the Console under a
detached supervisor, so Restart Console (exit 75) relaunches it on the same
address. A non-dev detached Console is unchanged. A deployed --sso --send
Console has no organization routes and keeps its root autonomy transport;
a test pins both.
Self-service operation from the WebUI, for a dev instance first.
- Settings > Console > Restart Console. A foreground `mosaic console
start` now supervises the webui: the child exits 75 after answering a
restart and the supervisor relaunches it with the same argv. Org buses
keep running. /api/config carries a per-process boot id, so the open
page polls until a new process answers and then reloads. A detached
Console has no supervisor and answers 409.
- Restart bus on every "Restart needed" receipt and on the bus-down
banner: POST /api/orgs/<id>/restart/bus restarts a running bus or
starts a stopped one, then shows a done receipt with the time.
- Settings > Routing: after a save, the page lists how the change
reaches each agent (next start, session end, thread idle) and offers
"Restart <agent> now" for a running one. A session is terminated with
the reason "route change" and launched again; a thread is terminated.
- Organization settings: the signed-in owner's settings, routing,
agent, plug-in and Model proxy writes now reach the selected org's
bus instead of answering 403. Org mode exists only under
--dev-local-owner. Proxy setup stays a terminal step; a dev-only note
names the two commands.
Every control needs the signed-in owner session, the page's exact
Origin and Sec-Fetch-Site: same-origin. The tester listener, granted
users, API tokens, agents and bus roles are refused before any work.
Each use is written to <dataRoot>/console/actions.jsonl (0600, no
symlinks) with who, when, what and the outcome. The Console and bus
restart trails fail closed. No change to credential handling, the
broker, the bus tenant boundary or v2 schemas.
mosaic console start --dev-local-owner --dev-insecure-bind ADDR
--dev-allow-host NAME[,NAME...] binds 0.0.0.0 or an IPv4 address and
answers only NAME:<bound port> plus the loopback names. Both flags are
refused without the dev owner, the bind without an allowed name, and a
specific ADDR that is not itself a name. Start and console status print
the no-sign-in warning; the state file records bind and allowHosts.
serve.mjs takes devAllowHosts only with the dev owner; SSO, preview and
tester listeners stay loopback. Writes need Origin http://<same Host>.
Chromium sends no Fetch Metadata from a LAN http origin, so for an
allowed name a write with that exact Origin and no Sec-Fetch-Site counts
as same-origin; an explicit header is still judged by the routes.
chat.js builds its operation keys without crypto.randomUUID, which an
insecure context lacks.
console start and stop move a console.json whose recorded process is gone
aside instead of refusing (P19 #857). mosaic org lock show|clear reports a
lifecycle lock holder and clears it only when the holder is dead.
mosaic bus recover marks a bus host stopped when its process is gone and its
socket does not answer, and writes a recovery receipt (P19 #862).