Commit Graph

337 Commits

Author SHA1 Message Date
admin e8a5bdc492 docs(audit): DIAGNOSE re-enrolled drives not binding after 9201 re-provision
Root cause: controller handleStorageRegister registers the raw /mnt/<name> path
instead of the stable /mnt/felhom-drives/<name> path the agent binds the drive at.
Drives ARE live in guest+container at the stable path; controller watches an empty
rootfs placeholder. Not v0.40.0 mp1; not stale agent state. Read-only diagnosis,
no fix applied. Recommended fix direction documented.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PsnU2ASocYrvzqE82YDYW
2026-06-23 17:15:30 +02:00
admin add5be5bd5 docs(tests): test campaign #3 'NO MERCY' findings (brutal chaos/edge, demo 9201)
7 phases. No silent-corruption, no path-escape/exfil found. Findings: S1 settings.json
crash-loop (medium, no safe-defaults), F2 restore stack_name traversal not validated
upfront (medium defense-in-depth, no escape observed), S3 corrupt quiesce marker silently
ignored (low). All else fail-safe held. Phase4 time-chaos SKIP (unprivileged LXC shares
host clock). No code changes. Demo restored to baseline.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 22:06:00 +02:00
admin 445db9a625 docs(controller): storage doc — v0.75.0 drive-absent userdata MkdirAll gate (1c)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 20:55:10 +02:00
admin e4f49491a3 docs(tests): Finding #1 re-diagnosis — TEST ARTIFACT (docker kill != crash); controller auto-recovers
Read-only diagnosis: restart-manager works (natural-exit probe RestartCount climbs;
manualRestart=false); docker kill is a manual stop so restart is correctly suppressed.
Definitive: kill -9 the controller PID (real crash) -> unless-stopped auto-restarts it,
RestartCount=1 healthy in 5s. Daemon stable (NRestarts=0, no OOM). Finding #1 downgraded
in the campaign-2 doc. Separate minor obs: boot-time drive-ordering race. No fix applied.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 19:35:08 +02:00
admin 58fe93034f docs(tests): test campaign #2 findings (chaos/edge-cases, demo 9201)
Storage lifecycle (unblocked by v0.74.0), break-and-recover C1-C8, backup edge cases.
Headline finding: docker restart-policy not honored -> a crashed felhom-controller has
no automatic recovery (oneshot bootstrap + dead restart policy). Plus disconnect-recreate
race, agent loopback whitelist, carried-forward #1 gaps. Demo restored to baseline.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 19:10:51 +02:00
admin a9ca5b4e68 docs(tests): 8443 unreachability ROOT CAUSE — controller http.Transport leak (read-only diagnosis)
Confirmed H5 (ephemeral-port exhaustion): agentClient() builds a new http.Transport
per call (IdleConnTimeout:0, never CloseIdleConnections) -> ~5.8k leaked idle ESTABLISHED
sockets/day to 162:8443, exhausts the 28k ephemeral range in ~5 days of controller uptime
-> EADDRNOTAVAIL. :8006 immune (controller never dials pveproxy). Cleared by restart.
H1/H2/H3/H4/H6 ruled out with positive evidence. Fix is controller-side (reuse one
Client), NOT an agent rebind. No changes applied.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 17:00:24 +02:00
admin f70c011749 docs(tests): unattended test campaign findings (2026-06-22, demo 9201)
Full-feature validation across the running demo: PBS backup, komga/gitea HC fixes,
deploy sweep, backup+restore, DR rebuild, storage, monitoring/alerts/hub, guest reboot.
Headline finding: controller->agent local-API (8443) unreachable from the controller
container, gating storage UI + host metrics + whole-guest backup.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 16:29:10 +02:00
admin 4a2d72e238 REPORT: hub v0.13.1 DR-recipe v1 drive-shape sync — live-validated assembly, zero secrets
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 20:34:44 +02:00
admin 149a3b092e hub v0.13.1 — DR recipe v1 drive-shape sync (test-data + regression guard only)
Tracks felhom-agent v0.39.0, which dropped role + restic_repo_coord from the host-half
drives[]. Hub reads drives as json.RawMessage (verbatim passthrough) → no store/handler
change needed. Dropped role from the store golden + drHostHalf fixture; re-synced the api
host-report golden byte-identical with the agent copy (it previously lacked dr_recipe
entirely). Added TestAssembleDRRecipe_V1DriveShape regression guard (demonstrated to fail
when the fixture re-adds role, then reverted). No behavior change; redeploy optional.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 20:25:51 +02:00
admin 5f5e3c54a1 hub v0.13.0: DR recipe — assemble + store + view the secret-free reconstruction recipe
DR recipe slice (hub half), grounded in SPIKE-dr-recipe-2026-06-16. The hub
receives two additive dr_recipe halves on the existing report paths (agent
storage/guest/PBS on host-report; controller customer/apps on the controller
report), stores them PLAINTEXT in a DEDICATED dr_recipe table keyed by customer
(each half preserves the other), and AssembleDRRecipe stitches them into one
operator-readable recipe (ignore-unknown + version-skew tolerant).

