Approved-but-not-executed plan to collapse the two-user model (left4me + l4d2-sandbox) into one. The build-time-idmap that translates sandbox writes back to left4me uid becomes a no-op when source uid == target uid, so it's removed along with ~30 lines of helper plumbing. Hardening already covers the same-uid attack surface the sandbox uid was defending against, so collapsing makes the architecture consistent with the web/server hardening-only decision. Plan: docs/superpowers/plans/2026-05-15-uid-collapse.md Handoff: docs/superpowers/specs/2026-05-15-session-handoff.md Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
121 lines
5.5 KiB
Markdown
121 lines
5.5 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 `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). Deliberately deferred.
|
|
- **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`
|