diff --git a/CLAUDE.md b/CLAUDE.md index a51d808..8b20988 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,8 +1,6 @@ # CLAUDE.md — Project Instructions for Claude Code (`felhom.eu`) -> Read automatically by Claude Code when it works in this repo. Keep it updated as the project -> evolves. Cross-repo orientation (the felhom system, artifact taxonomy, access) lives in the -> workspace-root `e:\git\CLAUDE.md`; this file is `felhom.eu`-specific. +> Read automatically by Claude Code when it works in this repo. Keep it updated as the project evolves. Cross-repo orientation (the felhom system, artifact taxonomy, access) lives in the workspace-root `e:\git\CLAUDE.md`; this file is `felhom.eu`-specific. ## Project overview @@ -10,34 +8,24 @@ This repo (`felhom.eu`) 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 at `hub.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` (topology/trust, controller module map, host-agent, signing, - hub), `proxmox-platform.md`, and `tests/phase{0,1-2,3,4}-findings.md`. Read these before designing. +- **Architecture docs** (`documentation/`) — the **authoritative design home for the whole Felhom system**: `architecture/01..05-*.md` (topology/trust, controller module map, host-agent, signing, hub), `proxmox-platform.md`, and `tests/phase{0,1-2,3,4}-findings.md`. Read these before designing. See `README.md` for full architecture/DNS/email/SEO docs. See `TASK.md` for the current task (if any). ## 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. +- **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. -The hub is **not** just controller monitoring anymore. As of slice 3 it ingests **two report -streams**: the agent's host-domain report (`POST /api/v1/host-report`, the heartbeat) and the -legacy controller report (`POST /api/v1/report`). The controller path is **frozen and retires at the -slice-10 cutover** — do not modify it until then. +The hub is **not** just controller monitoring anymore. As of slice 3 it ingests **two report streams**: the agent's host-domain report (`POST /api/v1/host-report`, the heartbeat) and the legacy controller report (`POST /api/v1/report`). The controller path is **frozen and retires at the slice-10 cutover** — do not modify it until then. ## Hub — current state (v0.7.x) -- **Tables:** `customer_configs`, `events`, `app_telemetry`/`app_log_issues`, the legacy `reports`, - and the slice-3 host-domain additions `hosts` / `guests` / `host_reports` (additive; columns - marked inert exist for the slice-10 cutover but are unused now). -- **Auth:** Bearer — global key, per-customer key (legacy), and per-host key (`GetHostByAPIKey`, - slice 3). Provisional global-key host mint at `POST /api/v1/admin/hosts`. -- **Monitoring:** the controller `StalenessChecker` (over `reports`) AND a sibling - `HostStalenessChecker` (over `host_reports`, emitting `host_stale`/`host_down`/`host_recovered`). +- **Tables:** `customer_configs`, `events`, `app_telemetry`/`app_log_issues`, the legacy `reports`, and the slice-3 host-domain additions `hosts` / `guests` / `host_reports` (additive; columns marked inert exist for the slice-10 cutover but are unused now). +- **Auth:** Bearer — global key, per-customer key (legacy), and per-host key (`GetHostByAPIKey`, slice 3). Provisional global-key host mint at `POST /api/v1/admin/hosts`. +- **Monitoring:** the controller `StalenessChecker` (over `reports`) AND a sibling `HostStalenessChecker` (over `host_reports`, emitting `host_stale`/`host_down`/`host_recovered`). - Two-tier notifications (operator English / customer Hungarian, Resend, cooldowns); `events` audit. ## Code quality rules @@ -49,14 +37,18 @@ slice-10 cutover** — do not modify it until then. ## 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. +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, update `hub/CHANGELOG.md`, - and **append** a section to this repo's root `REPORT.md` (this repo appends; newest section last). +- **`TASK.md` / `TASK-*.md`** — a spec for you to implement. Then push and update this repo's changelog (`hub/CHANGELOG.md`) and root `REPORT.md` per 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). A step is human-only only when it genuinely needs physical presence, a real-world decision, or credentials CC truly lacks — mark those steps HUMAN. Do not decline a whole procedure because it touches a live host or a privileged token. (Judgment still applies: confirm before irreversible ops on real customer data — but demo scratch guests are fair game.) - Validation of a push against a spec's criteria is project Claude's job, not yours, unless asked. +> **In every repository where you make a change, update both files in that repo:** +> - **`CHANGELOG.md`** — a cumulative log of **all** changes; newest entry on top. +> - **`REPORT.md`** — **overwrite** with a summary of the **most recent** implementation (or significant validation/operational run) only; not cumulative. +> +> **Never write secrets** — tokens, passwords, private keys, API keys — into `CHANGELOG.md`, `REPORT.md`, or any committed file. Reference them as "stored out-of-band" instead. + ## Tech stack (Hub) - **Language:** Go 1.24+ (build server is go1.26.0). @@ -66,8 +58,7 @@ pushes; **you (Claude Code) implement**. A file being open in the editor is NOT ## SSH access -Use the Windows OpenSSH binary (Git Bash's `/usr/bin/ssh` can't reach the Windows agent and fails -silently): `SSH=/c/Windows/System32/OpenSSH/ssh.exe`. All SSH commands below use `$SSH`. +Use the Windows OpenSSH binary (Git Bash's `/usr/bin/ssh` can't reach the Windows agent and fails silently): `SSH=/c/Windows/System32/OpenSSH/ssh.exe`. All SSH commands below use `$SSH`. | Host | IP | User | Role | |------|----|------|------| @@ -79,38 +70,25 @@ silently): `SSH=/c/Windows/System32/OpenSSH/ssh.exe`. All SSH commands below use After code changes to `hub/`, you **MUST** build, push, and deploy. 1. **Commit + push:** `cd /e/git/felhom.eu && git add -A && git commit -m "" && git push` -2. **Check running version:** - `$SSH kisfenyo@192.168.0.180 "sudo kubectl get deploy -n felhom-system hub -o jsonpath='{.spec.template.spec.containers[0].image}'"` -3. **Build + push image** (next version; build script lives on the build server, not in this repo): - `$SSH kisfenyo@192.168.0.180 "cd ~/build/felhom-hub && ./build.sh --push"` - (pulls latest from Gitea, builds with version+build-time ldflags into `main.Version`, pushes - `gitea.dooplex.hu/admin/felhom-hub:` and `:latest`.) -4. **Deploy:** - `$SSH kisfenyo@192.168.0.180 "sudo kubectl set image -n felhom-system deploy/hub hub=gitea.dooplex.hu/admin/felhom-hub:"` -5. **Verify:** - `$SSH kisfenyo@192.168.0.180 "sudo kubectl get pods -n felhom-system -l app=hub && sudo kubectl logs -n felhom-system -l app=hub --tail 10"` - (expect Running + `[INFO] felhom-hub starting`.) +2. **Check running version:** `$SSH kisfenyo@192.168.0.180 "sudo kubectl get deploy -n felhom-system hub -o jsonpath='{.spec.template.spec.containers[0].image}'"` +3. **Build + push image** (next version; build script lives on the build server, not in this repo): `$SSH kisfenyo@192.168.0.180 "cd ~/build/felhom-hub && ./build.sh --push"` (pulls latest from Gitea, builds with version+build-time ldflags into `main.Version`, pushes `gitea.dooplex.hu/admin/felhom-hub:` and `:latest`.) +4. **Deploy:** `$SSH kisfenyo@192.168.0.180 "sudo kubectl set image -n felhom-system deploy/hub hub=gitea.dooplex.hu/admin/felhom-hub:"` +5. **Verify:** `$SSH kisfenyo@192.168.0.180 "sudo kubectl get pods -n felhom-system -l app=hub && sudo kubectl logs -n felhom-system -l app=hub --tail 10"` (expect Running + `[INFO] felhom-hub starting`.) -> If the hub deployment is ArgoCD-managed (auto-sync), a manual `kubectl set image` may be reverted -> by ArgoCD drift-correction — confirm the deploy path before relying on step 4. +> If the hub deployment is ArgoCD-managed (auto-sync), a manual `kubectl set image` may be reverted by ArgoCD drift-correction — confirm the deploy path before relying on step 4. ## Build & deploy — Website / Manifests -- **Website** auto-deploys via git-sync; just push to `main` (live in 1–2 min). Emergency edits: - FileBrowser at `https://files.felhom.eu`. -- **Manifests** are applied manually (git pull on the build server first if you pushed): - `$SSH kisfenyo@192.168.0.180 "sudo kubectl apply -f /home/kisfenyo/git/felhom.eu/manifests/.yaml"` +- **Website** auto-deploys via git-sync; just push to `main` (live in 1–2 min). Emergency edits: FileBrowser at `https://files.felhom.eu`. +- **Manifests** are applied manually (git pull on the build server first if you pushed): `$SSH kisfenyo@192.168.0.180 "sudo kubectl apply -f /home/kisfenyo/git/felhom.eu/manifests/.yaml"` ## Key patterns -- Hub ingests **host-reports from agents** (`POST /api/v1/host-report`, Bearer per-host) and legacy - **controller reports** (`POST /api/v1/report`). The host-report `received_at` is the dead-man's- - switch liveness signal. +- Hub ingests **host-reports from agents** (`POST /api/v1/host-report`, Bearer per-host) and legacy **controller reports** (`POST /api/v1/report`). The host-report `received_at` is the dead-man's-switch liveness signal. - Status logic: OK (report < 30m), WARN (30m–1h or health=warn), DOWN (> 1h or health=fail). - SQLite timestamps vary in format — use `parseSQLiteTime()`. -- Dashboard/detail auto-refresh every 60s via ``. Geo-restricted to - Hungary via nginx ingress annotation. +- Dashboard/detail auto-refresh every 60s via ``. Geo-restricted to Hungary via nginx ingress annotation. ## File encoding -All `website/` HTML is **UTF-8 with BOM** — preserve it. Hub Go source is standard UTF-8 (no BOM). \ No newline at end of file +All `website/` HTML is **UTF-8 with BOM** — preserve it. Hub Go source is standard UTF-8 (no BOM). diff --git a/REPORT.md b/REPORT.md index fd44f17..21e7d42 100644 --- a/REPORT.md +++ b/REPORT.md @@ -1,7 +1,6 @@ # felhom.eu — task reports -> One section per task, **appended** (newest last) — not overwritten. Cumulative -> hub history lives in [hub/CHANGELOG.md](hub/CHANGELOG.md). +> **Overwrite** this file with a summary of the most recent task only (uniform with the other repos; not cumulative). The cumulative hub history lives in [hub/CHANGELOG.md](hub/CHANGELOG.md). Sections below predate this convention change and are retained as history. --- diff --git a/hub/CHANGELOG.md b/hub/CHANGELOG.md index ec7cc66..327977e 100644 --- a/hub/CHANGELOG.md +++ b/hub/CHANGELOG.md @@ -1,5 +1,11 @@ # Felhom Hub — Changelog +## Repo docs — no hub version change (2026-06-08) + +### Changed +- **Reflowed `felhom.eu/CLAUDE.md`** — removed hard mid-paragraph line wraps (prose, list items, blockquotes now single-line); tables untouched; rendered output unchanged. +- **Unified the REPORT/CHANGELOG convention**: this repo's `REPORT.md` switches from *append/cumulative* to **overwrite-latest** (uniform with the sibling repos); `CHANGELOG.md` (this file) stays the cumulative log, newest on top. Updated `REPORT.md`'s header note accordingly (existing sections retained as history). Added an explicit **no-secrets** rule. No hub code change → no version bump. + ## v0.7.1 (2026-06-08) ### Changed