extra-forges: fully dashboard-provisioned, no host config

Per mara's feedback on PR #2407 ("better: you can also provide url in
dashboard, same as with matrix, no host config"), drops
services.hyperhive.extraForges and the admin-API mint/revoke flow
entirely. The operator now creates a token on the external forge
themselves and pastes a label + base URL + access token into the
dashboard's FORGES tab, the same shape as the GitHub PAT flow plus the
base-URL field from the matrix extra-account flow. hive-c0re only ever
writes/deletes two local files per account (forge-<label>-token,
forge-<label>.json sidecar for the URL) via hive-priv — no remote
account creation, no admin token, no revoke-on-the-remote-side, no nix
config to enumerate.

- nix/host-modules/hive-forge/default.nix: removed the extraForges
  option, its label-format assertion, and the HYPERHIVE_EXTRA_FORGES
  env forwarding.
- hive-c0re/src/forge/extra.rs: deleted (REST admin-API provisioning,
  no longer needed).
- hive-c0re/src/dashboard/extra_forges.rs: GET /api/extra-forges?
  agent= lists an agent's stored forges by scanning its state dir
  (mirrors matrix_accounts.rs's filename-scan listing), POST
  /api/extra-forge-account (agent/label/base_url/token/
  action=add|remove) stores or removes an account.
- hive-sh4re/priv_proto.rs + hive-priv/main.rs: new
  WriteAgentExtraForgeAccount/DeleteAgentExtraForgeAccount priv
  requests (adds base_url, writes/deletes a JSON sidecar alongside the
  token).
- hive-c0re/src/priv_client.rs: matching wrapper functions.
- frontend/packages/dashboard/src/credentials.{html,js}: FORGES tab is
  a per-agent list + add-account paste form (label/base_url/token), no
  grant/revoke-from-catalog UI.
- docs/web-ui/dashboard.md: FORGES tab section rewritten.

Supersedes the design in PR #2407 (already approved+green on the old
admin-API model) — opening as a fresh PR against the same issues
rather than force-pushing over the approved one.
This commit is contained in:
iris 2026-07-14 18:11:47 +02:00 committed by mara
commit dbf880ac66
10 changed files with 558 additions and 2 deletions

View file

@ -427,6 +427,45 @@ pub enum PrivRequest {
token: String,
},
/// Write a per-agent account for an external, dashboard-declared forge:
/// the access token to
/// `AGENT_STATE_ROOT/<agent_name>/state/forge-<label>-token` (0600) and
/// a `forge-<label>.json` sidecar (`{"base_url": <base_url>}`, 0600) so
/// the base URL survives without any host-side nix config — the whole
/// account (label + URL + token) is operator-entered on the dashboard,
/// same shape as `WriteAgentMatrixToken`'s homeserver sidecar.
///
/// `label` MUST be validated as a plain identifier (same rule as the
/// matrix `account` suffix) before it goes into the filename — a
/// crafted label could otherwise traverse out of the state dir. Same
/// write semantics as `WriteAgentForgeToken` — validates `agent_name`,
/// creates the state dir if absent, writes both files 0600, chowns to
/// the agent.
WriteAgentExtraForgeAccount {
/// Logical agent name (validated by `validate_agent_name`).
agent_name: String,
/// Dashboard-chosen label for this external forge. Validated as a
/// plain identifier before use.
label: String,
/// Base HTTP(S) URL of the external forge, operator-entered on the
/// dashboard (no host-side config).
base_url: String,
/// Token value. hive-priv appends a trailing newline before writing.
token: String,
},
/// Remove a previously-written `forge-<label>-token` + `forge-<label>.
/// json` from an agent's state dir — the revoke half of
/// `WriteAgentExtraForgeAccount`. Missing files are not an error
/// (idempotent revoke).
DeleteAgentExtraForgeAccount {
/// Logical agent name (validated by `validate_agent_name`).
agent_name: String,
/// The forge label to revoke. Validated as a plain identifier
/// before use.
label: String,
},
/// Restart `hive-matrix-daemon.service` inside an agent container via
/// `systemctl --machine=h-<agent_name> restart hive-matrix-daemon.service`.
/// Used by hive-c0re to kick the daemon after a successful token write