fix(settings): align agent-fetcher config to the VS-37 wire contract #44

Merged
David merged 1 commit from fix/vapp-agent-fetcher-settings-contract into main 2026-06-21 16:50:44 +02:00
Owner

Problem

Clicking the agent download button in "+ New Device" 404s, and the Settings "Agent binaries" card shows "no settingsget reply from vervain-server (the action may require admin rights)". This is not a VERVAIN_SERVER_URL problem - the control channel connects and the site-admin gate passes.

Root cause: the card and the download were written against an assumed VS-37 settings-overlay contract (there's a comment admitting it) that didn't match what vervain-server shipped, so an admin can neither read nor save the agentbinaryfetcher config. The fetcher stays unconfigured, and vervain-server returns 404 from /vervainagents/<id> when no fetcher is configured (crates/vervain-web/src/lib.rs:1257,1309), so every download 404s.

What was wrong (verified against the live server source)

  • Read: apps sent {"action":"settingsget"}, but SettingsGet { section: String } (user_session.rs:1212) requires a section. The request couldn't deserialize, no reply came, and the card timed out.
  • Write: apps sent {"action":"settingsupdate","key":"agentbinaryfetcher",...}, but the server wants the field section (not key), a value block with the source type discriminant (forgejo/http), and acks a success result of ok:installed=N,failed=M / saved:refresh-failed:<e> (settings_overlay.rs:215-227), not the bare "ok" the apps request_ack required.

Fix (apps-side, src/server_fns/mod.rs + model docs)

  • get_agent_fetcher_config: send section: "agentbinaryfetcher"; read the block from the reply's data.
  • update_agent_fetcher_config: send section (not key) with type: "forgejo" in the value; accept ok:/saved: ack prefixes as success, map not-authorized / error:<msg> to the inline error.
  • parse_fetcher_config: derive enabled from a configured source (no server enable flag) and token_set from the redacted __redacted__ token.
  • Reword the stale "assumed contract" comment and the AgentFetcher* model docs to the pinned contract.

After this, an admin can configure the Forgejo fetcher in Settings; the server fetches the binaries on save (settingsupdate runs refresh_now), and the download serves instead of 404ing.

Known follow-up

Preserving an already-stored token across an edit that blanks the token field needs the server's __redacted__ echo-back; omit-on-blank (correct for first-time config) is kept here and the refinement is documented on AgentFetcherUpdate.

Verification

just check passes: fmt, clippy, server build, wasm build, 21 unit tests.

Closes VAPP-32.

## Problem Clicking the agent download button in "+ New Device" 404s, and the Settings "Agent binaries" card shows "no settingsget reply from vervain-server (the action may require admin rights)". This is **not** a `VERVAIN_SERVER_URL` problem - the control channel connects and the site-admin gate passes. Root cause: the card and the download were written against an **assumed** VS-37 settings-overlay contract (there's a comment admitting it) that didn't match what vervain-server shipped, so an admin can neither read nor save the `agentbinaryfetcher` config. The fetcher stays unconfigured, and vervain-server returns 404 from `/vervainagents/<id>` when no fetcher is configured (`crates/vervain-web/src/lib.rs:1257,1309`), so every download 404s. ## What was wrong (verified against the live server source) - **Read:** apps sent `{"action":"settingsget"}`, but `SettingsGet { section: String }` (`user_session.rs:1212`) requires a `section`. The request couldn't deserialize, no reply came, and the card timed out. - **Write:** apps sent `{"action":"settingsupdate","key":"agentbinaryfetcher",...}`, but the server wants the field `section` (not `key`), a `value` block with the source `type` discriminant (`forgejo`/`http`), and acks a success `result` of `ok:installed=N,failed=M` / `saved:refresh-failed:<e>` (`settings_overlay.rs:215-227`), not the bare `"ok"` the apps `request_ack` required. ## Fix (apps-side, `src/server_fns/mod.rs` + model docs) - `get_agent_fetcher_config`: send `section: "agentbinaryfetcher"`; read the block from the reply's `data`. - `update_agent_fetcher_config`: send `section` (not `key`) with `type: "forgejo"` in the value; accept `ok:`/`saved:` ack prefixes as success, map `not-authorized` / `error:<msg>` to the inline error. - `parse_fetcher_config`: derive `enabled` from a configured source (no server enable flag) and `token_set` from the redacted `__redacted__` token. - Reword the stale "assumed contract" comment and the `AgentFetcher*` model docs to the pinned contract. After this, an admin can configure the Forgejo fetcher in Settings; the server fetches the binaries on save (`settingsupdate` runs `refresh_now`), and the download serves instead of 404ing. ## Known follow-up Preserving an already-stored token across an edit that blanks the token field needs the server's `__redacted__` echo-back; omit-on-blank (correct for first-time config) is kept here and the refinement is documented on `AgentFetcherUpdate`. ## Verification `just check` passes: fmt, clippy, server build, wasm build, 21 unit tests. Closes VAPP-32.
fix(settings): align agent-fetcher config to the VS-37 wire contract
All checks were successful
Check / fmt + clippy + build + tests (pull_request) Successful in 2m26s
Create release / Create release from merged PR (pull_request) Has been skipped
ab602d3cda
The Settings "Agent binaries" card and the agent download were written against an assumed VS-37 settings-overlay contract that did not match what vervain-server shipped, so an admin could neither read nor save the `agentbinaryfetcher` config. The fetcher stayed unconfigured, and vervain-server returns 404 from `/vervainagents/<id>` when no fetcher is configured, so every agent download 404'd. It was never a `VERVAIN_SERVER_URL` problem: the control channel connects and the site-admin gate passes.

Read: `get_agent_fetcher_config` now sends the required `section: "agentbinaryfetcher"` on `settingsget` (the server's `SettingsGet` requires it, so the old request got no reply and the card showed "no settingsget reply") and reads the block from the reply's `data` field.

Write: `update_agent_fetcher_config` now sends `section` (not `key`) and includes the `type: "forgejo"` source discriminant the server validates against, and accepts the ack `result` prefixes `ok:` (applied and re-fetched) and `saved:` (saved, live re-fetch failed) as success instead of requiring a bare `"ok"`, mapping `not-authorized` / `error:<msg>` to the inline error.

`parse_fetcher_config` derives `enabled` from a configured source (the server has no enable flag) and `token_set` from the redacted `__redacted__` token sentinel. Stale "assumed contract" comment and `AgentFetcher*` model docs updated to the pinned contract.

Token preservation across an edit that blanks the token field is deferred (documented on `AgentFetcherUpdate`); omit-on-blank is correct for first-time configuration.

just check passes: fmt, clippy, server + wasm builds, 21 tests.

#VAPP-32
David merged commit 67858b5e6e into main 2026-06-21 16:50:44 +02:00
David deleted branch fix/vapp-agent-fetcher-settings-contract 2026-06-21 16:50:44 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/vervain-apps!44
No description provided.