Files
felhom-controller/CLAUDE.md
T

111 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CLAUDE.md — `felhom-controller`
> Stable orientation only — **current state lives in `CONTEXT.md` and the top of `CHANGELOG.md`**,
> never here. Cross-repo conventions (clean-tree gate, secrets, trunk-based, artifact taxonomy):
> workspace-root `/mnt/5_hdd/felhom.eu/git/CLAUDE.md`. Path-scoped detail: `.claude/rules/`.
## What this repo is
The **in-guest controller** — one per customer LXC, Docker-only, **holds NO Proxmox credentials**. It
owns the app domain: stack/deploy management, the Hungarian web UI, app-data backup, metrics,
integrations, git-sync, notifications. Disk/host/Proxmox concerns are delegated to the host agent via
`internal/agentapi`. Whole-guest backup (PBS vzdump) is the agent's, not ours.
**Don't confuse the two ex-"controllers":** `felhom-agent` (host, operator-tier, was
`proxmox-controller`) vs this repo (in-guest, was `deploy-felhom-compose`).
## Doing X → read Y
| Doing | Read |
|---|---|
| writing any new code | `REUSE.md` — canonical helpers, patterns, traps, seams |
| needing current state / roadmap | `CONTEXT.md` |
| needing a feature or architecture reference | `controller/README.md` |
| build, deploy, publish, verify a version | the **`felhom-build-deploy`** skill |
| writing or reviewing a test, fixing a bug | the **`felhom-testing`** skill |
| UI, tokens, badges, Hungarian copy | the **`felhom-ui-design`** skill |
| which box may I break | `felhom.eu/documentation/runbooks/target-selection.md` |
| host addresses, break-glass, node facts | `felhom.eu/documentation/operations/nodes.md` |
| what version is live anywhere | ask the hub (`/hosts`, `/configs`) or the box — **never a doc** |
| the authoritative design | `felhom.eu/documentation/architecture/NN-*.md` (01–03 for this repo; 07 backup, 09 updates, 10 language) |
## Session-critical invariants
The rest live in `REUSE.md`. These cost incidents to learn:
- `docker compose restart` does NOT pick up new images/env — always `up -d` (`RedeployFromEnv`).
- Docker's `.State` says "running" even for unhealthy containers — the `.Status` parse is the truth.
- In-memory `Deployed` is set BEFORE `compose up -d` (slow-pull race); reverted on failure.
- `compose up -d` exits 0 on crash-loops — the post-start status check is the detection.
- Env var KEYS are logged, never values. Protected stacks (traefik, cloudflared, felhom-controller,
and always samba) cannot be stopped from the UI.
- Verify a container image HAS the healthcheck tool before using it (BusyBox wget / python3 / curl —
the catalog `REUSE.md` maps the families).
- `IsRunning()` is CONCURRENCY, false during a verification restore — display MUST use
`RestoreStatus()`.
## Live validation — the fence
Exercise the SERVER-SIDE PIPELINE a real user triggers, end-to-end (connect → enroll → deploy). **The
forbidden shortcut is BYPASSING that pipeline** — the F9 episode was a raw agent guest-attach with
hand-set state, and it proved nothing.
`claude-in-chrome` is NOT available on DooPlex. The standard method is endpoint-level: invoke the
exact endpoint the UI invokes (no server logic is skipped, only rendering) and **say which method was
used**. Strict end-to-end UI coverage is a manual click-through by the operator.
Two traps in that method live in `.claude/rules/ui-hungarian.md` (ASCII-only greps; `!` in
credentials) — they load when you touch a template or stylesheet.
## Commands — one per surface
| Surface | Command |
|---|---|
| Gates (after ANY change) | `python3 scripts/controller_gates.py` — from `controller/` |
| Green gate | `go build ./... && go vet ./... && go test ./...` |
| Build + deploy | the **`felhom-build-deploy`** skill — do not hand-roll it |
Guest 9201 is **bootstrap-managed — there is no compose file**;
`felhom-controller-bootstrap.service` runs the tag written in `/etc/felhom-controller-image`. Catalog
changes (`app-catalog-felhom.eu`) are picked up by controller sync ≤15 min, or via the "Sablonok
frissítése" button.
## Working with CHANGELOG.md
**DO NOT read the full file** — it is large and will waste context.
- Session start: `CONTEXT.md` + `controller/README.md` for current state.
- Adding an entry: Read only the top ~30 lines for format, then Edit-insert after line 1.
- History: Grep for topics instead of reading.
## End-of-session checklist
1. **Commit and push** all code changes (explicit paths; no `git add -A`).
2. **Build, push, and deploy** the new controller image, if controller code changed.
3. **`CHANGELOG.md`** — always, whenever code changed and was pushed.
4. **`CONTEXT.md`** — decisions made, state, what is next.
5. **`controller/README.md`** — whenever a feature was added, modified or removed.
6. **`REPORT.md`** — overwrite with this run's summary only.
7. **`REUSE.md`** — if a shared helper or pattern was added/changed/deprecated (same commit).
8. **Verify** the deployment (`docker ps` + logs).
<!--
WHY THIS FILE IS SHORT (2026-08-06, instruction-trim task).
Removed from here and rehomed, not lost:
- the `## Layout (verified against the tree)` block -> derivable by `ls internal/`; REUSE.md
carries the per-package seams and traps that the annotations were really for.
- the `!!! IMPORTANT !!!` header -> its two requirements are checklist items 3 and 5. One voice,
one place; a rule stated twice in one file is a rule that gets edited in one of them.
- the host/access table -> documentation/operations/nodes.md is the single home. The copy here
had drifted: it gave demo-felhom as plain root@192.168.0.162 (the LAN fallback, not the route),
pinned "agent 0.93.0" against the project's own no-versions-in-docs rule, and claimed no drill
VM was provisioned on demo-hp. Measured 2026-08-06: `qm list` on demo-hp shows VM 300
`drill-r50` present. felhom-agent/CLAUDE.md was right; this file was wrong.
- the "felhom-pve is back on the home LAN" block -> it was bookkeeping about a retired block; the
record is in documentation/audits/AUDIT-vacation-remote-ops-2026-07-20.md.
- the "Legacy: Windows workstation" block -> the workspace-root CLAUDE.md carries the full version.
- the gates/logging/coupling/UI paragraphs -> .claude/rules/*.md, which load when a matching file
is read instead of in every session.
Full per-block accounting: felhom.eu/documentation/audits/LEDGER-instruction-trim-2026-08-06.md
-->