Commit Graph

722 Commits

Author SHA1 Message Date
admin 0f311adaa1 controller v0.118.0: backup integrity F7/F6/F5 — docs + CHANGELOG + REPORT + CONTEXT
F7 atomic volume dumps, F6 no single-copy (volume-only tier-2 + honest single-drive
signal), F5 stale-primary sweep. Part 4 locality fork = A (doc-only). Live-validated
on 9201: F7 money-shot byte-identical through mid-write cut, F6/F5 confirmed, restore
round-trip byte-identical.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017CDMFpFx84pfviCTVuGGhf
2026-07-12 09:18:05 +02:00
admin e3903be0f1 test: F6 restore-point SSD label now clear (was blank)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017CDMFpFx84pfviCTVuGGhf
2026-07-12 09:01:17 +02:00
admin 68b3a3932e controller: F7 atomic volume dumps + F6 no-single-copy + F5 stale-primary sweep (WIP, pre-build)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017CDMFpFx84pfviCTVuGGhf
2026-07-12 09:00:16 +02:00
admin b389e73fff docs: REPORT for v0.117.0 (deployed 9201; Q1c reboot validation green; stub branches test-level only)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-11 21:25:12 +02:00
admin 4a9c54a105 test: pin netProbeFSClass=network in the C5 child-body suite (real statfs on linux correctly refuses tempdir)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-11 21:15:48 +02:00
admin c0f3e12483 v0.117.0: consuming-namespace NAS verification + deploy-view truth (RCA fixes 2+4)
statfs fsclass helper (network/autofs/stub/unknown, fail-open); probe not_network_fs
assertion (stub can never verify — red-proven); deploy-time stub refusal (idle autofs
proceeds — red-proven); distinct stub badge, stub wins over unreachable (unreachable line
byte-identical); deployed select shows stored HDD_PATH (red-proven vs IsDefault-only).
MinAgent unchanged 0.81.0. Gates green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-11 21:12:48 +02:00
admin 6e9dd1bfa1 docs: REPORT + CONTEXT for v0.116.0/v0.116.1 (deployed 9201, live-validated at info level)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-11 17:19:14 +02:00
admin 458d7e1ebc v0.116.1: ungate /debug + /api/debug from logging.level — the viewer must exist wherever the ring does
Live validation at logging.level=info 404'd the whole debug surface (the
motivating incident's blind spot). Auth unchanged (RequireAuth + CSRF).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-11 17:12:20 +02:00
admin 26a43708b7 v0.116.0: observability pass — always-on debug ring + leveled sweep + agent tab + self-log pull — MinAgent: 0.81.0
Capture layer: LogBuffer always exists; logger = MultiWriter(LevelFilterWriter
(stdout, logging.level), ring) so DEBUG detail exists remotely without a config
flip while docker logs keep respecting the level. New internal/logx leveled
helpers. Report ACK gains controller_log_requested (additive); next report
ships controller_log_tail (128KB, consume-once, app-tail wire byte-compatible).
Debug page: Vezérlő|Ügynök tabs; agent tab proxies agent /debug/logs with the
pre-0.83 notice on typed 404. Sweep: netstorage_job phases, netprobe, handler
validation refusals + orphan WARN, SupportsWithSource gate line, agentapi
per-call DEBUG, migrate phase lines, tier2/offbox unswallowed persists.
Red-proofs: filter-disabled, drain-removed, dropped-phase-line all FAIL.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-11 16:45:57 +02:00
admin 647116480a docs: REPORT v0.115.0 + CONTEXT (version-aware Supports, DSM guidance, Q1c FAIL)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-11 15:47:21 +02:00
admin b6842a4bc3 v0.115.0: version-aware Supports (agent header channel) + DSM-validated NFS guidance — MinAgent: 0.81.0
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-11 15:03:41 +02:00
admin ac6adaaa44 docs: REPORT v0.114.0 — capability gate shipped, red-proofs, live validation (supported branch)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-11 14:05:32 +02:00
admin 53ab971fe4 feat: debug-log the capability-gate verdict per add + SupportState.String()
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-11 13:59:23 +02:00
admin d9da5a0678 docs: v0.114.0 CHANGELOG (MinAgent header convention) + README NAS gate + CONTEXT + REUSE + coupled-feature rule in CLAUDE.md
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-11 13:54:09 +02:00
admin 4a5c40b7cb test: fix TestBackupTier2Restore_DoubleClickRefused scheduling flake
IsRunning flips before the restore goroutine parks in StopStack; under parallel
load the ==1 assertion raced it and read 0. Wait for the first stop to land, then
assert — the red-proof property (no-fast-path mutant → count 2) is preserved.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-11 13:50:35 +02:00
admin 50da7329ac feat(ui): agent-outdated banner on the NAS settings page (capability gate, Part 3)
- networkStoragePageData threads NetAddSupport (yes/no/unknown) via the short-budget
  netAddSupport probe (2 s ctx + cache — a down agent cannot stall the page)
