left4me/docs/superpowers/specs/2026-05-15-session-handoff.md
mwiegand 2834ad4911
deploy: move scripts/{libexec,sbin}/ into deploy/scripts/
Layout consistency: everything ckn-bw deploys to the host now lives
under deploy/. ckn-bw's install_left4me_scripts copy-action goes away
in lockstep with this commit and is replaced by target-side symlinks.

Also updates all path references in docs, tests (conftest.py parents[]
depth, test_overlay_helper.py HELPER_SOURCE), and deploy/README.md.

Part of 2026-05-15-deployment-responsibility-design.md migration step 4.
2026-05-15 19:38:42 +02:00

123 lines
5.6 KiB
Markdown

# Session handoff — next: execute uid-collapse plan
The hardening refactor landed and was verified on `left4.me` earlier
in this session day. A follow-up question surfaced — the
two-user model (`left4me` + `l4d2-sandbox`) is inconsistent now
that systemd hardening covers the same-uid attack surface. The
asymmetry was hashed out and **Option C** (collapse to one user)
chosen. A plan was written but **not executed**. The next session
picks it up.
## What just landed (committed + pushed earlier today)
The hardening refactor — full directive composition deployed to
`left4.me`. server@1 went 7.5 → 1.3 systemd-analyze; web 8.7 → 4.1;
all Test 8 attack vectors blocked. See the prior session-handoff
content in this file's git history (`git log --oneline -- this-file`)
and the close-out commits.
## What's next: execute `2026-05-15-uid-collapse.md`
Plan: `docs/superpowers/plans/2026-05-15-uid-collapse.md`. Approved
in plan-mode this session; not executed.
Scope (10 steps; see plan for detail):
1. Strip the idmap block from `deploy/scripts/libexec/left4me-script-sandbox`
(~30 lines deleted), change `User=l4d2-sandbox``User=left4me`,
`BindPaths="${STAGING}:/overlay"``BindPaths="${OVERLAY_DIR}:/overlay"`.
Keep the `nsenter` self-wrap (it's about namespace escape, not
uid — unaffected).
2. Update `scripts/tests/test_script_sandbox.py` — assertion changes
+ delete the `test_script_sandbox_uses_idmap_staging` test.
3. Update two inline comments referencing `l4d2-sandbox`.
4-6. Doc updates: mark `2026-05-15-build-time-idmap.md` and
`2026-05-14-overlay-idmap.md` superseded; revise the
user-uid-split superseded header to say "1 user" instead of
"2"; one-line notes in the hardening specs.
7. Remove `l4d2-sandbox` from `~/Projekte/ckn-bw/bundles/left4me/items.py`
(users + groups dicts). Tighten `/var/lib/left4me` mode from
`0711``0755`.
8. **On-host pre-flight**: `ssh left4.me` + `sudo find -uid 981`,
chown any stragglers to `left4me` BEFORE applying. ckn-bw won't
remove a user whose files (or processes) are still on disk
gracefully.
9. Push both repos; `bw apply ovh.left4me`.
10. Verify: `getent passwd l4d2-sandbox` empty, no uid-981 files,
sandbox build runs as left4me end-to-end via the web UI.
Rollback path documented in the plan (git revert + bw apply
recreates the user).
## Why we're doing this
The two-user setup was the inconsistent middle ground:
- Server + web run as `left4me` because hardening covers the
threat — uid split would be 1-2 days of cross-repo migration for
marginal kernel-enforcement benefit.
- Sandbox runs as `l4d2-sandbox` for historical reasons — the
build-time-idmap design baked it in.
The hardening composition on the sandbox unit (which the
script-sandbox helper applies via `systemd-run -p ...`) already
gives the same protection profile as the gameserver unit. The
separate uid is defense-in-depth only.
Picking one principle:
- **C** (collapse to one): cheap, deletes ~30 lines of helper code,
removes the build-time-idmap concern entirely. Architecture
simpler. Consistent with the web/server hardening-only decision.
- A (status quo): inconsistent. Documented but not principled.
- B (split fully): 1-2 days of work; we already rejected this for
server/web.
Operator picked C.
## Decision-relevant context already on the host
- After the hardening refactor + bw apply earlier, `left4me-server@*`
and `left4me-web` are running with the full hardening profile.
`kernel.yama.ptrace_scope=2` is set system-wide via the bundle.
- The sandbox unit is currently inactive (it's transient — only
exists during a build). Per the build-time-idmap plan, the
staging path lives at `/var/lib/left4me/tmp/sandbox-idmap-<id>`
during a build.
- ckn-bw's `users` bundle handles the removal mechanically; no
custom dance needed beyond the pre-flight chown.
## Open questions to clarify with the operator before/during execution
- Whether to expand the pre-flight `find -uid 981` from
`/var/lib/left4me` + `/opt/left4me` to all of `/` for paranoia.
Probably not needed; flag for the implementer's judgement.
- Whether to combine left4me + ckn-bw into a single PR-equivalent
cross-repo commit pair, or push left4me first then ckn-bw. Plan
assumes both pushed before `bw apply`.
## What's NOT next
- **`build-overlay-unit` refactor**
(`docs/superpowers/specs/2026-05-15-build-overlay-unit-design.md`).
Sequenced after this; will inherit `User=left4me` cleanly.
- **Broader configmgmt responsibility reshape** (drop-ins owned by
left4me, ckn-bw as thin file-shipper). Framed as a brainstorming
session at `docs/superpowers/specs/2026-05-15-handoff-deployment-responsibility.md`;
sequenced after uid-collapse lands.
- **Stale RCON port app bug** flagged in the earlier executor's
handoff. Separate scope.
- Renaming `left4me` to anything else. Cosmetic.
## Pointers
- The plan to execute: `docs/superpowers/plans/2026-05-15-uid-collapse.md`
- Hardening refactor that just landed: `docs/superpowers/plans/2026-05-15-hardening-refactor.md`
- Hardening threat model + defenses survey + test plan (commit
`461b8d0` recorded the test results inline):
`docs/superpowers/specs/2026-05-15-hardening-{threat-model,defenses-survey,test-plan}.md`
- Build-time-idmap plan (about to be marked superseded):
`docs/superpowers/plans/2026-05-15-build-time-idmap.md`
- uid-split spec (also affected — answer revises from "stay at 2"
to "collapse to 1"):
`docs/superpowers/specs/2026-05-15-user-uid-split-design.md`
- Live source for unit emission: `~/Projekte/ckn-bw/bundles/left4me/metadata.py`
- Live source for users/groups: `~/Projekte/ckn-bw/bundles/left4me/items.py`