diff --git a/REPORT.md b/REPORT.md index d382e4c..29c6ca8 100644 --- a/REPORT.md +++ b/REPORT.md @@ -1,69 +1,58 @@ -# REPORT — v0.116.0/v0.116.1: observability pass (always-on debug ring + agent tab + self-log pull + sweep) +# REPORT — v0.117.0: consuming-namespace NAS verification + deploy-view truth (RCA fixes 2+4) -**Date:** 2026-07-11 · **Version:** controller v0.116.1 (from v0.115.0; 0.116.1 = the debug-surface -ungate found by live validation) · **MinAgent:** 0.81.0 unchanged · **Deployed:** guest 9201 -(`0.116.1` healthy) · **NOT published/vouched** — Peti stays 0.113.0; this reaches him with the next -publish train. Pairs with agent v0.83.0 + hub v0.46.0. Task-wide record: this file + each repo's -CHANGELOG + `felhom.eu/documentation/runbooks/logging-conventions.md` (the codified conventions). - -## Motivating incident → root causes closed - -A NAS-verify refusal on an `info` box showed NOTHING remotely. Three stacked causes, all fixed: -1. the `LogBuffer` ring only EXISTED at `logging.level=debug` (setupLogger) → now always built; - stdout respects the level via `LevelFilterWriter` (docker logs unchanged); -2. the new flows emitted few lines → the leveled `internal/logx` sweep (phases, verdicts, durations); -3. **the `/debug` page + `/api/debug/*` 404'd at info** (found live — v0.116.1): the viewer is now - available at any level, still session-authed (RequireAuth + CSRF); the nav link always renders. +**Date:** 2026-07-11 · **Version:** controller v0.117.0 (from v0.116.1) · **MinAgent:** 0.81.0 +UNCHANGED (all checks controller-namespace-local; no new agent API) · **Deployed:** guest 9201 +(`0.117.0` healthy) · **NOT published/vouched** — Peti stays 0.113.0. Pairs with agent v0.84.0 +(RCA fix 1). Commits: `c0f3e12` + `4a9c54a` (linux-suite test pin). +**Source:** `felhom.eu/documentation/audits/AUDIT-nas-cwa-rca-2026-07-11.md`. ## What shipped -- **Capture layer**: always-on 1000-entry ring; `MultiWriter(LevelFilterWriter(stdout, level), ring)`; - `logx.Debugf/Infof/Warnf/Errorf` (caller-attributed); legacy `isDebug()` emission sites untouched. -- **Report self-log pull** (`report/selftail.go`): ACK `controller_log_requested` → next report ships - `controller_log_tail` (128 KB, consume-once, the v0.111.0 logtail.go shape; the customer-visible - `operator log pull served` INFO rides IN the tail). App-tail wire byte-compatible (schema-tested). -- **Debug page tabs**: `Vezérlő | Ügynök`; the agent tab proxies agent `GET /debug/logs` via the new - `Client.DebugLogs` (typed-404 → "Az ügynök naplónézete az ügynök következő frissítése után érhető - el."; non-404 stays an honest error). Template gates green. -- **Sweep**: netstorage_job (start + per-phase transitions + verdicts + rollback outcomes + - durations), netprobe exec/result, handler validation refusals (which check), orphan-share WARN, - capability gate line now carries the SOURCE (`SupportsWithSource`: version/probe-cache/probe), - agentapi per-call DEBUG (`SetLogger` on the memoized client) + version-change line, migrate - per-phase + duration, tier2/offbox run-start + previously swallowed status-persist errors → WARN. +- **`internal/system/fsclass*.go`** — statfs f_type classifier for THIS process's namespace: + `network` (nfs/cifs/smb2) | `autofs` (healthy idle trigger, NEVER force-mounted) | `stub` | + `unknown` (error/3 s timeout → fail open). Seams: `statfsFn`, `netProbeFSClass`, + `Server.classifyFSPath`, `Router.classifyFSPath`. +- **Fix 2a — probe assertion:** `--netprobe` child creates the probe file first (legitimately + triggers the automount), then REQUIRES a mounted network fs → exit 5 → category + `not_network_fs`, new §3.2 Hungarian message, full rollback, nothing registered. +- **Fix 2b — deploy refusal:** `POST /api/stacks/{name}/deploy` → `refuseNetworkStubDeploy`: a + registered network `HDD_PATH` classifying as stub refuses 409; idle autofs / live / unknown / + local / unregistered / empty all proceed. +- **Fix 2c — stub badge:** `networkStorageWarnings` → (warnings, stubs); stub leg runs even when + the agent is unreachable; dashboard + stacks cards render "Hálózati tárhely hibás — az alkalmazás + nem a NAS-t látja"; stub WINS over unreachable; the unreachable line stays byte-identical + (template-asserted). Pure core `networkStorageWarningsIn` + `stubNetworkPaths`. +- **Fix 4 — deploy-view truth (the RCA S-C symptom):** deployed-app storage select marks `selected` + by the STORED `HDD_PATH`; absent stored path → extra disabled ` (nem elérhető)` option; + `IsDefault` selects only for NEW deploys. -## Red-proofs (demonstrated, restored) +## Tests + red-proofs -| Scenario | Reverted shape | Failure seen | +| Test | Result | Red-proof | |---|---|---| -| S1 | LevelFilterWriter pass-through | `stdout carries the DEBUG line at level info` | -| S2 | self-tail drain removed | `second build shipped again — consume-once broken` | -| S7 | probe-verdict line dropped | `phase line "probe verdict: ok=true" missing` | +| magic table + seam + real-local-dir-is-stub (linux) | PASS | — | +| `TestNetProbeChild_StubRefused` / `_AutofsAfterCreateRefused` / `_RealLocalDirRefused` (linux) | PASS | assertion disabled → **the stub VERIFIED** (exit 0) → FAIL | +| `TestNetAdd_StubProbe_RollsBackNotRegistered` (rollback + not registered + Hungarian) | PASS | same mutation → job phase `done` → FAIL | +| `TestRefuseNetworkStubDeploy_Table` (7 rows) | PASS | mounted-only gate → idle-autofs + unknown rows FAIL (over-refusal) | +| `TestNetworkStorageWarningsIn_StubWins` / `_UnreachableAloneUnchanged` | PASS | — | +| `TestNetworkBadgeTemplates_DistinctStrings` (unreachable line byte-identical) | PASS | — | +| `TestDeployPage_DeployedSelectShowsStoredHDDPath` (real Manager + real template render) | PASS | IsDefault-only revert → default drive selected → FAIL (both assertions) | +| `TestDeployPage_MissingStoredPathRendersTruthOption` | PASS | — | -(S3 schema + S6 both-polarity notice tests pass; their traps are asserted structurally.) +Full suite green on Windows AND on 180 (linux); the linux run caught the pre-existing C5 child-body +suite needing the classifier pinned to `network` (fixed in `4a9c54a` — the real statfs correctly +refuses a tempdir). Gates: `template_id_gate.py` + `emoji_gate.py` OK. -## Live validation (9201, `logging.level: info`, 2026-07-11 ~17:10 CEST — via the exact endpoints the UI invokes; rendering-only residual) +## Deploy + live validation -- Real NAS add (`POST /api/storage/netstorage/add`, unreachable endpoint 192.168.0.199) → job - `failed` with `category=unreachable` + the exact §3.2 Hungarian message in ~2 s. -- **Vezérlő tab** (`/api/debug/logs?level=DEBUG`) at info shows the whole flow: capability gate - `netstorage_verify=yes (source=version)` ← the 0.82/0.83 version channel live, add started INFO, - `[agentapi] POST /netstorage/add -> 502 (2001ms)`, failed WARN with category+duration. -- **Ügynök tab** (`/api/debug/agent-logs`) proxies the agent ring (201 entries) incl. - `POST /netstorage/add status=502 duration_ms=2001`. +- Image `0.117.0` built+pushed on 180, deployed to 9201 via the bootstrap mechanism; healthy. +- **Q1c reboot validation (operator GO, with agent 0.84.0):** post-reboot, no manual action — + CWA auto-started healthy on the NAS, health `status=ok` on the first cycle, dashboard renders NO + stub badge (grep count 0 against the live page). +- **NOT live-validated (test-level only, by design):** the stub refusal branches — producing a live + stub post-fix would require breaking a healthy guest (the agent now heals it at start). Covered by + the red-proven unit/render tests above. -## NOT live-validated (expected + why) +## Follow-ups -- **Hub bundle round-trip (button → pending → bundle → download):** the hub UI is operator-password- - gated and no logged-in browser session was available — **operator follow-up: click "Request - controller logs" + "Request agent logs" on hub.felhom.eu/hosts/ and download both.** - The full round-trip incl. consume-once + S6 stays-pending is proven by hub API tests. -- **Blocked-secret branch live:** deliberately test-level only (no real secret is ever planted live). - -## Observations - -- Legacy `isDebug()` call sites left in place per spec — their DEBUG detail still doesn't exist at - info (only NEW logx lines do). Future sweeps can migrate them incrementally. -- Swallowed-error branches found + fixed with a WARN (not more): tier2 `SetCrossDriveConfig` ×3, - offbox `UpdateOffboxStatus` ×2. The offbox stats persist (best-effort, stale-safe) left as-is. -- The guest's local-API token was incidentally printed to the operator terminal during config - inspection (never into a file/commit); rotating it is cheap if desired. +RCA fixes 3/5/6 queued as separate tasks. Peti publish train: 0.84.0 + 0.117.0.