docs(#2627): add READMEs for the remaining infra crates
Second increment of the per-crate README effort, covering the rest of the infra/wire/priv column: hive-priv, hive-metric, hive-types, hive-sh4re, hive-core-agent-sock, hive-agent-sock. Same shape as the first batch — purpose + when-to-use, and point at the crate-root //! docs plus the relevant docs/ pages rather than duplicating them. Wires readme = "README.md" into each Cargo.toml [package]. Disjoint from the batch-1 crates, so the two increments compose cleanly.
This commit is contained in:
parent
4017a57350
commit
bbfc578c95
12 changed files with 162 additions and 0 deletions
|
|
@ -2,6 +2,7 @@
|
||||||
name = "hive-agent-sock"
|
name = "hive-agent-sock"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
|
readme = "README.md"
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
|
||||||
26
hive-agent-sock/README.md
Normal file
26
hive-agent-sock/README.md
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
# hive-agent-sock
|
||||||
|
|
||||||
|
Wire types for the **in-agent socket** — the one the `hive-agent` harness serves
|
||||||
|
*inside* the container to its local producers (the matrix / bash MCP daemons and
|
||||||
|
`forge_notify`). Unlike the host-served sockets, this one **never leaves the
|
||||||
|
container**.
|
||||||
|
|
||||||
|
## What it carries
|
||||||
|
|
||||||
|
- the loose-ends-v2 **todo** op family
|
||||||
|
- the harness-local **reminder** op family
|
||||||
|
|
||||||
|
More in-agent request families may be added over time — the socket is
|
||||||
|
deliberately named for the agent, not for the todos.
|
||||||
|
|
||||||
|
## Why in-container
|
||||||
|
|
||||||
|
The harness owns the todo + reminder stores locally and signals its own turn
|
||||||
|
loop directly, so `hive-c0re` is not in either path: no broker round-trip, no
|
||||||
|
long-poll, no marker files. That locality is the point — it's also what lets
|
||||||
|
these stores travel with the agent for hive portability.
|
||||||
|
|
||||||
|
## Not to be confused with `hive-core-agent-sock`
|
||||||
|
|
||||||
|
That crate is the *host*-served core↔agent protocol on `/run/hive/mcp.sock`
|
||||||
|
(the harness talking out to `hive-c0re`). This socket is purely intra-container.
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
name = "hive-core-agent-sock"
|
name = "hive-core-agent-sock"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
|
readme = "README.md"
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
|
||||||
21
hive-core-agent-sock/README.md
Normal file
21
hive-core-agent-sock/README.md
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
# hive-core-agent-sock
|
||||||
|
|
||||||
|
Wire types for the **per-agent + manager socket** (`/run/hive/mcp.sock`) — the
|
||||||
|
unified `Request` / `Response` protocol spoken between an agent's in-container
|
||||||
|
harness (and the manager) and the `hive-c0re` daemon.
|
||||||
|
|
||||||
|
## Why it's its own crate
|
||||||
|
|
||||||
|
Re-homed out of `hive-sh4re` so this one socket owns its protocol crate,
|
||||||
|
mirroring the `hive-host-sock` / `hive-priv-sock` splits. The shared payload
|
||||||
|
types it references (`Message`, `LooseEnd`, `Approval`, …) stay in `hive-sh4re`,
|
||||||
|
which this crate depends on — this crate is just the request/response envelope
|
||||||
|
for this socket.
|
||||||
|
|
||||||
|
## Not to be confused with `hive-agent-sock`
|
||||||
|
|
||||||
|
This is the **host-served** protocol: the harness talks *out* to `hive-c0re`
|
||||||
|
over `/run/hive/mcp.sock` (broker sends, approvals, questions, lifecycle).
|
||||||
|
`hive-agent-sock` is the separate *in-container* socket the harness serves to
|
||||||
|
its own local producers — that one never leaves the container. See
|
||||||
|
`docs/boundary.md` for the socket topology.
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
[package]
|
[package]
|
||||||
name = "hive-metric"
|
name = "hive-metric"
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
|
readme = "README.md"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
|
|
||||||
26
hive-metric/README.md
Normal file
26
hive-metric/README.md
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
# hive-metric
|
||||||
|
|
||||||
|
A tiny CLI that pushes **a single labeled metric** to the OTEL collector, then
|
||||||
|
exits. Built on the OpenTelemetry Rust SDK with the OTLP HTTP/JSON exporter.
|
||||||
|
|
||||||
|
## When to use it
|
||||||
|
|
||||||
|
For emitting a one-off counter or gauge from a shell script or systemd unit
|
||||||
|
without embedding an OTEL SDK in the caller — the harness and various hive
|
||||||
|
scripts use it to record per-agent metrics.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```text
|
||||||
|
hive-metric <name> <value> [--type counter|gauge] [--labels key=value ...]
|
||||||
|
```
|
||||||
|
|
||||||
|
Standard OTEL environment variables are read automatically by the SDK:
|
||||||
|
|
||||||
|
- `OTEL_EXPORTER_OTLP_ENDPOINT` — collector URL (**required**)
|
||||||
|
- `OTEL_EXPORTER_OTLP_HEADERS` — auth headers (`Key=Value,...`)
|
||||||
|
- `OTEL_RESOURCE_ATTRIBUTES` — resource labels (`k=v,...`)
|
||||||
|
|
||||||
|
The harness populates all of these per-agent when
|
||||||
|
`services.hyperhive.otel.enable = true`. See `docs/observability.md` for the
|
||||||
|
collector setup and the metrics hyperhive exports.
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
name = "hive-priv"
|
name = "hive-priv"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
|
readme = "README.md"
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
|
||||||
32
hive-priv/README.md
Normal file
32
hive-priv/README.md
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
# hive-priv
|
||||||
|
|
||||||
|
The minimal **root privileged-helper** for hive-c0re. It runs as root and
|
||||||
|
exposes a narrow unix socket at `/run/hive/priv.sock` that accepts `PrivRequest`
|
||||||
|
JSON lines and performs only the handful of operations that genuinely require
|
||||||
|
root — bind-mount edits, `nsenter` into a container, btrfs subvolume ops. All
|
||||||
|
coordination logic (broker, HTTP, scheduling) stays in the *unprivileged*
|
||||||
|
`hive-c0re` process, which delegates here.
|
||||||
|
|
||||||
|
## Why it exists
|
||||||
|
|
||||||
|
Privsep. `hive-c0re` runs as the unprivileged `hive-core` user so a bug or a
|
||||||
|
prompt-injection in the large daemon can't directly wield root. The few root
|
||||||
|
operations it needs are funnelled through this small, auditable helper instead.
|
||||||
|
See `docs/boundary.md` and `docs/security.md` for the privilege boundary.
|
||||||
|
|
||||||
|
## Security model
|
||||||
|
|
||||||
|
- **Strict allowlist.** Every request is validated against a container-name
|
||||||
|
allowlist before any filesystem or process operation — only names matching the
|
||||||
|
hive convention (`h-*`, the manager container, known sibling service
|
||||||
|
containers) are accepted.
|
||||||
|
- **No pass-through.** Every `PrivRequest` variant maps to a single known
|
||||||
|
operation; there is no arbitrary-command escape hatch.
|
||||||
|
- **Socket-activated, always.** systemd binds `/run/hive/priv.sock`
|
||||||
|
(`SocketGroup=hive-core`, `0660`) and passes the listener as fd 3
|
||||||
|
(`LISTEN_FDS`); the helper requires this and has no self-bind fallback, so dev
|
||||||
|
and prod take the identical path and the group grant always holds.
|
||||||
|
|
||||||
|
The wire contract (`PrivRequest` / response types) lives in the separate
|
||||||
|
`hive-priv-sock` crate so this root binary depends on just the protocol shapes,
|
||||||
|
not the whole daemon-shared crate.
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
name = "hive-sh4re"
|
name = "hive-sh4re"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
|
readme = "README.md"
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
|
||||||
33
hive-sh4re/README.md
Normal file
33
hive-sh4re/README.md
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
# hive-sh4re
|
||||||
|
|
||||||
|
The **shared wire types** between `hive-c0re` and the in-container harness — the
|
||||||
|
common vocabulary (`Message`, `Approval`, `LooseEnd`, `HelperEvent`, the
|
||||||
|
Agent / Manager request + response shapes) that the unix-socket protocols are
|
||||||
|
built from.
|
||||||
|
|
||||||
|
## Where it sits
|
||||||
|
|
||||||
|
This is the shared payload crate; the per-socket *protocol envelopes* have been
|
||||||
|
split into their own smaller crates so specialised binaries don't have to pull
|
||||||
|
in all of `hive-sh4re`:
|
||||||
|
|
||||||
|
- `hive-host-sock` — host admin socket (`hivectl` ↔ `hive-c0re`)
|
||||||
|
- `hive-core-agent-sock` — per-agent/manager socket (`/run/hive/mcp.sock`)
|
||||||
|
- `hive-priv-sock` — the privileged-helper socket
|
||||||
|
|
||||||
|
Those crates re-export or reference the payload types that still live here
|
||||||
|
(`Approval`, `Message`, `LooseEnd`, …).
|
||||||
|
|
||||||
|
## Modules
|
||||||
|
|
||||||
|
- **`jobs`** — the job-queue wire types (`DagView`) surfaced to the dashboard SSE
|
||||||
|
stream + hivectl.
|
||||||
|
- **`wire_time`** — the timestamp convention: wire fields are
|
||||||
|
`chrono::DateTime<Utc>` (serialized RFC 3339), while sqlite storage + input
|
||||||
|
args stay unix-epoch `i64`; this module owns the two boundary conversions.
|
||||||
|
- **`paths`** — well-known on-disk path helpers.
|
||||||
|
- **`assets`** — resolves bundled runtime asset paths (branding, prompts) under
|
||||||
|
`HIVE_ASSETS_DIR`.
|
||||||
|
|
||||||
|
Agent-name fields are typed as `hive_types::Ident` for serde-validated parsing at
|
||||||
|
the socket boundary.
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
name = "hive-types"
|
name = "hive-types"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
|
readme = "README.md"
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
|
||||||
18
hive-types/README.md
Normal file
18
hive-types/README.md
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
# hive-types
|
||||||
|
|
||||||
|
Foundational shared **newtypes** for the hyperhive workspace. A zero-dependency
|
||||||
|
(bar `serde`) leaf crate, so every wire-type crate (`hive-sh4re`,
|
||||||
|
`hive-host-sock`, `hive-core-agent-sock`) and both binaries (`hive-c0re`,
|
||||||
|
`hivectl`) can share them without cross-crate coupling and without growing
|
||||||
|
`hive-sh4re`.
|
||||||
|
|
||||||
|
## What's here
|
||||||
|
|
||||||
|
- **`Ident`** — a validated agent-name newtype. Typing agent-name fields as
|
||||||
|
`Ident` (rather than bare `String`) gets serde-validated parsing **at the
|
||||||
|
socket boundary for free**: a malformed name is rejected at deserialize time
|
||||||
|
instead of flowing into a handler that has to re-validate by hand.
|
||||||
|
|
||||||
|
The crate is deliberately a leaf with the smallest possible dependency footprint
|
||||||
|
so anything in the workspace can depend on it. See `docs/conventions.md`
|
||||||
|
("identity = socket") for how agent identity is modelled across the sockets.
|
||||||
Loading…
Reference in a new issue