docs: session handoff (state, open fail2ban/UFW detection bug, work recipes)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>feat/v1-foundation
parent
f5f903046d
commit
2930f16d12
|
|
@ -0,0 +1,106 @@
|
|||
# Clusev — Session Handoff (2026-06-14)
|
||||
|
||||
Self-contained ramp-up for the next session. Read `rules.md` (R1–R17) + `CLAUDE.md` first;
|
||||
this file = current state, open items, and the exact work recipes. `handoff.md` is the
|
||||
original foundational decisions doc (do not overwrite it).
|
||||
|
||||
---
|
||||
|
||||
## 1. Current state
|
||||
|
||||
- **Branch:** `feat/v1-foundation` (never commit to `main`). Remote: Gitea
|
||||
`git.bave.dev/boban/clusev.git`.
|
||||
- **Shipped tags** (all pushed):
|
||||
- `v0.3.0` — full bilingual UI (DE default + EN), user-selectable; rule **R16**.
|
||||
- `v0.4.0` — change the panel domain from the dashboard (DB snapshot → applied on restart;
|
||||
Caddy on-demand TLS; request-derived Reverb endpoint; anti-lockout middleware).
|
||||
- `v0.4.1` — fixed a garbled `<header>` on every signed-in page (Blade raw-block bug → rule
|
||||
**R17**); made broadcast channels **private** (metrics no longer public).
|
||||
- **Dev stack** runs on this VM via `docker compose` (app container IP **172.18.0.6**, host
|
||||
`10.10.90.136:80`). Managed fleet host = **10.10.90.162** (Debian / apt / ufw; the only
|
||||
live-verified target — dnf/zypper/firewalld command strings are built but not live-tested).
|
||||
|
||||
---
|
||||
|
||||
## 2. OPEN BUG (priority) — fail2ban & UFW falsely shown "nicht installiert"
|
||||
|
||||
**Symptom:** the Hardening checklist shows `fail2ban` and `Firewall (UFW)` as **OFFEN ·
|
||||
nicht installiert**, while the fail2ban-Status panel below shows `aktiv · 14 gesperrt` with
|
||||
real SSH-scanner bans. Contradiction.
|
||||
|
||||
**Root cause — two different detection methods (same host):**
|
||||
- `HardeningService` (checklist): installed = `dpkg -l <pkg> | grep -q '^ii'`
|
||||
(`PackageManager::isInstalledTest`, apt) / `FirewallTool::installedTest()` for ufw; active =
|
||||
`systemctl is-active`. → asks "is the **apt package** recorded?"
|
||||
- `Fail2banService::status` (panel): installed = `command -v fail2ban-client`; active =
|
||||
`systemctl is-active`; jails via `fail2ban-client status`. → asks "is the **binary present +
|
||||
service running**?"
|
||||
- The host is Debian/apt and fail2ban is genuinely running (14 real bans), but dpkg does not
|
||||
list it as `^ii` → checklist false-negative. Same for ufw.
|
||||
|
||||
**Fix direction:** make the checklist's "installed" = (apt `ii`) OR (`command -v` binary
|
||||
present) OR (service active) — align with `Fail2banService`. Touch:
|
||||
`app/Services/HardeningService.php` (~lines 50–66, the `$cmd` probe),
|
||||
`app/Support/Os/PackageManager.php::isInstalledTest`,
|
||||
`app/Support/Os/FirewallTool.php::installedTest`. Verify on 10.10.90.162 how fail2ban/ufw are
|
||||
actually installed (apt vs source vs `rc` config-only). A task chip was spawned for this.
|
||||
|
||||
---
|
||||
|
||||
## 3. Other open items / follow-ups
|
||||
|
||||
- `resources/js/app.js` `dualChart` is **dead code** — the dashboard chart is a server-rendered
|
||||
SVG, nothing subscribes via Echo. Consider removing it (its `Echo.private('metrics')` is the
|
||||
only metrics subscriber and it never runs).
|
||||
- **Caddy on-demand TLS / real ACME issuance is config-validated only** (no Caddy in dev, no
|
||||
public DNS). App-side logic (`/_caddy/ask`, snapshot, redirects, Reverb tunnel) is
|
||||
browser-verified; the actual cert issuance needs a real prod + DNS test.
|
||||
- "Install-with-domain → clear-to-bare-IP" is the rough edge: re-run `install.sh` for a clean
|
||||
bare-IP realtime (REVERB_* in `.env` otherwise stays domain-shaped).
|
||||
- firewalld is read-only (rule add/delete is ufw-only) — needs a RHEL/Fedora/openSUSE host to
|
||||
finish.
|
||||
|
||||
---
|
||||
|
||||
## 4. Plugins installed this session (need a SESSION RESTART to load)
|
||||
|
||||
Installed via the server's `claude` CLI (`~/.claude/remote/ccd-cli/<ver>`), scope **user**,
|
||||
into the **local** plugin system (separate from the cloud-synced set):
|
||||
- `caveman@caveman` — ultra-compressed output (token saver); SessionStart hook auto-activates.
|
||||
- `superpowers@superpowers-dev` (v5.1.0) — workflow skills (TDD, systematic-debugging, …).
|
||||
- `ui-ux-pro-max@ui-ux-pro-max-skill` (v2.5.0).
|
||||
|
||||
Marketplaces persisted in `~/.claude/plugins/known_marketplaces.json`. They are **not** in the
|
||||
current session's skill registry until the session is **restarted** (that's why `/caveman:caveman`
|
||||
still fails this session). After restart: `/caveman:*`, `/superpowers:*`, `ui-ux-pro-max` work.
|
||||
|
||||
---
|
||||
|
||||
## 5. Work recipes (how to actually verify & ship)
|
||||
|
||||
- **Everything in containers (R8).** Pint:
|
||||
`docker compose exec -u "${HOST_UID:-1002}:${HOST_GID:-1002}" -T app ./vendor/bin/pint --dirty`.
|
||||
Build: same prefix + `npm run build`.
|
||||
- **R12 — verify in a real browser, BOTH locales:** every touched route → HTTP 200 + 0 console
|
||||
errors AND **inspect the rendered DOM** for leaked `@` / `{{ }}` / `$var` / `group.key` text
|
||||
(R17 — this is how the v0.3.0/v0.4.0 `<header>` bug slipped: 200 + clean console but garbage
|
||||
markup). Recipe: headless Puppeteer image `ghcr.io/puppeteer/puppeteer:latest` on docker
|
||||
network `clusev_clusev`, target `http://172.18.0.6`, `NODE_PATH=/home/pptruser/node_modules`.
|
||||
Auth via a **TEMP** route `Route::get('/__peek', fn (Request $r) => [AuthFacade::loginUsingId(1),
|
||||
redirect($r->query('to','/'))][1])` — **remove before commit** (route:clear after). Locale is
|
||||
per-user (`user->locale` wins over session), so to test EN the peek must also persist
|
||||
`user->locale`. Dashboard route is `/` (not `/dashboard`).
|
||||
- **R15 — Codex:** `export PATH="$HOME/.npm-global/bin:$PATH"; codex review --uncommitted` until
|
||||
clean (filter node_modules noise).
|
||||
- **Localization (R16):** every visible string in `lang/{de,en}/<group>.php`, keys identical in
|
||||
both. Verify: scan all `__('group.key')` usages resolve via `Lang::has($k,'de'/'en')` and that
|
||||
each `lang/de/*.php` group has the same keys as `lang/en/*.php`.
|
||||
- **Push:** token in `/home/nexxo/.env.gitea` (`GIT_ACCESS_TOKEN`) — read ONLY at push time,
|
||||
never echo/commit; sanitize push output
|
||||
(`sed -E 's#https://[^@]*@#https://<redacted>@#g; s/[0-9a-f]{40}/<redacted>/g'`).
|
||||
- **Fleet host safety:** SSH password is in the encrypted vault (never in code/logs). Never
|
||||
ban/lock-out the control plane (10.10.90.x).
|
||||
|
||||
**Done = ** Pint clean → npm build → R12 (200 + 0 console + DOM scan, DE+EN) → Codex clean →
|
||||
version bump + CHANGELOG → commit on `feat/v1-foundation` → tag → push (sanitized) → temp
|
||||
`/__peek` removed.
|
||||
Loading…
Reference in New Issue