feat(firstboot): force root + operator password on first boot (console gate) #139

Merged
clawdie merged 6 commits from force-root-password-on-first-boot into main 2026-06-25 07:21:34 +02:00

6 commits

Author SHA1 Message Date
2fa7825f12 fix(iso): bind colibri_daemon_require_secured=YES to complete the interlock
The rc.conf.sample on the live USB now sets require_secured=YES.
Together with the paired colibri change, this ensures the daemon
disables autospawn until the console gate writes .secured.
2026-06-25 07:05:16 +02:00
73b603d995 feat(firstboot): opt-in require-secured knob + 'will not' skip message
clawdie-iso half of the .secured interlock:
- build.sh writes colibri_daemon_require_secured="YES" to the operator image's
  rc.conf. Opt-in so DEPLOYED colibri hosts (shared colibri_daemon.in via the
  FreeBSD port, no firstboot gate) are unaffected — they never set this knob.
- gate skip message upgraded to 'agent will NOT start or register until secured'.

Depends on the colibri-side consumer (colibri_daemon.in prestart): when
colibri_daemon_require_secured is YES and /var/db/colibri/.secured is absent,
export COLIBRI_AUTOSPAWN=NO (after the provider.env source block). Tracked as the
colibri follow-up; both must ship in the same 0.12 image for the message to hold.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 06:16:34 +02:00
e135c305a4 docs(firstboot): make the skip message honest about unsecured state
The '.secured' marker is written but not yet consumed by colibri, so the gate
must not imply colibri/zot are blocked. Reword the skip message to state the
node is UNSECURED and the agent SHOULD NOT register/run while unsecured — true
as a policy statement, without claiming enforcement we haven't built. Upgrade to
'will not' once the colibri .secured interlock lands.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 06:08:14 +02:00
f428bc7fcb feat(firstboot): visible 'Continuing in 3s 2s 1s' countdown before boot resumes
Replace the silent trailing sleeps with a counting-down message so the operator
sees the result (secured / skipped) and a clear cue before clawdie_live_gpu
repaints the screen. Same ~3s pause, now visible.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 06:02:01 +02:00
70731cddda fix(firstboot): run the password gate before the GPU/KMS switch
Reorder the gate to REQUIRE: FILESYSTEMS devfs / BEFORE: clawdie_live_gpu LOGIN
so it runs on the plain early boot text console, before clawdie_live_gpu does its
KMS/framebuffer mode-switch. That removes the console-flush race entirely, so the
sleep 1 + screen-clear workaround is gone. Still before LOGIN, hence before sddm
and colibri_daemon (race-free property preserved).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 05:59:05 +02:00
0cd59efa6d feat(firstboot): force root + operator password on first boot (console gate)
Adds clawdie_firstboot_rootpw, an rc.d gate ordered BEFORE sddm and
colibri_daemon. On the text console (operator present at first boot) it runs a
15s countdown to engage; if engaged it forces a root AND operator (clawdie)
password, echo-off, applied via 'pw usermod -h 0' over stdin (secret never in
argv/ps, never near the agent). Idempotent via a persistent success marker
/var/db/colibri/.secured (/var persists: varmfs=NO). Skipping leaves the node
open and re-prompts next boot — never bricks an unattended/headless boot.

Running before the daemon means the security decision is always made before any
agent can autospawn/node_register, so no cross-component interlock is needed
(rc ordering replaces it). The .secured marker is also the signal a future
colibri change can read to label an unsecured node to mother.

Tests: tests/firstboot-rootpw-test.sh proves marker skip, password validation,
and that the secret is delivered on stdin and NEVER appears in argv (10/10).

Console interactivity (read -t countdown, stty echo-off on /dev/console) must be
verified by booting on osa/bhyve before merge.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 05:54:13 +02:00