gosalyn: Case 2 design r7 for #416 (T2): root steps 2a and 2c owned by ops-01 via localadmin (#423 step 1), no supplementary groups with an id -G check, Hermes sudo as Mos's residual until #423 step 5, C2-13 brief to match (webby-0023, mos-1064)

This commit is contained in:
jason.woltje committed 2026-10-20 15:02:03 -05:00
1 parent a0ce2ffb84
commit 8645cb4560
2 files changed
+65 -24

No files matched your search

+57 -18
View File
@@ -1,4 +1,4 @@
# Case 2 design: the creative writing hub (r6)
# Case 2 design: the creative writing hub (r7)
Gosalyn, 2026-10-20 (from `date -u`). Track T2 in jason-master-restart `projects/mosaic-mvp/PLAN.md`,
Vikunja #416, DECISIONS Q176-Q178. The requirement is Jason's text in TARGET.md (addendum 2026-10-20).
@@ -8,6 +8,28 @@ Base: `refactor` at 9ae8c73ac. r1 cited 5d019d876. `git diff --stat 5d019d876 9a
adapters roles scripts` is empty (Mos in mos-0980, Webby in webby-0001), so every `file:line` holds at
9ae8c73ac. Paths are relative to the repository root.
## Changes from r6
Webby's review (webby-0023, CHANGES, notes at agents/webby/work/case2-r6/REVIEW.md, 216302d65).
- B1. r6 said the install creates `mosaic`, but step 2 and C2-13 run the install as `<user>`. A user
can't create itself, and `mosaic` without sudo can't install a system unit. The #421 plan that owned
those root steps stopped. They are now their own items in section 10: 2a creates `mosaic` and
`/srv/mosaic`, and 2c installs and enables the unit after the install. ops-01 owns them (mos-1064)
and runs them under Jason's go for step 2, over ssh as `[email protected]` with NOPASSWD sudo.
#423 step 1 creates that account. They use neither `melanie`'s sudo nor pve root. So the install
depends on #423 step 1 and on nothing else in #423. C2-13 writes the unit file and doesn't install
it. Section 9 cites Q183 for the layout, not the stopped plan.
- Mos, mos-1064 item 3. r6 said Jason's acceptance covers `melanie`'s sudo. It covers the factory's
paths to .54 (Q182, Q183): pve root, ssh as `melanie`, and the root her sudo gives through those
paths. It doesn't cover the Hermes processes, which run as `melanie` and could use her sudo to read
`/srv/mosaic`. That part is Mos's residual. Q181 keeps Hermes running, and #423 step 5 removes her
sudo once Bean and Chet are live. Section 9 and the r5 notes now say so.
- N1. A system user always has its primary group. Section 9, the C2-13 row and the precheck now say no
supplementary groups, and the precheck checks that `id -G` prints exactly one entry.
The mos-1050 hold on step 1 stays until Webby approves r7 (mos-1064).
## Changes from r5
Mos, mos-1057, after Jason confirmed Q4 (DECISIONS Q183, read at `DECISIONS.md:1533-1545`). The #421
@@ -17,8 +39,9 @@ approves this diff. Steps 2 to 9 still go to Jason.
- Step 1 now says the install creates `mosaic` without sudo, FED R8 records Jason's acceptance, and the
in-VM tightening on .54 is Vikunja #423, which doesn't gate the install.
- Section 9 no longer counts on ops-01's step 2b to remove `melanie`'s sudo. That residual stays until
#423, and Jason's acceptance in FED R8 covers it and the factory's paths to .54.
- Section 9 no longer counts on ops-01's step 2b to remove `melanie`'s sudo. Jason's acceptance in FED
R8 covers the factory's paths to .54. The Hermes processes that could use her sudo are Mos's
residual until #423 step 5 (r7, mos-1064).
## Changes from r4
@@ -914,7 +937,7 @@ Chains follow Q177 merge-chaining. S marks a slice row.
| C2-10b | S | Console chat: cited-item renderer through `renderItems`, the status line | C2-06, C2-09a, C2-03a | Haiku high | webui tests for items, scope badges, notices, "changed since" and the status line |
| C2-12 | S | The setup sheet for Melanie (7.1, including N2 and N4, and what changes for Bean and Chet in 4) and the survey run sheet for `<host>` | C2-01 | Luna | doc only, reviewed against the survey's real flags |
| C2-20 | S | Persona import (9.1): a script that reads only the persona definitions of the two Hermes profiles, confirms profile to name, and writes each persona file (4) with its `persona.name` and `persona.sha256` for the business file. Prints names, byte counts and sha256 only. A `--dry-run` mode, run before Jason's go, prints only counts of files, lines and lines starting `# ` or `## ` | C2-08 | Opus (Gosalyn), run under Jason's go | fixture Hermes profile trees: the right fields are taken, memory and session files are never opened (a read trace on the fixture), a profile with no persona field refuses, a persona that would fail C2-08's fence check refuses, output holds no persona text, each written file is 0600 and its digest matches, `--dry-run` writes nothing and prints the right counts for a fixture with two heading lines and no marker string from it |
| C2-13 | S | Install script and precheck for `<host>` as `<user>`: bootstrap, release activate, business file with the mapping, `bean` and `chet` with their persona vars and files, any specialists she picks, her human id, token slot path, the `mosaic-stack.service` unit. Jason or his delegate runs it (10) | C2-04, C2-03a, C2-20 | Opus (Gosalyn), Jason's go | precheck: config validates, `<user>` has no sudo and no groups, `bus.tester` is not on, the business file, `.history`, `changes.jsonl` and persona files have the modes in 4 and each persona digest matches, the run root is 0700, one marker prompt run through the host's claude with `--system-prompt-file` shows it replaces the default prompt (its version printed), free memory printed, `library.sync` fetches her repo read-only, `library.status` lists R-problems, no Discord binding exists. Tested against a scratch data root and a local bare repo |
| C2-13 | S | Install script and precheck for `<host>` as `<user>`: bootstrap, release activate, business file with the mapping, `bean` and `chet` with their persona vars and files, any specialists she picks, her human id, token slot path, and the `mosaic-stack.service` unit file, which root installs in 10 step 2c. Jason or his delegate runs it (10) | C2-04, C2-03a, C2-20 | Opus (Gosalyn), Jason's go | precheck: config validates, `<user>` has no sudo and `id -G` prints exactly one entry, `bus.tester` is not on, the business file, `.history`, `changes.jsonl` and persona files have the modes in 4 and each persona digest matches, the run root is 0700, one marker prompt run through the host's claude with `--system-prompt-file` shows it replaces the default prompt (its version printed), free memory printed, `library.sync` fetches her repo read-only, `library.status` lists R-problems, no Discord binding exists. Tested against a scratch data root and a local bare repo |
| C2-14 | S | End-to-end acceptance on a scratch data root and a bare repo in her layout: sync, ask a creative agent in its thread, a reply whose cites verify, a playground cite as canon refused, a force-push held as diverged, the Console shows the reply as items | slice rows | Opus | one script, which the reviewer also runs |
| C2-02 | | Bus writes: `writeLibraryFile`, `commitFile` refactor, r1's S0 rule on the working tree | C2-04 | Sol (Rocko) | writer tests, `packages/project/tests` unchanged and green |
| C2-03b | | Push path, race retry, `unpushed`, `library-remote-invalid` on writes | C2-02, C2-03a | Opus | push tests against a bare repo |
@@ -944,10 +967,11 @@ compaction count and clear context (GAP-MAP C2.12, C2.13). Until then, a new thr
## 9. Where it runs, Bean and Chet's move, and what can't be ready by 2026-10-27
Where it runs (Jason, Q181, relayed in mos-1031). `<host>` is her VM 10.1.1.54, W-Melanie-OC, VM 1012
on pve. `<user>` is `mosaic`, a system user with no sudo, no groups and no keys, home `/srv/mosaic` at
mode 0700. It runs as the system unit `mosaic-stack.service` with `ProtectHome`, so nothing it needs may
on pve. `<user>` is `mosaic`, a system user with no sudo, no supplementary groups and no keys, home
`/srv/mosaic` at mode 0700. It runs as the system unit `mosaic-stack.service` with `ProtectHome`, so nothing it needs may
live under `/home`. Its config directory, `<configDir>`, is `/srv/mosaic/.config/mosaic-dev`, and the token
slot and persona files live under it (ops-01's plan, section 3, Vikunja #421). The rest of the design
slot and persona files live under it. ops-01's plan, section 3, set this layout. That plan stopped
with #421, and Q183 keeps a `mosaic` user without sudo on each VM. Section 10 step 2a creates it. The rest of the design
still names `<host>` and `<user>`, so a later move changes only the install inputs. The bus, data root,
mirror and runners live under `<user>`. It needs outbound HTTPS to git.mosaicstack.dev and the model
providers. It needs nothing from her user, because her writing reaches it through the Gitea remote she
@@ -959,10 +983,16 @@ measured 300 to 390 MB on dragon-lin. I estimated at least 2 GB more than the 3.
cores at 2026-10-21T09:00Z (mos-1031, mos-1038), which covers both. C2-13's precheck still prints free memory before the start.
Isolation on that host. `<user>` without sudo keeps the hub from touching her files. The reverse is the
B7 residual from r2: `melanie` has passwordless sudo (mos-1000), and the factory reaches .54 through pve
root and ssh as `melanie` (jason-master-restart `projects/mosaic-mvp/MELANIE-HOST-RECON.md:27-39`). Jason accepted those paths (Q183), and FED R8 records
his acceptance instead of refusing to start. The in-VM tightening is Vikunja #423, and changes to the
`melanie` account wait until Bean and Chet are live (10 step 1).
B7 residual from r2, and it has two parts.
- The factory's paths to .54: pve root, ssh as `melanie`, and the root her passwordless sudo gives
through those paths (mos-1000, jason-master-restart `projects/mosaic-mvp/MELANIE-HOST-RECON.md:27-39`).
Jason accepted them (Q182, Q183), and FED R8 records his acceptance instead of refusing to start.
- The Hermes processes. They run as `melanie` and could use her sudo to read `/srv/mosaic`. Jason's
acceptance doesn't cover this part. It is Mos's residual (mos-1064). Q181 keeps Hermes running, and
it ends when #423 step 5 removes her sudo once Bean and Chet are live.
The in-VM tightening is Vikunja #423. Only its step 1, the `localadmin` account, gates the install
(10 step 2).
### 9.1 Moving Bean and Chet (C2-20)
@@ -1014,15 +1044,24 @@ What it adds is one bot account with read access to that one repo.
1. The host is set (Q181): 10.1.1.54 as `mosaic` under `/srv/mosaic`, 16 GiB and 6 cores. Jason
confirmed Q4 (Q183), so #421 is closed and the install doesn't wait on it.
- The install creates the `mosaic` user without sudo (9). C2-13's precheck refuses if it has sudo or
any group.
- Root steps on `<host>` create the `mosaic` user and its home, under step 2's go (2a). C2-13's
precheck refuses if `<user>` has sudo or any supplementary group.
- FED R8 records Jason's acceptance of the factory's paths to .54. Gizmoduck's r4.10 of the
federation design writes that wording, and it is in progress.
- The in-VM tightening on .54 is Vikunja #423. It doesn't gate the install. Changes to the `melanie`
account wait until Bean and Chet are live.
2. Running the install on `<host>` as `<user>`, by him or his delegate: `scripts/bootstrap.sh`, release
package and activate, the pinned harness, and which model accounts its agents use. Model use is spend,
so the accounts are his call.
- The in-VM tightening on .54 is Vikunja #423. Only its step 1, which creates `localadmin`, gates
the install, through step 2. Its step 5 removes `melanie`'s sudo once Bean and Chet are live, and
that ends Mos's residual (9).
2. The install on `<host>`. Jason's go covers all three parts. 2a and 2c are root steps, owned by
ops-01 (mos-1064). The path is ssh as `localadmin@10.1.1.54` with NOPASSWD sudo, which #423 step 1
creates. Neither uses `melanie`'s sudo or pve root. They are acts on Melanie's machine, so ops-01
doesn't run them without the go.
- 2a, ops-01 via `localadmin`: `useradd` `mosaic` as a system user with no sudo, no supplementary
groups and no keys. Create `/srv/mosaic` at 0700, owned by `mosaic`.
- 2b: the install as `<user>`, by him or his delegate. `scripts/bootstrap.sh`, release package and
activate, the pinned harness, and which model accounts its agents use. Model use is spend, so the
accounts are his call.
- 2c, ops-01 via `localadmin`: install the unit file that C2-13 writes as `mosaic-stack.service`,
and enable it. The unit starts only at step 9.
3. A new Gitea bot account for the hub, with read access to the books repo only. Not bean-brain, and not
her other three repos. Her repo's access list is hers, so adding the bot means asking her or acting as
admin, which is his call.
+8 -6
View File
@@ -2,8 +2,8 @@
Gosalyn, 2026-10-20 (from `date -u`), for sage-1329. Every section follows `docs/plans/BRIEF-TEMPLATE.md`.
The design they build is `agents/gosalyn/work/case2/DESIGN.md` on `gosalyn/case2-design`. Webby
approved r5 at e1635308b in webby-0021, with notes at dba33aaf6. r6 at 1508fd175 changes only section 10
step 1 and the isolation paragraph of section 9 (mos-1057, Q183), and that diff is with Webby. Below, "the design" means that
approved r5 at e1635308b in webby-0021, with notes at dba33aaf6. r6 and r7 change only sections 9 and 10
and C2-13's row (mos-1057, Q183, webby-0023), and that diff is with Webby. Below, "the design" means that
file, with its section number. A builder follows the design and doesn't reopen a decision in it. A
departure goes to Sage before the build continues.
@@ -721,12 +721,14 @@ starts.
The install does: bootstrap, release package and activate, the business file with the mapping, `bean`
and `chet` with their persona vars and files, any specialists she picks, her human id, the token slot
path, and the `mosaic-stack.service` unit. Every host value is an input, so a later host move changes
path, and the `mosaic-stack.service` unit file. It runs as `<user>`, so it doesn't create `<user>` or
install the unit. Root does those in design 10 steps 2a and 2c. Every host value is an input, so a later host move changes
only inputs.
The precheck refuses unless all of these hold:
- The config validates.
- `<user>` has no sudo and no groups, and `bus.tester` is not on.
- `sudo -n true` fails as `<user>`, and `id -G` prints exactly one entry, its primary group. A system
user always has one, so the check is for supplementary groups. `bus.tester` is not on.
- The business file, `.history`, `changes.jsonl` and persona files have the modes in design 4, and
each persona digest matches.
- The run root is 0700.
@@ -743,8 +745,8 @@ claude check runs against a fake claude that appends rather than replaces, and t
### Out of scope
Running it on the host. Design 10 steps 2 to 7 are Jason's. Step 1 no longer waits on #421 (Q183), and
its hold lifts once Webby approves r6. The in-VM tightening on .54 is #423 and doesn't gate the
install. The Gitea bot account and the token slot are steps 3 and 4. Stopping Hermes
its hold lifts once Webby approves r7. The root steps 2a and 2c are ops-01's, over ssh as `localadmin`,
so the install waits on #423 step 1 and on nothing else in #423. The Gitea bot account and the token slot are steps 3 and 4. Stopping Hermes
is step 9 and her choice.
### Gate