fix: clawdie pre-build hardening + Codex handoff #6

Merged
clawdie merged 2 commits from fix/clawdie-prebuild-hardening into main 2026-06-02 10:49:22 +02:00
3 changed files with 125 additions and 12 deletions

View file

@ -90,9 +90,13 @@ COLIBRI_COST_MODE="${COLIBRI_COST_MODE:-smart}"
# cargo build --release -p clawdie)
# Leave them blank to ship a "bring your own key" binary configured via the
# rc.d env file (/usr/local/etc/clawdie/clawdie.env) at runtime instead.
# CLAWDIE_ENABLE defaults NO: stage the binary + rc.d but do not auto-start at
# boot until rc.d supervision is proven on the target image (same caution as
# COLIBRI_DAEMON_ENABLE), so clawdie cannot interfere with SDDM/live boot.
# Start it manually with `service clawdie start`, then flip to YES once proven.
FEATURE_CLAWDIE="${FEATURE_CLAWDIE:-NO}"
CLAWDIE_ARTIFACT_DIR="${CLAWDIE_ARTIFACT_DIR:-}"
CLAWDIE_ENABLE="${CLAWDIE_ENABLE:-YES}"
CLAWDIE_ENABLE="${CLAWDIE_ENABLE:-NO}"
# Local LLM runtime (optional)
# Choices: none | ollama | llama_cpp

View file

