Three refusals, one doctrine: detect, refuse, name the repair — and never
back out state rig did not create.
- verify_effective_tag grows the same <back-out|keep> mode discipline as
verify_user_owned. First join keeps the logout-and-die on an untagged key;
the already-joined path now refuses WITHOUT logout — the untagged node may
be a login-joined workstation (untagged by design) that a join=authkey
re-run must not tear off the tailnet. The die names both ways out.
- verify_user_owned fails CLOSED on a stalled backend: empty tags is its
success signal, so a 30s poll that never saw Running waved a tagged node
on a slow tailscaled through as user-owned. state!=Running now dies in
both modes, logging nothing out — nothing was verified, so the repair is
to re-run and verify, not to undo a join that may be fine.
- The permitrootlogin acceptance is class-gated. class=human keeps
no|prohibit-password|without-password (`no` is the close-root state).
class=server accepts only prohibit-password|without-password: root SSH is
the control plane's automation door, and `no` there means a leftover
00-rig-users.conf from a former class=human life has fleet management
silently dead. Refused loudly, drop-in named, never auto-removed —
silently reopening a root door is worse than a loud stop.
Harness greps pin all three die messages so a deleted guard cannot ship
green (repo precedent: the tag-refusal greps).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>