fix(cli,organization,discord,seat,control-board): refusals name the field or file by label, never a host path or value (#1873) #1933

Merged
jason.woltje merged 8 commits from org-redact6 into refactor 2026-11-11 16:23:31 +00:00
Owner

Refusal redaction, round 6 (#1873): refusals name the field, the file by label, or the system call and error code. They no longer quote a host path, a config value, or a raw e.message or stderr that carries one. Exit codes, refusal codes and check order are unchanged.

  • Shared helpers: quietMessage/quiet move to organization org-registry.mjs (a Node system error becomes cannot <syscall> <what> (<CODE>), quieted once). system-config-problem.mjs gives one label for the system config, reused by cli config.mjs, scripts/mosaic-config.mjs and stack-instances, with a business old-path re-export.
  • cli launcher: relay() strips host-path tokens and reason() prefers quietMessage. A plain Error from a harness preflight reads threw <Name> without a system code. Sandbox, skills, persona, workspace rename, sessions file and MOSAIC_CLAUDE_BIN refusals use labels. The claude-code and pi preflights name the variable, not its value.
  • Session helpers label the thread store, session store, workspace lock and run dir under the data root.
  • Discord: git refusals drop host-path lines and name a configured root by the binding's repo name; approvals, journal and context-file reads are quieted. BINDING_NAME moves to errors.mjs and binding.mjs re-exports it, so journal importers no longer load the binding's config readers.
  • plain()/plainKey describe a non-plain key instead of echoing it, in control-board scan, seat, discord and webui sso-config.
  • HTTP: control-board's board API error body now carries the seen marks file label, pinned by a test that starts a board and checks the body. webui org-admin adds no text to an HTTP body.

Review: security (daybreak-blue) changes 8 (P1 x7, P2 x1), all fixed in the review-round commit; the reviewer's 15 leak probes all fail against the candidate. Re-check 1 changes 1 (P2, a file swapped between check and read could put a native error carrying the path into a refusal at discord binding readToken, the realpath of context files and tool roots, and the setspark keyFile), fixed in d9023e28d with 5 race tests. Re-check 2 changes 1 (the same pattern at the discord cli session dir and the journal STOP and turn reads), fixed structurally in 63e2a574a: the discord cli top-level catch prints a native fs error only as its operation, a label and its code; journal and engine-pi label their fs calls at the source; the build report carries a sweep table of every fs call in the changed discord files. 14 new tests, 0/14 on the parent and 14/0 after. Re-check 3 changes 1 (P2: connector.start() still quoted the journal directory in its STOP refusal), fixed by the Lead in ce4fe048b with journalLabel, the same label the CLI and journal refusals use; the connector test now asserts the path is absent, 22/1 on the old source and 23/0 after.

Lane gate on c3fe6b77a (after the fourth rebase, onto 5320e3d2c): 5538/2. Both reds are conversation reader and flows CHAT-01 schema checks that fail the same way on BASE: they run the system python3, which has no jsonschema. Case 1 back to back, BASE and candidate both 57/0, 19/0, 8/0, 3/0. Lane run on 63e2a574a: 63 files 854/2, the same two schema reds. Lead check on ce4fe048b: 62 files: every touched test file, the full discord suite, conversation claim, control-board and queue, 882/0 with 2 skips (systemd user scopes unavailable in the test env, same on BASE).

Deferred (T1 files, out of this lane): organization-config.mjs file refusals, including two A4 refusals at 165-166 that quote the tracker.bot and tracker.botId values; role.mjs, resolve.mjs, organization.mjs, composition; the launcher organization-refused relay; the org-service validate relay; config.mjs root agent warning; discord discord-business-unreadable; the definitions refusals in definitions.mjs and org-definitions.mjs.

Refusal redaction, round 6 (#1873): refusals name the field, the file by label, or the system call and error code. They no longer quote a host path, a config value, or a raw `e.message` or stderr that carries one. Exit codes, refusal codes and check order are unchanged. - Shared helpers: `quietMessage`/`quiet` move to organization `org-registry.mjs` (a Node system error becomes `cannot <syscall> <what> (<CODE>)`, quieted once). `system-config-problem.mjs` gives one label for the system config, reused by cli `config.mjs`, `scripts/mosaic-config.mjs` and stack-instances, with a business old-path re-export. - cli launcher: `relay()` strips host-path tokens and `reason()` prefers `quietMessage`. A plain Error from a harness preflight reads `threw <Name> without a system code`. Sandbox, skills, persona, workspace rename, sessions file and `MOSAIC_CLAUDE_BIN` refusals use labels. The claude-code and pi preflights name the variable, not its value. - Session helpers label the thread store, session store, workspace lock and run dir under the data root. - Discord: git refusals drop host-path lines and name a configured root by the binding's repo name; approvals, journal and context-file reads are quieted. `BINDING_NAME` moves to `errors.mjs` and `binding.mjs` re-exports it, so journal importers no longer load the binding's config readers. - `plain()`/`plainKey` describe a non-plain key instead of echoing it, in control-board scan, seat, discord and webui sso-config. - HTTP: control-board's board API error body now carries the seen marks file label, pinned by a test that starts a board and checks the body. webui org-admin adds no text to an HTTP body. Review: security (daybreak-blue) changes 8 (P1 x7, P2 x1), all fixed in the review-round commit; the reviewer's 15 leak probes all fail against the candidate. Re-check 1 changes 1 (P2, a file swapped between check and read could put a native error carrying the path into a refusal at discord binding readToken, the realpath of context files and tool roots, and the setspark keyFile), fixed in d9023e28d with 5 race tests. Re-check 2 changes 1 (the same pattern at the discord cli session dir and the journal STOP and turn reads), fixed structurally in 63e2a574a: the discord cli top-level catch prints a native fs error only as its operation, a label and its code; journal and engine-pi label their fs calls at the source; the build report carries a sweep table of every fs call in the changed discord files. 14 new tests, 0/14 on the parent and 14/0 after. Re-check 3 changes 1 (P2: `connector.start()` still quoted the journal directory in its STOP refusal), fixed by the Lead in ce4fe048b with `journalLabel`, the same label the CLI and journal refusals use; the connector test now asserts the path is absent, 22/1 on the old source and 23/0 after. Lane gate on c3fe6b77a (after the fourth rebase, onto 5320e3d2c): 5538/2. Both reds are conversation reader and flows CHAT-01 schema checks that fail the same way on BASE: they run the system `python3`, which has no `jsonschema`. Case 1 back to back, BASE and candidate both 57/0, 19/0, 8/0, 3/0. Lane run on 63e2a574a: 63 files 854/2, the same two schema reds. Lead check on ce4fe048b: 62 files: every touched test file, the full discord suite, conversation claim, control-board and queue, 882/0 with 2 skips (systemd user scopes unavailable in the test env, same on BASE). Deferred (T1 files, out of this lane): `organization-config.mjs` file refusals, including two A4 refusals at 165-166 that quote the tracker.bot and tracker.botId values; `role.mjs`, `resolve.mjs`, `organization.mjs`, composition; the launcher `organization-refused` relay; the org-service validate relay; `config.mjs` root agent warning; discord `discord-business-unreadable`; the definitions refusals in `definitions.mjs` and `org-definitions.mjs`.
jason.woltje added 8 commits 2026-11-11 16:23:24 +00:00
redact6. A refusal names the field, the file or the instance. It never quotes a
config value, a host path, or a raw e.message or stderr that carries one.

- organization: checkCredentialRef names the field and each forbidden root by
  label; OrgError keeps .path only for a document field ($...); the registry,
  fence and lock refusals use the quiet helpers (call and code).
- cli: loadSystem never relays mosaic-config stderr: instance refusals keep
  their code and names, everything else reads as a field and its constraint
  against a labelled config. Project-key, access warning, halt gate, sessions
  file, launch socket, harness relays and the workspace rename name labels.
  Launch-log reasons read a Node system error as its call and code.
- scripts/mosaic-config: configuration not found names where the config came from.
- discord, seat, control-board: config, token, context, tool-root, journal,
  binding, registration and seen-marks refusals name labels.

Exit codes, refusal codes and check order are unchanged. Each new or changed
test fails on BASE be698e602.
Review "changes 8" fix round for org-redact6.

- launcher: a harness module's throw names its system code or class,
  never its message; preflight, loader, bundle, checkout, sandbox and
  route text is relayed with host paths replaced (relay()).
- claude-code and pi preflights name MOSAIC_CLAUDE_BIN and the
  repository's node_modules, never a path; persona and skill bundle
  errors and sandboxProblem name their file or the sandbox by label.
- seat session: thread store, legacy store, overlap, busy lock and
  newRun refusals name the place under the data root.
- discord: unknown keys, binding names and turn ids are described when
  not plain; approvals, journal and repository read errors name the file
  and code; git drops stderr lines that carry a host path and a spawn
  failure names its code only.
- seat, control-board: registration fields and seen keys are described
  when not plain; invalid seat name and layout state the constraint.
- organization: the registry names the config directory and registry
  file by label; --project is quoted only when it is a plain name;
  systemConfigProblem moves to its own module.
- scripts/mosaic-config.mjs: the config by where it came from, the data
  root and its marker by role, keys and arguments only when plain, and
  error codes in place of raw messages. Exit codes unchanged.
- webui sso-config: an unknown console key is named only when plain.

Sentinel tests in each package's path-redaction-labels file fail on
BASE; pins that quoted a path now assert the label and its absence.
rename-b-identity pins one packages/business/src module per moved
organization module; the review round's new module needs its shim.
The board API returns a scan refusal in its JSON error body. The test
starts a board on port 0 over a seen.json that is not an object and
checks the body names seen.json by label, with no sentinel or scratch
path. It fails on BASE, where the body quotes the host path.
The journal label import pulled binding.mjs and its config readers into
every journal.mjs importer. The queue test repo copies only journal.mjs
and errors.mjs, so its genesis failed with ERR_MODULE_NOT_FOUND (webui
reads.test.mjs red, 4 tests). BINDING_NAME now lives in errors.mjs and
binding.mjs re-exports it, so its export is unchanged.
A token file, context file, tool root, data root or setspark key file
that changes between its check and its read failed with a native error
whose message carried the host path. Each read now names the file by
label and code (quietRead): same error object, type and code, so exit
codes, refusal codes and check order are unchanged.
The discord CLI's top-level handler prints a native Node error that is not
already a labelled refusal as 'cannot <syscall> <label> (<CODE>)'. The journal
and approvals readers and writers name the file by label at the source, so
conversation, control-board and webui callers get the label too. The session
directory check moves to engine-pi.mjs as sessionContinues(). Exit codes and
refusal codes are unchanged.
Re-check 3 found connector.start() still quoted the journal directory in
its STOP refusal, and the CLI passes a DiscordError through unchanged.
It now uses journalLabel like the CLI and journal refusals. The connector
test asserts the path is absent: 22/1 on the old source, 23/0 after.
jason.woltje merged commit ce4fe048bb into refactor 2026-11-11 16:23:31 +00:00
Sign in to join this conversation.