View: a DR-recipe panel on the customer page + GET /customers/{id}/dr-recipe.json
download (operator-auth, no secrets to redact). Plaintext-at-rest is correct —
the recipe is the clean inverse of the retired infra-backup.

Tests: store round-trip (each half preserves the other), assemble-matches-golden,
ignore-unknown + version skew, partial halves, no-secrets sweep. Manifest tag
bumped to v0.13.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 18:49:45 +02:00
admin 228dac4c06 docs(audit): SPIKE — Phase 2 DR recipe + storage diagnosis (report-only)
Part 0 (live): flash apps on 9201 were down due to an operator pct reboot at
10:26 UTC + a boot-ordering race — dockerd auto-starts unless-stopped flash apps
~18s before the agent re-binds felhom-flash, so the create-time bind mkdir fails
(permission denied) and RestartCount=0 never retries. Drive healthy, data intact,
no USB drop, durable-id fine, drive-gate uninvolved. v0.70.0 self-restart RULED
OUT (container restart, not a guest reboot; +38min after exits). Fix: restarted
the 7 apps via the controller (drive present) — all Up. Flagged the intermediary
mount app-start race as an architectural gap.

Parts 1-3 (cited): characterized escrow (K + identity under recovery code R,
fingerprint-gated, hub zero-knowledge) + PBS whole-CT contents (rootfs/secrets in,
external drives out) + capstone DONE vs PENDING (agent-side recovery orchestration
not wired, syncer.go:92). Defined the secret-free DR recipe (guest sizing + drive
durable-id/role inventory + PVE storage + app bindings + PBS coords), sourced from
facts the agent/controller already hold, landing in the reserved
WireDesiredState.storage_manifest placeholder. Field-by-field boundary proof + a
no-secrets test spec. Fork list + recommendation: spec/emit/store the recipe now,
defer re-enrollment auth to slice 10D, never touch the escrow/PBS secret path.

No code changes, no version bump.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 14:18:39 +02:00
admin 691c0208c5 docs: REPORT.md for hub v0.12.0 infra-backup retirement
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 11:16:11 +02:00
admin 0635640848 hub v0.12.0: retire Infra Backup, purge its plaintext secrets, fix backup-deadline email
Phase-1 of SPIKE-infra-backup-2026-06-15. The infra-backup mechanism was dead
since slice 8C yet stored plaintext customer secrets at rest (app-secret key,
restic password, Cloudflare tokens) — a zero-knowledge violation — and its
absence made the daily expected_backup_missed email fire for healthy customers.

- Repoint monitor.CheckBackupDeadlines backup half to the agent host-report's
  PBS snapshots (+vzdump): alarm only on no-backup / >26h stale / verify failed.
  Keep the db_dump half. No host-report → no backup alarm (liveness owns that).
  New store.GetLatestHostReportJSON. Tests incl. a companion that fails pre-fix.
- Remove the infra-backup endpoints, store methods/types, and operator panel;
  /recovery now returns config_yaml only.
- migrate(): DROP infra_backup_versions/infra_backups + VACUUM (+wal_checkpoint)
  to physically reclaim the plaintext pages, gated on table existence.

