reviewer, coder, pm and cto declare gitea and vikunja credentials, and the row keeps credentials out. The writer refuses an added instance or a definition change whose definition declares credentials, with a named refusal that says why, and never writes an instance without its binding. One added test line. Acceptance 314 is covered: security-reviewer and merge-gate declare none. Jason rules on credential binding in daylight.
7.4 KiB
Adding and changing role instances without editing the file, 2026-10-18
Status: written by Sage, lead, on Mos's relay mos-0787 of Jason's answer
to P19 332. Line numbers are at d62c61fbd. It follows
docs/plans/BRIEF-TEMPLATE.md, one ## heading per row.
Jason's answer, verbatim: "I want a command and a WebUI surfacing for the modifications".
Mos's reading: Jason wants to add and change role instances through a
mosaic CLI command and a Console view instead of hand-editing the
business file. That is the pattern of Q169
(docs/plans/2026-10-16_q169-assistant-config.md). Gitea #1662.
Confirmed. Mos relayed Jason's answer on 2026-10-18 (mos-0805),
verbatim: "Q4: yes". DECISIONS Q171 and Q172 record the reading above: a
mosaic CLI command plus a Console view for adding and changing role
instances, for example a second reviewer, so nobody hand-edits the
business file. The hold is lifted. The row moves to briefed once row 155
is done. Until this row lands, acceptance 314 stays as written
(docs/acceptance/314.md:27-29): Jason adds the security-reviewer and
merge-gate instances by editing the business file.
Correction, 2026-10-18 (mos-0823). The second reviewer in the
example above waits on a follow-up, P19 367. This row can't add it.
reviewer, coder, pm and cto each declare gitea and vikunja credentials
in roles/*.json, and this row keeps credentials out (What ships item
1, Out of scope). So the writer refuses, with a named refusal whose
message says why, any added instance and any definition change whose
definition declares credentials. It never writes an instance without
its credential binding. Changing vars or launch membership of an
instance that already has its binding stays allowed and leaves the
binding untouched. security-reviewer and merge-gate declare no
credentials, so acceptance 314 is covered. Whether the human binds
credentials through this command is a question Mos puts to Jason. Until
Jason rules, nothing binds credentials through it.
The human adds and changes role instances
Problem
What exists at d62c61fbd:
- No verb adds a role instance. The organization writers change only
what exists:
packages/business/src/launch-settings.mjs:46-52setsvars.modelon an instance and refuses one the file doesn't declare, andpackages/business/src/business.mjs:130refuses alaunch.instancesentry the file doesn't declare. Row 141's names table and row 155's assistant writer don't add instances either. - So staffing a role the file doesn't declare means editing
~/.config/mosaic-dev/businesses/<id>.jsonby hand, with no revision check, no actor and no change record. Acceptance 314 does this today. - The safe write path exists.
organizationWriter().write(packages/business/src/organization.mjs:177-219) takes the file's revision and an actor, refuses a stale revision withrevision-conflict, validates the document withvalidateBusinessDocumentbefore and after serialization, and appends prepared and committed entries with the actor, the before and after hashes and the changes tobusinesses/.history/<id>/changes.jsonl. mosaic business validate(packages/business/src/cli.mjs:64) runsloadBusiness, which callsvalidateBusinessDocument, and then resolves every instance against every project file.
Owner and reviewer
- Owner: Darkwing, after row 155, which changes the same writers, CLI and Console settings view.
- Reviewers: Dewey, for security, and Filbert.
Files owned
packages/business/src/: one new instance writer besidelaunch-settings.mjs, built onorganizationWriter().write.packages/cli/src/: the human's command below.packages/webui/src/serve.mjsandpackages/webui/src/public/: the Console view and its routes.- Tests in those packages, the webui browser tests, the business and cli
READMEs, and
docs/TOOLS.md. docs/acceptance/314.md, only to replace the hand edit with the command once the row lands.
What ships
- A role instance here is one entry under the business file's
roles, plus its place inlaunch.instances. The human can:- add an instance: a new id, a
definitionfromroles/, itsvars, and whether it goes intolaunch.instances; - change an existing instance's
definitionandvars, and add it to or remove it fromlaunch.instances.holder,credentialsandtrackerstay out of this row. Deleting an instance from the file is out of scope.
- add an instance: a new id, a
- The CLI command is under
mosaic business(the owner proposes the verb and flags in the packet before any code). The Console gets a view that lists instances and a form for the same two operations. Both carry the file's revision, and a stale one is refused withrevision-conflict. - Only the human. The CLI command needs the human proof the other organization writers use, and the Console routes need the signed-in human. No role, the chief of staff included, gets a tool or a grant for this in this row. Jason hasn't ruled on the chief of staff, so that waits for him.
- Validation goes through the same path as
mosaic business validate. The writer refuses any document thatvalidateBusinessDocumentrefuses, and any document in which an instance doesn't resolve against a project file, the checkvalidateruns after loading. A write that lands always leaves a file thatmosaic business validateaccepts. The writer can't change any instance's definition to one inEND_PROTECTEDor remove the assistant's protection; row 155's rule holds here too. - Each change writes an audit entry through the writer's change log: the actor, the business, the before and after hashes and the changed keys. The CLI prints the new revision and the transaction id.
- A change reaches a running bus the way row 141's and row 155's changes do. The packet says which reads pick it up and whether anything needs a bus restart.
Tests:
- the CLI and the Console add an instance;
mosaic business validatethen exits 0 and the change log has the human as actor; - changing an instance's definition, vars and launch membership succeeds and logs before and after;
- each
validateBusinessDocumentrefusal and an unresolvable instance are refused, and the file's bytes don't change; - a stale revision is refused;
- a call without the human proof, and any role's attempt, are refused;
- a definition change into
END_PROTECTED, or one that strips the assistant's protection, is refused. - adding an instance whose definition declares credentials, or changing
an instance's definition to one that does, is refused with the named
refusal, its message says why, and the file's bytes don't change; a
varschange on an instance that already has its binding succeeds and leaves the binding as it was (mos-0823).
Mutants: one per behavior above, with the killing test in the packet.
Out of scope
Deleting instances. Changing holder, credentials or tracker. Any
chief of staff tool or grant, until Jason rules. Editing the
repository's role files in roles/, which change only through reviewed
commits. Any live change: the row goes live through a re-pin with Mos's
go.
Gate
- Jason's confirmation, relayed by Mos (mos-0805, Q171 and Q172). Done.
- Dewey and Filbert approve on the row's issue naming the candidate manifest.
- Mos's decision 123 go on the
public/diff. - Business, cli and webui suites and every
scripts/test-*.shgreen on Sage's gate. - Needs row 155 done.