Merge forgejo/master: reconcile diverged lineages [ci skip]
Local checkout carried the 2026-06-10 DNS/registry architecture series (pfSense forward-zone, CoreDNS viktorbarzin.me:53 carve-out, nodes stock) + vzdump/nfs-mirror/workstation-rebuild commits that never reached the canonical remote, while forgejo master received the emo-access series via isolated worktrees. Viktor asked to merge. Conflict resolutions (newest iteration wins in each file): - stacks/forgejo/cleanup.tf: LOCAL — dry_run=true (2026-06-10 revert after live retention orphaned OCI indexes; remote had 06-09 enable) - .claude/CLAUDE.md, docs/architecture/backup-dr.md: LOCAL — final registry/DNS architecture + implemented vzdump alerts - scripts/workstation/setup-devvm.sh: LOCAL — pinned-version, reproducible-rebuild refactor (kubelogin pin, restructured staging) - scripts/workstation/managed-settings.json: FORGEJO — the allow-then-audit claudeMd (matches /etc deployment byte-for-byte) - scripts/t3-provision-users.sh: FORGEJO comment; refresh_locked_clone intact [ci skip]: all stack changes in the local lineage were applied live this morning — CI would re-walk 100+ stacks via the modules/ fallback for zero state change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
commit
8cfd0e5e5c
10 changed files with 160 additions and 5 deletions
|
|
@ -45,6 +45,25 @@ install_locked_clone() {
|
|||
runuser -u "$user" -- git -C "$home/code" checkout --quiet master
|
||||
}
|
||||
|
||||
# Keep an EXISTING non-admin clone fresh (the admin's tree is never touched): fetch
|
||||
# all remotes, then fast-forward master only when that is provably safe — on master,
|
||||
# clean tree, upstream configured. Never rebases/merges; a non-ff master (local
|
||||
# commits) is the user's to reconcile and is only WARNed about. Fetch failures
|
||||
# (offline, missing credentials) are non-fatal: freshness is best-effort.
|
||||
refresh_locked_clone() {
|
||||
local user="$1" home
|
||||
home="$(getent passwd "$user" | cut -d: -f6)"
|
||||
[[ -n "$home" && -d "$home/code/.git" ]] || return 0
|
||||
if [[ "$DRY_RUN" == 1 ]]; then echo "[dry-run] refresh clone -> $user:$home/code"; return 0; fi
|
||||
runuser -u "$user" -- env GIT_TERMINAL_PROMPT=0 git -C "$home/code" fetch --all --prune --quiet 2>/dev/null \
|
||||
|| { log "WARN: clone fetch failed for $user (offline/credentials?) — skipped"; return 0; }
|
||||
[[ "$(runuser -u "$user" -- git -C "$home/code" symbolic-ref --short -q HEAD)" == master ]] || return 0
|
||||
[[ -z "$(runuser -u "$user" -- git -C "$home/code" status --porcelain)" ]] || return 0
|
||||
runuser -u "$user" -- git -C "$home/code" rev-parse --verify -q 'master@{upstream}' >/dev/null || return 0
|
||||
runuser -u "$user" -- git -C "$home/code" merge --ff-only 'master@{upstream}' >/dev/null 2>&1 \
|
||||
|| log "WARN: $user master not fast-forwardable (local commits?) — left as-is"
|
||||
}
|
||||
|
||||
# Per-user OIDC kubeconfig (kubelogin/PKCE — the `kubernetes` Authentik client is
|
||||
# public, no secret). Identical for all users: identity comes from each user's own
|
||||
# interactive OIDC login, which the apiserver maps (email claim) to their RBAC.
|
||||
|
|
@ -177,8 +196,9 @@ while IFS=$'\t' read -r os_user tier shell groups_csv; do
|
|||
log "add $os_user -> group $g"; run gpasswd -a "$os_user" "$g" >/dev/null
|
||||
done
|
||||
fi
|
||||
if [[ "$tier" != admin ]]; then # non-admins: locked clone + kubeconfig + shared Claude token
|
||||
if [[ "$tier" != admin ]]; then # non-admins: locked clone (kept fresh) + kubeconfig + shared Claude token
|
||||
install_locked_clone "$os_user"
|
||||
refresh_locked_clone "$os_user"
|
||||
install_user_kubeconfig "$os_user"
|
||||
install_user_claude_token "$os_user"
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"claudeMd": "# Viktor Barzin homelab — shared multi-user Claude Code Workstation (devvm)\n\nYou are running as a specific OS user on a SHARED devvm Workstation, not as the admin. These org-wide rules apply to EVERY user and sit at the top of settings precedence (they cannot be overridden by a user's own config):\n\n- Respect your permission tier. Your kubectl, Vault, and infra access are scoped to your RBAC tier (admin / power-user / namespace-owner). Do not attempt to escalate privileges or reach another user's resources.\n- Secrets are per-user. Never read another user's home directory, credentials, tokens, or ~/.claude secrets. Your own secrets live in your home at mode 600.\n- Infrastructure changes go through Terraform/Terragrunt (scripts/tg apply) — never direct kubectl apply/edit/patch. Pushing to git does NOT deploy; applies are manual and admin-gated, so your edits cannot take effect without an admin apply.\n- Follow the engineering rules in ~/.claude/rules/ (execution, planning, quality) and every CLAUDE.md in the repo tree.\n- The monorepo is at ~/code. Non-admins get a git-crypt-LOCKED clone: secret files read as ciphertext — that is expected, not an error.",
|
||||
"claudeMd": "# Viktor Barzin homelab — shared multi-user Claude Code Workstation (devvm)\n\nYou are running as a specific OS user on a SHARED devvm Workstation, not as the admin. These org-wide rules apply to EVERY user and sit at the top of settings precedence (they cannot be overridden by a user's own config):\n\n- Respect your permission tier. Your kubectl, Vault, and infra access are scoped to your RBAC tier (admin / power-user / namespace-owner). Do not attempt to escalate privileges or reach another user's resources.\n- Secrets are per-user. Never read another user's home directory, credentials, tokens, or ~/.claude secrets. Your own secrets live in your home at mode 600.\n- Infrastructure changes go through Terraform/Terragrunt — never direct kubectl apply/edit/patch. Committed stack changes are auto-applied by CI on push to master; you can verify the live result with your read-only kubectl.\n- The AGENT does ALL git mechanics silently — the user may not know git, so never ask them to commit, push, pull, or open anything, and never surface git jargon. When you finish a change in ~/code: commit it ON master and push to the forgejo remote. THE COMMIT MESSAGE IS THE AUDIT TRAIL — subject says WHAT changed; body says WHY in plain words (paraphrase the user's actual request) — this matters more than the change itself. Never use [ci skip] as a non-admin (it would hide the change from the audit feed; harmless no-op applies are fine). If the push is rejected non-fast-forward, git pull --rebase forgejo master and push again. If it is rejected by branch protection (user not whitelisted), fall back to a <os-user>/<topic> branch + PR via the Forgejo API (token = password field in ~/.git-credentials). Keep ~/code on a clean master when done so background auto-refresh keeps working. Tell the user in plain words what happened ('done — your change is live/recorded'). Full recipe: AGENTS.md → 'Non-admin workstation users' in ~/code.\n- Follow the engineering rules in ~/.claude/rules/ (execution, planning, quality) and every CLAUDE.md in the repo tree.\n- The monorepo is at ~/code. Non-admins get a git-crypt-LOCKED clone: secret files read as ciphertext — that is expected, not an error.",
|
||||
"model": "claude-fable-5"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,19 @@ fi
|
|||
|
||||
cd "$HOME/code" 2>/dev/null || cd "$HOME"
|
||||
|
||||
# Freshen ~/code at session start so the user begins on current upstream state
|
||||
# (the hourly t3-provision-users reconcile does the same in the background).
|
||||
# Fast-forward only, and only when safe (on master + clean tree); hard 15s cap so
|
||||
# an offline remote never stalls the launch. No-op for repos without remotes.
|
||||
if [ -d "$HOME/code/.git" ]; then
|
||||
GIT_TERMINAL_PROMPT=0 timeout 15 git -C "$HOME/code" fetch --all --prune --quiet 2>/dev/null || true
|
||||
if [ "$(git -C "$HOME/code" symbolic-ref --short -q HEAD)" = master ] \
|
||||
&& [ -z "$(git -C "$HOME/code" status --porcelain 2>/dev/null)" ] \
|
||||
&& git -C "$HOME/code" rev-parse --verify -q 'master@{upstream}' >/dev/null 2>&1; then
|
||||
git -C "$HOME/code" merge --ff-only 'master@{upstream}' >/dev/null 2>&1 || true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Prefer the system-wide `claude` (installed by setup-devvm.sh); fall back to npx.
|
||||
launch() {
|
||||
if command -v claude >/dev/null 2>&1; then
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue