feat(#2014): hivectl open verb + Urls host request for web surfaces

This commit is contained in:
damocles 2026-06-26 23:13:06 +02:00 committed by mara
commit cae1dd8147
6 changed files with 200 additions and 32 deletions

View file

@ -50,10 +50,13 @@ pub enum HostRequest {
/// Reuses the dashboard's per-agent `ContainerView` aggregation.
AgentStatus,
/// Report this hive's canonical DNS domain
/// (`services.hyperhive.domain`), or `None` when unset. Lets the
/// operator CLI fill in the hive's own identity (e.g. the federation
/// peer-config block) without the operator retyping it.
HiveDomain,
/// (`services.hyperhive.domain`) plus the browser-facing home /
/// forge / matrix URLs, daemon-sourced so custom forge/matrix
/// domains resolve correctly. Each URL is `None` when its subsystem
/// is unreachable from a browser (e.g. forge not behind the gateway,
/// matrix GUI disabled). Backs `hivectl open` + the federation
/// peer-config block (which reads the bare `domain`).
Urls,
/// List pending approval requests.
Pending,
/// Approve a pending request by id; the action runs immediately.
@ -132,6 +135,25 @@ impl LifecycleScope {
}
}
/// This hive's canonical domain plus the browser-facing URLs for its
/// web surfaces — the `Urls` request result. Every field is `None` when
/// the corresponding surface can't be reached from a browser (domain
/// unset, forge not behind the gateway, matrix GUI disabled), so the CLI
/// can give a precise hint instead of opening a dead link.
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct HiveUrls {
/// Canonical hive domain (`services.hyperhive.domain`).
pub domain: Option<String>,
/// Operator dashboard root (`https://<domain>/`).
pub home: Option<String>,
/// Forge browser URL (`HIVE_FORGE_PUBLIC_URL`) — only the
/// behind-gateway public URL; `None` on direct-port forge deploys.
pub forge: Option<String>,
/// Matrix GUI (fluffychat) browser URL — `None` when the matrix GUI
/// is disabled.
pub matrix: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HostResponse {
pub ok: bool,
@ -141,10 +163,10 @@ pub struct HostResponse {
pub agents: Option<Vec<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub approvals: Option<Vec<Approval>>,
/// This hive's canonical DNS domain — `HiveDomain` result. `None`
/// when the domain is unset (no `services.hyperhive.domain`).
/// `Urls` result — this hive's domain plus the browser-facing
/// home / forge / matrix URLs. `None` for every other request kind.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub domain: Option<String>,
pub urls: Option<HiveUrls>,
/// `AgentStatus` result — one row per managed agent with its
/// running/health flags + technical state. `None` for every other
/// request kind.
@ -245,7 +267,7 @@ impl HostResponse {
error: None,
agents: None,
approvals: None,
domain: None,
urls: None,
agent_statuses: None,
}
}
@ -257,7 +279,7 @@ impl HostResponse {
error: Some(message.into()),
agents: None,
approvals: None,
domain: None,
urls: None,
agent_statuses: None,
}
}
@ -269,7 +291,7 @@ impl HostResponse {
error: None,
agents: Some(agents),
approvals: None,
domain: None,
urls: None,
agent_statuses: None,
}
}
@ -281,20 +303,20 @@ impl HostResponse {
error: None,
agents: None,
approvals: Some(approvals),
domain: None,
urls: None,
agent_statuses: None,
}
}
/// `HiveDomain` result — this hive's canonical domain (or `None`).
/// `Urls` result — this hive's domain + browser-facing web URLs.
#[must_use]
pub fn hive_domain(domain: Option<String>) -> Self {
pub fn urls(urls: HiveUrls) -> Self {
Self {
ok: true,
error: None,
agents: None,
approvals: None,
domain,
urls: Some(urls),
agent_statuses: None,
}
}
@ -307,7 +329,7 @@ impl HostResponse {
error: None,
agents: None,
approvals: None,
domain: None,
urls: None,
agent_statuses: Some(rows),
}
}