Commit graph hyperhive/hive-c0re/src/main.rs
Author SHA1 Message Date
damocles
0977006ec6 refactor(#2569): remove the c0re todo store + handlers (todos now owned in-container) 2026-07-20 23:29:26 +02:00
damocles
6685b33c9d feat(#2569): DB-backed per-agent todo store + mcp.sock upsert/clear/list/mark-done ops 2026-07-19 13:28:17 +02:00
iris
cfed36582e fix: move matrix_sweep_banner to module scope (items_after_statements) 2026-07-17 10:02:57 +02:00
iris
84ea7b8e7d sweep: dedupe matrix ensure_all banner closure 2026-07-17 10:02:57 +02:00
iris
b889f403d5 sweep: wire matrix::ensure_all() into the warning-banner registry
Fast-follow for #2289 — matrix::ensure_all() (admin user, per-agent
sync, hive Space + chat-room provisioning/invites) ran periodically
every 30 minutes but only ever warn!'d to the journal on failure, so a
persistent problem (missing invites, broken admin token, etc.) was
invisible to the operator.

ensure_all() now returns bool (aggregate ok/fail across every
sub-step) instead of (), and both call sites in main.rs feed that into
a debounced SweepHealth("matrix_ensure_all", warn, threshold=2) —
matches the existing knowledge_pull pattern. A lone bad sweep
self-heals silently; two consecutive failures raise a banner that
clears on the next clean sweep.

forge::ensure_all()'s remaining independent steps are still open —
that sweep only runs once at startup (no periodic loop), so the
debounced pattern doesn't map as directly; left for a follow-up.
2026-07-17 10:02:57 +02:00
damocles
673aea4e50 fold hive-c0re module tree into the daemon binary + drop dead pub items surfaced by bin-only (#2513) 2026-07-16 10:43:08 +02:00
atlas
419c9659a3 feat(#2007): export per-agent container cpu/mem/disk via otel
hive-c0re already samples each agent container's cgroup load for the
dashboard (stats/container_stats.rs); this rides those gauges out to the
configured OTLP endpoint, reusing the existing services.hyperhive.otel
config (endpoint + auth header) — no new toggle.

- New stats/otel_metrics.rs: exports via the OpenTelemetry Rust SDK (same
  crates as hive-metric) with the semconv container.* metric names +
  container.name attribute so off-the-shelf OTel/Grafana dashboards work,
  plus the hive agent label. container.cpu.time (counter, s, from cumulative
  cpu.stat usage_usec), container.memory.usage, container.memory.usage.limit;
  memory peak / on-disk storage / instantaneous cpu percent stay hyperhive.*
  custom (no semconv equivalent). Observable instruments read a shared
  snapshot an async task refreshes (gather() is async; SDK callbacks sync).
- container_stats: expose cpu_time_usec (cumulative) on ContainerResource.
- The OTLP auth header is loaded onto hive-c0re's own unit via systemd
  LoadCredential and read from $CREDENTIALS_DIRECTORY/otel-headers.
- docs/observability.md documents the host-emitted semconv metrics.

Host-side export, so it covers containers even when their agent is idle.
2026-07-15 22:51:31 +02:00
damocles
cc67a05974 refactor(#2352): extract standalone hivectl crate, hive-c0re daemon-only 2026-07-15 22:36:13 +02:00
damocles
3f1643c594 refactor(#2464): rename hive-ag3nt crate to hive-agent, collapse lib into main 2026-07-15 16:09:39 +02:00
damocles
96c748475e refactor(#2352): re-home host-control wire types into hive-host-sock crate 2026-07-13 15:55:20 +02:00
atlas
7b1b1d9db8 fix(#2164): address argus review — Option<String> secret + stale hook cleanup
Two issues flagged by argus in PR #2388 review:

1. Empty-key fallback: when load_or_generate() failed, webhook_secret was
   String::new(). An attacker knowing this could forge deliveries with a
   valid HMAC of the empty key. Fix: change to Option<String>; on None,
   skip hook registration entirely and return 503 from /webhook/* handlers
   (rather than 401 with a misleadingly-verifiable empty-key HMAC).

2. Stale hook cleanup: on upgrade from old code, old loopback hooks
   (http://127.0.0.1:.../webhook/knowledge, .../webhook/config-pr) were
   left alongside the new domain-URL hook. Fix: during ensure_webhook /
   ensure_config_pr_webhook, after listing hooks, delete any that end with
   our path suffix but point at a different base URL.

clippy + nix fmt clean.
2026-07-12 02:21:33 +02:00
atlas
79a29873e3 fix(#2164): domain-URL webhooks + HMAC + config-PR polling fallback
Both webhook registrations (knowledge push + config-PR pull_request) now
use the public hive domain instead of loopback:
  https://<HYPERHIVE_HIVE_DOMAIN>/webhook/{knowledge,config-pr}

This routes deliveries through the gateway, bypassing the Forgejo SSRF
guard that blocked loopback delivery and silently broke the config-PR
merge flow since launch.

Changes:
- webhook_secret: new module — auto-generate + persist a 32-byte HMAC
  secret to STATE_ROOT/webhook-secret on first startup; verify
  X-Hub-Signature-256 on every incoming webhook POST (HMAC-SHA256).
- forge/mod.rs: ensure_config_pr_webhook now takes hive_domain +
  webhook_secret; sets secret in Forgejo hook config.
- workers/knowledge.rs: ensure_webhook same update.
- dashboard/webhook.rs: both handlers read raw Bytes first, verify HMAC,
  then parse JSON. Returns 401 on signature mismatch.
- dashboard/mod.rs: AppState carries webhook_secret; serve() takes it.
- main.rs: load/generate secret at startup; pass to registration tasks
  + dashboard; add 5-minute config-PR polling fallback task.
- forge/config_pr_poll.rs: new — scan agent-configs/* for open PRs with
  no pending MergeConfigPr approval; queue them. Idempotent.
- stores/approvals.rs: has_pending_merge_config_pr() for poll dedup.
- nix/modules/hive-gateway.nix: remove dashboardAuth from /webhook/
  location (HMAC replaces basic auth for webhook endpoints; Forgejo
  cannot send HTTP Basic credentials with webhook deliveries).
2026-07-11 23:28:16 +02:00
atlas
d5a81f9195 feat(#2377): forge-webhook-triggered config-PR merge flow
Replace the request_merge_config_pr MCP tool with a Forgejo
pull_request webhook on the agent-configs org. Agents now open a
config PR normally; hive-c0re auto-queues the MergeConfigPr approval
from the webhook event — no extra tool call needed.

Changes:
- dashboard/webhook.rs: add POST /webhook/config-pr handler
  - parses Forgejo pull_request payload (opened/synchronize)
  - strips agent-configs/<agent> prefix to extract agent name
  - calls submit_merge_config_pr → queues dashboard approval card
  - always 200 to prevent Forgejo retries; errors logged at warn
- dashboard/mod.rs: wire /webhook/config-pr route
- forge/mod.rs: add ensure_config_pr_webhook() — idempotent org-level
  hook registration on agent-configs at startup; CONFIG_ORG now
  pub(crate) for webhook handler
- main.rs: call ensure_config_pr_webhook alongside knowledge webhook
- socket_server/config_approvals.rs: drop handle_request_merge_config_pr;
  make submit_merge_config_pr pub(crate) for webhook handler
- socket_server/mod.rs: re-export submit_merge_config_pr; drop dispatch arm
- hive-sh4re/src/lib.rs: remove AgentRequest::RequestMergeConfigPr
  wire type; drop from ToolGroup::Approvals tool list
- hive-ag3nt/src/mcp/: drop request_merge_config_pr tool + args struct
- docs: update approvals.md (webhook trigger), conventions.md (tool
  group), agent-hierarchy.md, tools/lifecycle.md

Hardening from #2375-merge-config-pr-hardening branch preserved:
- pr_is_open check at queue time (rejects closed/merged PRs)
- atomic fetched_sha INSERT via submit_kind(fetched_sha: Some(&sha))

Approve-handler machinery unchanged (run_merge_config_pr,
ff_push_to_main, fetch_pr_head_into_applied, mark_pr_merged).
2026-07-11 12:19:52 +02:00
damocles
187c364feb refactor(#2285): repoint all hive-c0re host-path consumers to paths.rs 2026-07-10 20:32:03 +02:00
damocles
28dbb529c0 feat(#2289): debounced SweepHealth banner tracker, wire knowledge pull 2026-07-10 14:46:43 +02:00
damocles
9f98925c14 feat(#2289): push-based server-warning registry with RAII guard 2026-07-10 13:52:59 +02:00
atlas
73f1020a7e refactor(#2290): replace mcp_sockets poll with event-driven register_agent
mara: the background worker is redundant if c0re knows when its own
sockets go missing. damocles: 10s poll latency and redundancy are two
faces of the same issue — poll adds a reconnect window and does
redundant work when c0re could react directly.

design: c0re owns the MCP listener lifecycle, so the only time a
listener disappears without c0re knowing is when c0re itself restarts.

- replace spawn_poll (recurring 10s loop) with sync_on_start (one-shot
  sweep at daemon boot): re-registers all running agents on startup
  after /run/hyperhive/agents/ is cleared by the tmpfs reset.
- run_reconcile (reconcile-start path): add coord.register_agent(name)
  immediately after start_with_fallback — event-driven, no poll delay.
- run_create already calls register_agent eagerly; kill/destroy paths
  already call unregister_agent — no changes needed there.

tracker: #2290
2026-07-09 01:08:38 +02:00
atlas
15fc33d2e1 style: rustfmt 2026-07-09 00:58:51 +02:00
atlas
3d919b596f feat(#2290): split ensure_runtime — dirs to lifecycle, listeners to mcp_sockets supervisor
- lifecycle::ensure_agent_runtime_dir(name): pure filesystem op, no
  Coordinator dep. Creates /run/hyperhive/agents/<name> without touching
  the MCP listener map.

- workers/mcp_sockets::spawn_poll(coord): 10 s reconcile loop (same shape
  as agent_sockets::spawn_poll). Converges 'agent running => MCP listener
  bound'. First tick is immediate so hive-c0re restarts re-register all
  running agents without waiting a full interval. Fixes the dead-listener-
  after-daemon-restart gap.

- All ensure_runtime() call sites updated:
  - Prebuild/Swap/WriteDropin: Coordinator::agent_dir() (pure, no IO)
  - Reconcile-Start: ensure_agent_runtime_dir + agent_dir (dir may be
    missing after reboot; listener deferred to supervisor)
  - run_create / handle_spawn: ensure_agent_runtime_dir + register_agent
    (eager on first spawn so socket ready before harness first turn)
  - apply_commit / merge_config_pr: ensure_agent_runtime_dir + agent_dir
  - Manager (auto_update): ensure_agent_runtime_dir + agent_dir
    (manager has no MCP listener; socket_server::start_manager owns it)

- ensure_runtime() retained in Coordinator with updated doc pointing at
  the preferred split form. No callers remain outside tests.
2026-07-09 00:58:51 +02:00
atlas
ae3ecc1de2 fix(#2290): drop redundant async blocks around sync_tmpfiles spawn 2026-07-09 00:52:32 +02:00
atlas
9d1f5ebe76 feat(#2290): maintain /etc/tmpfiles.d/hyperhive-agents.conf for boot safety
Root cause of the boot outage: container@h-* units try to start before
hive-c0re reaches ensure_runtime, so bind-mount source dirs are missing.

Fix: hive-c0re (via hive-priv, which runs as root) writes
/etc/tmpfiles.d/hyperhive-agents.conf whenever the agent set changes.
systemd-tmpfiles-setup.service (sysinit.target) reads it at every boot
BEFORE any container units start, pre-creating:

  /run/hyperhive/agents/<name>  — MCP socket dir (bind -> /run/hive)
  /run/hive-agent/<name>        — web socket dir (bind -> /run/hive-agent)

This alone removes the outage class: even if hive-c0re is slow to start,
the bind-mount sources exist and container units can activate.

Added:
- PrivRequest::SyncAgentTmpfiles { agents } in hive-sh4re
- sync_agent_tmpfiles() in hive-priv: generates content, writes atomically,
  calls systemd-tmpfiles --create to apply immediately
- priv_client::sync_agent_tmpfiles() wrapper
- lifecycle::sync_tmpfiles() best-effort helper (list + priv call)
- Call sites: hive-c0re startup, handle_spawn success, destroy success
2026-07-09 00:52:32 +02:00
müde
7946e03fde feat(hive-c0re): replace rebuild queue with generic job-DAG queue
jobs are now DAGs of primitive nodes (prebuild, stop-for-update, swap,
reconcile, signal, drain, ...) driven by one scheduler with N build
slots + per-agent lifecycle leases. per-agent power intent (wanted
up/offline) is durable in agent_power.sqlite; Reconcile nodes converge
observed state to it. kills the graceful-stop watcher thread, the
deferred-start follow-up, and the cascade pre-enqueue (fan-out on
MetaLock completion instead). tracker: #2166
2026-07-06 20:36:57 +02:00
damocles
fac326aa35 fix(broker): route all wakes through sqlite, remove transient ping buffer 2026-07-05 11:55:40 +02:00
damocles
2c5d9ed336 wire types: use chrono DateTime<Utc> as the timestamp type throughout 2026-07-03 22:07:23 +02:00
damocles
1e205289c5 wire types: WireTime newtype for timestamps instead of adaptor-annotated i64 2026-07-03 22:07:23 +02:00
atlas
ae41e39dfb refactor(#2111): remove nixpkgs-unstable, source claude-code from main nixpkgs 2026-07-01 19:32:46 +02:00
damocles
49fc61212b fix(#2031): move bash-tasks + events vacuum agent-side (privsep ownership) 2026-06-27 10:14:47 +02:00
atlas
f5f06a5f14 refactor(#1865): consolidate agent + manager socket servers into one
The per-agent and manager sockets ran two parallel dispatchers with
duplicated lifecycle handlers (agent-side topology-gated, manager-side
ungated) plus a manager-only handler set. Collapse to one parameterized
server in socket_server.rs:

- one serve() + dispatch(req, agent, privileged, coord); start() binds
  the per-agent sockets (privileged=false), start_manager() binds the
  manager socket (privileged=true).
- each lifecycle/config handler (start/restart/kill/update/init_config/
  apply_commit) merges its dual: the topology guard (require_child /
  require_new_child) runs only on the !privileged path; init_config
  records the requester as parent only when !privileged. restart keeps
  the orthogonal, capability-gated + audited infra-container branch.
- the agent-state queries (loose-ends / reminder count + rollup) branch
  on privileged: privileged keeps any-target + the "*" hive-wide sweep
  (query_agent_state-gated), non-privileged keeps the topology/cap gate.
- the privileged-only verbs (schedules / meta-inputs / get_logs) plus
  the submit/schedule/watchdog helpers move into socket_server; they are
  reached via dispatch_privileged_only(), which rejects the whole group
  on a non-privileged socket.
- delete manager_server.rs; repoint refs; merge the test modules.

No behavior change: the topology guard still applies on every
non-privileged lifecycle call, the privileged socket still acts on any
agent, and privileged-only verbs are still rejected on agent sockets.
2026-06-22 13:58:52 +02:00
damocles
65895c6ebf hive-c0re: fast lane for dashboard start/stop queue ops 2026-06-21 22:04:19 +02:00
damocles
d57f8845b4 feat(c0re): per-container disk-size sampler on container-load (#1659) 2026-06-17 19:05:35 +02:00
atlas
a452a92fb1 feat(audit): persistent audit log of agent-initiated privileged actions
Adds a durable, operator-visible audit trail of privileged operations
hive-c0re performs on behalf of an agent — the ones that cross the
agent/operator trust boundary. First entry: infra-container restarts via
the infra_admin-gated `restart` tool, which until now were recorded only
as a hive-priv journal trace.

Backend:
- new `audit_log` module: sqlite-backed store (audit_log.sqlite, same dir
  as build_logs) with schema (ts/agent/action/target/outcome/detail),
  best-effort `record`, `list_recent` (clamped 500), 90-day `vacuum`, and
  a process-singleton handle mirroring build_logs.
- Coordinator opens + installs the handle; main spawns the hourly vacuum.
- agent_server::handle_restart_infra records every attempt (ok, error, and
  capability-denied) via the global handle — best-effort, never fails the
  underlying action.
- dashboard: `GET /api/audit-log` returns recent entries as JSON.

Scope is deliberately agent-initiated privileged actions only (not every
PrivRequest — token writes + nspawn edits are constant lifecycle noise).
Extensible: future agent-initiated priv ops record via the same handle.

Unit tests cover record/list ordering, the 500 clamp, and retention vacuum.

The dashboard *surface* (an AUDIT view consuming /api/audit-log) is a
frontend follow-up coordinated with iris.
2026-06-13 13:45:02 +02:00
atlas
98660d134a refactor(c0re): pass hive-c0re serve config via a --config file, shrink ExecStart
The systemd ExecStart carried every host-level setting as its own flag —
nine of them, including two escaped JSON blobs (the context-window map and
the model-price table). Collapse them into a single `--config <file>` JSON.

- Reuse the existing HiveEnv as the container-injected config shape (add
  Deserialize + Default), and add a ServeConfig wrapper = flattened HiveEnv
  plus the hive-c0re-local model_prices table (kept out of HiveEnv since it
  is never injected into containers). serde(default) lets any field be
  omitted and fall back to its canonical default.
- clap: add --config; the per-setting flags become optional overrides
  (config file is the base, explicit flags win — preserves hivectl/debug
  ergonomics and bare `hive-c0re serve`).
- Coordinator::open and cmd_serve now take the bundled HiveEnv, which drops
  their too_many_arguments clippy allows. cmd_serve keeps a single
  too_many_lines allow (inherent daemon-boot orchestration, not arg-driven).
- nix: write the config as JSON to the store + pass --config, so ExecStart
  is one short line.
- Add a round-trip test proving the flatten + per-field defaults work.

Closes the ExecStart-length issue.
2026-06-08 21:57:46 +02:00
iris
a9560ebb51 review: update default model prices to current Anthropic list pricing
Per operator request on the PR: the built-in/default prices were the old
Claude 3 numbers (opus 15/75, etc.). Update opus + haiku to the current
Claude 4.x family list pricing (cache_write = the default 5-minute cache
TTL); sonnet was already correct:

- opus:   input 5, output 25, cache_read 0.5,  cache_write 6.25
- sonnet: input 3, output 15, cache_read 0.3,  cache_write 3.75  (unchanged)
- haiku:  input 1, output 5,  cache_read 0.1,  cache_write 1.25

Updated in both builtin_prices (hive_stats.rs) and the nix modelPrices
default (hive-c0re.nix), with cross-reference "keep in sync" notes on
both sides. Also addresses the earlier reviewer note: dropped the
over-strong "single source of truth" wording in the --model-prices arg
doc (the nix default does mirror the numbers in production).
2026-06-08 20:02:31 +02:00
iris
60caef73f9 review: address damocles nits on modelPrices
- modelPrices submodule fields use lib.types.numbers.nonnegative
  instead of lib.types.float: accepts bare ints (15) as well as floats
  (15.0) and rejects negative prices for free.
- Collapse the triple-sourced default: hive-c0re serve --model-prices
  now defaults to "{}" so builtin_prices() is the single in-code
  fallback. The nix option default still carries the full
  opus/sonnet/haiku table to self-document prices for operators.
2026-06-08 20:02:31 +02:00
iris
cc8f58fb24 feat(stats): make ST4TS model price table operator-tunable
The hive-wide cost estimate on the dashboard's ST4TS tab used a
hard-coded model->price table in hive_stats.rs. Anthropic list pricing
drifts, so move the table to a nix option operators can keep current
without a code change.

- New `services.hyperhive.modelPrices` option: attrset of model-family
  short name -> { input, output, cache_read, cache_write } USD per
  million tokens. Passed to `hive-c0re serve --model-prices <json>`.
- hive_stats: `Prices` is now public + Deserialize; add `PriceTable`
  type and `resolve_prices` (longest case-insensitive substring key
  wins) with the old hard-coded table preserved as `builtin_prices`
  fallback for any model not covered.
- Coordinator holds the parsed table (hive-c0re-local, not injected
  into containers, so not part of HiveEnv); `/api/stats-hive` reads it.
- Docs: dashboard.md ST4TS cost note updated; option self-documents
  via nixosOptionsDoc.

Closes #1434
2026-06-08 20:02:31 +02:00
damocles
6e39515669 feat: type-scope events vacuum to prune only stream rows (14d) + drop turn-stats vacuum 2026-06-06 07:57:27 +02:00
damocles
14c7b0d406 feat: group host-side /var/lib/hyperhive state into db/ forge/ matrix/ run/ subdirs with startup migration 2026-06-05 23:01:47 +02:00
damocles
fb726197ea fix(#1375): clean up pedantic warnings and re-enable -D warnings without pedantic bypass 2026-06-05 16:55:09 +02:00
atlas
734fe88858 fix(ci): unblock nix flake check after clippy 0.1.95 bump (#1368)
The nixpkgs bump to clippy 0.1.95 / cargo 1.95.0 added + strengthened a
large batch of lints. CI denied ALL warnings (`-D warnings`) against the
`pedantic = warn` workspace lint, so the bump hard-failed `nix flake
check` workspace-wide with zero code changes — and would recur on every
future clippy bump.

Posture fix (the durable part): CI now runs
`-D warnings -A clippy::pedantic`, so the default/correctness/style lints
stay a hard gate while the "extra, opinionated" pedantic group is
advisory only (still `warn` for local `cargo clippy` via the workspace
lints table, just non-blocking in CI). `-A` rather than `-W` so the
group drop doesn't re-enable the specific pedantic lints the workspace
allows (e.g. `must_use_candidate`).

Also fixes the genuine DEFAULT/STYLE lints the bump surfaced across the
workspace (doc_lazy_continuation, collapsible_if, ptr_arg,
match_like_matches_macro, …) via `cargo clippy --fix` + manual stragglers
(`too_many_arguments` #[allow] on the host-config constructors), and
three tests that had rotted while the CI runner was offline (#1221):
- topology::top_level_agents_in_multi_root — hardcoded unsorted expected
- rebuild_queue::depends_on_evicted_dep_counts_as_resolved — needs
  MAX_HISTORY_PER_KIND newer terminals to evict, not one
- coordinator::agent_paths doctest — illustrative pseudo-code, now `ignore`

Validated: clippy + formatting + cargo-test checks all pass.
2026-06-05 15:32:07 +02:00
damocles
5fdc3ffdbf fix: remove issue ref from comment, use forge::FORGE_HTTP in knowledge.rs 2026-06-04 12:31:25 +02:00
damocles
78db47b00b fix: auto-create knowledge webhook + periodic pull fallback
hive-c0re now auto-creates the Forgejo push webhook for
internal/knowledge at startup (ensure_webhook). this is what was
missing — the webhook endpoint existed but was never registered in
forgejo, so merging iris's PR didn't trigger a pull.

also adds a periodic hourly pull as a fallback (and an immediate pull
at startup to reconcile commits that landed while c0re was offline).

fixes #1244.
2026-06-04 12:12:20 +02:00
damocles
1c5936febb fix: recover from M_UNKNOWN_TOKEN in hive-matrix-daemon
when the homeserver rejects the token (stale session after state wipe or
expiry), the daemon now deletes the token file + matrix-sdk state dir
and exits cleanly instead of crash-looping.

hive-c0re's matrix::ensure_all sweep now runs periodically every 30
minutes (in addition to startup) so deleted token files get
re-provisioned without requiring a hive-c0re restart. the systemd.paths
watcher on the token file path then restarts the daemon with a fresh
token.
2026-06-04 12:12:20 +02:00
damocles
d1fbb4aef8 feat(#1184): make agent CPU quota and memory limit configurable 2026-06-03 21:39:14 +02:00
damocles
eb3c6cd0c4 cleanup(#1177): unify manager socket path, remove dead manager-name branches, rename ensure_manager 2026-06-03 20:39:45 +02:00
damocles
a1c6736ba5 feat(#1106): transient wake for bash tasks — bypass broker sqlite 2026-06-03 12:30:30 +02:00
atlas
db50da570a refactor(#1003): nixpkgs + nixpkgs-unstable as top-level meta inputs
Per mara's direction: both nixpkgs and nixpkgs-unstable are now
top-level meta flake inputs with explicit store-path URLs.  Hyperhive
follows them rather than the other way around:

  inputs.nixpkgs.url            = "path:${pkgs.path}";
  inputs.nixpkgs-unstable.url   = "path:${nixpkgs-unstable}";
  inputs.hyperhive.url          = "...";
  inputs.hyperhive.inputs.nixpkgs.follows            = "nixpkgs";
  inputs.hyperhive.inputs.nixpkgs-unstable.follows   = "nixpkgs-unstable";

New NixOS host options (auto-set at build time, overridable):
  services.hyperhive.c0re.nixpkgsFlake
    default: "path:${pkgs.path}" — host's evaluated nixpkgs.
  services.hyperhive.c0re.nixpkgsUnstableFlake
    default: "path:${nixpkgs-unstable}" from hyperhive's flake.nix —
    the channel that carries claude-code.  Operators can override to
    track a different unstable snapshot.

Legacy fallback (both args empty) preserved for backward compat.
Two new Rust tests cover the full-URL and fallback paths.
2026-06-01 23:30:04 +02:00
atlas
fe5a41288d feat(#1003): inject pkgs.path into meta flake as explicit nixpkgs.url
meta flake was using `nixpkgs.follows = "hyperhive/nixpkgs"` but
`hyperhive` is a store-path input, so nix resolves hyperhive's own
pinned lock rather than the host's follows-substituted version.
When an operator sets `inputs.hyperhive.inputs.nixpkgs.follows =
"nixpkgs"` in their host flake, the meta flake was silently ignoring
it and using hyperhive's pinned nixpkgs instead.

Fix: hive-c0re.nix injects `--nixpkgs-flake path:${pkgs.path}` into
the daemon's ExecStart. `pkgs` IS the host's nixpkgs when follows is
set; otherwise it's hyperhive's own pin — so the meta flake gets the
right nixpkgs in both cases. render_flake emits `nixpkgs.url = "..."`
(explicit) when nixpkgs_flake is non-empty, falling back to the old
`follows` form when empty for backward compat.
2026-06-01 23:29:54 +02:00
atlas
4bff450343 feat(gateway): hivectl gateway user management + fix htpasswdFile assertion
Add `hivectl gateway {create-user,delete-user,list-users}` subcommands for
managing htpasswd files used by gateway Basic auth. Pure Rust bcrypt
(cost 12, $2y$ prefix nginx accepts). No external htpasswd binary required.

Also fix the NixOS module assertion: `cfg.auth ? htpasswdFile` is always
true in the module system (declared options always exist as keys); switch
to `nullOr path; default = null` + `!= null` check so the assertion
actually fires with a useful error when enable=true but no file is set.
Guard bind-mount and nginx config against null to prevent eval errors.

Update docs/gateway.md to show hivectl commands instead of raw htpasswd.
2026-06-01 23:25:28 +02:00
atlas
5c5ca38fe8 fix(#999): resolve all clippy warnings across the workspace
All crates now pass `cargo clippy --workspace -- -D warnings` cleanly.

Fixes span six crates (hive-sh4re, hive-ag3nt, hive-c0re, hive-forge,
hive-priv, hive-matrix-mcp was already clean):

- doc_markdown: wrap snake_case, type names, constants in backticks
- collapsible_if / collapsible_match: fold nested ifs into let-chains
- duration_suboptimal_units: Duration::from_secs(N) → from_mins/from_hours
- implicit_hasher: allow on HashMap-param fns where generalization is risky
- items_after_statements: hoist use to function tops
- map(f).unwrap_or(x) → map_or(x, f); map(f).unwrap_or_else(g) → map_or_else
- is_ok_and / is_none_or in place of map().unwrap_or(bool)
- needless_continue: {} instead of continue in loop match arms
- match_same_arms: Ok(None) | Err(_) merged
- format_push_str: write!() instead of push_str(&format!())
- while let replaces loop { let Some(..) = x else { break } }
- struct_excessive_bools / dead_code: allow on purpose-built structs
- too_many_lines / too_many_arguments: allow where refactor not worth it
- unused_async: remove async from poll_once in bash_runner
- needless_borrow: fix &repo deref in hive-forge comments verb
- cast_possible_truncation: allow u64→usize in fetch_tail

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 22:31:06 +02:00
iris
ab278affc7 rename(#162): scrub remaining hm1nd references from comments and MCP instructions
All functional renames (MANAGER_NAME, MANAGER_AGENT → "root") were done in
earlier commits. This cleans up the stale `hm1nd` strings that remained in
doc comments, test fixture labels, and the manager MCP server instructions
(which told the manager its config lived at /agents/hm1nd/config/agent.nix).
2026-06-01 19:18:02 +02:00