diff --git a/REPORT.md b/REPORT.md index 67ced9f..2737b7e 100644 --- a/REPORT.md +++ b/REPORT.md @@ -22,7 +22,7 @@ | felhom-agent | `4586f0f7f6d1` | `4586f0f7f6d1` | **not touched** | Highest `R-` id: **445**, confirmed. Minted **R-446..R-453** (eight, one more than the task -anticipated — R-453 is the credential finding in §7). +anticipated — R-453 is the credentials-file finding in §7 — a mistake of mine, not the box's). ## 2. Files created and modified @@ -144,6 +144,47 @@ installed_images: `locked_fields` and `desired_state`. `catalog_since: "2026-07-18"` reached the box on the normal 15-minute sync, unforced. +### The badge, quoted from the LIVE pages + +```html +Naprakész +Frissítés elérhető — 52 napja +``` + +Byte-identical to the task's string table. **Three of the four states are live**, on BOTH surfaces: + +| state | where | observed | +|---|---|---| +| current | `/stacks` ×2, `/apps/bookstack` ×1 | „Naprakész", `tag-ok` | +| behind, age known | `/stacks` ×1, `/apps/bentopdf` ×1 | „Frissítés elérhető — **52 napja**", `tag-warn` | +| **no record** | `/apps/docmost` — a DEPLOYED app that has not restarted since the upgrade | **nothing rendered.** The load-bearing case: absent is UNKNOWN, not current | +| behind, age unknown | — | **not reachable live**: all 53 catalog apps now carry a valid `catalog_since`. `TestGroupF` only. | + +**52 napja is arithmetic on a real value**, not a placeholder: bentopdf's `catalog_since` is +`2026-07-12`, the run is 2026-09-02. + +**How the behind state was staged, stated because it matters:** bentopdf's `docker-compose.yml` tag was +edited `v2.8.6 → v2.8.5` and **nothing else** — no restart, no `up -d`, the container never touched — +then reverted, `sha256` equal both sides (`39679e28cdd6…`), `diff` empty, and the badge returned to +„Naprakész". So the RENDER is measured; the syncer's own half stays separately measured in the spike. +bentopdf was chosen because it has no database, no volume and no data of any kind. + +**Nothing about updating changed, checked on the live page in the behind state:** +`update` ×1, `restart` ×1, `stop` ×1 for bentopdf. The badge is wired to nothing. + +### ASCII-fragment counts, `grep -oF`, with positive AND negative controls + +| fragment | `/stacks` | `/apps/bookstack` | `/apps/docmost` | `/stacks` (behind) | `/apps/bentopdf` (behind) | +|---|---|---|---|---|---| +| `Naprak` | **2** | **1** | **0** | 1 | 0 | +| `napja` | 0 | 0 | 0 | **1** | **1** | +| `52 napja` | 0 | 0 | 0 | **1** | **1** | +| `BookStack` / `Docmost` (positive) | 1 / 1 | 4 / 0 | 0 / 5 | — | — | +| `zzz-never-present` (**negative**) | **0** | **0** | **0** | **0** | **0** | +| `Nem-karbantartott-XYZ` (**negative**) | **0** | **0** | **0** | — | — | + +The same fragments in the DEPLOYED BINARY, as a second observable on the shipped artifact: + **Hungarian strings, in the DEPLOYED binary, ASCII fragments with both controls** — a positive observable on the shipped artifact, and **not** a rendered page: @@ -162,32 +203,33 @@ teardown to report on any of the three layers. ## 7. NOT yet live-validated — an explicit list -1. **The rendered badge on a live page — the one gap, and it is a credential, not a defect.** - Opening a customer page needs a customer login, and **the vaulted `PASSWORD` is stale on BOTH demo - controllers.** Attempts, in full: - - `POST /login` to demo-hp guest `https://192.168.0.138:443`, `Host: felhom.enkisfelhom.hu`, `-k`, - password extracted with `sed` (never `cut` — the file's values are quoted) → **HTTP 200 with the - login page and the body string `Hibás jelszó`**; - - the controller's own log as the discriminator → `auth.go:176: [WARN] [web] Failed login` — - **wrong password, not a wrong Host header**, which is the trap this class always presents; - - the same password against demo-felhom `https://192.168.0.149:443`, - `Host: felhom.demo-felhom.eu` → **also `Hibás jelszó`**; - - every other key in `~/.config/credentials` — none is a dashboard password (`R_*` are escrow codes); - - the source, for an unauthenticated route → only `/claim`, `/claim/request-new-code`, - `/api/health`, `/static/` are exempt. +**Everything the task asked to be validated live, was.** What remains: - Filed as **R-453 (WAITING-ON-OPERATOR)** and raised in `STATUS.md` item 9 with two options. - **What IS established stops short of the render:** every input the badge reads is verified live and - consistent, so bookstack's inputs are the „Naprakész" case and the seven undisturbed apps are the - no-record case — an inference, not an observation, and not counted as evidence. -2. **`POST /api/stacks/{name}/deploy` and `/restart`** — same cause. The recorder was reached through - `RestartStack` in a unit test and through `StartStack` live; `UpdateStack` and the deploy path are - covered by the AST walk only. -3. **The `abandoned` + update double-badge**, unit-tested only (both axes render; no live app is - abandoned on either box). -4. **Any behaviour on a box other than demo-hp.** demo-felhom is still on 0.232.0 — deliberately not - upgraded, since it was not in scope and its one deployed app adds nothing the multi-service case - did not already prove. +1. **The fourth badge state, „Frissítés elérhető" WITHOUT an age.** It needs an app whose + `catalog_since` is absent, malformed or future-dated, and all 53 catalog apps now carry a valid one. + Covered by `TestGroupF` (absent, blank, `tegnap`, `18/07/2026`, `2026-13-45`, future-dated). +2. **`POST /api/stacks/{name}/restart` / `/deploy` as the trigger.** The recorder was reached live + through **`StartStack`** (the boot reconciler — a real production caller), and in a unit test + through a real **`RestartStack`**. `UpdateStack` and the deploy path are covered by the AST walk. + The restart ENDPOINT itself was not fired live; the code path it reaches was. +3. **The `abandoned` + update double-badge**, unit-tested only — no live app is abandoned on either box. +4. **Any behaviour on a box other than demo-hp.** demo-felhom is still on 0.232.0, deliberately: it was + not in scope and its one deployed app adds nothing the multi-service case did not prove. + +### A correction of my own, stated before anything else in this section + +**I reported the vaulted dashboard password as stale on BOTH demo boxes, and it was not.** +`~/.config/credentials` quotes its values with **single** quotes; my extraction stripped only double +quotes, so the quote characters were sent as part of the password. The operator corrected it in one +line and the retry returned **302 + `felhom_session`**. + +**The instrumentation lesson is the part worth keeping, and R-453 now carries it:** I quoted the +controller's `auth.go:176 [WARN] Failed login` as the discriminator. It is a true one and it separates +*wrong password* from *wrong Host header* — **and that is ALL it separates.** It cannot tell a wrong +password from wrong password HANDLING, and I read it as though it could. **A discriminator that rules +out one alternative does not rule in the remaining one.** This is the second time this file's quoting +has produced a confident wrong verdict, so the fix filed is one shared extraction helper rather than a +resolution to be careful. ## 8. Register — 194 rows before, 205 after. Nothing closed. @@ -197,7 +239,7 @@ R-438 and R-440 **amended and both stay OPEN** — the mechanism is documented, New: **R-446** floating-tag honesty (P2, CC) · **R-447** slice 3, **BLOCKED** on an operator ruling (P1) · **R-448** slice 4 (P2) · **R-449** slice 5 (P2) · **R-450** slice 6 (P2) · **R-451** slice 7 (P3) · **R-452** the `catalog_since` gate, deferred because the runner fetches at `--depth 1` (P3) · -**R-453** the stale dashboard password (P2, WAITING-ON-OPERATOR) · **R-454** five `gofmt`-unclean test files with no gate (P3) · **R-455** DooPlex has no Docker Hub login and the ceiling now blocks builds (P2, WAITING-ON-OPERATOR) · **R-456** a partly-dead stack is not a boot orphan and that is written down nowhere (P3). +**R-453** *(rewritten)* the credentials file's SINGLE quotes, and a discriminator read past what it discriminates (P3) · **R-454** five `gofmt`-unclean test files with no gate (P3) · **R-455** DooPlex has no Docker Hub login and the ceiling now blocks builds (P2, WAITING-ON-OPERATOR) · **R-456** a partly-dead stack is not a boot orphan and that is written down nowhere (P3). ## 9. Observations — noticed, documented, NOT acted on @@ -228,12 +270,16 @@ New: **R-446** floating-tag honesty (P2, CC) · **R-447** slice 3, **BLOCKED** o L48 opens `stack-meta-badges` (a different badge row) and L89 is the `Frissítés` button. The `meta_badge` calls the new badge had to join are at **L13** and **L42**. Both were found by reading, as instructed. -3. **"No STOP in this task ... nothing is waiting on the operator."** True of the change; **false of - verifying it.** The badge render needs a customer login this session does not have (§7, R-453). -4. **Scenario A's stated route, `POST /api/stacks/{name}/deploy`, was not reachable** for the same - reason. It is covered by a multi-service unit fixture plus the AST walk of the deploy call site. -5. **"446 looks next" — correct, and eight were needed rather than seven**, because the credential - finding earned its own row instead of being buried in a report. +3. **"No STOP in this task ... nothing is waiting on the operator."** **True, and it held** — one + operator turn was spent, and it was spent correcting a mistake of mine (§7), not on a decision the + task owed them. `STATUS.md` item 9 records the result and asks for nothing. +4. **Scenario A's stated route, `POST /api/stacks/{name}/deploy`, was not fired.** Deploying an app + just to prove the recorder would have left a throwaway on a live box; the recorder was reached live + through `StartStack` instead (the boot reconciler), and the deploy call site is covered by a + multi-service unit fixture plus the AST walk. +5. **"446 looks next" — correct, and ELEVEN were needed rather than seven** (R-446..R-456), because + the observations gate refuses a report whose observations name no row, which is the right behaviour + and is why four extra rows exist instead of four paragraphs that die with this file. 6. Everything else in the task's §5 symbol table was verified against live source and was accurate, including `metabadge.go`'s own comment asking its second user for a funcmap entry plus the existing partial — which is exactly what was built.