## R-543 live validation — controller v0.245.0, 2026-09-16, demo-hp
## Method: endpoint-level. Every request below is the exact request the browser makes (same handler,
## same session cookie, same CSRF); only rendering is skipped. claude-in-chrome is not available here.
## Reachability note: neither guest answers on its LXC address from DooPlex, and the controller does
## not listen on the guest's 127.0.0.1 — it answers on the container address 172.17.0.2:8080 with the
## mandatory Host header. All requests therefore run INSIDE the guest via `pct exec`.
## Secrets: the dashboard password was read with scripts/read_credential.py (value never printed,
## file->file, 0600) and passed to curl as --data-urlencode password@<file>.

### THE SEAM, STATED
The two halves of this proof are on two boxes, not one box before and after a ceremony:
  * PAUSED half  — guest 9202 (scratch), off-site configured and escrow NOT complete.
  * ESCROWED half — guest 9201 (demo), off-site configured, escrowed, running.
Running a real escrow ceremony on a fresh target would provision off-site storage, and this task's
fences put ep0 out of bounds. So the escrowed side is OBSERVED on a box that is already escrowed
rather than produced here. What is NOT weakened by the seam: both boxes run the same binary
(0.245.0), and the paused box's state was produced through the product's own configuration endpoint.

## ── 1. ESCROWED + ACTIVE — guest 9201 (0.245.0) ────────────────────────────────────────────────
login OK
GET /dashboard    -> 200  bytes=60816   escrow-bar-hits=0
GET /launcher     -> 200  bytes=44462   escrow-bar-hits=0
GET /backups/apps -> 200  bytes=106304  escrow-bar-hits=0
tier-1 file sentence, as rendered (2 class-A apps):
  "Az alkalmazás fájljait a távoli másolat (és a második meghajtó) védi — ez a helyi mentés a
   beállításokat és az adatbázist tartalmazza."
word counts on /backups/apps:  Kulcslet=0   szünetel=0   védi=2   védené=0
=> a box whose recovery code exists is NOT nagged, and the promise it prints is a true one.

## ── 2. PAUSED — guest 9202 (0.245.0) ───────────────────────────────────────────────────────────
The state was produced through the product's own endpoint, POST /backup/offbox/config, with a
throwaway ed25519 key and a pinned known_hosts line. 9202 has no agent local API, so the escrow
STAGE could not run — the handler said so and saved the target anyway:

  POST /backup/offbox/config -> 302
  flash: "A távoli mentési cél elmentve. — a kulcs letéti előkészítése nem sikerült
          (az ügynök nem elérhető); próbáld újra."

