honker: PRD 1.8 draft r2: Mos's edits a-f (mos-1124, sage-1534): account.create with Q190 quoted, the chief-only reading put to Jason at approval, revoke by the assistant in its own organization and the tester on a dev instance, Approve is mosaic decide until #412, REQ-WEB-2 stays with #266, the Gitea and GitHub units to a later design; Duckworth's B1 (an unfinished grant undone on the stack side, the rest pending) and B2 (Approve or the user's own business file), N1-N6

This commit is contained in:
2026-10-20 17:24:21 -05:00
parent 3c30f1036a
commit 60f5ca8fa8
+99 -51
View File
@@ -7,6 +7,14 @@ Mos its id. Base: `docs/prd/mosaic-stack.md` version 1.6 at 008746b6e, plus the
approved (PRD-1.7-DRAFT.md r2, 9ba31b5b3, decision d52febb5, mos-1089). Where 1.7 is not yet written into
the PRD file, this draft's anchors name 1.7's sections.
Revision 2 makes Mos's edits a to f (mos-1124, through Sage, sage-1534) and fixes Duckworth's B1 and B2
with notes N1 to N6 (duckworth-0057) on r1 at 3c30f1036.
For Jason at approval: "The main agent or chief of staff" in Q10 is read as one role under two names,
the chief of staff. So only the chief raises a grant request, and your assistant passes your own request
to the chief. That reading is Mos's (mos-1124). To change it, say so when you approve, and REQ-GRANT-1 changes
before the text goes into the PRD.
## What it changes
Today an agent acts without a raise only on actions its role file grants within-role, and the role
@@ -35,23 +43,27 @@ This version adds:
The hard waits stay with the user (Mos, mos-1117): spending money, deleting data, new external accounts,
messages outside the fleet and the rest of REQ-WAIT-1. Approving a grant is the user resolving one of
those hard waits, `credential.mint` and, when the grant makes an account, `account.create`. So no hard
wait moves to an agent.
those hard waits, `credential.mint` and, when the grant makes an account, `account.create`. A seat's own
Gitea user (Q190) is such an account. So no hard wait moves to an agent.
When this version lands, reviewed commits:
1. add the manual-mode list to the organization file schema, written only on the human's path
(REQ-TRUST-2), and make the broker classify a listed action as needing a decision for each use, before
any other routing.
2. add the grant request: a decision the chief of staff raises with action `credential.mint`, naming the
agent, the method and target, and the exact rights (REQ-GRANT-1). The broker refuses the raise from any
other role.
2. add the grant request: a decision the chief of staff raises with action `credential.mint`, or
`account.create` when the grant makes an account, naming the agent, the method and target, and the
exact rights (REQ-GRANT-1). The broker refuses the raise from any other role.
3. add the grant code that runs on a resolved Approve, one method at a time, and the grant record it
writes (REQ-GRANT-2, Vikunja #435 and #436).
4. add the user's token store, written from the WebUI (or the CLI until the Console knows the signed-in
human) and read only by the grant code (REQ-GRANT-3).
5. move `host.sudo` into both `ROUTED` lists, as row 199 does for `git.push.remote`, and route it under
REQ-CRED-4. Which definitions list it within-role is a separate reviewed role commit in `roles/`.
6. update the role contracts that list the hard waits: `roles/chief-of-staff.md:75` raises grant
requests with the REQ-GRANT-1 fields, and `roles/pm.md:55` asks the chief of staff for a grant instead
of raising `credential.mint` itself (line numbers on origin/refactor). Other roles that list the hard
waits get the same line as the PM.
## Text for the PRD
@@ -61,7 +73,7 @@ Status line, appended to the current paragraph:
> default, a manual mode for per-use raises, and grants the chief of staff requests and the user
> approves, approved by Jason in decision <prd.approve decision id>.
Source, a new bullet above "Version 1.7 source":
Source, two new bullets above "Version 1.7 source":
> - Version 1.8 source, Jason's ruling Q188 (DECISIONS, 2026-10-20), his answers to Q8 and Q10, in part.
> Q8: "I would rather grant the grant right to an agent that runs with strict guardrails. That agent
@@ -82,6 +94,8 @@ Source, a new bullet above "Version 1.7 source":
> with Mos's Q10 points 3 to 6: protected stack code does every step on Approve, his tokens are entered
> in the WebUI and agents never see them, a command on the approved list runs without a click and any
> other is refused, and he, Mos or the tester can revoke a grant at once.
> - Version 1.8 source, Jason's ruling Q190 (DECISIONS, 2026-10-20), his answer "Q12: O1": each agent seat
> gets its own account on his Gitea, created through the Q188 approval path once the Gitea grants exist.
Under "Decisions", after REQ-DEC-6, a new section:
@@ -121,45 +135,59 @@ Under "Credentials", after REQ-CRED-3 (version 1.7):
> action whose definition doesn't list it within-role still needs a decision for each use. Only a
> reviewed role change adds an action to a definition. `host.sudo` routes under this requirement.
> - **REQ-GRANT-1.** No agent creates or writes a grant. A grant request follows the chain of command,
> and only the chief of staff raises it to the user's inbox. Any other role that needs a grant for itself or for an
> agent it directs asks the chief of staff, through its chain: a worker role through its PM, the PM and
> the CTO directly. The assistant passes the user's own request to the chief of staff (REQ-ASSIST-1).
> The request names the agent, the grant method and its target, the exact rights, and a rotate-by or
> expiry date. The chief raises one only for an agent whose reviewed role definition allows that kind of
> credential, and the broker refuses any other. A grant can't name a wildcard, a shell or an empty
> command. The request is a decision with the action `credential.mint`, so it goes to the user as a hard
> wait (REQ-WAIT-1). A request that makes an account, such as a new Gitea user, is also
> `account.create`.
> and only the chief of staff raises it to the user's inbox. Any other role that needs a grant for
> itself or for an agent it directs asks the chief of staff, through its chain: a worker role through its
> PM, the PM and the CTO directly. The assistant passes the user's own request to the chief of staff
> (REQ-ASSIST-1). The request names the agent, the grant method and its target, the exact rights, and a
> rotate-by or expiry date. The chief raises one only for an agent whose reviewed role definition
> allows that kind of credential, and the broker refuses any other. A grant can't name a wildcard, a
> shell or an empty command. The request is a decision with the action `credential.mint`, so it goes
> to the user as a hard wait (REQ-WAIT-1). A request that makes an account, such as a seat's own Gitea
> user (Q190), is raised with the action `account.create` and names the credential it makes as well.
> Both actions are hard waits, so the request goes to the user either way, and the user's one
> resolution covers the account and its credential. So the hard-waits list doesn't change. The broker
> checks that the chief of staff raised the request. The chain of command before that is in the role
> contracts, not a broker check.
> - **REQ-GRANT-2.** The user approves or denies each grant request in the inbox. Approve is the only thing
> that creates a grant. On Approve, protected stack code does every step, not an agent and not the user:
> it records the grant, makes the key or token, installs it on the machine or creates it on the service,
> and logs each step. On Deny nothing is made, and the denial is logged. The grant methods are:
> that makes the grant code create a grant. No agent creates a grant. The user creates one by Approve,
> or by writing it in their own business file on the human's path, as row 210 does. On Approve,
> protected stack code does every step, not an agent and not the user: it records the grant, makes the
> key or token, installs it on the machine or creates it on the service, and logs each step. On Deny
> nothing is made, and the denial is logged. The grant methods are:
> - machine key: a key for one agent on one enrolled host, with the command allowlist of REQ-CRED-4. A
> host's identity comes from the host side when the user enrolls it, never from a first connection;
> - Gitea: a token for one agent, with named read or write scopes and an expiry. The all scope and the
> admin scope are never granted;
> - GitHub: a grant for one agent, with the rights unit set by a later design that Jason approves.
> - Gitea: a token for one agent, and for an agent seat its own Gitea user (Q190), with an expiry. The
> all scope and the admin scope are never granted;
> - GitHub: a grant for one agent.
>
> The approval binds the exact rights the user saw. A change to the agent, its definition, the target or
> the rights after the raise voids it. An approval is used once. A grant the code couldn't finish undoes
> what it made, and a new grant needs a new approval, never an automatic retry. The grant code runs only
> on a request the user resolved. A request resolved by an arbiter, the tester or any agent makes
> nothing. Until the Console knows the signed-in human, Approve is `mosaic decide` in the CLI
> (REQ-DEC-3).
> The Gitea and GitHub rights units come in a later design that Jason approves.
>
> The approval binds the exact rights the user saw and the target's enrolled identity. A change to the
> agent, its definition, the target, the target's identity or the rights after the raise voids it. An
> approval is used once. A grant the code couldn't finish is undone at once on the stack's side, so it
> is never used. What it left on the host or service stays visible as pending until it is removed, as
> for a revoke (REQ-GRANT-4). A new grant needs a new approval, never an automatic retry. The grant
> code runs only on a request the user resolved. A request resolved by an arbiter, the tester or any
> agent makes nothing. A `credential.mint` or `account.create` decision raised before version 1.8, or
> without the fields of REQ-GRANT-1, makes nothing. Until the Console knows the signed-in human (Vikunja
> #412), Approve is `mosaic decide` in the CLI (REQ-DEC-3).
> - **REQ-GRANT-3.** The user enters their own personal access tokens and API tokens in the WebUI, or the
> CLI. Only the grant code reads them, to make grants. No agent ever sees a token value or a key's
> private half. Values appear in no event, log, message, prompt or agent file, and no agent can read
> them back (REQ-VAR-2). Until the Console knows the signed-in human, they are entered through the
> CLI.
> - **REQ-GRANT-4.** A grant can be revoked at once by the user, the assistant or the tester. A revoke needs
> no decision and no new trust. It takes effect at once on the stack's side, without waiting on the
> network, so the next use is refused. Removing the key or token at the host or service follows. Until
> that removal is done it stays visible as pending. Every revoke is logged with who made it.
> - **REQ-GRANT-4.** A grant can be revoked at once by the user, by the assistant for a grant in its own
> organization, or by the tester on a dev instance (Q173). A revoke needs no decision and no new trust.
> It takes effect at once on the stack's side, without waiting on the network, so the next use is
> refused. Removing the key or token at the host or service follows. Until that removal is done it stays
> visible as pending. A revoke while the grant is being made stops it, and what was made is handled the
> same way. Every revoke is logged with who made it.
REQ-CRED-1, appended:
> Since version 1.8, a token or key made for a grant is made by the grant code on the user's Approve
> (REQ-GRANT-2), not by hand. Tokens that exist stay as they are.
> Since version 1.8, a token or key for a grant is made by the grant code on the user's Approve
> (REQ-GRANT-2). A grant the user writes in their own business file, with its key made by hand, stays
> allowed. Tokens that exist stay as they are.
REQ-WAIT-3, appended:
@@ -181,14 +209,15 @@ Under "Risks and open questions", a new bullet:
- The hard waits stay with the user (mos-1117). REQ-GRANT-1 makes the grant request a `credential.mint`
decision, already a hard wait under REQ-WAIT-1, so Approve is the user resolving it. REQ-WAIT-2 stands:
no role file grants `credential.mint`. The grant code acts on the user's resolution, not on a role
grant. So 1.8 doesn't change the hard-waits list.
- Manual mode: Sage asked who sets it, where it lives and what it changes. Choices made here, for Mos and
Jason to change: a list of actions in the organization file, empty by default, changed only by the
user, outside the chief's organization writes. A list rather than one switch follows Gizmoduck's #436
draft section 7 (gizmoduck/machine-grant-design f6b6a04b6), so Jason can make host commands manual
without making every action manual. Listing every within-role action gives the whole-organization
manual mode. Row 210's per-call `host.run` decision, bound to host, argv and stdin and spent once, is
this mode's decision for a host command (Q188, Mos's reading).
grant. A grant that makes an account, such as a seat's Gitea user under Q190, is also `account.create`,
already a hard wait. So 1.8 doesn't change the hard-waits list (mos-1124 a).
- Manual mode: Sage asked who sets it, where it lives and what it changes. Mos accepted these choices
(mos-1124 b), and Jason can change them: a list of actions in the organization file, empty by
default, changed only by the user, outside the chief's organization writes. A list rather than one
switch follows Gizmoduck's #436 draft section 7 (gizmoduck/machine-grant-design f6b6a04b6), so Jason
can make host commands manual without making every action manual. Listing every within-role action
gives the whole-organization manual mode. Row 210's per-call `host.run` decision, bound to host, argv
and stdin and spent once, is this mode's decision for a host command (Q188, Mos's reading).
- Gizmoduck's draft proposes REQ-CRED-5 (section 8) for the machine grant. Its content is in REQ-GRANT-1
to REQ-GRANT-4 here, generalized to all three methods, so 1.8 has no REQ-CRED-5. Their bounds in
gizmoduck-0062 items 4a to 4g are in the text: the chief raises only for an allowed definition, the
@@ -196,13 +225,30 @@ Under "Risks and open questions", a new bullet:
is at once on the stack's side with the host or service removal visible until done, every grant has a
rotate-by or expiry date, and the host identity comes from the host side. Duckworth hasn't reviewed
their draft yet, so a change there may need a change here.
- B2 (duckworth-0057): REQ-GRANT-2 lets the user create a grant by Approve or by writing it in their own
business file. The other choice, existing grants stay and every new one needs an Approve record, would
leave no way to make a new grant between row 210 landing and the grant code (#435, #436) landing. Q188
calls requiring the user to do the steps a no-fly. This text allows the hand path and requires it
nowhere. Mos or Jason can close it once the grant code is live.
- N4 (duckworth-0057): a decision carries one action (`a.action`, broker.mjs:1678 on origin/refactor). A
request that makes an account is raised as `account.create` and names its credential, so the decision
shape doesn't change.
- N5 (duckworth-0057): once `host.sudo` is routed, a raise for it that cites the spec and isn't
within-role goes to the arbiter for its domain, like any gated raise (broker.mjs:1677-1678 on
origin/refactor), not to the user. REQ-CRED-4's grant and allowlist bound what the arbiter can allow.
Mos to say whether that is wanted or `host.sudo` should go to the user in any case.
- N6 (duckworth-0057): the broker checks only that the chief of staff raised a grant request. Which
role asked the chief, and through whom, is in the role contracts (step 6 of "When this version
lands"), not a broker check. REQ-GRANT-1 says so.
- Approving a grant doesn't by itself let a command run without a click. That needs REQ-CRED-4 and
`host.sudo` in the routed lists, step 5 of "When this version lands" (gizmoduck-0062 item 4i).
- Which roles may request: Q188 says "Not all agents are capable or authorized to request directly. It
must follow the chain of command properly." The text makes the chief of staff the only role that raises,
the PM and the CTO ask it directly, and worker roles ask through their PM. Jason's words also name "the
main agent", but REQ-ASSIST-1 keeps the assistant out of directing agents, so it passes the user's
request to the chief rather than raising one. Mos to confirm.
request to the chief rather than raising one. Mos accepted this (mos-1124 c) and reads "the main agent
or chief of staff" as one role under two names. That reading is Mos's, so the top of this draft puts it
to Jason at approval.
- REQ-CRED-4 keeps row 210's conditions (origin/gizmoduck/row210-on-199-r2,
agents/gizmoduck/work/queue-210/DESIGN.md:376-392): the definition declares the kind, the grant names
the agent, an exact argv-prefix allowlist with wildcards refused, the key issued, and only a reviewed role
@@ -210,18 +256,20 @@ Under "Risks and open questions", a new bullet:
what Approve records, so "the business file grants that agent that host" becomes "a grant names that
agent and that host".
- Revoke: Q188 says "you, Mos or the tester". Mos is Jason's assistant (REQ-ROLE-4), so the text says the
assistant. If revoke should stay with Mos the seat and not every user's assistant, the line needs a
different name. Mos to confirm.
assistant, limited to grants in its own organization, and the tester only on a dev instance (Q173).
Mos accepted this with those limits (mos-1124 d).
- Approve in the Console needs the Console to know the signed-in human (Q175 phase 2, #412). Until then
Approve is `mosaic decide`, which REQ-DEC-3 already allows. This draft doesn't take REQ-WEB-2, the id
held for the Console decide buttons amendment (Vikunja 19/266). That amendment, or a later version,
moves Approve into the Console.
- The Gitea unit is the scoped token roles already use (`<read|write>:<category>`, all and admin never
granted, `packages/business/src/vocabulary.mjs:105-106` on origin/refactor). Only the machine key is
Approve is `mosaic decide`, which REQ-DEC-3 already allows (mos-1124 e). This draft doesn't take
REQ-WEB-2, which stays with the Console decide buttons amendment (Vikunja 19/266). That amendment, or a
later version, moves Approve into the Console.
- Roles already use a scoped Gitea token (`<read|write>:<category>`, all and admin never granted,
`packages/business/src/vocabulary.mjs:105-106` on origin/refactor). It is a likely Gitea unit, not a
settled one. Only the machine key is
designed so far. Gitea and GitHub are a later #436 draft, and minting a Gitea token needs an admin
credential the user enters, which is a design of its own (Gizmoduck's draft section 11). GitHub's
rights unit isn't settled, so the text leaves it to a later design Jason approves. The PRD names
outcomes and checks, not the grant code's steps, as REQ-CRED-3 does.
rights unit isn't settled. So the text leaves both units to a later design Jason approves (mos-1124 f),
and keeps only the bounds: an expiry, and never the all or admin scope. The PRD names outcomes and
checks, not the grant code's steps, as REQ-CRED-3 does.
- Jason expects the inbox Approve and the Gitea and GitHub grants by 10-27 (Q188 point 6). That is a
delivery date, so it is in the source and not in the requirement text.
- This draft follows the PRD's own style: plain words, no semicolons in new sentences, and the status