Commit Graph

29 Commits

Author SHA1 Message Date
admin fb0b8c1d42 docs: C6 destructive drill PASSED; R-23(a) mostly banked
Capability map — the destroy-then-recover drill ran through the customer UI:
photos deleted, TRASH EMPTIED, full files+database restore. 40 files placed
against 6 in the earlier non-destructive run, 1 DB dump replayed rc-0, 11
assets active, no drift, timeline confirmed. That is the proof the 6D
downgrade asked for, so the offsite-restore row earns PROVEN-LIVE. The
customer-restore row records the honest residual: an operator ran it, so the
row's literal 'a customer, not the operator' wording still owes one pass.

ROADMAP R-23(a) — the STOP-2 floor save released the held wait in the SAME
SECOND (hub 18:56:27 CEST = controller 16:56:27Z), out-of-cycle report 2s
later, generation advanced 0 -> 1. Still open: the self-restart single-fire
leg, since the floor was set to a version the box already ran.

Trap recorded: the wake is logx.Debugf, so it is invisible in docker logs at
INFO and lives only in the debug ring.
2026-07-20 19:23:11 +02:00
admin 0a399e3c02 docs(capability-map): offsite-restore stays PARTIAL — the 6D scope lesson applies
The operator confirmed the immich timeline renders correctly after the
2026-07-20 reconstitute, which was the last named residual. But that run
restored over an already-good state (11 assets before, 11 after), so it
proves the H4 window is closed and the operation is clean — it is NOT a
destroy-then-recover drill.

Flipping the row on it would repeat the 6D overclaim verbatim: 'immich
end-to-end from offsite alone' must not be claimed by a run in which
nothing was ever lost. Row stays PARTIAL pending a real destructive drill.
2026-07-20 19:07:20 +02:00
admin 9c8505649a docs: R-47 live-validated + golden 0.153.0 published
ROADMAP R-47 and the capability map's offsite-restore row now carry the live
evidence: a supervised reconstitute of immich from snapshot 49e7cb46 — the
same snapshot that aborted in round 2 — ran stop -> DB-service-only start ->
replay rc-0 -> full start, with no 'already exists', a SUCCESS outcome, and
immich's own 'No schema drift detected' twice where round 2 left it
reporting drift.

The offsite-restore row's residual for a PROVEN-LIVE flip is now only the
immich timeline screenshot (no browser on DooPlex).

Golden 0.153.0 baked and published the same day, sha256 15fdd191f3c660a6...,
first golden carrying all four infra images.
2026-07-20 18:04:02 +02:00
admin db3378bbf7 docs: R-47 shipped in controller v0.153.0 — H4 window closed on both restore paths
ROADMAP: R-47 collapsed to a shipped one-liner naming both paths (offsite
ReconstituteFromOffsite and local RestoreFromRecoveryUnit), the DB-only
window mechanism, the fail-closed rule, and the no-agent-coupling
declaration (MinAgent stays 0.90.0).

Capability map: the offsite-restore PARTIAL row and the customer-restore
MISSING row both note that H4 is closed in controller v0.153.0 and that they
now await only one clean acceptance run.

Also corrects the stale "closes in v0.149" wording in BOTH rows — v0.149.0
was the F3 dashboard BackupStatus fix; R-47 shipped in v0.153.0.
2026-07-20 17:26:17 +02:00
admin 30fd9d3ecd docs(audits): remote-ops remediation — F1 mitigated, F2 closed, F3 fixed (v0.149.0), Immich resolved; R-50..R-53 minted 2026-07-20 09:09:25 +02:00
admin 97249099d6 docs: DIAG round 2 — H1 confirmed, H4 found; two standing rulings landed
VERDICT. H1 confirmed: the reconstitution never ran. /backup/offbox/reconstitute
was never hit (reconstituted/safety-dump/replay line counts all 0); the operator
clicked the old missing-only button, which merged 34 files and left the DB
untouched. H2 rejected (the full path never executed; staging used the correct
snapshot 49e7cb46). H3 rejected (no replay happened; DB was genuinely asset:0).