@ -121,7 +121,7 @@ echo " Pkg : ${DEFAULT_PKG_BRANCH}"
echo " GPU : ${GPU_DRIVER:-auto-detect}"
echo " Target : ${TARGET:-baremetal}"
echo " Colibri : ${FEATURE_COLIBRI:-NO}"
echo " Clawdie : ${FEATURE_CLAWDIE:-NO}"
echo " Clawdie agent : ${FEATURE_CLAWDIE:-NO}"
echo ""
# Name the output for the thing we are actually building.
@ -794,18 +794,16 @@ install_clawdie_service() {
env \
COLIBRI_REPO="${_resolved_clawdie_repo}" \
CLAWDIE_ARTIFACT_DIR="${_resolved_clawdie_artifact_dir}" \
CLAWDIE_STAGE_ENABLE="${CLAWDIE_ENABLE:-YES}" \
CLAWDIE_STAGE_ENABLE="${CLAWDIE_ENABLE:-NO}" \
"${SCRIPT_DIR}/scripts/stage-clawdie-iso.sh" "${MOUNT_POINT}"
if ! /usr/sbin/pw -R "${MOUNT_POINT}" groupshow clawdie >/dev/null 2>&1; then
/usr/sbin/pw -R "${MOUNT_POINT}" groupadd clawdie
fi
# The clawdie agent runs as the operator `clawdie` account (same pattern as
# Clawdie-AI). configure_live_operator_session() creates that user/group
# earlier in the build, so we reuse it rather than re-creating a conflicting
# nologin account here. Assert it exists instead of silently diverging.
if ! /usr/sbin/pw -R "${MOUNT_POINT}" usershow clawdie >/dev/null 2>&1; then
/usr/sbin/pw -R "${MOUNT_POINT}" useradd clawdie \
-g clawdie \
-d /var/db/clawdie \
-s /usr/sbin/nologin \
-c "Clawdie Agent"
echo "ERROR: clawdie user missing — configure_live_operator_session must run before install_clawdie_service"
exit 1
fi
mkdir -p \
@ -821,7 +819,7 @@ install_clawdie_service() {
"${MOUNT_POINT}/var/run/clawdie" \
"${MOUNT_POINT}/var/log/clawdie"
set_config_line "${MOUNT_POINT}/etc/rc.conf" "clawdie_enable=\"${CLAWDIE_ENABLE:-YES}\""
set_config_line "${MOUNT_POINT}/etc/rc.conf" "clawdie_enable=\"${CLAWDIE_ENABLE:-NO}\""
set_config_line "${MOUNT_POINT}/etc/rc.conf" 'clawdie_user="clawdie"'
set_config_line "${MOUNT_POINT}/etc/rc.conf" 'clawdie_group="clawdie"'
set_config_line "${MOUNT_POINT}/etc/rc.conf" 'clawdie_data_dir="/var/db/clawdie"'

View file

@ -0,0 +1,111 @@
# Clawdie agent — Codex ISO Builder handoff
**From:** Claude Reviewer (Linux) · **To:** Codex ISO Builder (FreeBSD 15 host)
**Subject:** stage + validate the simplified `clawdie` agent on the operator USB
The `clawdie` binary is the simplified, operator-friendly Colibri agent: one
small Rust binary (glasspane + herdr supervision + a DeepSeek-backed Telegram
bot). All quota/cost-mode/provider-fallback complexity is lifted. It is wired
into the ISO behind `FEATURE_CLAWDIE` (default `NO`) and runs as an rc.d service
like Clawdie-AI.
## Precondition (blocking)
Two PRs must be merged to `main` **before** step 1 — until colibri `main` has
the `clawdie` crate, the workspace build won't produce the binary:
- colibri: `feat/clawdie-agent` → main
- clawdie-iso: `fix/clawdie-prebuild-hardening` → main (this branch)
## Task checklist
- [ ] 1. Build colibri release artifacts (incl. `clawdie`) on the FreeBSD host.
- [ ] 2. Run ISO preflight syntax checks.
- [ ] 3. Build the image with `FEATURE_CLAWDIE=YES` (staged, NOT auto-started).
- [ ] 4. Inspect the mounted image.
- [ ] 5. Validate on real hardware (SDDM/XFCE first, then start clawdie).
- [ ] 6. Cleanup only after the ISO build consumed the artifacts.
### 1. Build colibri (do NOT `cargo clean` afterward — the ISO consumes `target/release`)
```sh
cd /home/clawdie/colibri
git fetch origin && git pull --ff-only
# Baked creds are compiled into the binary and are extractable from the image.
# For a distributable image, OMIT both flags and use the rc.d env file instead
# (/usr/local/etc/clawdie/clawdie.env at runtime).
CLAWDIE_TG_TOKEN="<telegram-bot-token>" \
CLAWDIE_DEEPSEEK_KEY="<deepseek-key>" \
cargo build --workspace --release
ls -lh target/release/clawdie && file target/release/clawdie
```
### 2. ISO preflight
```sh
cd /home/clawdie/clawdie-iso
git fetch origin && git pull --ff-only
sh -n build.sh
sh -n scripts/stage-clawdie-iso.sh
```
### 3. Build with the clawdie lane on (staged but disabled at boot)
`build.cfg` ships `FEATURE_CLAWDIE=NO` / `CLAWDIE_ENABLE=NO`. Enable staging for
this image; leave `CLAWDIE_ENABLE=NO` so clawdie cannot interfere with SDDM/live
boot until rc.d supervision is proven on hardware. Use the standard
`clawdie:3` / `iso` tmux pane per the `iso-build` skill.
```sh
FEATURE_CLAWDIE=YES /usr/bin/script -q \
tmp/operator-usb-$(git rev-parse --short HEAD)-build.log \
./build.sh --skip-memstick-fetch --live-default-password
```
### 4. Mounted-image inspection (before flashing)
- `/usr/local/bin/clawdie` present + executable
- `/usr/local/etc/rc.d/clawdie` present
- `etc/rc.conf``clawdie_enable="NO"` (staged-disabled is intentional)
- `clawdie` is the **operator** account (reused, not a second nologin user)
- `/var/db/clawdie`, `/var/run/clawdie`, `/var/log/clawdie` owned
`clawdie:clawdie`, mode 0750
### 5. Hardware validation (final proof — bhyve/static inspection is not enough)
1. Boot real hardware; confirm **SDDM → XFCE** first (clawdie disabled, so it
can't be blamed for any boot issue).
2. `service clawdie start``service clawdie status`
3. `sockstat | grep clawdie` (Herdr socket bound); tail
`/var/log/clawdie/clawdie.log`
4. Message the Telegram bot → expect a DeepSeek reply.
5. If clean, flip `CLAWDIE_ENABLE=YES` for the next image so it boots as a
service.
### 6. Cleanup (only after the ISO build consumed the artifacts)
```sh
cd /home/clawdie/colibri && cargo clean && rm -rf /tmp/colibri-*
```
## Notes / caveats
- The clawdie daemon runs as the operator `clawdie` user (same pattern as
Clawdie-AI's rc.d service). `install_clawdie_service` reuses that account and
errors if it is missing rather than creating a conflicting nologin user.
- No new FreeBSD system deps: `reqwest`/`rustls`/`tokio`/`portable-pty`/`rusqlite`
are already in the colibri workspace. Build proof so far was Linux-only — this
handoff covers the first FreeBSD build.
- Reference docs on colibri `main` after merge: `docs/CLAWDIE-BUILD.md`,
`docs/CLAWDIE-AGENT-WIKI.md`.
## Deletion criteria
Delete this handoff once the first `FEATURE_CLAWDIE=YES` image has booted on real
hardware, clawdie has been started and confirmed (socket + Telegram reply), and
the result is recorded below.
## Results
_(Codex: record build host, commit SHAs, binary size, mounted-image findings,
and hardware validation outcome here.)_