diff --git a/docs/approvals.md b/docs/approvals.md index 0f92ccfa..ff1ab9c7 100644 --- a/docs/approvals.md +++ b/docs/approvals.md @@ -88,6 +88,55 @@ creates the container; subsequent ones rebuild it with new config. This gives the manager (and operator) an explicit review gate on the initial configuration before any container is created. +### Approval kinds (wire shapes) + +`ApprovalKind` carries five variants; each maps to a different +`commit_ref` encoding because that field is overloaded as the +kind-specific payload carrier. + +- `ApplyCommit` — `commit_ref` is the manager-supplied git sha + (7-40 hex chars). The canonical, hive-c0re-vouched sha after the + proposal fetch lives in `fetched_sha` on the same `Approval` + row (only `ApplyCommit` populates it). See the End-to-end flow + above. +- `Spawn` — direct container creation under the default + `agent.nix` template. `commit_ref` is empty. Submitted via + `HostRequest::RequestSpawn` (operator-gated, the + `◆ R3QU3ST SP4WN` dashboard button + `hive-c0re request-spawn` + CLI). The host-level `HostRequest::Spawn` variant bypasses the + approval queue entirely — privileged-context use only (operator + on the host shell, test scripts, one-off recoveries). The + manager-side `RequestSpawn` is gone; managers go through the + `InitConfig` → `ApplyCommit` two-step instead so the spawn + captures their customised config. +- `InitConfig` — `commit_ref` is empty; the variant just gates + "seed the proposed repo with the default template" against + operator approval. Step 1 of the two-step spawn flow above. +- `UpdateMetaInputs` — `commit_ref` stores the JSON-encoded inputs + array (`"[]"` = all inputs, `"[\"nixpkgs\"]"` = just nixpkgs, + etc.). `agent` field is set to `hm1nd` (the requesting manager). + On approve hive-c0re runs `nix flake update [inputs...]` on the + meta flake and commits the resulting lock changes. +- `SchedulePrompt` — `commit_ref` stores the JSON-encoded + `SchedulePromptPayload` (target list, body, schedule) so the + approval row carries the full submission verbatim. On approve + hive-c0re inserts a row into `scheduled_prompts` with + `source = approval:`; the worker fans the body out as + inbox messages to each target at the scheduled time, recurring + when `interval_seconds` is set. + +### Destroy semantics + +`HostRequest::Destroy { name, purge }` is the lifecycle tear-down, +not an approval. Stops + removes the nspawn container, drops the +systemd drop-in, fails any pending approvals. Persistent state +(proposed/applied repos, claude credentials, `/state/` notes) is +**kept by default** — recreating the agent with the same name +reuses prior config + login. With `purge = true` the agent's +`/var/lib/hyperhive/{agents,applied}//` trees are also +wiped (config history + creds + notes gone forever). The manager +refuses to destroy itself. + ## Meta flake The hive-c0re-owned repo at `/var/lib/hyperhive/meta/` diff --git a/hive-sh4re/src/lib.rs b/hive-sh4re/src/lib.rs index 5162145b..4544b0ad 100644 --- a/hive-sh4re/src/lib.rs +++ b/hive-sh4re/src/lib.rs @@ -14,29 +14,17 @@ pub mod assets; #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(tag = "cmd", rename_all = "snake_case")] pub enum HostRequest { - /// Create and start a sub-agent container directly (no approval). Use - /// this from privileged contexts (operator on the host); it bypasses the - /// approval queue intentionally so test scripts and one-off recoveries - /// don't need a separate approve step. + /// Create and start a sub-agent container directly, bypassing the + /// approval queue. Privileged-context only. See + /// `docs/approvals.md::Approval kinds (wire shapes)`. Spawn { name: String }, - /// Submit a spawn request for the operator to approve. On approval the - /// host creates and starts the container with the default `agent.nix` - /// template. The dashboard's `◆ R3QU3ST SP4WN` button and the - /// `hive-c0re request-spawn` CLI both go through this. The - /// previously-mirrored manager-side `RequestSpawn` was removed - /// (#442) — managers now go through the two-step `request_init_config` - /// and `request_apply_commit` flow so the spawn captures the - /// manager's customised config. + /// Submit a spawn request for the operator to approve. See + /// `docs/approvals.md::Approval kinds (wire shapes)` (`Spawn`). RequestSpawn { name: String }, /// Stop a managed container (graceful). Kill { name: String }, - /// Tear down a sub-agent container: stop + remove + drop the systemd - /// drop-in, purge pending approvals. Persistent state (proposed/applied - /// repos, Claude credentials) is KEPT by default — recreating the agent - /// with the same name reuses prior config + login. With `purge=true` - /// the agent's `/var/lib/hyperhive/{agents,applied}//` trees are - /// also wiped (config history + creds + notes gone forever). Manager - /// not destroyable. + /// Tear down a sub-agent container, optionally purging state. + /// See `docs/approvals.md::Destroy semantics`. Destroy { name: String, #[serde(default)] @@ -74,22 +62,22 @@ pub struct HostResponse { pub approvals: Option>, } +/// One row in the approval queue. `commit_ref` is overloaded per +/// `kind` — see `docs/approvals.md::Approval kinds (wire shapes)` +/// for the encoding table and lifecycle. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Approval { pub id: i64, pub agent: String, #[serde(default)] pub kind: ApprovalKind, - /// For `ApplyCommit`: the git sha the manager submitted. For `Spawn`: - /// empty. Note that this is the manager's *claimed* ref — the - /// canonical, hive-c0re-vouched sha after the proposal fetch lives - /// in `fetched_sha`. + /// Kind-specific payload (git sha / inputs array / schedule + /// payload / empty). See the Approval struct doc. pub commit_ref: String, - /// The sha hive-c0re fetched from the proposed repo into applied at - /// submission time, then tagged `proposal/`. Stable for the - /// lifetime of the approval — manager amends in proposed don't - /// change what gets built. Only set for `ApplyCommit` after the - /// successful fetch. + /// `ApplyCommit` only: the canonical hive-c0re-vouched sha after + /// the proposal fetch, tagged `proposal/`. Stable for the + /// approval's lifetime — manager amends in proposed don't change + /// what gets built. #[serde(default, skip_serializing_if = "Option::is_none")] pub fetched_sha: Option, pub requested_at: i64, @@ -98,44 +86,31 @@ pub struct Approval { pub resolved_at: Option, #[serde(default, skip_serializing_if = "Option::is_none")] pub note: Option, - /// Optional free-text description the manager attached at submission - /// time — shown on the dashboard approval card so the operator can - /// understand the change without opening the diff. + /// Free-text description the manager attached at submission time; + /// shown on the dashboard approval card. #[serde(default, skip_serializing_if = "Option::is_none")] pub description: Option, } /// What action the approval, when granted, will trigger. +/// Variant-specific payload encoding + flow lives in +/// `docs/approvals.md::Approval kinds (wire shapes)`. #[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "snake_case")] pub enum ApprovalKind { - /// Apply a manager-proposed config commit (existing flow). + /// Apply a manager-proposed config commit. #[default] ApplyCommit, - /// Create + start a new sub-agent container with the given name. - /// Used today by the host admin socket / dashboard "request spawn" - /// button; the manager-side `RequestSpawn` surface was removed in - /// favour of the two-step `InitConfig` → `ApplyCommit` flow (#442). + /// Create + start a new sub-agent container with the given name + /// (under the default `agent.nix` template). Spawn, - /// Initialise a new agent's proposed config repo so the manager can - /// customise it before submitting a `request_apply_commit`. On - /// approval hive-c0re seeds `proposed//` with the default - /// `agent.nix` template but does NOT create the container — that - /// requires a subsequent `ApplyCommit` approval pinning the - /// customised config sha. + /// Seed an agent's proposed config repo for manager customisation + /// (step 1 of the two-step spawn flow). InitConfig, /// Run `nix flake update [inputs...]` on the meta flake and commit - /// the resulting lock changes. The `commit_ref` field stores the - /// JSON-encoded inputs array (`"[]"` = all inputs). Agent field is - /// set to `hm1nd` (the requesting manager). + /// the resulting lock changes. UpdateMetaInputs, - /// Add a scheduled prompt (closes #444). On approval hive-c0re - /// inserts a row into `scheduled_prompts` with - /// `source = Approval { id }`; the worker fans the body out as - /// inbox messages to each target at the scheduled time, recurring - /// when `interval_seconds` is set. `commit_ref` stores the - /// JSON-encoded `SchedulePromptPayload` so the approval row carries - /// the full submission verbatim (target list, body, schedule). + /// Add a scheduled prompt to the broker queue. SchedulePrompt, } @@ -146,10 +121,10 @@ pub enum ApprovalStatus { Approved, Denied, Failed, - /// Manager withdrew the request before the operator acted on it - /// (closes #250). Distinct from `Denied` (operator decision) and - /// `Failed` (post-approval lifecycle error) so the dashboard can - /// chip / sort cancellations separately. + /// Manager withdrew the request before the operator acted on it. + /// Distinct from `Denied` (operator decision) and `Failed` + /// (post-approval lifecycle error). See + /// `docs/approvals.md::Withdrawing a pending approval`. Cancelled, }