fix(organization): check organization definitions against held credentials at start, launch, issue and hire (#1873) #1932

Merged
jason.woltje merged 5 commits from org-defscan into refactor 2026-11-11 14:50:21 +00:00
Owner

T1 follow-up (#1873): every path that turns organization definition text into an agent's contract checks it against the live credential store and refuses definition-holds-credential. The refusal carries the definition name and key path, never the value or the credential's name.

  • Bus start checks the boot copy's org: definitions, the raw organization file, and the A4 boot copy snapshot. A hit refuses start with exit 3, records bus.boot.refused with the reason, and keeps lastGood as it was.
  • Launch: check() asks the bus definitionScan with the entry from the same file read that built the contract, before skills or a bundle exist. The final admission before spawnSession re-checks the instance's org: definition.
  • credentials.issue and rotate refuse a value already present in any served organization's definitions or the boot snapshot, before any state changes. An unreadable organization file refuses definition-scan-unreadable (new TI entry).
  • A4 hire path: hireDecisions.adjusted() scans the proposal entry, so the broker refuses before it consumes the decision. apply() scans the approved entry again before the writers.
  • Refusal table: new entries for both codes. No existing refusal text changed.

Review: security (daybreak-blue) changes 1 (P2, issue between launch scan and spawn), fixed with the admission re-check. Re-check found the IPC gap after admission, closed by the issue-time check. Re-check 2 approve 0. Re-check 3 of the hire path and boot snapshot approve 0. The last commit adds definitionScan to the lifecycle fixture's op table and changes no product code.

Lane gate on 5e93356cf (before the rebase): 364 files 3756/0, Case 1 back to back BASE 57/0 then candidate 57/0, stack-release 237/0, test-config 55/0, test-task 95/0. Total 4200/0. Lead check: rebased onto 4a122699a (PR #1931), range-diff all identical; 16 files covering bus definition-scan, credentials, credential verbs and store, hire decisions, broker, org runtime, organization definitions, and cli definition-scan, lifecycle, org-definitions, boot-status, launcher and access-boot, 170/0.

Deferred, recorded: final admission does not resolve root or project copy definitions from the boot snapshot (issue-time check covers them); a credential issued after the broker's pre-consume check burns the decision, though no held text is written; reload does not re-scan; a running agent keeps its contract.

T1 follow-up (#1873): every path that turns organization definition text into an agent's contract checks it against the live credential store and refuses `definition-holds-credential`. The refusal carries the definition name and key path, never the value or the credential's name. - Bus start checks the boot copy's `org:` definitions, the raw organization file, and the A4 boot copy snapshot. A hit refuses start with exit 3, records `bus.boot.refused` with the reason, and keeps `lastGood` as it was. - Launch: `check()` asks the bus `definitionScan` with the entry from the same file read that built the contract, before skills or a bundle exist. The final admission before `spawnSession` re-checks the instance's `org:` definition. - `credentials.issue` and rotate refuse a value already present in any served organization's definitions or the boot snapshot, before any state changes. An unreadable organization file refuses `definition-scan-unreadable` (new TI entry). - A4 hire path: `hireDecisions.adjusted()` scans the proposal entry, so the broker refuses before it consumes the decision. `apply()` scans the approved entry again before the writers. - Refusal table: new entries for both codes. No existing refusal text changed. Review: security (daybreak-blue) changes 1 (P2, issue between launch scan and spawn), fixed with the admission re-check. Re-check found the IPC gap after admission, closed by the issue-time check. Re-check 2 approve 0. Re-check 3 of the hire path and boot snapshot approve 0. The last commit adds `definitionScan` to the lifecycle fixture's op table and changes no product code. Lane gate on 5e93356cf (before the rebase): 364 files 3756/0, Case 1 back to back BASE 57/0 then candidate 57/0, stack-release 237/0, test-config 55/0, test-task 95/0. Total 4200/0. Lead check: rebased onto 4a122699a (PR #1931), range-diff all identical; 16 files covering bus definition-scan, credentials, credential verbs and store, hire decisions, broker, org runtime, organization definitions, and cli definition-scan, lifecycle, org-definitions, boot-status, launcher and access-boot, 170/0. Deferred, recorded: final admission does not resolve root or project copy definitions from the boot snapshot (issue-time check covers them); a credential issued after the broker's pre-consume check burns the decision, though no held text is written; reload does not re-scan; a running agent keeps its contract.
jason.woltje added 5 commits 2026-11-11 14:50:18 +00:00
T1 follow-up. A definition's text becomes an agent's contract, but a load ran the
held-secret check with an empty store. Bus start now checks every definitions entry
(the boot copy's org: entries and the file's own) with the live store, and the
launch check asks the bus the same question for the org: definition it just read,
before a contract exists. A hit refuses as definition-holds-credential, a new code
in the refusal table; the refusal names the definition and key, never the text or
the credential. bus start records the refusal in the boot status.
Review round (P2): a credential issued between the launcher's definition scan and
spawn could make text already in the definition a held value; a same-date rotate
leaves the organization file's revision unchanged, so the revision fence missed it.
The bus's final request.admission for an instance, the last bus op before spawn,
now runs the held-secret check on the org: definition the instance names, on the
bus loop that issue runs on, and refuses definition-holds-credential.

Self-found: check() takes the scanned entry from the same read as resolveInstance,
before any await can let another check replace the shared organization.
credentials.issue runs a check after it normalizes the value and before the store, the
organization file or memory changes: the value must not appear in the definitions of any
organization the bus serves (instructions, personality and every other field or key). A hit
refuses definition-holds-credential naming the organization, definition and key, never the
value or the credential. An organization file the check cannot read refuses
definition-scan-unreadable (new TI entry). The check runs on the bus loop inside issue, so a
launch admission can no longer pass and then see its definition text become held before spawn.
The final admission re-scan stays as the backstop for values held outside the verb.
The hire service takes the bus's definition check as scanDefinition and runs
it on the stored proposal entry before preview, check or apply goes further,
and on the approved entry again just before the writers. An approval whose
definition holds a credential the store came to hold after the raise refuses
definition-holds-credential before the decision is consumed; nothing is
written. Without the hook the entry still goes through assertClean whole.

Bus start and credentials.issue also check the boot copy snapshot's
definitions (A4 root agents file definitions, re-applied on every reload),
which no organization file holds.
A4's hire writes an org:hire-<uuid> definition, so the chief's in-session
launch of its hire now reaches the launcher's held-secret check. The fixture's
op table lacked definitionScan and refused invalid-host-request; process.mjs
answers it.
jason.woltje merged commit 5320e3d2c0 into refactor 2026-11-11 14:50:21 +00:00
Sign in to join this conversation.