PRD 1.11: v1 is the 10-27 goal (Q211, mos-1227, Vikunja 459)
Follows Jason's Q211 ruling and Mos's reading. Adds to v1 and removes nothing. - Status and a Version 1.11 source bullet quoting Q211. - Users: two v1 users on their own instances (Q176). Where it runs: two PVE VMs, dragon-lin dev only (Q180, Q181). - Out of scope: minting credentials (Q188, Q190), SSO (Q175) and access beyond localhost (Q176, Q179, Q180) move into v1. The bundled Pocket ID stays out (REQ-INST-2, Q203). Codex and SetSpark stay out. Case 2's own organization is v1. - REQ-CRED-1: Gitea per seat through a grant (Q190). - REQ-FED-1: person-to-person v1, agent-to-agent post-v1 (Q179, Q180). - New REQ-INST-3: one-command install and upgrade, Console unit enabled in both v1 profiles (Q187, Q189). - Acceptance: the 10-27 goal (Q176). The 1.10 note at :1217 now points to Q211. A Version 1.11 technical note keeps the old list text. requirements.json goes to 1.11 with 71 ids. Both requirements tests are updated to match.
This commit is contained in:
1 parent
cca206cdce
commit
ea0b2a16d6
4 files changed
+100
-19
No files matched your search
+92
-12
@@ -1,6 +1,6 @@
|
||||
# PRD: Mosaic Stack
|
||||
|
||||
- Status: approved, version 1.10. Jason approved draft 0.4 unchanged as
|
||||
- Status: approved, version 1.11. 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
|
||||
@@ -29,6 +29,24 @@
|
||||
chose in Q203, relayed by Mos on 2026-10-21 (mos-1202). Version 1.10
|
||||
adds REQ-INST-2, post-v1: the second sentence of Jason's Q203 answer,
|
||||
with Mos's reading, relayed by Mos on 2026-10-21 (mos-1202, mos-1204).
|
||||
Version 1.11 records Jason's ruling Q211 of 2026-10-21: v1 is the 10-27
|
||||
goal. It updates the lines that the 10-27 rulings settle and adds
|
||||
REQ-INST-3. Q211 sets the path: one seat drafts, a second seat reviews,
|
||||
and Sage lands it. So there is no in-Stack prd.approve for it.
|
||||
- Version 1.11 source, Jason's answer to Q23 in T3, relayed by Mos on
|
||||
2026-10-21 (DECISIONS Q211, mos-1227): "It appears that I have expanded
|
||||
the requirements for v1. My recent goal for the 10-27 release is the
|
||||
goal. The PRD may need to be updated to reflect this change. The PRD can
|
||||
be considered partly stale." Mos's reading, which this version follows:
|
||||
- The Console's own OIDC sign-in (REQ-WEB-2) is v1.
|
||||
- v1 is the 10-27 goal: Q176 (the Given list and Cases 1 and 2) plus the
|
||||
later rulings that put items on the 10-27 path, such as Q179, Q184,
|
||||
Q187, Q188, Q189 and Q190. Where the PRD and those rulings differ, the
|
||||
rulings win.
|
||||
- The answer adds to v1 and removes nothing. Cutting a v1 item goes to
|
||||
Jason.
|
||||
- Rulings that keep an item off the 10-27 path still hold: Q186, Q198's
|
||||
timing, Q203's dragon-lin line and Q208. REQ-INST-2 stays post-v1.
|
||||
- Version 1.10 source, the second sentence of Jason's Q203 answer quoted
|
||||
under 1.9 below, Mos's reading of it in mos-1202, and his ruling in
|
||||
mos-1204 on 2026-10-21 to add it as drafted and mark it post-v1 the
|
||||
@@ -190,13 +208,16 @@ and outstanding decisions don't collect anywhere.
|
||||
|
||||
## Users
|
||||
|
||||
For now the only user is Jason. The stack must still be installable by
|
||||
outside users later, which means:
|
||||
v1 has two users, each on their own instance: Jason on Case 1, the
|
||||
software factory, and Melanie on Case 2, the creative writing hub (Q176,
|
||||
Q211). The stack must still be installable by outside users later, which
|
||||
means:
|
||||
- an installer;
|
||||
- no paths or names specific to Jason;
|
||||
- configuration through the variable layers.
|
||||
|
||||
(Round 1, answer D.)
|
||||
(Round 1, answer D. The 1.10 text began "For now the only user is
|
||||
Jason.")
|
||||
|
||||
## Problem statement
|
||||
|
||||
@@ -228,14 +249,28 @@ decides it later.
|
||||
Self-hosted, on Jason's machines and homelab (round 1, "A first"). Cloud
|
||||
workers aren't ruled out later.
|
||||
|
||||
v1 runs as two instances on VMs on the PVE node: Case 1 on VM 1008 and
|
||||
Case 2 on VM 1012. Each instance runs under its own OS user without sudo.
|
||||
Jason's workstation, dragon-lin, is for dev work only. (Q180, Q181, Q211.)
|
||||
|
||||
### Out of scope for v1
|
||||
|
||||
Round 2, "all":
|
||||
- businesses other than Mosaic Stack (SetSpark joins after v1);
|
||||
- minting credentials (v1 hands out tokens Jason creates);
|
||||
Round 2, "all", as version 1.11 updates it (Q211):
|
||||
- businesses other than Mosaic Stack on Case 1 (SetSpark joins after
|
||||
v1). Case 2's hub runs its own organization on its own instance, and
|
||||
that is v1 (Q176);
|
||||
- Codex (v1 covers Pi and Claude Code, and Codex comes next);
|
||||
- Pocket ID and SSO;
|
||||
- access from beyond localhost.
|
||||
- the bundled Pocket ID (REQ-INST-2, Q203).
|
||||
|
||||
Version 1.11 moves three round 2 items into v1:
|
||||
- Minting credentials. On the user's Approve, protected stack code makes
|
||||
the key, the token or a seat's own Gitea user (REQ-GRANT-2; Q188, Q190).
|
||||
- SSO. The Console runs its own OIDC sign-in (REQ-WEB-2; Q175, Q211).
|
||||
- Access from beyond localhost. Each case runs on its own VM, and people
|
||||
get access across the two instances (Q176, Q179, Q180). The Console's
|
||||
own sign-in (Q175) comes first for any instance that a second user or
|
||||
another instance can reach (Q176). A new listener reachable from outside
|
||||
the host is still a `network.expose` hard wait (REQ-WAIT-1).
|
||||
|
||||
## Requirements
|
||||
|
||||
@@ -401,6 +436,10 @@ Added in version 1.7:
|
||||
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.
|
||||
|
||||
Since version 1.11, Gitea follows Q190: each agent seat gets its own
|
||||
Gitea user through a grant (REQ-GRANT-1, REQ-GRANT-2), not a bot user
|
||||
per role made by hand. Vikunja is unchanged.
|
||||
- **REQ-CRED-2.** A session that finds only founder credentials stops.
|
||||
|
||||
Added in version 1.7:
|
||||
@@ -965,7 +1004,12 @@ Added in version 1.1 (decision 03130d08).
|
||||
in another's. Added in version 1.2.
|
||||
- **REQ-TPL-1.** Templates exist for agent roles and for organization
|
||||
types.
|
||||
- **REQ-FED-1.** Installs can federate with each other. This is post-v1.
|
||||
- **REQ-FED-1.** Installs can federate with each other. Person-to-person
|
||||
federation is v1: a person gets access to another instance by signing in
|
||||
to its Console (REQ-WEB-2), the broker enforces the grants that give
|
||||
that access, and the access can be revoked. Agent-to-agent federation is
|
||||
post-v1. (Version 1.11; Q179, Q180, Q211. The 1.10 text ended "This is
|
||||
post-v1.")
|
||||
|
||||
### Installer
|
||||
|
||||
@@ -988,6 +1032,20 @@ Added in version 1.4 (decision 1ea053cc).
|
||||
- Pocket ID is passkey-only for people. Agents keep per-role service
|
||||
tokens.
|
||||
|
||||
Added in version 1.11 (Q187, Q189, Q211):
|
||||
|
||||
- **REQ-INST-3.** Install and upgrade are one command each.
|
||||
- Install sets up a fresh host as a named instance with its config. The
|
||||
per-case setup is installer config, a profile per case, not one-off
|
||||
scripts.
|
||||
- Upgrade backs up, moves to the new release, and rolls back if its
|
||||
checks fail.
|
||||
- Both are proven on a throwaway VM on the PVE node, install, upgrade to
|
||||
the next release, then rollback, before either v1 VM gets the stack.
|
||||
- Both v1 profiles enable the Console unit, so the Console starts at
|
||||
install and at every boot (Q189). dragon-lin is unchanged.
|
||||
- The container-based install comes after v1.
|
||||
|
||||
## Acceptance criteria and success measures
|
||||
|
||||
v1 is done when Jason gives one-sentence requests to the assistant, in a
|
||||
@@ -1002,6 +1060,11 @@ Version 1.5 adds Jason's Q167 acceptance run, `docs/acceptance/314.md`.
|
||||
It passes when one need goes from Jason's spec to a landed commit with
|
||||
only hard waits in his inbox.
|
||||
|
||||
Version 1.11 adds the 10-27 goal (Q176, Q211). v1 is also done only when
|
||||
both instances are installed and handle their cases: Case 1, the
|
||||
software factory, and Case 2, the creative writing hub. 2026-10-27 is a
|
||||
latest-by date and a hard target (Q176).
|
||||
|
||||
## Technical considerations
|
||||
|
||||
- Vikunja v2.7.0 is AGPL-3.0. Its API tokens can't create users or mint
|
||||
@@ -1214,10 +1277,27 @@ only hard waits in his inbox.
|
||||
re-pin carries row 252. This amendment adds the requirement only.
|
||||
- Version 1.10:
|
||||
- REQ-WEB-2 (1.9) uses the Console's own OIDC sign-in from Q175. The
|
||||
out-of-scope list above still names 'Pocket ID and SSO'. Jason hasn't
|
||||
ruled on that line (vikunja:19/459).
|
||||
out-of-scope list above then still named 'Pocket ID and SSO'. Jason
|
||||
ruled on that line in Q211, and version 1.11 updates it
|
||||
(vikunja:19/459).
|
||||
- The design row for REQ-INST-2 is row 255 (#1760). This amendment adds
|
||||
the requirement only.
|
||||
- Version 1.11:
|
||||
- The 1.10 out-of-scope list, under Round 2, "all", was: businesses
|
||||
other than Mosaic Stack (SetSpark joins after v1); minting credentials
|
||||
(v1 hands out tokens Jason creates); Codex (v1 covers Pi and Claude
|
||||
Code, and Codex comes next); Pocket ID and SSO; access from beyond
|
||||
localhost.
|
||||
- Q211 names Q176's Given list and Cases 1 and 2 as v1. They are
|
||||
tracked on Vikunja #414, #415 and #416. This version doesn't add
|
||||
requirement ids for the items in them that the PRD lacks.
|
||||
- The Case 2 MVP for 10-27 is the Markdown library (#416). The WYSIWYG
|
||||
editor (Q195, Q196) is an add-on that doesn't gate it.
|
||||
- Today the stack has an upgrade tool with activate, rollback and a
|
||||
practice run, and nothing that sets up a fresh host (Q187). The
|
||||
installer row is Vikunja #432, and the throwaway VM proof is #433.
|
||||
- REQ-INST-3 replaces the hand start of the Console for the two v1 VMs
|
||||
only (Q189, mos-1097 item 1).
|
||||
|
||||
## Risks and open questions
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ test('requirements returns the committed list to a holding role session, and no
|
||||
const pm = agent('pm');
|
||||
const list = call(b, pm, 'requirements');
|
||||
assert.deepEqual(list, loadRequirements());
|
||||
assert.equal(list.requirements.length, 70);
|
||||
assert.equal(list.requirements.length, 71);
|
||||
assert.deepEqual(call(b, agent('coder'), 'requirements'), list);
|
||||
assert.throws(() => call(b, human, 'requirements'), /agent-required/);
|
||||
assert.throws(() => call(b, reader, 'requirements'), /read-only/);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"prd": "docs/prd/mosaic-stack.md",
|
||||
"version": "1.10",
|
||||
"version": "1.11",
|
||||
"requirements": [
|
||||
{ "id": "REQ-ROLE-1", "title": "Each role is a reviewed roles/<name>.json: contract, authority map, credentials" },
|
||||
{ "id": "REQ-ROLE-2", "title": "One holder per role instance, one per thread for the assistant; the chief of staff may end a run, others need a decision" },
|
||||
@@ -69,8 +69,9 @@
|
||||
{ "id": "REQ-THREAD-1", "title": "Threads live under projects" },
|
||||
{ "id": "REQ-THREAD-2", "title": "The user creates projects and named threads; each thread is its own assistant session with kept history" },
|
||||
{ "id": "REQ-TPL-1", "title": "Templates for agent roles and for organization types" },
|
||||
{ "id": "REQ-FED-1", "title": "Federation between installs (post-v1)" },
|
||||
{ "id": "REQ-FED-1", "title": "Federation between installs: person-to-person in v1, agent-to-agent post-v1" },
|
||||
{ "id": "REQ-INST-1", "title": "The installer offers optional components: pinned, health-checked, removable, switched on in config; first is SearXNG" },
|
||||
{ "id": "REQ-INST-2", "title": "With no OIDC provider to configure, the installer deploys a bundled Pocket ID, Q203 (post-v1)" }
|
||||
{ "id": "REQ-INST-2", "title": "With no OIDC provider to configure, the installer deploys a bundled Pocket ID, Q203 (post-v1)" },
|
||||
{ "id": "REQ-INST-3", "title": "One-command install of a named instance from a profile, and one-command upgrade with backup and rollback" }
|
||||
]
|
||||
}
|
||||
@@ -18,10 +18,10 @@ test("the list holds the PRD's requirement ids, in its order, at its version", (
|
||||
const ids = [...prd.matchAll(/^- \*\*(REQ-[A-Z]+-[0-9]+)\.\*\*/gm)].map((m) => m[1]);
|
||||
// Any other mention of a bold id would be a bullet this pattern missed.
|
||||
assert.equal(ids.length, [...prd.matchAll(/\*\*REQ-/g)].length);
|
||||
assert.equal(ids.length, 70);
|
||||
assert.equal(ids.length, 71);
|
||||
assert.deepEqual(list.requirements.map((r) => r.id), ids);
|
||||
assert.match(prd, new RegExp(`^- Status: approved, version ${list.version.replace('.', '\\.')}\\.`, 'm'));
|
||||
assert.deepEqual([list.prd, list.version], ['docs/prd/mosaic-stack.md', '1.10']);
|
||||
assert.deepEqual([list.prd, list.version], ['docs/prd/mosaic-stack.md', '1.11']);
|
||||
});
|
||||
|
||||
test('the committed list loads frozen', () => {
|
||||
@@ -74,7 +74,7 @@ test('the schema refuses any other shape', () => {
|
||||
const twice = raw();
|
||||
twice.requirements.push(structuredClone(twice.requirements[0]));
|
||||
writeFileSync(join(dir, 'twice.json'), JSON.stringify(twice));
|
||||
assert.throws(() => loadRequirements(join(dir, 'twice.json')), listError('requirements[70].id: REQ-ROLE-1 twice'));
|
||||
assert.throws(() => loadRequirements(join(dir, 'twice.json')), listError('requirements[71].id: REQ-ROLE-1 twice'));
|
||||
} finally {
|
||||
rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user