From 3feb69e379abd10d5eb4403e6f0b100fe1edf568 Mon Sep 17 00:00:00 2001 From: Viktor Barzin Date: Mon, 8 Jun 2026 14:09:13 +0000 Subject: [PATCH] =?UTF-8?q?workstation:=20pin=20verified=20config-inherita?= =?UTF-8?q?nce=20mechanism=20in=20design=20=C2=A74=20[ci=20skip]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Spike GO (claude 2.1.168): managed claudeMd reaches a session; no managed-skills key exists so skills/rules inherit via per-user ~/.claude symlinks to the base (seeded in /etc/skel). Records the settings.json 0664->0600 leak fix. Co-Authored-By: Claude Opus 4.8 --- docs/plans/2026-06-07-multi-user-workstation-design.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/plans/2026-06-07-multi-user-workstation-design.md b/docs/plans/2026-06-07-multi-user-workstation-design.md index f78f93dc..2148ae27 100644 --- a/docs/plans/2026-06-07-multi-user-workstation-design.md +++ b/docs/plans/2026-06-07-multi-user-workstation-design.md @@ -70,13 +70,14 @@ Run via the existing systemd timer (OnBoot + periodic) for self-healing, plus on **Verified 2026-06-08:** t3 is itself built on `@anthropic-ai/claude-agent-sdk` and opts into `settingSources: [user, project, local]`; the SDK also reads `/etc/claude-code/managed-settings.json` independently. So the managed layer + `~/.claude` reach **both** surfaces — the t3 web UI *and* a terminal `claude`. Two caveats: it's **Claude-specific** (a t3 user who picks Codex/OpenCode won't inherit Claude config), and `rules/` loads via the per-user `user` source (so Task 1.1's "managed-`claudeMd` vs per-user symlink" question stays real). -| What inherits | Base location (machine-wide) | Native mechanism (live) | Per-user override | +| What inherits | Layer (machine-wide) | Native mechanism (live) | Notes | |---|---|---|---| -| Claude skills/prompts/rules/CLAUDE.md/hooks/settings | `/etc/claude-code/managed-settings.json` + managed skills | Claude merges enterprise ⊕ user; auto-reloads | `~/.claude/skills…` (adds; base authoritative on clash) | -| Shell (zsh/aliases/env) | `/etc/zsh/zshrc`, `/etc/profile.d/*.sh`, `/etc/skel` | sourced at login; skel seeds new homes | `~/.zshrc` layers on top | +| **Org guidance** (enforced) | `/etc/claude-code/managed-settings.json` → `claudeMd` | top precedence, every session, non-overridable | NO secrets; **spike-confirmed on claude 2.1.168** | +| **Skills / rules / agents / commands** | per-user `~/.claude/{skills,rules,…}` **symlinks** → Config base | loaded from the `user` source; symlink ⇒ base edits are live | there is **NO** managed-skills key — symlinks ARE the mechanism (the proven emo pattern) | +| Shell (zsh/aliases/env) | `/etc/profile.d/*.sh`, `/etc/skel` | sourced at login; skel seeds new homes | `~/.zshrc` layers on top | | Tools/binaries | system-wide `/usr/local` + apt manifest | one host → shared `/usr` | `pip install --user` in `~` | -`wizard` edits the base → commit → every child inherits on next prompt/login. **No copy, no mirror, no drift** (this replaces today's hand-mirrored per-user setup — the documented emo-drift pain, memory id=3205/4015). Per-user *mutable* state (`~/.claude.json`, `.credentials.json`, `projects/`, history) is never shared — local only. *(Caveat: the managed layer natively covers settings/skills/`claudeMd`; the bespoke `~/.claude/rules/` + `agents/` dirs are delivered via the managed `claudeMd` OR a per-user symlink to the base — pinned in plan Task 1.1. This is also what replaces the old `start-claude.sh: cd /home/wizard/code` hack: config now comes from the managed layer regardless of CWD, so a new user's launcher just `cd ~/code`.)* +`wizard` edits the base → commit → every child inherits on next prompt/login. **No copy, no mirror, no drift** (this replaces today's hand-mirrored per-user setup — the documented emo-drift pain, memory id=3205/4015). Per-user *mutable* state (`~/.claude.json`, `.credentials.json`, `projects/`, history) is never shared — local only. *(Resolved 2026-06-08, spike GO: skills/rules/agents are delivered via per-user `~/.claude/*` symlinks to the base — seeded in `/etc/skel/.claude/` (a symlink there is copied **as a symlink** by `useradd -m`) and reinforced by the provisioner; the managed `claudeMd` carries enforced org guidance. Base = wizard's chezmoi-versioned `~/.claude` (override via `WORKSTATION_CONFIG_BASE`). This replaces the old `start-claude.sh: cd /home/wizard/code` hack — config now comes from the managed layer + symlinks regardless of CWD, so a new user's launcher just `cd ~/code`.)* **Secret leak found+fixed 2026-06-08:** `~/.claude/settings.json` was `0664`, exposing `MEMORY_API_KEY` to every devvm user → `0600` (the chezmoi source is non-private, so it needs a `private_` prefix + the key templated out to persist). ### 5. Infra access (per-user writable locked clone — changes NOT gated)