|
|
|
@@ -1,6 +1,6 @@
|
|
|
|
|
# PRD: Mosaic Stack
|
|
|
|
|
|
|
|
|
|
- Status: approved, version 1.6. Jason approved draft 0.4 unchanged as
|
|
|
|
|
- Status: approved, version 1.8. Jason approved draft 0.4 unchanged as
|
|
|
|
|
1.0 on 2026-10-05 (lead decision 61). They approved version 1.1, the
|
|
|
|
|
Organization requirements, in decision 03130d08-ddce-480d-a601-e59f64744fc3
|
|
|
|
|
on 2026-10-14. They approved version 1.2, the chief of staff, the
|
|
|
|
@@ -15,7 +15,64 @@
|
|
|
|
|
confirmation of the text is the approval, so there is no in-Stack
|
|
|
|
|
prd.approve for it. Version 1.6 records Jason's ruling Q169 of
|
|
|
|
|
2026-10-16, on who removes and who configures the assistant. It is
|
|
|
|
|
never edited in place. Changes are a new version.
|
|
|
|
|
never edited in place. Changes are a new version. Version 1.7 routes the
|
|
|
|
|
chief of staff's hire and fire actions and the coder's push to its own
|
|
|
|
|
fork, and adds agent host access through the credential store, approved
|
|
|
|
|
by Jason in decision d52febb5 (prd.approve, yes). Version 1.8 records
|
|
|
|
|
Jason's ruling Q188 of 2026-10-20: trusted actions within role
|
|
|
|
|
guardrails by default, a manual mode for per-use raises, and grants the
|
|
|
|
|
chief of staff requests and the user approves. Jason approved it in T3,
|
|
|
|
|
relayed by Mos on 2026-10-21 (DECISIONS Q192), so there is no in-Stack
|
|
|
|
|
prd.approve for it.
|
|
|
|
|
- Version 1.8 source, Jason's approval in T3, relayed by Mos on 2026-10-21
|
|
|
|
|
(DECISIONS Q192): "PRD 1.8: I am preemptively approving it. Do not
|
|
|
|
|
surface in the Mosaic Stack board. Just proceed."
|
|
|
|
|
- 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 presents
|
|
|
|
|
the final authorization for the user. Upon approval, the grant is
|
|
|
|
|
created programmatically. I see this as: User configures their PATs, API
|
|
|
|
|
tokens, authorizations within the WebUI. The agent presents the request
|
|
|
|
|
for grant with X rights for another agent. The user reviews, then clicks
|
|
|
|
|
Approve/Deny. Click of Approve fires off protected mechanical methods to
|
|
|
|
|
handle the grants on Github, Gitea, .... services as needed. The tooling
|
|
|
|
|
would need to exist and must be guarded." And "Disallowing the agents to
|
|
|
|
|
create grants autonomously is a necessary evil for better security.
|
|
|
|
|
Requiring the user to manually perform the steps is a no-fly." Q10:
|
|
|
|
|
"Agents should have tools and command access based on roles. Those roles
|
|
|
|
|
dictate the allowed tools and commands. The use of a tool or command
|
|
|
|
|
should not be raised to the user unless the system is configured with a
|
|
|
|
|
manual mode that requires user interaction. By default I want to have
|
|
|
|
|
the agents capable of running commands and tools at will within their
|
|
|
|
|
sandbox/guardrails. This allows autonomous actions by agents within
|
|
|
|
|
their lanes. Perhaps a "Trusted actions within approved guardrails"
|
|
|
|
|
methodology." And "The main agent or chief of staff would be responsible
|
|
|
|
|
for surfacing the request to the user's inbox for approval. Not all
|
|
|
|
|
agents are capable or authorized to request directly. It must follow the
|
|
|
|
|
chain of command properly." He agreed 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.
|
|
|
|
|
- Version 1.8 source, Jason's ruling Q191 (DECISIONS, through Mos in
|
|
|
|
|
mos-1149), that the assistant and the chief of staff are separate roles,
|
|
|
|
|
and only the chief raises a grant request: "Q13: that looks better".
|
|
|
|
|
- Version 1.7 source, TARGET.md line 66: "Chief of staff agent has
|
|
|
|
|
hire/fire authority for agents as needed; unless user forbids per
|
|
|
|
|
agent". And Jason through Mos (mos-1067), DECISIONS Q183, in part: "I
|
|
|
|
|
will still want to allow infra agent(s) on my .53 instance to access
|
|
|
|
|
other servers, etc. However, not all agents will need to have that
|
|
|
|
|
access. I envision a credential store within Mosaic Stack that works as
|
|
|
|
|
some sort of variable for the agent to call. The system will enforce
|
|
|
|
|
access to the credentials to keep the agents sandboxed with proper
|
|
|
|
|
security. I need to be able to trust my agents with assisting me. This
|
|
|
|
|
will require sudo access to several systems. If we can utilize the
|
|
|
|
|
credential store in Mosaic Stack and allow agents to perform their jobs
|
|
|
|
|
with NOPASSWD sudo on various machines, I am a happy man." DECISIONS
|
|
|
|
|
Q184, on whether that is in place by 10-27: "Q5: by 10.27"
|
|
|
|
|
- Version 1.6 source, Jason's ruling Q169 (DECISIONS, brain repo,
|
|
|
|
|
2026-10-16): "The only agent that should be able to remove the
|
|
|
|
|
assistant role is the chief of staff. The COS and the user should have
|
|
|
|
@@ -262,6 +319,39 @@ Added in version 1.2:
|
|
|
|
|
in its own words. It summarizes and doesn't relay their text. (Version
|
|
|
|
|
1.5.)
|
|
|
|
|
|
|
|
|
|
Added in version 1.7:
|
|
|
|
|
|
|
|
|
|
- **REQ-COS-3.** The chief of staff hires and fires role instances without
|
|
|
|
|
a decision each time. Hiring adds a role instance to the organization
|
|
|
|
|
file and lists it for launch. Firing ends the instance's runs and
|
|
|
|
|
removes it from the launch list. It stays in the organization file. Only
|
|
|
|
|
the user deletes an instance. These actions are `role.hire` and
|
|
|
|
|
`role.fire`. They leave the hard waits and route under this requirement,
|
|
|
|
|
within these bounds:
|
|
|
|
|
- The chief acts only in its own organization.
|
|
|
|
|
- The chief hires only role definitions that need no credentials, until
|
|
|
|
|
a later version adds credentialed roles.
|
|
|
|
|
- The chief hires only the role kinds its role file lists. Changing that
|
|
|
|
|
list is a reviewed commit.
|
|
|
|
|
- The chief hires only a role whose every action is on a fixed list of
|
|
|
|
|
plain work actions: sending messages, writing records, asking for
|
|
|
|
|
review, updating its assigned tasks, and the scope and working-push
|
|
|
|
|
actions of an assigned task. A role holding any other action, such as
|
|
|
|
|
launch, end, organization, naming, hire, review verdict or merge
|
|
|
|
|
authority, or any action added later, is never hired. So the chief
|
|
|
|
|
never hires a chief, never picks its own reviewers or merge gate, and
|
|
|
|
|
the author is never the reviewer. This holds whatever the role file's
|
|
|
|
|
list says. Adding to that list is a PRD change.
|
|
|
|
|
- The chief may set a hired instance's model and narrow its limits, and
|
|
|
|
|
nothing else about it.
|
|
|
|
|
- The user can forbid per agent. The user marks an instance so the chief
|
|
|
|
|
can't fire it, end its runs or change its model, and marks role kinds
|
|
|
|
|
the chief can't hire. Only the user changes these marks, through the
|
|
|
|
|
WebUI or the CLI.
|
|
|
|
|
- The kill switch stops every hire and fire while it is on.
|
|
|
|
|
- Every hire and fire is logged with the chief's instance, its run and
|
|
|
|
|
the reason.
|
|
|
|
|
|
|
|
|
|
### Variables
|
|
|
|
|
|
|
|
|
|
- **REQ-VAR-1.** Variables come in four layers: system, business, project
|
|
|
|
@@ -289,8 +379,111 @@ Added in version 1.2:
|
|
|
|
|
- in Vikunja, a `bot-<business>-<role>` user per role, plus one
|
|
|
|
|
read-only `bot-<business>-sync` that does all polling (lead
|
|
|
|
|
decisions 52 and 58).
|
|
|
|
|
|
|
|
|
|
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), not by hand. Tokens that exist stay
|
|
|
|
|
as they are.
|
|
|
|
|
- **REQ-CRED-2.** A session that finds only founder credentials stops.
|
|
|
|
|
|
|
|
|
|
Added in version 1.7:
|
|
|
|
|
|
|
|
|
|
- **REQ-CRED-3.** An agent with a grant can run commands with sudo on
|
|
|
|
|
another host. The agent asks for the host credential by name. The stack
|
|
|
|
|
checks that a grant exists for that agent and that host before the
|
|
|
|
|
credential is used. The agent never sees the key or any other secret
|
|
|
|
|
value (REQ-CRED-1, REQ-VAR-2). An agent without a grant for that host is
|
|
|
|
|
refused. Not every agent gets a grant. Who grants a host credential, and
|
|
|
|
|
how, is set by the #424 design, which Jason approves.
|
|
|
|
|
|
|
|
|
|
Added in version 1.8 (Q188):
|
|
|
|
|
|
|
|
|
|
- **REQ-CRED-4.** An action a role definition lists within-role, and that
|
|
|
|
|
uses a grant, runs without a decision for each use only when all of
|
|
|
|
|
these hold:
|
|
|
|
|
- the definition declares the credential kind the action uses;
|
|
|
|
|
- a grant names that agent, and that host or service;
|
|
|
|
|
- for a command, the command matches the grant's allowlist. A grant
|
|
|
|
|
lists exact argv prefixes. A wildcard grant is refused;
|
|
|
|
|
- the agent's key or token for that grant is issued and not revoked.
|
|
|
|
|
|
|
|
|
|
A command off the allowlist is refused, and adding one takes a new grant
|
|
|
|
|
request (REQ-GRANT-1). An 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 grant whose method
|
|
|
|
|
makes an account, such as a seat's own Gitea user (Q190), is the same
|
|
|
|
|
one decision: the method in the grant says it makes an account, the
|
|
|
|
|
request names the account, and the inbox shows the account name before
|
|
|
|
|
Approve. The user's one resolution covers the account and its
|
|
|
|
|
credential, so the hard-waits list doesn't change. An `account.create`
|
|
|
|
|
raise isn't a grant request and routes as version 1.7 has it. The broker
|
|
|
|
|
checks only that the chief of staff raised the request. The chain of
|
|
|
|
|
command before that is in the messaging lists and the role contracts,
|
|
|
|
|
not a broker check. The assistant and the chief of staff are separate
|
|
|
|
|
roles. No agent holds both, and the broker refuses a claim that would.
|
|
|
|
|
- **REQ-GRANT-2.** The user approves or denies each grant request in the
|
|
|
|
|
inbox. Approve is the only thing that creates a grant, and the code uses
|
|
|
|
|
a grant only when it has a matching Approve record. No agent creates a
|
|
|
|
|
grant. A grant written into the business file by hand makes nothing. Row
|
|
|
|
|
210's hand-written grants stay a test path until Vikunja #436a moves
|
|
|
|
|
`host.run` to grants made by Approve. 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 approves its enrollment, never from a first
|
|
|
|
|
connection. A host user with sudo receives a grant only after the user
|
|
|
|
|
approved that user by name;
|
|
|
|
|
- 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 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 or its
|
|
|
|
|
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` decision raised before version 1.8, or without the
|
|
|
|
|
fields of REQ-GRANT-1, makes nothing when it is approved. 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, 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 nothing it made
|
|
|
|
|
stays usable. Every revoke is logged with who made it.
|
|
|
|
|
|
|
|
|
|
### Decisions
|
|
|
|
|
|
|
|
|
|
- **REQ-DEC-1.** Every decision is a record in an append-only SQLite
|
|
|
|
@@ -338,6 +531,31 @@ Added in version 1.5 (Q167):
|
|
|
|
|
settled under one commit stays settled when a later commit lands, and
|
|
|
|
|
new raises cite the new commit.
|
|
|
|
|
|
|
|
|
|
### Trusted actions
|
|
|
|
|
|
|
|
|
|
Added in version 1.8 (Q188).
|
|
|
|
|
|
|
|
|
|
- **REQ-TRUST-1.** Agents act within their role guardrails without asking.
|
|
|
|
|
The default mode is "trusted actions within approved guardrails". An
|
|
|
|
|
action a role file grants within-role is done at will, inside the
|
|
|
|
|
agent's sandbox, its tool limit and its grants, and is logged. It raises
|
|
|
|
|
nothing to the user. An action the file doesn't grant within-role still
|
|
|
|
|
routes by REQ-DEC-2, and a hard wait still goes to the user
|
|
|
|
|
(REQ-WAIT-1). Only a reviewed role change adds an action to a role file,
|
|
|
|
|
and REQ-WAIT-2 still keeps every hard wait out of every role file.
|
|
|
|
|
- **REQ-TRUST-2.** The user can put chosen actions in manual mode. The
|
|
|
|
|
organization file holds the list of actions in manual mode, empty by
|
|
|
|
|
default. While an action is on the list, every use of it by any role
|
|
|
|
|
becomes a decision for that use, raised to the user, and the action
|
|
|
|
|
waits until the user resolves it. A decision denied, or not resolved,
|
|
|
|
|
refuses the action. Each decision is used once. For a command on another
|
|
|
|
|
host, the decision names the host, the command and its input. Actions
|
|
|
|
|
not on the list are unchanged. Only the user changes the list, through
|
|
|
|
|
the WebUI or the CLI. The chief of staff's organization writes
|
|
|
|
|
(REQ-ROLE-3) can't change it, and no agent can. Every change is logged
|
|
|
|
|
with who made it. A change applies to the next use, and a run already in
|
|
|
|
|
progress keeps no exemption.
|
|
|
|
|
|
|
|
|
|
### Hard waits
|
|
|
|
|
|
|
|
|
|
Added in version 1.5 (Q167).
|
|
|
|
@@ -371,6 +589,13 @@ Added in version 1.5 (Q167).
|
|
|
|
|
PRD version says it isn't. The reviewed commit that adds it names which
|
|
|
|
|
it is.
|
|
|
|
|
|
|
|
|
|
`role.hire` and `role.fire` were added as hard waits and route under
|
|
|
|
|
REQ-COS-3 since version 1.7. `git.push.remote` was added as a hard wait
|
|
|
|
|
and routes under REQ-LAND-2 since version 1.7.
|
|
|
|
|
|
|
|
|
|
`host.sudo` was added as a hard wait and routes under REQ-CRED-4 since
|
|
|
|
|
version 1.8.
|
|
|
|
|
|
|
|
|
|
### Messages
|
|
|
|
|
|
|
|
|
|
- **REQ-MSG-1.** Messages are addressed to a role. They are append-only
|
|
|
|
@@ -470,6 +695,37 @@ Added in version 1.5 (Q167, Mos's reading Q4).
|
|
|
|
|
decision; the check ships with whichever of rows 137 and 139 lands
|
|
|
|
|
second.
|
|
|
|
|
|
|
|
|
|
Added in version 1.7:
|
|
|
|
|
|
|
|
|
|
- **REQ-LAND-2.** A coder pushes its own work to its own fork. The action
|
|
|
|
|
is `git.push.remote`.
|
|
|
|
|
- What it pushes: one commit, by its oid, never a ref name. That commit
|
|
|
|
|
is the latest work commit the bus recorded for the coder's task, and
|
|
|
|
|
the coder made that push. A decision that authorizes a push names that
|
|
|
|
|
commit, and it doesn't authorize any other.
|
|
|
|
|
- Where it lands: only the branch
|
|
|
|
|
`refs/heads/<its Gitea user>/<branch>`. The host builds that name, the
|
|
|
|
|
agent never does. A push never forces.
|
|
|
|
|
- Which remote: the agent's own fork of the project's upstream. The
|
|
|
|
|
business file names the upstream, and the host never contacts it. For
|
|
|
|
|
each push the host builds the fork's address over https from the
|
|
|
|
|
upstream's host, port and repository name and the agent's own Gitea
|
|
|
|
|
user. The history check, the push and the credential match all use
|
|
|
|
|
that address. So the agent's own user owns the receiving repository on
|
|
|
|
|
every push, and the agent never names it.
|
|
|
|
|
- The host refuses an upstream on a host or port other than the agent's
|
|
|
|
|
Gitea, and an upstream the agent's own user owns. It refuses a fork
|
|
|
|
|
that is missing, empty or doesn't share the project's history. Gitea's
|
|
|
|
|
push-to-create stays off, so a push never creates a repository.
|
|
|
|
|
- Who may: the action routes under REQ-DEC-2 and is granted within-role
|
|
|
|
|
to the coder role only. No other role file grants it.
|
|
|
|
|
- Before version 1.7 the action was a hard wait under REQ-WAIT-3, so
|
|
|
|
|
each push needed a decision the human resolved, and that decision
|
|
|
|
|
named the commit.
|
|
|
|
|
|
|
|
|
|
Every push is logged with the remote, the ref, the commit and, when one
|
|
|
|
|
was given, the decision.
|
|
|
|
|
|
|
|
|
|
### Interface
|
|
|
|
|
|
|
|
|
|
- **REQ-CLI-1.** `mosaic` is the front door. From it Jason can:
|
|
|
|
@@ -925,6 +1181,13 @@ only hard waits in his inbox.
|
|
|
|
|
file only picks among modules already in the tree. The reviewed commit
|
|
|
|
|
that adds a module is the only check on what it does, which is why
|
|
|
|
|
modules from outside the repository wait for Jason (REQ-PLUG-1).
|
|
|
|
|
- Trusted mode lets an agent run its allowed commands at will. On another
|
|
|
|
|
host, an allowed command that writes a file as root or starts a shell
|
|
|
|
|
can plant a key, and the seat sandbox doesn't confine the network, so
|
|
|
|
|
root can outlive the grant and a revoke. The allowlist narrows this. A
|
|
|
|
|
seat sandbox with its own network namespace closes it. Until then the
|
|
|
|
|
host's own audit log is the check after the fact (row 210 design section
|
|
|
|
|
6).
|
|
|
|
|
|
|
|
|
|
## Milestones
|
|
|
|
|
|
|
|
|
|