- storage_network.html: support=no replaces the add form with the Hungarian
  alert-warning banner; share list + remove render in every state; yes/unknown
  render the form unchanged; load-time JS guarded for the formless render
- T5 render test (banner/no-form on 'no', form on yes/unknown); red-proof RP5 run
  (conditional dropped → banner assertions fail) and reverted
- template_id_gate + emoji_gate green

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-11 13:49:29 +02:00
admin d347dc48d2 feat: agent-capability gate for coupled features — typed StatusError + Supports probe/cache + netstorage add gate (option-1)
- agentapi: non-2xx GETs now surface as typed *StatusError (same text); features.go
  adds Feature/SupportState/SupportCache (route probe, TTL 5m, Yes/No cached,
  Unknown never cached or refused) + Client.Supports
- web: handleNetStorageAdd refuses up front (412, code agent_outdated, Hungarian
  message) when the agent predates /netstorage/verify-status (= pre-0.81 add
  semantics); gate runs BEFORE the single-flight claim; SupportUnknown passes
  through to the existing agent-error paths
- netAddSupport page-render helper lands here; its template consumer follows
- tests: T1 gate refusal (job never starts, slot free), T2 unchanged happy path +
  warm-cache negative assertion, T3 indeterminate never 'too old', T4
  classification incl. the string-match trap, T6 TTL, wire-level 404-typing;
  red-proofs RP1-RP4 run and reverted

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-11 13:45:49 +02:00
admin 5d06ecf374 docs: CHANGELOG v0.113.0 + REPORT + CONTEXT + README NAS section + REUSE seams
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-11 10:31:07 +02:00
admin a65dcff85a storage_network: full redesign on the canonical form pattern + protocol-honest guidance (v0.113.0 UI)
Kills the details/summary-button hack and the nonexistent form-row/form-input
classes (the unstyled-look root cause); rebuilds on the storage_attach pattern
(settings-card / form-group / form-control / form-actions / alert-*). SMB listed
first (consumer reality), NFS two-recipe guidance (map-all-users simple recipe +
full-fidelity anonuid=<uid+100000> with a live computed host-id), §3.2 staged
poll progress (Kapcsolódás/Csatolási teszt/Írásteszt/Regisztrálás), categorized
Hungarian errors with a collapsible raw-detail block, orphan rows with an Árva
badge + remove-only action. C8 render smoke guards the class regression.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-11 10:05:08 +02:00
admin bb8737a81f netstorage: verify-before-commit orchestration — agentapi verify fields, uid-1000 re-exec probe, detached add job, orphan rows
Controller half of the verify pipeline (SPIKE-nas-verify b57f6c1): AddNetStorage
gains verify/job fields + typed NetAddRefusedError; NetVerifyStatus polls the
agent slot; --netprobe hidden re-exec mode (SysProcAttr.Credential uid/gid 1000,
no shell) proves in-guest writability; the add handler starts a detached
single-flight job (agent_add → verifying → probing → registering LAST) with full
rollback on any failure incl. verify-lost-after-restart (Scenario F); §3.2
Hungarian error map server-side; live-but-unregistered shares surface as remove-
only 'Árva megosztás' rows.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-11 09:59:33 +02:00
admin 3db9126121 docs: REPORT + CONTEXT for v0.112.0 (deployed + live-proven credential-less on demo)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-10 18:02:05 +02:00
admin d910edd4ad docs: v0.112.0 CHANGELOG + README (registry access modes) + REUSE (runner vars seam, WWW-Authenticate parser)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-10 17:53:51 +02:00
admin b25ca60ab7 v0.112.0: self-update without credentials — anonymous Docker v2 token flow
Root cause (live on Peti's box): the updater piggybacked on Git Sync creds and refused when absent,
but the registry serves the public package anonymously (verified 2026-07-10). Credentials become what
they were meant to be — optional, for private catalogs only.

- queryRegistry: both creds empty → anonymous flow (plain GET → parse WWW-Authenticate realm/service
  from the header, never hardcoded → credential-free token → Bearer retry); creds present → BasicAuth
  path unchanged; half-configured pair → loud incomplete-credentials error
- pullImage: no creds → skip docker login entirely (docker's native anonymous flow); denied anonymous
  access → clear 'registry denied anonymous access — a private registry requires Git Sync credentials'
- settings page: 'Registry: nyilvános (hitelesítés nélkül) / hitelesített' mode line — credential-less
  is no longer an error state; DryRun.PullCapable counts anonymous as capable
- tests: fake registry httptest token dance (zero creds, no auth on token request, correct scope),
  creds path unchanged (BasicAuth, no dance), both denial paths, WWW-Authenticate parser table
  (quoted/bare/order/comma-in-quotes/missing-realm), fake-runner pull tests (no login invoked
  anonymously; login/pull/logout order + stdin token with creds; partial creds refuse)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-10 17:52:03 +02:00
admin b1250ad5a0 REPORT: live tail round-trip completed (see felhom.eu REPORT)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-10 16:54:52 +02:00
admin c414ba53b5 docs: REPORT + CONTEXT for v0.111.0 (deployed + live-validated on 9201)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-10 16:25:37 +02:00
admin 30927b6816 docs: v0.111.0 CHANGELOG + README (telemetry context/tails) + REUSE entries
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-10 15:45:45 +02:00
admin 544c42a618 v0.111.0: remote app-log diagnostics — error context capture (±5 lines, capped+redacted) + on-demand log tails via ACK pull pattern
- metrics: LogIssue.Context on first-occurrence errors (≤11 lines, ≤400 chars/line, warns carry none); RedactLine sanitizer (password/token/api-key/bearer/64-hex) applied to everything shipped; FetchContainerLogTail
- report: 16KB per-report context budget (lowest-count issues dropped first); log_tail_requests ACK flag → next report ships log_tails (200 lines, ≤64KB/app head-truncated, ordered, redacted); consume-once drain
- tests: synthetic-window context capture, caps, redaction, budget order, consume-once, fetch-error skip

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-10 15:43:29 +02:00
admin 332725a024 report: v0.110.0 C2/C1 fix deployed + live-validated (crash → next run self-heals)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-10 07:09:26 +02:00
admin cb9e992c7a v0.110.0: offbox stale-lock self-heal (campaign C2) + crash-truthful status (C1)
resticStep escalates a restic lock error to `unlock --remove-all` + one
retry (safe: single-writer repo — sub-account isolation + single-flight
mutex); plain `unlock` is stale-only and can't clear a crash lock across a
container-hostname change. Pre-run stale unlock hygiene on run+restore.
C1: NewManager flips a persisted LastStatus=running to a truthful error.
Both red-proofed (A reproduces the exact campaign backup failure).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-10 07:02:23 +02:00
admin 0bd4cd02be docs: v0.109.1 README + REPORT (SLICE 4 deployed + live-verified)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-10 00:24:57 +02:00
admin ddac21cd91 v0.109.1: re-apply preserves escrow custody + runtime status (live finding)
The QuotaGB hash change triggered a live re-apply that demoted the
escrowed demo to pending and wiped its runtime status. ApplyOffsiteTarget
now carries over EscrowState (custody tracks the preserved repo password,
not the coords) + status fields; fresh guests still land pending.
Red-proofed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-10 00:06:06 +02:00
admin f830325ca3 offsiteapply: include QuotaGB in the descriptor hash — quota changes re-apply
A hub-side quota raise now reaches the target: the marker hash changes and
the bridge re-applies via key-auth-first (no password consumed). Test:
quota-only change remaps the new quota with a panicking consumer.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-09 23:58:30 +02:00
admin 8917014991 v0.109.0: soft-quota gate + usage bar + offsite report status (SLICE 4)
QuotaGB rides the descriptor into OffboxTarget; RepoSizeBytes persisted
from restic stats. Pre-run gate: >=100% refuses NEW backups (Hungarian
notice + operator alert) but prune STILL runs (red-proofed) and restore is
never gated; >=80% warns. /backups usage bar (quota>0 only). The hub
report gains the non-secret offsite status object for the OffsiteChecker.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-09 23:48:42 +02:00
admin 994e15896f docs: v0.108.0 README (auto-confirm) + REPORT (deployed, Scenario E live)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-09 23:24:38 +02:00
admin febf6757dc v0.108.0: hub-verified escrow auto-confirm on current-password hash match (SLICE 3)
EscrowAutoConfirmer flips pending->escrowed ONLY when sha256(local repo
password) matches the ACK's restic_pw_sha256 (blob-presence alone never
confirms — red-proofed). Mismatch warns once per hash naming the ceremony;
never un-confirms; wipes the staged secret on flip. Pinned cross-repo hash
vector; manual confirm deprecated to a legacy-blob fallback.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-09 23:19:17 +02:00
admin fec2e8fd84 docs: v0.107.0 README (key-auth-first + wipe) + REPORT (deployed, one-off cleanup done)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-09 22:46:25 +02:00
admin a38c743926 v0.107.0: key-auth-first bridge + staged-secret wipe on escrow confirm
Key-auth-first: a KeyAuthProber seam lets the bridge skip consume+install
when the already-installed key still authenticates (pinned to the freshly
verified host key) — descriptor changes on provisioned guests no longer
loop on consume-404. Fingerprint verify still precedes everything.

Wipe-on-escrowed: confirm-escrow now calls the agent's new
DELETE /escrow/stage-secret (v0.78.0) best-effort, closing the hygiene gap
where a ceremony-less confirm left the staged password file behind.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-09 22:26:53 +02:00
admin 42af088308 readme: document the offsite provisioning apply-bridge (SLICE 2, v0.106.x)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-09 22:07:28 +02:00
admin 78fdec2897 report: offsite provisioning live e2e validation PASS (v0.106.1)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-09 22:05:23 +02:00
admin 0c4a4ec02c v0.106.1: ssh-copy-id -s requires ~/.ssh locally — create it in the installer
Live finding: SFTP-mode ssh-copy-id mktemp's under ~/.ssh; the container
image has no /root/.ssh, so the install died locally AFTER the one-time
password was consumed (fail-safe held; password never transmitted).
Probe confirmed the pinned known_hosts + StrictHostKeyChecking=yes chain
is sound against the real box once ~/.ssh exists.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-09 21:29:38 +02:00
admin 6d89c186f7 report: record 0.106.0 deploy verification on guest 9201 (healthy, sshpass shipped, bridge no-ops when disabled)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-09 19:26:45 +02:00
admin 9a34887acc harden offsite apply-bridge: pin verified host key on the install/verify sessions (no TOFU)
The SSHCopyIDInstaller used StrictHostKeyChecking=accept-new on the ssh-copy-id
and sftp-verify connections, so even though the bridge verifies the box host-key
fingerprint against the hub descriptor BEFORE installing, the actual install
connection was not pinned to that verified key — a MITM could substitute a
different key in the gap between the scan and the install (TOCTOU).

Now the bridge threads the scanner-verified known_hosts line into KeyInstaller,
which writes it to a temp known_hosts and connects with StrictHostKeyChecking=yes
+ UserKnownHostsFile — the install/verify sessions refuse any key but the one the
bridge already matched. Empty known_hosts now refuses to install.

Test asserts the installer receives the pinned known_hosts; red-proofed by passing
an empty line (the pre-fix TOFU shape) → test fails. Addresses the security-review
"host-key TOFU after verify" finding on internal/offsiteapply/seams.go.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-09 19:24:17 +02:00
admin aa61fb3411 v0.106.0: offsite provisioning SLICE 2 — controller apply-bridge
On startup reconcile the hub-served offsite: descriptor into a key-only offbox
target. internal/offsiteapply.Bridge: verify-pin box host key vs host_fingerprint
(NO blind TOFU) → consume the one-time password (single-use, never logged) →
sshpass ssh-copy-id -s -f install + verify → configure offbox → EscrowState=pending
(fork-4 via Manager.ApplyOffsiteTarget) → persist a descriptor-hash marker LAST.
Idempotent + fail-safe. Seams faked in tests; both red-proofs run+reverted.
Dockerfile + sshpass. NOT yet live-applied (supervised end-to-end next runbook).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-09 19:14:14 +02:00
admin fa9362f36f docs: v0.105.0 REPORT — fork-4 custody hand-off + atomicity gate + DR inject; deployed 9201
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-09 15:19:51 +02:00
admin 0b09a799cb v0.105.0: fork-4 offsite password custody — hand-off + atomicity gate + DR inject + coord
Pairs with agent v0.77.0. StageEscrowSecret pushes the repo password to the
agent (POST /escrow/stage-secret) at offsite-enable → EscrowState="pending".
Atomicity gate: RunOffboxBackup (scheduler + handler) refuses until
EscrowState="escrowed" (operator POST /backup/offbox/confirm-escrow after the
escrow ceremony) — no un-recoverable offsite ciphertext can exist. DR:
POST /backup/offbox/inject-password pre-places a recovered 64-hex password 0600
(honored by WriteOffboxSecrets' IsNotExist guard; refuses clobber without
force). DR recipe gains non-secret offsite_restic coords (DRResticCoord); SFTP
key regenerated at DR, not escrowed. New settings.OffboxTarget.EscrowState.
Tests + atomicity & inject companion red-proofs green; UI gates pass. NOT yet
live-validated (supervised ceremony).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-09 15:13:59 +02:00
admin bde43f3a74 docs: v0.104.0 REPORT — offbox discovery + no-silent-success; deployed 9201, red-proofs recorded
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-09 12:35:39 +02:00
admin 908e4b906a v0.104.0: off-box unit discovery (durable, deployment-independent) + no-silent-success
offbox located each toggled app's recovery unit via AppNamespaceRoot→GetAppDrivePath,
which reads the app's LIVE app.yaml HDD_PATH and silently falls back to systemDataPath
when the app isn't deployed → looked on the wrong drive, backed up nothing, reported
ok/0 (DIAG root cause). Now:

- discoverOffboxUnit/offboxCandidateNSRoots scan the durable storage registry
  (schedulable non-decommissioned paths ∪ systemDataPath) for backups/primary/<app>,
  independent of deploy state; newest-by-manifest-CreatedAt wins on drive churn.
- RunOffboxBackup: runOffboxInternal returns (backedUp, missing, err); 0-of-N toggled →
  hard error + operator alert; partial → ok + new OffboxTarget.LastWarning (shown on
  /backups, preserved across config edit).
- AppNamespaceRoot + primary WRITE paths unchanged.
- 6 non-hollow tests (A-E + edge) + both companion red-proofs run (reverted).
- NOT yet live-validated against the Storage Box (spike creds torn down).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-09 12:32:05 +02:00
admin 59eb3bea76 docs: v0.103.0 REPORT + CONTEXT — F-C2-1 config auth-integrity fix, live-validated
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-07 19:08:02 +02:00
admin 02d37a110b fix(config): F-C2-1 — stop os.ExpandEnv corrupting the bcrypt password_hash (v0.103.0)
loadAndParse + LoadFromBytes ran os.ExpandEnv over the whole YAML before parse;
a bcrypt hash ($2a$10$...) is full of $word sequences that get replaced with
empty env values, silently corrupting web.password_hash on load (a silent
auth-integrity bug: $2a$10$N9qo8uL... -> "a0"). Remove both ExpandEnv calls;
parse raw bytes. The typed applyEnvOverrides path (FELHOM_WEB_PASSWORD_HASH) is
the sanctioned env mechanism and is unchanged. Tests + red-proof.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-07 18:34:52 +02:00
admin cd0ebd2042 docs: v0.102.0 REPORT + CONTEXT — async restore family, F4 UX fixed + live-validated
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-06 20:43:11 +02:00