# 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/01/02/03-*.md` | ## 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) 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 controller/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).