Secrets program: integrate Vaultwarden PoC into the stack (seat identity, mosaic-secret, CLI enrollment) #956

Open
opened 2026-07-30 17:45:11 +00:00 by jarvis · 1 comment

Why

Owner directive (Jason, 2026-07-30): "The changes and fixes need to be properly integrated into the Mosaic Stack codebase. We are rapidly iterating, but I'm concerned that we aren't using the mosaic repo to make it stick."

He is right: the secrets PoC's durable artifacts currently live in jarvis-brain (runbook docs/plans/2026-07-30-secrets-poc-vaultwarden.md + scripts/secrets/), the defect record lives in issues here (#947, #949–#955), and no code has landed in this repo. Meanwhile ~/.config/mosaic/ (the deployed adapter the fleet actually runs, incl. tools/credentials.sh) is not under git on at least dragon-lin — fixes applied there die on re-install (the generated-artifact-vs-generator hazard, cf. #947's WOODPECKER_SERVER/URL split).

What must land HERE (not in jarvis-brain)

  1. Seat identity substrate (PoC step 2) — per-agent uids provisioned by mosaic install as system units (User=<agent-uid>, root-owned fragments). Criteria stack (each names the partial-fix world it kills — full text in the jarvis-brain runbook, step-2 block):
    • identity gated on the OS principal (env-derived identity is seat-asserted → forgery-capable)
    • mechanism = GIT_AUTHOR_*/GIT_COMMITTER_* env-pair override (repo-local git config is ruled out: shared .git/config, writers race)
    • cgroup is the derivation source, env var only a cache; fail closed outside a seat unit's cgroup
    • --user units disqualified: the derivation is only as trustworthy as the manager that asserts it, and a --user manager IS the seat itself
    • Gated behind the owner's authorship discussion (ruling: hold-and-discuss) and the brain-sync quiesce fix.
  2. mosaic-secret wrapper + secrets loader (PoC steps 3–4) as a stack package replacing credentials.sh, inheriting #947's acceptance constraints (rc observed not just value; VW-read-failure ≠ file-fallback-success; one name per value; requested-instance vs returned-identity check).
  3. mosaic CLI enrollment/teardown (PoC step 5) — revocable agent lifecycle against Vaultwarden. Field-verified inputs: invite→register→confirm chain scriptable on server 2026.6.0 (verification JWT in body under SMTP-off — bootstrap-only vs permanent is an OPEN owner decision); bw confirm org-member exists; public API absent (dual-arm measured), so all automation rides the member seat.
  4. Graduation of the PoC lab scripts (scripts/secrets/{orgkey-check.py,enroll-register.js,negative-visibility-check.sh,provision-collections.sh}) into tested stack code at step-4/5 build time. jarvis-brain remains the lab; this repo is where it sticks.
  5. Bring ~/.config/mosaic under generator control so deployed==generated is checkable (drift checker exists: mos-dt's mosaic-install-drift).

References

  • jarvis-brain: docs/plans/2026-07-30-secrets-poc-vaultwarden.md (runbook, criteria, verdicts — version-pinned server 2026.6.0 / CLI 2026.7.0)
  • Vault state: org mosaic on vw.woltje.com, 4 collections provisioned behind a passed negative-visibility gate, 2026-07-30
  • Related here: #947 (loader autopsy), #949/#954 (self-aiming family), #955 (pipe-rc lint)

Filed-by: jarvis (dragon-lin) — the PoC seat. Sequencing/ownership per owner discussion; nothing in this issue authorizes implementation ahead of the rulings it cites.

## Why Owner directive (Jason, 2026-07-30): *"The changes and fixes need to be properly integrated into the Mosaic Stack codebase. We are rapidly iterating, but I'm concerned that we aren't using the mosaic repo to make it stick."* He is right: the secrets PoC's durable artifacts currently live in jarvis-brain (runbook `docs/plans/2026-07-30-secrets-poc-vaultwarden.md` + `scripts/secrets/`), the defect record lives in issues here (#947, #949–#955), and **no code has landed in this repo**. Meanwhile `~/.config/mosaic/` (the deployed adapter the fleet actually runs, incl. `tools/credentials.sh`) is **not under git on at least dragon-lin** — fixes applied there die on re-install (the generated-artifact-vs-generator hazard, cf. #947's WOODPECKER_SERVER/URL split). ## What must land HERE (not in jarvis-brain) 1. **Seat identity substrate** (PoC step 2) — per-agent uids provisioned by mosaic install as **system units** (`User=<agent-uid>`, root-owned fragments). Criteria stack (each names the partial-fix world it kills — full text in the jarvis-brain runbook, step-2 block): - identity **gated on the OS principal** (env-derived identity is seat-asserted → forgery-capable) - mechanism = `GIT_AUTHOR_*`/`GIT_COMMITTER_*` env-pair override (repo-local `git config` is ruled out: shared `.git/config`, writers race) - **cgroup is the derivation source, env var only a cache**; fail closed outside a seat unit's cgroup - `--user` units disqualified: *the derivation is only as trustworthy as the manager that asserts it, and a `--user` manager IS the seat itself* - Gated behind the owner's authorship discussion (ruling: hold-and-discuss) and the brain-sync quiesce fix. 2. **`mosaic-secret` wrapper + secrets loader** (PoC steps 3–4) as a stack package replacing `credentials.sh`, inheriting #947's acceptance constraints (rc observed not just value; VW-read-failure ≠ file-fallback-success; one name per value; requested-instance vs returned-identity check). 3. **`mosaic` CLI enrollment/teardown** (PoC step 5) — revocable agent lifecycle against Vaultwarden. Field-verified inputs: invite→register→confirm chain scriptable on server 2026.6.0 (verification JWT in body under SMTP-off — bootstrap-only vs permanent is an OPEN owner decision); `bw confirm org-member` exists; public API absent (dual-arm measured), so all automation rides the member seat. 4. **Graduation of the PoC lab scripts** (`scripts/secrets/{orgkey-check.py,enroll-register.js,negative-visibility-check.sh,provision-collections.sh}`) into tested stack code at step-4/5 build time. jarvis-brain remains the lab; this repo is where it sticks. 5. **Bring `~/.config/mosaic` under generator control** so deployed==generated is checkable (drift checker exists: mos-dt's `mosaic-install-drift`). ## References - jarvis-brain: `docs/plans/2026-07-30-secrets-poc-vaultwarden.md` (runbook, criteria, verdicts — version-pinned server 2026.6.0 / CLI 2026.7.0) - Vault state: org `mosaic` on vw.woltje.com, 4 collections provisioned behind a passed negative-visibility gate, 2026-07-30 - Related here: #947 (loader autopsy), #949/#954 (self-aiming family), #955 (pipe-rc lint) Filed-by: jarvis (dragon-lin) — the PoC seat. Sequencing/ownership per owner discussion; nothing in this issue authorizes implementation ahead of the rulings it cites.
Author

Pre-uid-split sequencing item (mos-dt, measured on sb-it-1-dt, 2026-07-30 — recorded here at their direction because their comms message crossed this issue's filing):

The migration inventory in this epic has two triggers with different timing:

  • D-Bus / XDG_RUNTIME_DIR items are system-unit fallout (bite during the unit migration).
  • The tmux wake bus is UID-triggered and bites earlier. TMUX_TMPDIR is unset fleet-wide (0 references in mosaic tooling), so tmux resolves -L NAME under /tmp/tmux-$(id -u)/NAME (mode 700 per uid), and agent-send.sh passes -L through to the target host where the invoking uid resolves it. Cross-seat wake works today because of the exact uid collapse this epic's seat-identity work removes. After the uid split, seat A (uid X) waking seat B (uid Y) is both misdirected and permission-denied, presenting as no such session — indistinguishable from a dead seat. Landing the uid split without this item first silently converts the fleet's wake bus into a fleet that appears down, and debuggers will look at the seats, not the socket directory.

Mitigation installable NOW, independent of the rest of this epic: a fixed shared TMUX_TMPDIR, or agent-send resolving the target's socket dir instead of inheriting the caller's. One hardcode to clean alongside it: scripts/comms/install-comms.sh:39 (jarvis-brain). This is the one piece of the substrate that can be de-risked before the owner's authorship discussion resolves.

Filed-by: jarvis (dragon-lin), carrying mos-dt's measurement.

**Pre-uid-split sequencing item** (mos-dt, measured on sb-it-1-dt, 2026-07-30 — recorded here at their direction because their comms message crossed this issue's filing): The migration inventory in this epic has **two triggers with different timing**: - D-Bus / XDG_RUNTIME_DIR items are **system-unit fallout** (bite during the unit migration). - **The tmux wake bus is UID-triggered and bites earlier.** `TMUX_TMPDIR` is unset fleet-wide (0 references in mosaic tooling), so tmux resolves `-L NAME` under `/tmp/tmux-$(id -u)/NAME` (mode 700 per uid), and `agent-send.sh` passes `-L` through to the target host where the *invoking* uid resolves it. **Cross-seat wake works today because of the exact uid collapse this epic's seat-identity work removes.** After the uid split, seat A (uid X) waking seat B (uid Y) is both misdirected and permission-denied, presenting as `no such session` — indistinguishable from a dead seat. Landing the uid split without this item first silently converts the fleet's wake bus into a fleet that appears down, and debuggers will look at the seats, not the socket directory. **Mitigation installable NOW, independent of the rest of this epic:** a fixed shared `TMUX_TMPDIR`, or `agent-send` resolving the *target's* socket dir instead of inheriting the caller's. One hardcode to clean alongside it: `scripts/comms/install-comms.sh:39` (jarvis-brain). This is the one piece of the substrate that can be de-risked before the owner's authorship discussion resolves. Filed-by: jarvis (dragon-lin), carrying mos-dt's measurement.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#956