12 Commits
Author SHA1 Message Date
jason.woltje 163972e08e fix(cli): f6c review round, released start locks, ENOENT and path cut (#1873)
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.
2026-11-13 20:14:21 -06:00
jason.woltje 23e504f331 fix(cli,bus,organization): E2E6 lane f6c, refusal lines name the next step (#1873)
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.
2026-11-13 20:14:21 -06:00
jason.woltje 6f18f3d015 fix(cli): bus and Console lifecycle verbs refuse inside an agent run (#1873)
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.
2026-11-11 16:15:51 -06:00
jason.woltje ebe2af86de fix(console): D1 security re-check fixes for the dev-owner start (#1873)
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.
2026-11-11 14:16:09 -06:00
jason.woltje 1947a056fb fix(console): D1 review fixes for the detached dev-owner supervisor (#1873)
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.
2026-11-11 14:16:09 -06:00
jason.woltje 7ffe932250 feat(console): dev-local-owner Console writes autonomy and restarts when detached (#1873)
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.
2026-11-11 14:16:09 -06:00
jason.woltje 1b6cac2bdf feat(webui): restart the Console, the org bus and agents from the WebUI (F3)
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.
2026-11-09 13:37:28 -06:00
jason.woltje 87b7a34f1c Merge rename part A2: --org selectors with --business aliases
# Conflicts:
#	packages/cli/tests/org-console.test.mjs
#	packages/webui/src/cli.mjs
2026-11-08 23:04:19 -06:00
jason.woltje 9a52eecffd selector: org-console test asserts the Console child's exact argv
The detached Console is a selector producer: the test reads the child's
/proc cmdline and asserts serve --port 0 --business alpha --dev-local-owner.
2026-11-08 22:35:24 -06:00
jason.woltje 665a5148d4 Open the dev owner Console to allowed LAN names
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.
2026-11-08 21:13:53 -06:00
jason.woltje e9a7adab11 Recover stale Console state, dead org locks and wedged bus hosts
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).
2026-11-08 14:11:13 -06:00
jason.woltje 24e240d44e Scope buses to organization roots 2026-11-07 11:29:13 -06:00