Flagged out-of-scope: exposed creds need operator rotation; legacy reports table
holds historical plaintext restic_password rows (separate leak, not purged here).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 11:08:06 +02:00
admin 2f7acb7d07 docs(audit): SPIKE — characterize Infra Backup (revive vs retire)
Report-only audit. Confirms the infra-backup push died at slice 8C
(controller v0.37.0) — builder deleted, PushInfraBackup +
NotifyBackupCompleted left as caller-less stubs; agent never
re-implemented it. Same root cause as the daily deadline-check email
(no backup_completed emitter). Live hub records inspected read-only:
plaintext secrets at rest (AES master key + restic pw + Cloudflare
tokens) = zero-knowledge violation; disk_layout is bare-metal-era.
Recommends phased retire-now / revive-concept-later (secret-free DR
recipe) + fork list. No code changes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 10:04:55 +02:00
admin d105657355 docs: M3 live re-verification addendum (closes E14/E15 residual) + two controller UI fixes
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 21:53:10 +02:00
admin 9ee929ba6d docs(audit): storage lifecycle completion + acceptance sweep (incl. live host reboot)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 20:42:21 +02:00
admin f1df01b5c5 docs(spike): stable intermediary mount — swap drive underneath (C1-immune, no-restart)
Live-validated on demo guest 9201 (felhom-flash throwaway): shared/slave mount
propagation delivers host->guest drive swaps live with no restart and no pct
change; bind source = permanent stable dir => inherently C1-immune (clean boot
with drive absent). nsenter fallback non-viable on unprivileged LXC; ro-tmpfs
placeholder is the CAP_DAC_OVERRIDE-proof fail-close. Report-only, no code change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 15:26:37 +02:00
admin 4fe77fcd1b docs: B3 live storage-lifecycle exercise + feature sweep (2026-06-15)
Live unattended UI exercise of migration/decommission/re-enroll/eject +
feature sweep on shipped controller v0.66.2 / agent v0.32.0 (guest 9201).
No production code changed.

Migration engine solid (all moves checksum-verified identical, sources
cleaned, HDD_PATH flipped, apps healthy). Lifecycle gaps found:
- C1 (critical): decommission/eject leave a stale LXC mp (no pct delete)
  -> guest fails pre-start hook on next reboot, ALL apps down. Recovered
  live via pct set --delete mp1.
- H1: /api/storage/{disconnect,reconnect,restart-apps} are 404 (unrouted)
  though settings.js calls them.
- H2: no UI button for /api/storage/decommission.
- H3: no one-click re-enroll for a decommissioned drive.
- M1: decommissioning the default drive doesn't reassign the default.
- M2: eject does NOT auto-remount (intent-gated like decommission).
- M3: userdata/import/calibre created 755 at enroll; migrate-all doesn't
  re-assert setgid on pre-existing dirs (16/17 preserved 2775).
- M4: felhom-usb mount unit had stale UUID; M6: test-email fails (no SMTP).

End-state sane: apps healthy on felhom-flash (now default), both data
drives Aktiv, reboot-safe, sda/PBS/controller untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 12:39:44 +02:00
admin f24125ecdd docs: SPIKE raw-drive plug-and-enroll (GATE, 2026-06-15)
Report-only spike + one live throwaway FORMAT experiment on /dev/sdc.
No production code, no version bump.

