- Auto-refresh: the 60s reload fires only while a live tab is active
(nav data-live-tabs="overview,applications,events,host") AND no form is
dirty (delegated input/change listener; never reset — a reload clears it).
Skipped ticks reschedule; a muted (paused) hint shows next to the toggle on
non-live tabs / dirty forms. Toggle, localStorage key, 60s cadence, and
default-on behavior unchanged. The refresh script resolves the legacy
settings→edit hash alias like the tabs script.
- Rider 4a: every template's stylesheet link is /style.css?v={{hubVersion}}
(the v0.47.0 gotcha: max-age=3600 served stale styling for up to an hour
after a deploy). Red-proof run: a reverted bare link fails the test.
- Rider 4b: CLAUDE.md standing rule — never git add -A in this repo
(the 146d165 sweep incident); explicit paths + pull-rebase + one writing
session per clone.
- Tests: Group C structural pins (attribute read, dirty listeners, alias x2,
hint element, cadence/key survivors) + Group D cache-bust over six pages.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TZc5w5jDhFLv6qDC32KN5v
8.3 KiB
CLAUDE.md — Project Instructions for Claude Code (felhom.eu)
Read automatically when Claude Code works in this repo. Stable orientation only — current state lives in
CONTEXT.mdand the tops ofhub/CHANGELOG.md/scripts/CHANGELOG.md/website/CHANGELOG.md, never here. Cross-repo orientation (the felhom system, artifact taxonomy, access): workspace-roote:\git\CLAUDE.md; this file isfelhom.eu-specific.
Project overview
This repo contains:
- Website (
website/) — static HTML at felhom.eu, served via k3s nginx + git-sync sidecar. - Hub (
hub/) — Go application (felhom-hub), the operator backend, on k3s athub.felhom.eu. - K8s manifests (
manifests/) — k3s deployment manifests for felhom-system services. - Architecture docs (
documentation/) — the authoritative design home for the whole Felhom system:architecture/01..05-*.md,proxmox-platform.md,tests/phase*-findings.md, runbooks, audits. Read these before designing. - Skills (
skills/) — the versioned source of the Claude Code skills (felhom-build-deploy,felhom-ui-design,felhom-testing); install/update withpython scripts/install_skills.py(junction into~/.claude/skills/).
See README.md for full architecture/DNS/email/SEO docs. See TASK.md for the current task (if any).
See REUSE.md before writing new code.
The Felhom system (so the hub's role is in context)
Felhom is Proxmox-based, with a locked three-component model:
- Hub (this repo,
hub/) — operator backend. Authors operator intent; mirrors box reality; holds no data-plane role and never connects inbound to a box. - Host agent (repo
felhom-agent/) — one per Proxmox host; owns all Proxmox interaction. - In-guest controller (repo
felhom-controller/) — one per customer LXC; Docker-only.
Hub — architecture (version-free; current version = manifests/hub.yaml image tag)
The hub ingests two report streams — the agent's host-domain report (POST /api/v1/host-report, the
heartbeat/dead-man's-switch) and the legacy controller report (POST /api/v1/report, frozen until
the slice-10 cutover — do not modify) — plus structured controller events (POST /api/v1/event,
gated by allowedEventTypes). Around them: staleness/disk/storage-fill/leaf/capability monitor
checkers, the two-tier notification dispatcher (operator English / customer Hungarian, Resend,
cooldowns), the app-mail relay, customer-config + Day-0 artifact-manifest management (the checksum
trust root the host bootstrap verifies against), assets serving, and the password-gated operator web
UI. Package map, helpers, seams, extension points: REUSE.md (e.g. new event types must enter
allowedEventTypes + customerMessages together).
Code quality rules
- Always double-check generated code for bugs, logic issues, syntax errors.
- Handle edge cases without overcomplicating.
- Add debug capabilities (logging, verbose output).
- If you need more input or troubleshooting output, ask first — don't guess.
- Testing doctrine (non-hollow tests, red-proofs, seams): use the
felhom-testingskill. - UI/design work (tokens, gates, copy rules): use the
felhom-ui-designskill. - Logging: levels/English/no-secrets rules per
documentation/runbooks/logging-conventions.md(DEBUG = flow detail, INFO = state change + duration; logs are operator-tier English; keys never values — the hub's bundle secret-gate blocks violating pulls fail-closed).
Workflow & artifacts
The planning/architecture assistant ("project Claude", in claude.ai) writes specs and validates pushes; you (Claude Code) implement. A file being open in the editor is NOT an instruction.
TASK.md/TASK-*.md— a spec for you to implement. Then push and updatehub/CHANGELOG.mdand rootREPORT.mdper the convention below.RUNBOOK-*.md— an operational procedure. CC executes the steps it has access and capability for, including live validation on the demo nodes and the demo Proxmox host (CC has root@felhom-pve SSH + the felhom-agent token). Mark a step HUMAN only when it genuinely needs physical presence, a real-world decision, or credentials CC truly lacks.- Validation of a push against a spec's criteria is project Claude's job, not yours, unless asked.
- Browser automation available (
claude-in-chrome): CC can drivehub.felhom.eu, the website, or any*.demo-felhom.euUI for live validation + screenshots. Caveat: tools attach only to a session STARTED AFTER the bridge connected. Note: the hub UI is operator-password-gated — CC cannot log in; verify UI changes via render tests instead.
In every repository where you make a change, update both files in that repo:
CHANGELOG.md— cumulative log, newest on top (here: per-areahub/,scripts/,website/).REPORT.md— overwrite with the most recent implementation/validation summary only.Never write secrets into any committed file — reference them as "stored out-of-band".
- Update
REUSE.mdif you added/changed/deprecated a shared helper or pattern (same commit). - Never
git add -Ain this repo — parallel sessions share the clone and it sweeps foreign WIP (the v0.47.0146d165incident: a red-proof-mutated guard got swept tomain). Stage explicit paths only,git pull --rebasebefore every push, and do not run two writing sessions on one clone (usegit worktreeif truly needed).
Tech stack (Hub)
- Language: Go (stdlib
net/http+html/template, no frameworks). DB: SQLite viamodernc.org/sqlite(pure Go). Auth: bcrypt + Bearer tokens + session cookies + CSRF. - Deploy: Docker on k3s (
felhom-systemns). Storage: Longhorn PVC at/data/(SQLite DB). - Config: YAML via ConfigMap at
/etc/felhom-hub/hub.yaml. Secrets via out-of-bandsecretKeyRef(never inline stringData — REUSE.md §3).
SSH access
Use the Windows OpenSSH binary (Git Bash's ssh fails silently): SSH=/c/Windows/System32/OpenSSH/ssh.exe.
| Host | IP | User | Role |
|---|---|---|---|
| Build server (k3s node) | 192.168.0.180 | kisfenyo | Build + push images, sudo kubectl |
| Demo Proxmox host | 192.168.0.162 | root@pam (SSH alias felhom-pve) |
pveum/pct + live Proxmox validation |
Build & deploy — Hub (GitOps via ArgoCD)
Full runbook: use the felhom-build-deploy skill. The load-bearing rules:
The whole cluster is GitOps via a single ArgoCD app felhom syncing this repo's manifests/
to felhom-system. Auto-sync is OFF — deploys are a deliberate manual sync. ArgoCD's source of
truth is the manifest:
- A code change + CHANGELOG bump deploys NOTHING. The running image changes only when
manifests/hub.yaml'simage:tag changes in git and the app is synced. - Pin explicit versions, never
:latest. Never barekubectl set image/kubectl apply(reverted on next sync). - The live image can lag the CHANGELOG when a bump was committed but the manifest/sync step never happened — reconcile via the manifest, not the changelog.
- Green gate before any hub commit:
go build ./... && go vet ./... && go test ./...inhub/.
Steps: commit+push code → ./build.sh <VER> --push on 180 (~/build/felhom-hub) → bump
manifests/hub.yaml tag + push → ArgoCD hard-refresh + sync (kubectl-patch method in the skill) →
verify Synced/Healthy + rollout + image + startup log.
Build & deploy — Website / Manifests
- Website auto-deploys via git-sync; just push to
main(live in 1–2 min). Runpython scripts/site_gates.pyafter ANY website change; new pages go into itsPAGESlist. Emergency edits: https://files.felhom.eu. Allwebsite/HTML is UTF-8 with BOM — preserve it. - Manifests are GitOps via the
felhomapp — commit tomain, then deliberate sync.
Key patterns
- Hub status logic: OK (report < 30m), WARN (30m–1h or health=warn), DOWN (> 1h or health=fail); host liveness thresholds shared between UI and checker (never invent a second definition).
- SQLite timestamps vary in format — always
parseSQLiteTime(). - Dashboard/detail auto-refresh every 60s via meta refresh. Geo-restricted to Hungary via nginx ingress annotation.
- Helpers, seams, extension points, traps:
REUSE.md— the map is maintained same-commit.