gosalyn: Case 2 C2-13 brief takes row 195's asks: --profile factory|library, node 24 and bwrap precheck lines, copy id as the one varying ExecStart part (darkwing)

This commit is contained in:
jason.woltje committed 2026-10-20 15:38:32 -05:00
1 parent 3e25a829d7
commit 13a98bfd08
1 file changed
+25 -2
+25 -2
View File
@@ -734,10 +734,24 @@ path. It runs as `<user>` through `sudo -u mosaic -H` from `localadmin`, and `mo
doesn't create `<user>` and writes no unit file. Root does those in design 10 steps 2a and 2c. Every doesn't create `<user>` and writes no unit file. Root does those in design 10 steps 2a and 2c. Every
host value is an input, so a later host move changes only inputs. host value is an input, so a later host move changes only inputs.
Row 195 runs these scripts by input for Case 1 on 10.1.1.53 (darkwing to gosalyn, design at
`agents/darkwing/work/queue-195/DESIGN.md` section 2). They don't copy them. So the install and the
precheck take `--profile factory|library`, default `library`:
- `library` is everything this brief lists.
- `factory` skips the library mapping, the persona files and digests, the token slot, and
`library.sync` and `library.status`. It requires `bus.tester` on, because Case 1's acceptance uses the
tester.
- `factory` refuses a business file that has a `kind: "library"` project, with
`profile-library-business`. So Case 2 can't reach a tester-on check through a wrong flag.
- `library` refuses with `bus.tester` on, as before.
`case2-unit.sh` is the 2c step. Root runs it from a root-owned checkout of the reviewed commit outside `case2-unit.sh` is the 2c step. Root runs it from a root-owned checkout of the reviewed commit outside
`/srv/mosaic`, never from the release, because `mosaic` can write the release. It does the following: `/srv/mosaic`, never from the release, because `mosaic` can write the release. It does the following:
- It renders the unit from the checkout's template, with the user and home as inputs. - It renders the unit from the checkout's template, with the user, the home and the copy id as inputs.
- It refuses unless `User=`, `Group=`, `ExecStart=` and the hardening lines match fixed values. - It refuses unless `User=`, `Group=`, `ExecStart=` and the hardening lines match fixed values. The
copy id is the one part of `ExecStart=` that varies, so a re-pin to a new copy can re-render the
unit (row 195). It must be exactly 40 lowercase hex characters naming an existing directory directly
under `<home>`'s copies dir. Anything else refuses before the render.
- It refuses any `PermissionsStartOnly=`, and any `Exec*=` value whose leading run of prefix - It refuses any `PermissionsStartOnly=`, and any `Exec*=` value whose leading run of prefix
characters (`@`, `-`, `:`, `+`, `!`) holds a `+` or `!`. systemd takes those prefixes in any order, characters (`@`, `-`, `:`, `+`, `!`) holds a `+` or `!`. systemd takes those prefixes in any order,
so `-+/srv/mosaic/x` runs as root even with `User=mosaic`. The named-line check doesn't read these so `-+/srv/mosaic/x` runs as root even with `User=mosaic`. The named-line check doesn't read these
@@ -754,6 +768,11 @@ The precheck refuses unless all of these hold:
- The business file, `.history`, `changes.jsonl` and persona files have the modes in design 4, and - The business file, `.history`, `changes.jsonl` and persona files have the modes in design 4, and
each persona digest matches. each persona digest matches.
- The run root is 0700. - The run root is 0700.
- `node --version` is 24 or later, because every package's `engines` field says `>=24` (row 195: .53
has v22.22.2).
- `bwrap --unshare-all --ro-bind / / true` exits 0 as `<user>`. Without it no session starts. Row 195
found no bwrap on .53, and `kernel.apparmor_restrict_unprivileged_userns=1`, and .54 may be the same.
On a refusal, the precheck prints the sysctl's value and whether `bwrap` is on PATH.
- One marker prompt run through the host's claude with `--system-prompt-file` shows that it replaces - One marker prompt run through the host's claude with `--system-prompt-file` shows that it replaces
the default prompt. The claude version is printed. the default prompt. The claude version is printed.
- `library.sync` fetches her repo read-only, and `library.status` lists R-problems. - `library.sync` fetches her repo read-only, and `library.status` lists R-problems.
@@ -770,7 +789,11 @@ claude check runs against a fake claude that appends rather than replaces, and t
- a symlink at the unit path - a symlink at the unit path
- a template with `ExecStartPre=+/srv/mosaic/x` - a template with `ExecStartPre=+/srv/mosaic/x`
- a template with `ExecStartPre=-+/srv/mosaic/x` - a template with `ExecStartPre=-+/srv/mosaic/x`
- a copy id that is short, uppercase, holds `/` or `..`, or names no directory
Precheck cases for the new lines: a fake `node` printing v22 refuses, and a fake `bwrap` that exits 1
refuses. `--profile factory` passes with the tester on and no library items, and refuses a business
file with a library project. `--profile library` refuses with the tester on.
A clean render writes a 0644 file. A test checks the script for `systemctl link`. A clean render writes a 0644 file. A test checks the script for `systemctl link`.
### Out of scope ### Out of scope