R-44 is exonerated and working: 49e7cb46 carries offsite_run_id 20260719T102851Z
and its dump probes to asset:11 / user:1 — a properly coherent pair, against
round 1's asset:0 / user:0.

H4 (NEW, the more important result). Phase-3 recovery ran the real sequence and
the v0.148.0 path executed correctly — safety dump, stop, start, replay — then
the replay ABORTED: relation "clip_index" already exists. Proven to the second:
  10:58:25 controller begins replay
  10:58:33 immich-server "Reindexing clip_index" -> "Reindexed clip_index"
  10:58:35 dump's CREATE INDEX clip_index fails, exit 3
The replay races the app's own schema repair, because reconstitution starts the
stack before replaying (ImportDump needs a live container). The photos survived
only because pg_dump emits COPY data before CREATE INDEX — luck, not design. The
same start-then-replay shape is on the LOCAL path, so it is a class defect.

Recovery: PARTIAL and STOPPED as instructed. All 11 assets are back and visible
by every DB criterion (status=active, deletedAt null, all files resolve), but the
operation reported failure and immich reports schema drift. Not clean acceptance
evidence; no second attempt made; safety dump read only.

Findings -> R-47 (the replay race), R-48 (restore controls separable only by
layout — the proven cause of this incident), R-49 (1.1 GB of a 1.2 GB immich
backup is ML model cache + a postgres data-dir tar duplicating the .sql dump +
immich's own nightly dump; recorded, not changed).

RULINGS LANDED.
  - 00-capability-map.md:61 -> PARTIAL, scope-corrected: 6D's destruction hit the
    FILE TREE only; the DB survived in its named volume, so "end-to-end from
    offsite alone" overclaimed scope.
  - The 704.6 MiB "discrepancy" -> CLOSED, not a defect: it was immich's own
    Tarhely widget, never a controller page. Same for round 2's 650MiB->1.4GiB.
  - customer-restore row: partial evidence recorded, NOT flipped.

Diagnosis only — no code, label or layout changes; no forget/prune.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P9Nn14TWGzKoqAJAiVwC2s
2026-07-19 13:04:58 +02:00
admin 238472b8ed docs: R-43 + R-44 shipped in controller v0.148.0 (live acceptance still pending)
ROADMAP R-43/R-44 → SHIPPED with what actually landed:
  - R-43: ReconstituteFromOffsite — safety dump → stop → files overwritten to
    the snapshot version → start → the snapshot's own dump replayed from the
    SCRATCH unit (the live unit is still never overwritten). Invariants:
    nothing is ever deleted, and the undo is verified on disk before the act.
  - R-44: every run, manual AND nightly, refreshes dumps + units BEFORE the
    capture, so each snapshot is a coherent {DB@T, files@T} pair stamped with
    offsite_run_id + dumps_at. Nightly ordering is now structural rather than a
    coincidence of two scheduler entries at 02:30 and 04:15.

DIAG doc gains a "fixed in v0.148.0" header pointing at both.

Capability map deliberately NOT flipped: the DB half now exists but is PARTIAL,
not PROVEN-LIVE — shipped and deployed with no live acceptance behind it. The
customer-restore row stays MISSING, now blocked only on the evidence run rather
than on missing capability, and R-3 stays DRAFT.

Still open: the 00-capability-map.md:61 ruling — did CAMPAIGN-6D's "immich
end-to-end from offsite alone" exercise the DB half, or only the file half?

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P9Nn14TWGzKoqAJAiVwC2s
2026-07-19 12:27:11 +02:00
admin f3d1ba3062 docs: DIAGNOSE immich offsite restore — findings + ROADMAP R-43/R-44
Viktor deleted 11 immich photos to test offsite restore; both place runs
merged 0 files and flashed success. Two-layered root cause:

- A UI delete means TRASH, not deletion — no file left the disk, so there
  was genuinely nothing missing to restore. The test proved nothing.
- A valid test would also have failed: no offsite path loads a database.
  All three buttons are file-only (offbox_restore.go:171-232, :346-421).
  Files return; the library stays empty. The only DB replay is
  RestoreFromRecoveryUnit, reachable solely from the LOCAL restore panel.

Compounding: the manual push never refreshes dumps (offbox_handlers.go:
203-227) — today's unit dump is from 02:30 and probes to asset:0 / user:0 /
album:0, predating both the admin user and the photos. Had a full restore
loaded it, it would have written an empty DB over the live one, destroying
the trashed rows that were the only surviving recovery path.

Answer to "can a customer trust same-day offsite?" for a DB-indexed app:
no — files come back, content does not.

No product code changed. Photos left in trash (recovery not wanted).
Capability map: customer-restore row stays MISSING by finding, not by
absence of attempt; offsite-restore row flagged scope-contested pending
a ruling on whether CAMPAIGN-6D exercised the DB half.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P9Nn14TWGzKoqAJAiVwC2s
2026-07-19 08:47:34 +02:00
admin aa9c08f0dd docs(rehearsal): N100 S8 wrap — VALIDATION, map flips, ROADMAP R-30..R-39, R-3 draft
The 2026-07-18 N100 rehearsal ran the complete final-product flow on real metal
in one pass: RESET -> generic pairing ISO v1.20.0 -> customer self-bind -> day-0
-> managed-floor lift -> escrow ceremony -> offsite snapshots. No code changed;
every finding is recorded and ranked, none fixed.

VALIDATION-n100-rehearsal-2026-07-18.md — run context, a UTC-normalised timeline
built from the hub events stream / hub DB / controller log / bootstrap + agent
journals, per-ledger verdicts for S1-S8 + ledgers 8 and 9, 12 findings, the
not-exercised list, and 7 discrepancies against the brief.

Headline wall-clocks: bind -> credential 26 s; bind -> controller running the
current version 2 min 44 s; managed floor 0.143.0 -> 0.145.0 in 5 s unattended
(initiated_by: auto-floor); escrow ceremony -> offsite enabled 12 s; drive enrol
30.3 s. No post-bind leg stalled, which is the immediacy row's real-onboarding
proof.

Capability map (10 citations added):
- Bare-metal Felhom ISO           PARTIAL     -> PROVEN-LIVE (F1 closed on metal)
- Customer self-bind (slice 1)    IMPLEMENTED -> PROVEN-LIVE (customer_selfbind)
- Guest RAM resize (R-24)         IMPLEMENTED -> PROVEN-LIVE (shrink AND grow)
- Customer RESET                  two real firings + verified external teardown
- Escrow ceremony                 first live wizard firing
- Immediacy row                   "real-onboarding proof pending" cleared
- Publish train                   box-side floor lift proven on a fresh install
- Customer claim                  R-4 gmail half (Inbox under p=quarantine)
- Offsite orphan guard            staged live leg fired on its own
- DR tier by default              candidate PROVEN-LIVE upgrade WITHDRAWN (R-39)
Not flipped, as instructed: customer-performs-restore, BYO, DLNA, multi-user.

ROADMAP — collapsed R-1 (appliance half done, Peti half survives), R-21
(physically closed), R-24, R-27 slice 1, R-4. New ranked items:
  P2-HIGH  R-39 PBS DR applied-but-dead   R-30 liveness from the wait channel
           R-31 async offsite + status    R-32 RESET base-dir purge
           R-33 bootstrap quiet-poll
  P2       R-34 backup lifecycle          R-35 config-apply session survival
           R-36 post-RESET offsite prompt R-27c console-passphrase bind
  P3       R-37 post-RESET health card    R-38 installer GRUB slice
Plus a pre-invite checklist (golden 0.145.x rebuild, freemail.hu, C6, R-11).

R-39 is NEW and was not on the brief: the PBS DR descriptor auto-provisions and
the agent converges state=applied, but pvesm reports 401 Unauthorized/inactive
and a direct probe 401s on every endpoint including /version while WG is healthy.
The hub minted a second token secret two minutes after the agent applied the
first and consumed_at is still NULL; the converged state machine will not
re-apply, and the agent's verify loop cannot read the credential to notice it
(non-root read of a file it writes through a root wrapper). Rank is provisional
pending Viktor.

R-3 draft: all four [REFINE] slots filled, self-bind made the default path with
"send the link BEFORE the customer sees the console", the measured wall-clock
table added, and interim operator workarounds for R-31/R-36/R-39. C6 (renumbered
C7) is marked as the single unexecuted step and keeps the doc a DRAFT.

Evidence bundle: 180:~/n100-rehearsal/ (10 files + MANIFEST.md), collected before
the box was unplugged for travel. Secrets read only to run probes; recorded as
lengths and metadata, never values.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nn3VgQk9iwEGgyx6QJ2NvE
2026-07-18 19:56:17 +02:00
admin a03e142101 docs(R-7b): correction — all four legs PROVEN-LIVE, with snapshot evidence
Drops the false 'no offsite target on the demo box' clause from the ROADMAP row,
the capability-map SMB row and sharing.md. Cites offsite snapshots e0b9d723 /
4e2b15ec and the restore round-trip results. Root cause (guessed settings key) is
recorded in felhom-controller REPORT section 7b.
2026-07-18 14:32:39 +02:00
admin 4e3f6c48d4 docs(R-7b): share backup EXECUTION shipped (controller v0.145.0, Model B')
- capability map: SMB row KNOWN GAP cleared -> share data rides both tiers; the
  offsite leg + restore round-trip flagged as not-yet-live-exercised
- ROADMAP R-7b: idea -> SHIPPED, with the Model B' rationale and the live evidence
- controller/sharing.md: the KNOWN GAP block replaced by the execution contract;
  operator note corrected — samba IS liveness-monitored since v0.145.0
2026-07-18 13:35:00 +02:00
admin b76dad0c4e docs(R-7): Explorer leg PASSED — SMB server row MISSING -> PROVEN-LIVE
Viktor's human leg closed the last gate: both shares open from the Windows
Network view, an interactive Explorer save landed as uid 1000, and a write into
the read-only share was refused with the folder untouched. Capability map row
flipped to PROVEN-LIVE with that evidence; ROADMAP R-7 + sharing.md updated.
R-7b (shares classified but not in any live backup run) remains open.
2026-07-18 12:12:52 +02:00
admin d3a564cbff docs(R-7): SMB sharing slice 1 shipped — feature doc, map row, ROADMAP
controller/sharing.md (code-verified vs controller v0.144.0 + felhom-samba
1.0.0); capability map 'Files from Windows Explorer / Mac Finder (SMB server)'
MISSING -> IMPLEMENTED (PROVEN-LIVE pending Viktor's Explorer leg); ROADMAP R-7
-> shipped-slice-1 with the slice-2 remainder, and the backup design fork split
out as R-7b (shares are classified but not in any live backup run yet).
2026-07-18 12:05:15 +02:00
admin 592818492c hub v0.66.0 + ISO v1.20.0: customer self-bind (R-27 slice 1)
Let a customer bind their own freshly-installed appliance without the
operator: operator "Send self-bind link" mints a 7-day tokenized
capability link, emailed (Hungarian, sibling sender) to the customer, who
opens a public /bind/<token> page and proves two factors — the console
pairing code shown on the box screen + their retrieval passphrase — and
the hub stages the bind via the same BindAppliance (provenance
customer_selfbind). The box's ~30s appliance poll delivers.

Viktor's three rulings verbatim: console pairing code (no appliance list
ever rendered), operator-sent tokenized link, 5-attempt lockout ->
"call support". Wrong code == wrong passphrase (one generic failure, no
oracle, both factors compared unconditionally); expiry falls back to
operator-bind unchanged.

THE TRAP: one public prefix /bind/, exempt from auth+CSRF at both /login
gate sites via a single isPublicBindPath predicate (tight trailing-slash
match; ServeMux ..-cleans; handler rejects '/' in token). 9 tests
(Scenarios A-F + F1/F2); 4 red-proofs verified red-then-green (lockout,
oracle, widened-prefix, single-active). GC verdict: no appliance GC ->
the 7-day TTL stands alone. Controller/agent untouched; R-27b deferred.

Green: full hub build/vet/test (17 ok) + bash -n + hub confirm gate.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qDiBqKKQ5vPB5fXBqu7Kp
2026-07-17 23:56:53 +02:00
admin a9cd308398 docs: hub v0.65.0 PBS DR visibility (R-5) — REPORT + CONTEXT + capability-map (PBS DR row, data pipeline PROVEN-LIVE) + ROADMAP (R-5 restic+PBS) 2026-07-17 21:20:34 +02:00
admin f2e51e676b docs: hub v0.64.0 offsite pool-box aggregate (R-5) — REPORT + CONTEXT + capability-map (IMPLEMENTED, data pipeline PROVEN-LIVE) + ROADMAP (R-5 SHIPPED) 2026-07-17 20:25:55 +02:00
admin 85a14192e7 docs: R-24 guest RAM resize + R-28 fast-tick SHIPPED (agent 0.90.0 + controller 0.143.0) — capability-map rows + ROADMAP collapse 2026-07-17 19:29:32 +02:00
admin 50c090eeaa docs: hub v0.63.0 system-initiated immediacy — REPORT + CONTEXT + capability-map (immediacy row) + ROADMAP (R-28 agent fast-tick SECONDARY) 2026-07-17 17:33:34 +02:00
admin 4c9b0e8706 docs: R-21 slice C — REPORT/CONTEXT + capability-map (universal-ISO chain, slice C live-verified) + ROADMAP (R-21 SHIPPED A+B+C, R-27 self-bind future) 2026-07-17 15:50:33 +02:00
admin 3172df1927 scripts v1.18.0 — R-21 slice B: firmware loader option --loader shim|mkimage (F1)
Closes N100 F1 (HIGH): cheap AMI (AN3PLUS 0.01-class) UEFI firmware can't
relocate the ISO's stock signed GRUB from USB (relocation 0x0). The run's live
grub-mkimage workaround is now a first-class pipeline mode.

- build-felhom-iso.sh: --loader shim|mkimage (default shim, byte-for-byte
  unchanged; profile-settable FELHOM_LOADER; --loader wins). Loud banner +
  manifest loader:/grub-mkimage: fields + -mkimage filename suffix.
- mkimage-surgery.sh (new): post-prepare-iso, in the assistant container. Builds
  a monolithic grub-mkimage loader from the ISO's own GRUB (module set from its
  grub.cfg; embedded search --fs-uuid -> configfile the real menu). Swaps it into
  the ISO9660 tree (real lowercase path) + the efi.img ESP; xorriso re-master
  preserves BIOS-hybrid + UEFI + GPT-ESP, drops only Apple HFS+/APM. Recipe from
  the N100 run evidence, not re-derived.
- Dockerfile.assistant: grub-common + grub-efi-amd64-bin + mtools + dosfstools.
  profiles/n100.profile (new, mkimage + SB-off note).
- Validated on nested VM 311 (RUNBOOK-B legs): leg1 shim boots+installs under
  OVMF SB-enforcing + SeaBIOS; leg2 mkimage boots+installs under SB-off; leg3
  (red-proof) mkimage under SB-enforcing FAILS Access Denied (unsigned -> SB must
  be OFF); leg4 surgery byte-identical payload. bash -n + shellcheck clean.
  Physical N100 closure folds into the rehearsal (n100-safety match-nothing ISO
  built + sha-recorded, unbooted). PXE stays a deferred R-21 note.
2026-07-17 14:28:10 +02:00
admin d86d2699c3 docs: ROADMAP R-25b (DELETE↔RESET consistency) + capability-map Customer RESET row (PROVEN-LIVE external teardown) 2026-07-17 13:17:56 +02:00
admin 2752e12acc hub v0.60.1: host deletion demotes escrow custody (never destroys) + customer-delete purge point + S6b obsolete
- DeleteHost(deleteEscrow) demotes current host_escrow into host_escrow_superseded (copy-before-delete, same tx), spares existing; one shared demoteCurrentEscrowTx (reused by SaveHostEscrow). F-14 provenance/gate unchanged.
- DeleteCustomerConfig now purges both escrow tables for all the customer's hosts incl. already-deleted (F-14 provenance UNION) — the one true purge point.
- Wording: checkbox/refusal/Danger-zone → demotion. S6b OBSOLETE. Red-proofs TestDeleteHost_Demotes + TestDeleteCustomer_Purges + wording guard.
2026-07-17 11:25:38 +02:00
admin 106c3379b0 docs: offsite continuity Part B REPORT/CONTEXT; DIAGNOSE incident→fix pointer; capability map (offsite reinstall-continuity + escrow retention); ROADMAP R-25 (TOCTOU hardening) + R-26 (guided old-history recovery) 2026-07-17 10:55:17 +02:00
admin 1c737db4f4 docs: N100 F5/F6/F7 dispositions (fixed), capability map (fresh-USB wizard PROVEN-LIVE), ROADMAP (R-16 doc-drift closed, R-24 guest-resources-as-desired-state), iso README BIOS G3 note, REPORT/CONTEXT 2026-07-17 09:53:15 +02:00
admin 0c708a3bd0 docs: Direction-2a poke + F4/R-22 PROVEN-LIVE (real save→sync-poke delivered; ~31ms poke→tick; self-grant self-heal ~3s) — capability map + ROADMAP + REPORT/CONTEXT 2026-07-17 08:32:08 +02:00
admin 9d68d52fea docs: hub v0.59.0 + agent v0.89.0 — REPORT/CONTEXT overwrite, capability map (poke shipped, R-22 F4 closed, escrow live-reload), ROADMAP (R-22 shipped, R-13 first slice, R-3 deletion lifecycle) 2026-07-16 23:02:30 +02:00
admin bdb65a80e8 docs: capability-map row + ROADMAP R-23/R-13 + PROMPT-TEMPLATE N.5 for Direction-2 immediate-sync 2026-07-16 21:50:38 +02:00
admin d202b43b95 docs(map): capability-map evidence audit — verify every status claim against source
Opened every citation in 00-capability-map.md and judged each of the 55 rows
against the specific scenario (not topic adjacency). 23 confirmed (incl. 5
MISSING proven-absent by code sweep), 26 citation-corrected, 6 demoted; no
upgrades. Status: 32 PROVEN-LIVE / 15 IMPLEMENTED / 3 PARTIAL / 5 MISSING
(was 38 PROVEN-LIVE).

Demotions PROVEN-LIVE->IMPLEMENTED: B6 (post-deploy config — T-PAGE-ALL is
render-only), E7 (FileBrowser access — no browse/download proof), F1 (health
email — cited P3-DELIVERY is the enlarge-block trigger), F4 (metrics — cited
legs are H1/H2 harness artifacts), F6 (operator alerting — no corpus doc),
G6 (offsite fill/staleness/freeze — no live-fired leg, freeze inconclusive).

Key corrections: D6 cited CAMPAIGN-3 F10/F11/F12 which are the CRITICAL
failures — fixes shipped agent v0.85 and were re-validated live in CAMPAIGN-4
/6A; C6 cited offbox-restic doc for a PBS-restore claim -> CAMPAIGN-2 T-P9;
C1/C5/B5 cited defect-discovery docs instead of the fix-validation legs.

Closed ROADMAP R-20: operator-key pinning is fully automatic in day-0
(felhom-host-install.sh step_agent_config, L2044/2146-2156/2332-2337).
Header draft caveat swapped for the verified stamp. Full per-row verdict
table in REPORT.md.
2026-07-16 09:19:51 +02:00
admin 95853e3dff docs 2026-07-16 08:10:33 +02:00