setup/cms.test.ts: mock AGENT_DOMAIN='clawdie.si' via vi.mock so
server_name assertions don't depend on env/registry at test time.
src/explanation-grounder.test.ts: accept either PGPASSWORD branch or
no-password branch — OPS_DB_URL may or may not carry a password
depending on the install environment.
Both tests now pass on debby (Linux/Debian 13) and should be
environment-independent on all platforms.
---
Build: pass | Tests: FAIL — 17 failed
- setup/browser-jail.ts: NODE_PATH=/opt/browser-validation/node_modules -> /opt/clawdie/node_modules to match where ensureBrowserBackendDeps actually installs deps
- docs/internal/BROWSER-JAIL.md: Decided section now says host-resident xpra over SSH, not controlplane-streamed clone
Route jail exec through a new hostd bastille-cmd operation, remove the agent-jail sudoers requirement, and fall back to repository ownership when elevation does not provide SUDO_* metadata.
---
Build: pass | Tests: n/a (Vitest not run in this Linux environment per repo policy)
---
Build: pass | Tests: pass — 2375 passed (704 files)
Check jail root existence before getfacl and capture getfacl stderr so soft ACL verification failures do not pollute test output.
---
Build: pass | Tests: pass — 2370 passed (704 files)
Drop the temporary cleanup helper and all remaining clawdie-site references now that the docs project path is clawdie-docs.
---
Build: pass | Tests: pass — 2372 passed (704 files)
setup/cms.ts: removeLegacyDocsBootstrapMount() now strips any fstab
entry whose source path ends with bootstrap/cms/clawdie-site and
best-effort umounts the stale target before adding the new
clawdie-docs mount. Without this, existing installs would carry a
broken fstab line pointing at a renamed directory; the mount works
in-memory until the next bastille restart, then fails confusingly.
.agent/skills/{ansible-freebsd,astro,strapi}: replace clawdie-site
with clawdie-docs in skill text so agents are pointed at the new
project path.
NOTE: bootstrap/skills-memory/artifact.sql still needs to be
regenerated on the host via `just refresh-skills-artifact` once
OPENROUTER_API_KEY is set there — embedding regen cannot run from
this Linux side.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Make the docs renderer name match its purpose, add CMS_DOCS_SITE_PATH with ASTRO_SITE_PATH compatibility, and update docs publishing paths.
---
Build: pass | Tests: pass — 2372 passed (704 files)
Leave AGENT_DOMAIN blank until a real public DNS name exists, keep home.arpa for internal jail/service names, and mark ZFS as required for Bastille jails.
---
Build: pass
Tests: pass — 59 passed (4 files)
---
Build: pass | Tests: pass — 2372 passed (704 files)
The 10.maj.2026 force-renew run reloaded nginx twice back-to-back: once
because acme.sh's --renew ran the saved Le_ReloadCmd, and again because
setup/tls.ts unconditionally followed it with --install-cert. Short-circuit
the second call when Le_RealKeyPath, Le_RealFullchainPath, and Le_ReloadCmd
in the domain conf already match our canonical values; first issue and
no-prior-conf force-issue paths still install as before.
Also: per-cert failures no longer strand the rest of the batch. The run
loop aggregates failures, still installs the renewal cron, then exits 1
with FAILED_LABELS surfaced in the status line.
---
Build: FAIL | Tests: FAIL — 16 failed
The doctor checks at a2f2be6 surfaced that acme.sh is missing on the
live host: cert files exist at canonical nginx paths but nothing is
renewing them. clawdie.si expires 02.jun.2026 (~23 days); docs.clawdie.si
expires 11.jun.2026. The handoff doc's Step 4 ("optional, codify
acme.sh setup") is now necessary, not optional.
This commit lands the skeleton so the work doesn't get forgotten and
Codex has a concrete starting point. Default --dry-run means the step
is safe to call against the host without mutation.
setup/tls.ts shape:
- Phase 1: ensure acme.sh installed (pkg install or curl fallback —
Codex confirms which works on the deployed FreeBSD release)
- Phase 2: register Let's Encrypt account with $ACME_EMAIL
- Phase 3+4: per cert in DEFAULT_MANAGED_CERTS, --issue if missing or
--force-renew, --install-cert at canonical paths with reload hook
- Phase 5: --install-cronjob for renewal
Pure helpers tested from dev box (12 tests):
- buildAcmeIssueArgs / buildAcmeInstallCertArgs argument shapes
- parseArgs CLI surface (--apply, --cert, --email, --force-renew,
unknown-arg rejection)
- DEFAULT_MANAGED_CERTS sanity (clawdie + docs labels, www SAN)
Phases 2–4 throw `TODO(Codex)` errors when --apply is set, so
accidental invocation fails loud rather than half-acting. Phase 1 and
Phase 5 are implemented (idempotent, low-risk). Wired into setup/index
as `tls` step.
Handoff doc updated with the post-doctor finding, the skeleton
status, and a manual one-liner Codex can use to renew clawdie.si
before 02.jun.2026 in case the codification work isn't ready in time.
---
2291 tests passing locally (+12 from new tls tests). Pre-existing
argon2/controlplane-*/cms.test failures unchanged.
---
Build: FAIL | Tests: FAIL — 16 failed
The dns step previously rendered dnsmasq.conf to a project-local
tmp/ path and stopped there — the platform classified dnsmasq as a
shared service but never actually deployed, enabled, or started it.
This is the dnsmasq blind spot.
What changed:
- On FreeBSD as root, the rendered config now lands at
/usr/local/etc/dnsmasq.conf with a .bak of any prior content.
- sysrc dnsmasq_enable=YES is set so the service comes up on boot.
- service dnsmasq restart fires only when the config actually changed
or the service is not currently running. Idempotent.
- Off-host (tests, dev) the step still writes to tmp/dnsmasq.conf
and skips all lifecycle ops, so unit tests and dry-runs are unchanged.
Upstream resolvers were the other half of the gap — the previous
config had `no-resolv` with no `server=` directive, making it unusable
as a system resolver standalone. We now resolve upstream from, in
priority order:
1. $DNSMASQ_UPSTREAM (comma- or space-separated; operator override)
2. non-loopback nameservers parsed from /etc/resolv.conf
3. 1.1.1.1 + 9.9.9.9 fallback
Each step renders `server=<ip>` lines so dnsmasq can forward queries
outside the local zone.
Deliberately NOT changed: /etc/resolv.conf. Pointing the host at
dnsmasq for system-wide resolution is a separate operator decision —
mis-doing it can take a host offline. The structured status now emits
SETUP_DNS with DEPLOYED/SYSRC_ENABLED/SERVICE state so /publishreport
can surface where the resolver stands.
---
13 dns tests pass (up from 5). Pre-existing cms.test.ts failure in
the wider setup/ run is unrelated to this change.
---
Build: FAIL | Tests: FAIL — 16 failed
system-update was complete but unwired — only callable directly via
`npx tsx setup/system-update.ts`. This commit:
- Adds it to setup/index.ts STEPS so `npm run setup -- --step system-update`
works the same as the other lifecycle steps.
- Adds a sibling `system-update-cron` step that drops a managed wrapper
at /usr/local/sbin/clawdie-system-update and a cron entry at
/etc/cron.d/clawdie-system-update. Default schedule is 06:50 daily so
the morning patch state lands before the 08:00 operator status report.
- Folds `pkg audit -F` into the system-update run — read-only CVE scan
that always executes (even in dry-run) and surfaces vulnerable count
in the structured status.
- Adds a reboot-pending detector that compares running kernel (uname -r)
to installed userland (freebsd-version). When a kernel patch lands,
REBOOT_PENDING=yes appears in the status; the platform never reboots
itself — the operator decides.
Cadence is daily, not weekly: freebsd-update fetches are cheap, security
patches benefit from same-day rollout, and pairing with the morning
report makes the result legible. Heavier `pkg upgrade` (full userland
refresh, not just CVE scan) is a separate question for later.
Tests cover the new pure helpers (parsePkgAudit, rebootPending) plus
the cron entry/wrapper builders. The orchestrator wiring is mechanical.
---
Targeted tests pass (system-update + system-update-cron, 21 tests).
Codex to validate end-to-end on host: install the cron module, confirm
/etc/cron.d/clawdie-system-update lands, confirm the wrapper is exec'd
on the next 06:50, and confirm the structured status reaches the 08:00
report pipeline.
---
Build: FAIL | Tests: FAIL — 16 failed
---
Build: FAIL | Tests: FAIL — 16 failed
Autogenerate the docs sidebar from the public content tree, sync Slovenian docs into the Starlight content copy, remove stale Astro-only English and guide duplicates, use honest 404s for missing docs pages, and repair stale Codeberg links.
---
Build: pass
Tests: pass — 2221 passed (166 files)
---
Build: pass | Tests: pass — 2221 passed (656 files)
Mount and deploy the platform landing Astro site from the CMS setup step, add the cms jail nginx server block for clawdie.si/www.clawdie.si, and surface platform landing/docs availability in /publishreport.
---
Build: pass
Tests: pass — 2221 passed (166 files)
---
Build: pass | Tests: pass — 2221 passed (656 files)
Recognize Pi auth.json credentials for OAuth-backed providers such as openai-codex, keep env and Ollama validation intact, and document the headless Codex login flow in install/operator docs.
---
Build: pass | Tests: pass — 2209 passed (654 files)
Sweep active code, tests, identity files, public docs, CMS seed content, and stale handoffs so old assistant-name fixtures no longer leak into current Clawdie/system-namespace behavior. Keep the skills-memory SQL artifact unchanged per regeneration policy.
---
Build: pass
Tests: pass — 2197 passed (164 files)
---
Build: pass | Tests: pass — 2197 passed (650 files)
Follow-up to a99f971: covers the remaining ${TENANT_ID} interpolation
sites that produced leading-hyphen / empty-path values on root installs.
- setup/ollama.ts, setup/llama-cpp.ts: preferred jail names
- setup/sanoid.ts: tenant-era home candidate
- setup/hosts.ts: jail-name discovery filter (+ test mock)
- src/telegram-commands.ts: status identity line, suppress empty
tenant clause on root installs
Root-detection sites that key off TENANT_ID === '' are intentionally
left untouched; the invariant is preserved.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---
Build: FAIL | Tests: FAIL — 15 failed