Files
felhom-controller/REPORT.md
T

4.4 KiB

REPORT — most recent implementation

felhom-controller v0.143.0 — guest RAM resize UI (R-24) — 2026-07-17

Baseline: v0.142.0 (f900c83) → v0.143.0 (3286c7f, pushed). MinAgent: 0.90.0 (couples to felhom-agent v0.90.0's /guest/memory). Deployed + LIVE-validated on the nested demo guest.

What shipped

The customer sees the guest's current memory + the allowed range on the Rendszer settings page and resizes it. The controller only proxies + maps the agent's machine code to Hungarian — the agent (felhom-agent v0.90.0) enforces every bound and applies the change live (no reboot). Memory only.

  • agentapi (internal/agentapi/client.go): GuestMemory (GET) + ResizeMemory (POST). A ruled 412 surfaces *MemoryRefusedError (machine code + fresh bounds); a pre-0.90 agent 404s → typed *StatusError.
  • Capability (internal/agentapi/features.go): FeatureGuestMemoryResize + featureMinAgent 0.90.0
    • a featureProbes row. The probe TYPE-ASSERTS the one method it needs (GuestMemory), so the shared SupportProber/netAgent seams and their fakes are untouched (minimal-coupling choice — see Observations).
  • UI (internal/web/system_memory_handlers.go new; templates/settings_system.html): a "Szerver memória (RAM)" card; POST /api/system/memory/resize (mounted /api/system/ in main.go) → capability gate (SupportUnknown passes) → agent → response flash. JS confirm ONLY on a shrink. Code→Hungarian map; agent-outdated hides the control (+"rendszerfrissítése szükséges" note); agent-unreachable falls back to the guest's own /proc/meminfo (control disabled, honest note; the page never 500s).

Tests

  • agentapi: GuestMemory decode + 404-typed; ResizeMemory success + refusal-code (*MemoryRefusedError); capability table (0.89→No / 0.90→Yes via the version fast-path; probe 404→No / ok→Yes).
  • web handler: success maps to the Hungarian old→new line; below_usage_floor maps + the agent's English never leaks; agent_outdated gate refuses with ResizeMemory NEVER called.
  • Gates: template_id_gate + emoji_gate OK. go build/vet/test all pass (23 packages).

Deploy + LIVE validation

Built + pushed felhom-controller:0.143.0; deployed to BOTH demo guests (guest 9201 on felhom-pve AND the nested guest 9201 inside demo-vm-felhom-4846bc) — both Up … (healthy).

LIVE end-to-end through the REAL controller endpoint (login → CSRF → POST) on the nested demo guest — the exact pipeline the settings page drives (no server logic skipped; method: authenticated curl to the controller container, browser bridge unavailable):

GET  /api/system/memory → {"allocated_mb":2890,"usage_mb":181,"host_total_mb":3914,"min_mb":2048,"max_mb":1866,"floor_mb":2048,"running":true}
POST /api/system/memory/resize {memory_mb:5000} → {"code":"above_max"}  "A megengedett maximum 1866 MB (a gazdagép tartaléka miatt)."
POST /api/system/memory/resize {memory_mb:1024} → {"code":"below_min"}  "A minimális memória 2048 MB."

The full chain is proven live: controller auth → capability gate resolving SupportYes via the X-Felhom-Agent-Version=0.90.0 header → agentapi → agent enforcement → machine code → Hungarian mapping (the agent's English is not shown). The lxcfs ripple (guest /proc/meminfo follows a real resize) is Phase-0-proven at the agent layer.

NOT yet live-validated

  • A successful resize through the bounded endpoint could not be shown on the tiny 4 GB nested host: its bounds are degenerate (max_mb 1866 < current 2890) so every target is correctly refused. The successful live cgroup apply (2890→3146→2890, no reboot) is Phase-0-proven at the agent layer (agent REPORT §2). On a normal-sized customer box a grow/shrink will succeed — folds into the rehearsal (S6 gains the resize touch).
  • Full browser click-through of the card (the bridge attaches only to sessions started after it connected).

Observations

  • The featureProbes type-assertion (vs. widening the shared SupportProber) keeps the memory feature from coupling netAgent and every unrelated prober/fake to the memory surface. A prober that can't be asked → a non-404 error → SupportUnknown (fail-open), never a false "supported".
  • The memAgent seam carries NetVerifyStatus + AgentVersion purely to satisfy the shared SupportProber / version fast-path (production *agentapi.Client has them anyway) — the one small wart of reusing the cache.