Persisted state afterwards (read from the guest's own settings.json):
  enabled=True  host=192.168.0.162  repo_path=/mnt/nvme-1tb/r543-paused-proof
  escrow_state=pending  last_run=None  last_status=None  snapshot_count=None
  data/offbox/:  known_hosts 95 B (0644) | repo_password 64 B (0600) | ssh_key 411 B (0600)
=> OffboxConfigured() is genuinely true (valid target + both secret files), and the escrow is NOT
   complete. This is the state a fresh box lands in on day one.

### 2a. The bar is on EVERY page, not on the three someone remembered
  GET /dashboard     -> 200   escrow-bar-hits=1
  GET /launcher      -> 200   escrow-bar-hits=1
  GET /backups/apps  -> 200   escrow-bar-hits=1
  GET /settings      -> 200   escrow-bar-hits=1
  GET /apps          -> 404   escrow-bar-hits=0   (no such route; a 404 carries no bar)

Quoted from /dashboard:
  "A távoli mentés szünetel, amíg nem hozod létre a helyreállítási kódot."
  <a href="/backup/escrow">  (the route out, on the bar itself)

### 2b. A manual off-site run, while paused — refused, FOR THE RIGHT REASON
  POST /backup/offbox/run -> 302
  flash: "A távoli mentés a kulcs letétbe helyezésére vár."
  after the attempt: last_run=None  last_status=None  snapshot_count=None
=> No snapshot, and the refusal came from the fork-4 escrow gate (offbox_handlers.go:224
   OffboxRunnable), NOT from an unreachable target — the target was never contacted. This matters:
   a run that failed to connect would have proven nothing about the pause.

### 2c. „Most nem" is for the visit only
  POST /backup/escrow/banner/dismiss -> 302
  Set-Cookie: felhom_escrow_banner=1; Path=/; HttpOnly; SameSite=Lax
    ^ no Max-Age and no Expires => a browser SESSION cookie, exactly as R-241 does it
  same visit, cookie sent -> escrow-bar-hits=0
  next visit, no cookie   -> escrow-bar-hits=1
=> the off-site tier is still paused tomorrow, so the question is still asked tomorrow.

### 2d. The tier-1 FILE sentence, live, with the tier paused
The first pass of this phase could not show it: 9202 had no class-A app, so the sentence had nothing
to render („védi"=0 AND „védené"=0 — the „szünetel"=1 on that page was the BAR in the layout, not the
sentence). Recorded because it was briefly written down as a limit and it was not one. A throwaway
class-A app was then deployed on the box's own drive and the off-site copy turned on for it:

  POST /api/stacks/calibre-web/deploy -> 202  {"ok":true,"message":"Telepítés elindítva ..."}
  (HDD_PATH=/mnt/felhom-drives/scratch_hdd — the guest's own registered data drive, 938 G)
  POST /backup/offbox/toggle app=calibre-web enabled=true -> 302

Rendered on /backups/apps, with the tier configured and PAUSED:

  "Az alkalmazás fájljait a távoli másolat védené — a távoli mentés a helyreállítási kód
   létrehozásáig szünetel."
  ...followed by the route: "Helyreállítási kód létrehozása →"

  word counts on /backups/apps:  Kulcslet=1   szünetel=3   védi=0   védené=1
    Kulcslet=1 is the tier-3 row's own state („Kulcsletétre vár").
    szünetel=3 is the bar + the sentence + the tier row.
    védi=0 is the point: the page no longer claims a protection that has never run.

=> Both wordings are now observed LIVE on real boxes running 0.245.0: „védi" on the escrowed box
   (9201, §1) and „védené … szünetel" on the paused box (9202, here).

## ── 3. TEARDOWN, three layers ──────────────────────────────────────────────────────────────────
Recorded after the evidence above was already written to DooPlex (R-320: evidence leaves the machine
at the END OF THE PHASE, before any revert — not at the end of the session).

MACHINE (guest 9202, scratch):
  * the throwaway class-A app removed WITH its data and its backups:
      POST /api/stacks/calibre-web/stop   -> 200
      POST /api/stacks/calibre-web/remove -> 200  {"removed":"calibre-web",
        "volumes_removed":["calibre-web_calibre_web_config"],"hdd_paths_removed":[],
        "hdd_note":"Az alkalmazás nem tárolt saját adatot…"}
      verified after: containers named calibre = 0, drive folders = 0
  * the off-site target this proof created is GONE:
      before: offbox present=True, data/offbox/ held ssh_key, repo_password, known_hosts
      after : offbox present=False, data/offbox/ ABSENT, all three files `shred -u`'d
      MY OWN MISTAKE, recorded: the first teardown pass used the CONTAINER's view of the data path
      (/opt/docker/felhom-controller/data) from a shell running in the GUEST, where that path does
      not exist. It printed „offbox dir now: ABSENT" — which was TRUE of a path that never existed
      and FALSE of the thing being claimed. The target was still fully configured. The same wrong
      path had already produced three FileNotFoundError tracebacks earlier in this phase; I read
      those as noise instead of as the instrument telling me it was pointed at nothing. The re-run
      stops the controller first, edits the real file, shreds the secrets, restarts, and RE-READS
      the state to confirm — a teardown asserted is not a teardown observed.
  * controller restarted and healthy: felhom-controller:0.245.0 Up (healthy)
  * temp files: none left (`ls /tmp/.r543*` empty in the guest)
  * NOT touched: filebrowser, traefik, the box's registered data drive, its password, its claim state.

HOST (demo-hp): /tmp/.r543pw and /tmp/.r543key shredded; .r543kh, the scripts and one stray
  /tmp/.r543out removed. Verified: 0 files matching /tmp/.r543* remain.

HUB: provisioned nothing. Guest 9202 has hub reporting OFF and no tunnel, so no customer, no host
  record, no escrow row and no event was created by any of this. Nothing to tear down.

NOT torn down, deliberately: guest 9201 now runs controller 0.245.0. That is the release being
shipped, not a drill artifact, and its own off-site tier was never touched (still escrowed, active).
