2026-06-09 08:45:33 +00:00
# THE single source of truth for the devvm Workstation lifecycle (onboard -> offboard).
# Consumed by roster_engine.py (derive/validate) + t3-provision-users.sh (apply).
#
# os_user (the map KEY, pinned) -> authentik_user . k8s_user . tier . namespaces
# The three identifiers differ per person (verified 2026-06-08) -- no email->username
# derivation; record each explicitly.
#
# Tiers: admin | power-user | namespace-owner
# admin - cluster-admin, unlocked tree, secrets (groups: sudo,docker,code-shared)
# power-user - cluster-wide READ (no Secrets) via oidc-power-user-readonly; locked clone
# namespace-owner - admin in their own namespace(s) only; locked clone
#
workstation: per-user code_layout — workspace puts project repos under ~/code (ancamilea + tripit)
Viktor asked to restructure Anca's setup: her ~/code WAS the infra clone
itself; he wants ~/code to be the directory where all her project repos
(tripit etc.) live side by side, with infra moved to a subdirectory.
- roster.yaml gains per-user 'code_layout: single|workspace' + 'repos',
validated + derived by roster_engine.py (12 new tests, 40 total).
- t3-provision-users reconcile: auto-migrates a single-layout ~/code to
~/code/infra (running processes follow the moved inode), hoists nested
project clones to the workspace root, clones roster repos from Forgejo
AS the user (their PAT makes private repos work), and wires the
documented forgejo remote + forgejo/master upstream into clones that
predate that contract.
- Fixed a latent TSV bug: empty jq @tsv fields collapse under tab-IFS
read, shifting later fields left (groups was only safe by being the
last field) — emit '-' sentinels instead.
- start-claude.sh session freshen is layout-aware (freshens each repo
under ~/code for workspace users).
- managed claudeMd + AGENTS.md non-admin recipe + multi-tenancy.md
updated in the same change.
Applied live: ancamilea = workspace (infra at ~/code/infra, her existing
tripit clone hoisted to ~/code/tripit, master upstream switched to
forgejo/master); emo stays single layout, untouched. [ci skip]
2026-06-10 18:05:31 +00:00
# Optional per-user code layout (non-admins):
# code_layout: single (default) - ~/code IS the locked infra clone
# code_layout: workspace - ~/code is a directory of per-project clones:
# the locked infra clone at ~/code/infra, plus
# each `repos` entry cloned from Forgejo
# viktor/<name> with the user's own PAT.
# A single-layout ~/code is auto-migrated.
#
2026-06-09 08:45:33 +00:00
# wizard IS listed (as admin): the reconcile REGENERATES /etc/ttyd-user-map +
# dispatch.json from this file, so omitting him would drop his t3 instance. The
# provisioner skips account/group/clone mutations for already-existing users, so
# listing him is safe (he keeps his unlocked tree + cluster-admin untouched).
users :
wizard : {authentik_user: vbarzin, k8s_user: wizard, tier : admin} # base config author + cluster-admin
emo : {authentik_user: emil.barzin, k8s_user: emo, tier : power-user} # NET-NEW k8s_users entry (add as power-user before provisioning)
workstation: per-user code_layout — workspace puts project repos under ~/code (ancamilea + tripit)
Viktor asked to restructure Anca's setup: her ~/code WAS the infra clone
itself; he wants ~/code to be the directory where all her project repos
(tripit etc.) live side by side, with infra moved to a subdirectory.
- roster.yaml gains per-user 'code_layout: single|workspace' + 'repos',
validated + derived by roster_engine.py (12 new tests, 40 total).
- t3-provision-users reconcile: auto-migrates a single-layout ~/code to
~/code/infra (running processes follow the moved inode), hoists nested
project clones to the workspace root, clones roster repos from Forgejo
AS the user (their PAT makes private repos work), and wires the
documented forgejo remote + forgejo/master upstream into clones that
predate that contract.
- Fixed a latent TSV bug: empty jq @tsv fields collapse under tab-IFS
read, shifting later fields left (groups was only safe by being the
last field) — emit '-' sentinels instead.
- start-claude.sh session freshen is layout-aware (freshens each repo
under ~/code for workspace users).
- managed claudeMd + AGENTS.md non-admin recipe + multi-tenancy.md
updated in the same change.
Applied live: ancamilea = workspace (infra at ~/code/infra, her existing
tripit clone hoisted to ~/code/tripit, master upstream switched to
forgejo/master); emo stays single layout, untouched. [ci skip]
2026-06-10 18:05:31 +00:00
ancamilea : {authentik_user: ancaelena98, k8s_user: anca, tier: namespace-owner, namespaces: [plotting-book], code_layout: workspace, repos : [ tripit]} # ALREADY provisioned in-cluster -- assert, don't re-create
2026-06-09 08:45:33 +00:00
# gheorghe: {authentik_user: vabbit81, k8s_user: vabbit81, tier: namespace-owner, namespaces: [vabbit81]} # already a cluster ns-owner; uncomment to give him a devvm workstation