- Q1: raw-disk discovery gap confirmed — Observe AND localapi GET /disks
  are both built only from PVE storages (ListStorage/NodeStorage); a
  not-yet-storage disk is invisible. proxmox client has no /disks/* method.
- Q3: safety classifier (RoleForRawDevice/SystemDisks/RoleForStorage)
  already protects sda/felhom-pbs live, but needs two hardening checks:
  whole-disk-granularity enrolled-subtraction + LVM-PV membership.
- Q6: FORMAT path proven end-to-end live — pvesh disks/directory create
  -> agent Observe -> controller "Regisztralas" enroll. sdc left as the
  clean enrolled felhom-flash B3 migration target. sda/sdb untouched.
- Premise correction: felhom-pbs is remote (no local PBS disk).
- Fork list for the build spec in the audit doc + REPORT.md.
2026-06-15 10:57:33 +02:00
admin ee3efb0fae docs(claude): note Claude-in-Chrome browser automation for live validation
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 08:50:49 +02:00
admin ebf3c0cbea docs(spike): userdata/ layout + shared-storage ownership mapping (report-only gate)
Maps current namespace dir creation/ownership (live on 9201), the 9-app/13-mount
media blast radius, run-identity table (FileBrowser=uid1000, komga/audiobookshelf=root),
LXC idmap, and proposes the setgid GID-1000 convention. Flags: MigrateAll's merge walk
drops setgid+owner on userdata. Ends with a 7-item fork list. No code/deploy.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 21:15:24 +02:00
admin 45052da4dc docs(spike): bake in locked fork decisions (B0 gate cleared)
1) keep operator-signed decommission; 2) Q4 both — intent-aware
ReassertGuestBinds load-bearing/sufficient, GuestBindStore.Remove hygiene
(re-commission re-Records via recordGuestBind, B2 to state); 3) data move
= controller via rsync copy-verify-remove (not cp -a); 4) decommission
role-gated unmount. Gate cleared; B1/B2 may proceed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 18:14:08 +02:00
admin 326aa1ca17 docs(spike): decommission/migration feasibility (TASK B0)
Report-only feasibility spike: data-move layer (controller, proven live),
vestigial migrate button, self-serve POST /disks/decommission design,
re-bind gap (intent-unaware ReassertGuestBinds + no GuestBindStore.Remove),
soft-marker registry. Gates B1/B2.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 17:52:26 +02:00
admin b5a961477d docs(f9): reject recommendation #1 auto-register-on-attach (A3)
Contradicts the new->enrolled manual-enrollment model; manual enroll is
by design. The additive-discovery sub-point was adopted (controller
v0.64.0 A1) but only for paths deployed apps reference, not auto-register
of agent-attached drives.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 17:33:33 +02:00
admin 1fd6e1a22f docs(diagnosis): post-F9 storage-registration gap (read-only diagnosis, no fix)
HDD attached at the agent layer (F9 bind) but never entered the controller storage
registry: enroll/register flows (runStorageInit/runStorageAttach/handleStorageRegister)
are the only paths that call registerStoragePath, and F9 attached via the agent directly;
AutoDiscoverStoragePaths is a one-time seed scanning only deployed-app HDD_PATHs. So the
HDD is 'Nem regisztrált' + absent from the deploy dropdown (GetSchedulableStoragePaths).
Verdict: F9 NOT closed. Fix direction: auto-register-on-attach + clearer manual register.
2026-06-14 16:04:36 +02:00
admin c1c8fe2a7d docs: F9/F20-BUG2/F20-BUG3 FIXED (agent v0.31.0, live-validated); queue golden controller-tag follow-up 2026-06-14 15:43:07 +02:00
admin 98fa8b299a docs(backlog): mark M18 + M19 FIXED in controller v0.62.0
M18 (dump re-validation perf) @ f8afe5c and M19 (deriveStackName misattribution) @
6bab68b implemented trunk-based on controller main with regression tests + deployed.
Notes retained for provenance.
2026-06-14 14:17:59 +02:00
admin 751941ca6a docs(audits/backlog): preserve live-drive findings+fixspec and M18/M19 fix-plans
Relocates the 2026-06-14 live-drive findings + fixspec from the felhom-controller
repo root into documentation/audits/ (alongside the bughunt-reconcile/deep-sweep
records), and preserves the M18/M19 implementable fix-plans (from the deleted
controller fix/m18 + fix/m19 branches) into a new documentation/backlog/. Part of
the trunk-based no-branches reconciliation.
2026-06-14 11:00:26 +02:00
admin 4c0eb2f5d4 docs: close doc-gaps (hub v0.11.0, onlyoffice:nextcloud occ internals, metricsDBPath verified)
- 05-hub-architecture.md: stale 'felhom-hub v0.6.3' -> v0.11.0 (design-draft note).
- auth-hub-sync-integrations.md: full onlyoffice:nextcloud occ command sequence.
- storage-monitoring-metrics.md: metricsDBPath verified to coincide with the volume-backed
  data_dir on the bootstrap guest (persists; hardcoding is latent fragility only).
- REORG-NOTES: gaps 2/3 CLOSED, gap 5 partially closed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 23:10:04 +02:00
admin 280781115d docs(audits): AGENT-001 -> MERGED + DEPLOYED (agent v0.30.0)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 22:32:23 +02:00
admin e68fe3eb19 docs(reorg-notes): correct controller/README handling (banner, not full slim)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 19:42:50 +02:00
admin 21d0e7cf4c docs: centralize controller documentation + top-level index (code-verified, v0.59.0)
New documentation/controller/ subtree (module map + deploy/stack-lifecycle, backup,
storage/monitoring/metrics, auth/hub/sync/integrations) grounded in current source;
top-level documentation/README.md index across controller/agent/platform/hub/audits;
REORG-NOTES with the verification ledger + flagged doc-gaps. Supersedes (keeps) the
v0.33 controller planning map. Additive only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 19:40:25 +02:00
admin 4320c01915 docs(audits): authoritative remediation records (deep-sweep + bughunt-reconcile)
Brings the 2026-06-13 audit + reconciliation under documentation/audits/ with
per-finding remediation status (controller v0.59.0 fixes deployed to demo;
AGENT-001 fix prepared/pending review).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 19:28:25 +02:00
admin d59691dd82 deploy: hub v0.11.0 (slice 10D DR capstone)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 09:50:33 +02:00
admin 3457415117 slice 10D (hub): DR capstone — recovery mode + re-enroll + directive serving (hub v0.11.0)
Recovery-mode toggle (global key, bounded auto-expiry) gates re-enroll +
restore-directive serving. Re-enroll rotates the agent<->hub credential to the
new box (old key revoked); returns the opaque escrow blobs + non-secret
directive. Store gains recovery_mode_until + identity_blob + directive_json.
Hub holds no usable secret + no Cloudflare write-power (operator-side rotation).
Doc 03 §9: slice 10 CLOSED.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 09:48:38 +02:00
admin a22b87e6e3 docs: slice 10D core spike findings (identity-escrow + tunnel re-establishment) — GO
Validated both unvalidated 10D mechanisms: (1) identity-bundle escrow round-trip
via age scrypt+AEAD (recover on a secret-less box, wrong-R fails closed), (2)
Cloudflare tunnel re-establishment — running the recovered token on a new box
routes the hostname there immediately (no DNS change); the old connector is a
hot standby, superseded in routing but not auto-retired -> 10D must rotate the
tunnel/PBS token + retire the stale connector for host-loss security. Redacted;
secrets shredded; live demo untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 23:17:53 +02:00
admin a98210ae00 docs: slice 10C escrow consumption productionized (doc 03 §8a/§9)
Agent-only implementation (felhom-agent v0.17.0 escrow.Consume); no hub code
change. 10C done; 10D is the last piece of slice 10.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 22:18:10 +02:00
admin 680b1592c5 deploy: hub v0.10.0 (slice 10B signed-op job completion)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 20:24:42 +02:00
admin 0c843286a2 slice 10B: signed-op job completion (DELETE clear-job) (hub v0.10.0)
Add DELETE /hosts/{id}/jobs/{job_id} (per-host self-scoped, idempotent) so the
agent clears a job after executing or terminally rejecting it. The hub stores
the operator-signed blobs opaquely (no signing key — cannot forge or open);
the agent verifies + executes. Doc 03 §4/§6/§9 updated (operator-signed path
live; 8C wipe completes; 10B done).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 20:14:32 +02:00
admin 8c54775b6f deploy: hub v0.9.0 (slice 10A desired-state serving)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 19:07:49 +02:00
admin e54f882e70 slice 10A: hub desired-state serving + signed-jobs queue (Down channel) (hub v0.9.0)
Serve operator intent to authenticated hosts: PUT /admin/hosts/{id}/desired-state
(global key) bumps desired_generation; GET /hosts/{id}/desired-state + /jobs are
per-host self-scoped; the host-report envelope now carries the real generation +
has_signed_ops. New signed_jobs table + store methods. Desired-state stored/served
opaquely (agent owns the schema). Cross-repo golden (envelope + desired-state)
byte-identical with felhom-agent; doc 03 §4/§9 updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 19:03:14 +02:00
admin f9af3243b9 docs: slice 10C escrow-consumption spike findings (GO)
Validated escrow consumption end-to-end on a genuinely key-less box against
the real felhom-spike datastore: recover K from (blob,R) via the real
escrow.Unwrap, restore REAL data (spike-lxc rootfs, 2.5G) with the recovered
key only, wrong-R fails closed (no plausible-but-wrong key), live K
byte-unchanged. Redacted (no R/K/secret). GO to spec 10C + build 10D.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 17:10:31 +02:00
admin 4590fc0ee0 slice 9 docs + wire-contract: host.cpu_temp_c golden + doc 03 GET /host/metrics
Update the cross-repo host-report golden byte-identical with felhom-agent
(host.cpu_temp_c). Document GET /host/metrics in doc 03 section 6 and define
slice 9 in the section 9 roadmap. No hub code change / no version bump.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 16:16:38 +02:00
admin 5dc363771b doc 03 §8/§9: slice 8B.2 implemented — resume at snapshotted (downtime ~24s->~3s) (2026-06-10)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 15:02:14 +02:00
admin c6dd0ed505 doc 03 §6/§4/§9 + doc 02: slice 8C implemented — controller de-privileged, slice 8 CLOSED (2026-06-10)
§6: disk-management endpoints + reframed principle (non-data-destructive
self-serve; data-destructive stays operator-signed; classifier = agent-internal
device inspection). §4: data-bearing-ness is agent-internal, never caller-claimed.
§9: 8C implemented, slice 8 CLOSED. doc 02: EXECUTED banner. Validated live
(data-bearing format refused; de-privileged controller).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 14:06:55 +02:00
admin d1a3cd0625 doc 03: slice 8B implemented — §8 controller-driven quiesce, §9 table, changelog (2026-06-10)
§8: controller-driven quiesce (stop stacks -> POST /backup -> restart) implemented
(controller v0.36.0 internal/quiesce + agent v0.11.0 cadence/phases); crash-safety
centerpiece + 8B.2 snapshot-mode fast-follow documented. Validated live: quiesced
postgres restore clean vs crash-consistent WAL recovery. §9 table: 8B implemented.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 11:04:36 +02:00
admin e436b61368 doc 03: slice 8A implemented — §6a local-API impl, §9 back-half row, §13 (2026-06-10)
§6a (new): the local-API implementation — stable leaf-SHA-256 pin, token->guest
self-scoping (cross-guest 403), bootstrap.json contract + controller ingestion
(c), baked-controller deploy (no registry cred in guest), firewall narrowing.
§9 slice table: back-half = slice 8A implemented (8B quiesce / 8C de-priv split
out); build-golden.sh bakes the controller. §13 + doc changelog.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 10:02:11 +02:00
admin 4a81a96678 slice 8A spike: agent<->controller channel + controller deploy plumbing findings
Doc-only spike (no hub code change). Validated on demo-felhom (guest 8200,
torn down): (1) guest->host HTTPS over vmbr0 with fingerprint-pin + bearer +
self-scoping (200/401/403, wrong-pin TLS fail, no firewall rule needed);
(2) config-mount + golden-baked bootstrap unit deploys+runs the controller
(docker login/pull/run v0.34.0) with no pct exec. Verdict: GO to 8A spec.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 08:57:48 +02:00
admin a500889b00 deploy: hub v0.8.0 (opaque escrow storage)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 07:47:59 +02:00
admin 7eb3772000 hub: opaque PBS recovery-code escrow storage (v0.8.0) + doc 03 §8a posture model
Slice-7 close-out (hub half). PUT /api/v1/hosts/{host_id}/escrow (per-host key)
stores the agent's OPAQUE R-wrapped blob verbatim against the host; the hub never
decrypts it (no recovery code, no decrypt path). host_escrow table + Save/GetHostEscrow.
Tests: verbatim store, rotation last-write-wins, 401/403/400 auth+body, wire contract.

doc 03 §8a rewritten into the key-custody posture model: separation principle,
topology matrix, default + anti-lockout ladder, SSH-vs-key, breach/legal, integrity
caveat. Corrected: hub opaque storage is slice 7 (this task); serving is slice 10.
Slice table + §13 updated.

No secrets committed (R/K never appear; spike findings + docs use placeholders).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 07:46:33 +02:00