Commit graph

2,149 commits

Author SHA1 Message Date
damocles
49067ad83e fix(#2018): surface permission error in hivectl agent lookup instead of misleading 'no such agent' 2026-06-26 22:00:13 +02:00
damocles
b0c89af817 chore(#1931): remove non-working hivectl migrate-stats verb 2026-06-26 18:06:46 +02:00
damocles
0d17ae69f4 docs: drop stale 'required infrastructure' framing from ensure_root_agent 2026-06-26 17:42:28 +02:00
damocles
c16eff0d5c fix(#2003): reword root auto-start comment (not 'required infra'; opt-out is a separate host setting) 2026-06-26 17:42:28 +02:00
damocles
916c0b11c5 fix(#2003): drop issue tag from inline comment (tracker-tag lint) 2026-06-26 17:42:28 +02:00
damocles
2cd089b65f fix(#2003): start root container if present-but-stopped on hive-c0re boot 2026-06-26 17:42:28 +02:00
damocles
ad8ed452fd fix(#2002): mkdir container /etc before writing bridge-DNS marker (fresh install) 2026-06-26 17:27:05 +02:00
atlas
8e366c8a10 docs(security): operator-merge IS enforced on the internal forge
Per mara (verified in forge.rs): agents have max_repo_creation=0, so every
internal-forge repo is core-created with branch protection on by default
(merge restricted to operators team + required operators-team approval via
apply_operator_branch_protection / the config-repo equivalent), and agents
(write collaborators, not admins) can't change it or self-merge. So it's
technically enforced there, not just convention — only external VCS (GitHub)
is unprotected. Corrects my prior over-correction.
2026-06-26 17:19:35 +02:00
atlas
524b1de98c docs(security): correct the operator-merge bullet (mara review)
Per mara: branch protection isn't a blanket enforced check, and it's not
set up for external VCS (GitHub). Reframe the bullet as the operator-merge
*convention* — technically enforced only on the core-managed config repos,
and explicitly NOT wired up for GitHub/external VCS (process + accepted
risk there, not a control).
2026-06-26 17:19:35 +02:00
atlas
9daed8acc1 docs(security): restore the State-file endpoint heading
The trust-model insert accidentally consumed the
'## State-file endpoint security model' heading, leaving that section
floating under the new one. Re-add the heading and collapse the extra
blank lines (argus review).
2026-06-26 17:19:35 +02:00
atlas
cf581d14b8 docs(security): document the agent trust model
Add an 'Agent trust model' framing section at the top of docs/security.md
covering the conceptual model the existing mechanism-level sections serve:

- trust boundary = the container, not credential storage (agents have
  passwordless sudo by default; isolating creds from the agent itself is
  not a goal — cross-tenant leakage is)
- scoped per-agent forge/matrix tokens bound the blast radius
- threat model: prompt injection -> confused deputy (untrusted input is
  the adversary; the agent + its tools are trusted)
- branch protection (agents push, operator merges) as the human-in-loop
  checkpoint, incl. external VCS
- capability = accepted risk ('don't grant what you can't afford to lose')
- no auto-sandboxing of external tokens (operator-accepted scope)

Emerged from the 2026-06-24 security discussion. Updates the CLAUDE.md
pointer for findability.
2026-06-26 17:19:35 +02:00
damocles
09dc3682d7 fix(#1995): send {} body on schedule cancel-all (was empty body 400) 2026-06-26 01:23:06 +02:00
damocles
eba637b36c docs(#1990): fix for_agent ordering doc + add # errors (argus review) 2026-06-26 01:22:20 +02:00
damocles
49db9d6e1c feat(#1990): surface pending recv() message count in get_loose_ends 2026-06-26 01:22:20 +02:00
damocles
678f50f3fb docs(#1989): add # errors doc to rebuild_agent + rebuild (argus review) 2026-06-25 23:59:54 +02:00
damocles
1f0cc010ad fix(#1989): don't relock on meta-update cascade rebuilds (was reverting the bump) 2026-06-25 00:36:52 +02:00
damocles
527dff0200 feat(#1985): add # Errors doc to subscription run (argus review) 2026-06-25 00:09:16 +02:00
damocles
fce9bb8c11 feat(#1985): subscription --list to audit watched repos 2026-06-25 00:09:16 +02:00
damocles
9f40bd13f9 fix(#1896): remove dead forge_notify reason drop-list + auto-unsubscribe 2026-06-24 23:07:48 +02:00
damocles
ca44fd56df fix(#1896): drop self-authored issue/pr creation wakes in forge_notify 2026-06-24 22:19:32 +02:00
damocles
c68706e899 fix(#1982): migrate-stats tolerates pre-session_id dbs + skips failed agents 2026-06-24 21:33:25 +02:00
damocles
a94fb9955f fix(#1974): pair token cols by array position (argus review) 2026-06-24 21:17:42 +02:00
damocles
5393f0e7d4 feat(#1974): migrate-stats — add session.id/start_type/terminal.type + session.count (review) 2026-06-24 21:15:30 +02:00
damocles
d9d5495f1f docs: regenerate hivectl-cli.md for the migrate-stats verb 2026-06-24 21:05:37 +02:00
damocles
ef6a86872d feat(#1974): hivectl migrate-stats — backfill per-agent token history to otel 2026-06-24 20:48:38 +02:00
damocles
af10a4bfef fix(otel): cumulative metric temporality + metricIntervalMs knob (real metrics-export fix) 2026-06-24 20:28:37 +02:00
damocles
609438a889 fix(#1977): exposeHostPorts is firewall-only (drop conflicting loopback proxy) 2026-06-24 19:48:50 +02:00
damocles
fe68bfbadc fix(network): co-locate exposeHostPorts firewall opening with the proxies (argus review on #1972) 2026-06-24 19:28:29 +02:00
damocles
0172106559 feat(#1971): network.exposeHostPorts to reach host-loopback services from agents 2026-06-24 19:17:37 +02:00
damocles
baa5ce3e1a gui: one shared dbus session bus for the gui session (#1906) 2026-06-24 00:06:07 +02:00
atlas
14ae7367cd fix(systemd): set explicit SyslogIdentifier on hyperhive-declared units
Follow-up to the harness fix: any unit whose ExecStart is a generated
wrapper (a NixOS `script =` block or a writeShellScript) gets its journal
SyslogIdentifier derived from the wrapper's store-path basename — an
opaque, unstable name. Pin an explicit stable identifier on every unit
hyperhive declares.

script/wrapper units (leaked store paths): forgejo-gpg-init,
hive-gateway-self-signed-cert, hive-tls-ca, hive-ci-prefetch,
hyperhive-isolated-dns, tea-login, forge-avatar-sync,
matrix-avatar-sync, hive-dashboard-links.

direct-binary units (basename already sane; explicit for tidiness +
future-proofing): hive-c0re, hive-priv, hive-matrix-daemon,
hive-bash-daemon, weston.

Only changes the displayed line identifier; journalctl -u <unit>
filtering (keys on _SYSTEMD_UNIT) is unaffected.
2026-06-23 22:53:33 +02:00
iris
fae2025247 docs(approvals): update helper-events routing to reflect shipped behavior
notify_manager (always-root) has been replaced by notify_submitter
(routes to the approval submitter, with root fallback for legacy rows).
Update three locations:

- Step 6 of end-to-end flow: "root agent's inbox" →
  "submitting agent's inbox"; explain notify_submitter + submitter column.
- InitConfig paragraph: remove limitation note; "to the root agent's inbox
  (current limitation...)" → "to the submitting agent's inbox via notify_submitter".
- Section header + prose: "Helper events to the root agent" →
  "Helper events to the submitting agent"; rewrite lead paragraph around
  notify_submitter semantics (approvals.submitter column, legacy fallback).
2026-06-23 22:45:43 +02:00
iris
60403fd27c docs(approvals): drop tracker-tag refs; add topology.rs pointer for role
Remove three bare #NNN tracker-tag references in docs/approvals.md
(hive-rules: no #NNN in code/comments/docs):

- Step 6 of end-to-end flow: "tracked in #1953" → "a known limitation
  under active development"
- InitConfig paragraph: same rewrite
- Helper events section: same rewrite

Also add a code pointer for `can_manage_top_level_agents`: the role is
defined as ROLE_CAN_MANAGE_TOP_LEVEL_AGENTS in hive-c0re/src/topology.rs,
now noted inline so reviewers can verify the name is real.
2026-06-23 22:45:43 +02:00
iris
136102cd27 docs(approvals): reframe stale 'the manager' as the root agent
The last docs/ piece of the manager-cleanup. The manager is no longer a
structural role — root-ness is purely topological. Reframe:
- title 'Approvals + manager + helper events' -> 'Approvals + helper events'
- section headers: 'Manager view of applied'/'Manager policy'/'Manager
  (ruth) is hive-c0re-managed'/'Helper events to the manager' ->
  root-agent / root-bootstrap-container equivalents
- body prose: 'the manager (ruth)' -> 'the root agent' (or 'the submitter'
  in the approval-flow steps)
- authority semantics: 'manager-only' -> approvals are submitted by an
  agent with the approvals tool group, for its direct children
- dropped the stale 'the manager refuses to destroy itself' line (the
  bootstrap container is now destroyable + transient; recreated on startup)

Kept the genuine code/protocol identifiers (nixosConfigurations.manager,
manager_server, role:manager prompt block, notify_manager, the
/run/hyperhive/manager/ socket path) — renaming those would diverge from
the source (de-hardcoding is its own backend cleanup).
2026-06-23 22:45:43 +02:00
atlas
e816cf4d72 fix(ci-log): address review — prose tags, correct module doc, typed miss
- Remove the two issue-number tags from Rust comments (tracker-tag lint).
- Correct the module doc: the durable download is keyed by the per-repo
  run NUMBER + attempt segment (matches the code + persisted_logs doc),
  not a global id — the earlier 'global id' wording was stale.
- Replace the fragile e.to_string().contains("out of range") branch with
  a typed StreamerMiss enum (StepOutOfRange vs Unavailable), so a usage
  error can never silently fall through to the persisted-log path if a
  message string changes.
2026-06-23 22:45:05 +02:00
atlas
d340c1773a fix: ci-log durable persisted-log fallback for pruned runs
ci-log drove only the live run-view streamer (POST .../runs/<n>/jobs/<j>
with logCursors), which reads the live act_runner task record. Forgejo
prunes that record once a run completes, so the streamer 500s with
'task ... resource does not exist' on quick or older runs even though
the web UI still shows the logs — the reader (argus, atlas) then had to
ask the operator to relay the error.

Add a fallback: when the streamer errors or returns no lines, download
the persisted whole-job log via the same web route the run page's view-
raw-logs link uses, .../runs/<n>/jobs/<job>/attempt/<a>/logs, keyed by
the per-repo run number with the attempt segment. It survives the task
prune. Live and recent runs keep the rich per-step streamed view; only
the pruned case takes the flat fallback (where --step can't apply). New
--attempt flag (default 1) selects the run attempt for re-runs.

Verified against a real pruned run whose streamer 500'd: the fallback
prints the full persisted log; a completed short job ends cleanly at
'Job succeeded', confirming the route returns complete logs.
2026-06-23 22:45:05 +02:00
damocles
3d2e0ef561 feat(#1906): non-root weston gui on a fixed vnc port 2026-06-23 22:41:20 +02:00
atlas
5caec9c1a9 fix(forge): config-repo main is fast-forward-only (no auto force-push)
Per operator directive: a silent automatic force-push is a bug. The
config-repo merge path already never force-pushes (run_merge_config_pr
lands via ff_push_to_main, a non-force git push). So set the branch
protection's enable_force_push to false — main only ever advances by
fast-forward.

The legacy push_config mirror does force-push (it re-points the status
tags and rewinds main on a failed-build rollback); the protection now
rejects those non-ff updates, so the mirror runs best-effort until the
agent-opened PR-merge flow retires it. Docs + comments updated to match.
2026-06-23 22:37:27 +02:00
atlas
60da6c14b4 fix(forge): reword tracker-tag references in doc comments to prose
Address argus review on the config-repo PR surface: 6 issue-number tags
appeared in Rust doc comments in forge.rs; the tracker-tag lint matches
${'#'}NNN in code comments (markdown docs are exempt, doc comments are not).
Reword to prose, no behavior change.
2026-06-23 22:37:27 +02:00
atlas
558552ec54 docs(forge): s/mirror/config repo/ in dashboard anchor bullet for consistency
Address iris review nit on #1948: the bullet above now reframes the
agent-configs entry as a config repo, so the dashboard-anchor bullet
should match. Pure wording, no behavior change.
2026-06-23 22:37:27 +02:00
atlas
2fe79aaef5 feat(#1787): make agent-configs/<n> the agent-editable, PR-merge config surface
Wires the per-agent config repo as the editable PR surface the #1838
merge handler (run_merge_config_pr) consumes, without yet retiring the
push_config force-mirror (that waits for #1838 P2 — the agent-opens-PR
MCP surface — so config changes keep working through the transition).

ensure_config_repo now, after creating agent-configs/<name>:
- adds the agent as a WRITE collaborator (can push config-change branches
  + open PRs);
- branch-protects main core-only via apply_config_repo_branch_protection:
  push + merge whitelists are core-only (only hive-c0re lands on main, via
  its verify-and-ff-push handler), operator-team approval required, the
  agent can't push main directly or self-merge.

The protection sets enable_force_push=true as a TRANSITIONAL allowance so
push_config's applied->main force-mirror keeps working until P2 retires it
(a protected branch otherwise rejects force-push). Forgejo's force-push
allowlist is deploy-keys-only — no per-user list — so this is a plain
enable_force_push toggle; only core is in the push-whitelist so only core
can force-push anyway. At P2, flip it to false and keep core in the
push-whitelist so ff_push_to_main still lands.

Agent code repos (AGENTS_ORG) are intentionally untouched — their merge
flow has no auto-merge handler yet, so switching them to core-only-merge
would strand those PRs.

All steps idempotent (runs on every spawn + startup sweep). Updated the
CONFIG_ORG doc comment + docs/forge.md to drop the "mirror-only" framing.
2026-06-23 22:37:27 +02:00
damocles
f7d84f4847 fix(#1957): persist hivectl-start running-agents snapshot in the broker kv table 2026-06-23 22:07:46 +02:00
iris
e5da5b900e docs: fix remaining bare /kill/ and /rebuild/ paths → /api/ variants
coordinator.md: GracefulStop entry referenced the old bare /kill/<agent>
path with the lax graceful=1 bool — update to /api/kill/<agent>?graceful=true.

approvals.md: the auto-update badge description referenced /rebuild/<name>
(bare, no /api/ prefix) — update to /api/rebuild/<name>.
2026-06-23 22:05:05 +02:00
iris
4634094502 docs(web-ui/dashboard): fix stale /kill/ bare paths → /api/kill/ + graceful=true
The graceful-stop description at the ■ ST0P confirm-dialog paragraph
referenced `/kill/<name>?graceful=1` and `/kill/<name>` (bare, no /api/
prefix; lax bool `1` instead of `true`).

The backend has registered these under /api/ since the /api/-prefix
migration, and the frontend was updated to send `graceful=true` (not `1`)
in commit f2f1a0b3 (fix: send graceful=true not =1 for the kill query param).
Align the docs with shipped code.
2026-06-23 22:05:05 +02:00
damocles
ebaf192476 fix(#1953): gate approval cancel on submitter ownership + document submitter_of errors 2026-06-23 22:04:56 +02:00
damocles
3618399d94 fix(#1953): route approval helper-events to the submitter, not the root agent 2026-06-23 22:04:56 +02:00
damocles
14539de7d0 fix(#1962): pin harness SyslogIdentifier so otel ExecStart wrapper doesn't rename the log unit 2026-06-23 21:44:19 +02:00
damocles
21ec7dc23d feat(#1930): forward otel headers credential into agent containers via nspawn --load-credential 2026-06-23 21:16:18 +02:00
damocles
838cc9af9a feat(#1930): move otel stats export to host-level services.hyperhive.otel 2026-06-23 21:16:18 +02:00
iris
e18ddff0b0 docs(approvals): reframe stale 'the manager' as the root agent
The last docs/ piece of the manager-cleanup. The manager is no longer a
structural role — root-ness is purely topological. Reframe:
- title 'Approvals + manager + helper events' -> 'Approvals + helper events'
- section headers: 'Manager view of applied'/'Manager policy'/'Manager
  (ruth) is hive-c0re-managed'/'Helper events to the manager' ->
  root-agent / root-bootstrap-container equivalents
- body prose: 'the manager (ruth)' -> 'the root agent' (or 'the submitter'
  in the approval-flow steps)
- authority semantics: 'manager-only' -> approvals are submitted by an
  agent with the approvals tool group, for its direct children
- dropped the stale 'the manager refuses to destroy itself' line (the
  bootstrap container is now destroyable + transient; recreated on startup)

Kept the genuine code/protocol identifiers (nixosConfigurations.manager,
manager_server, role:manager prompt block, notify_manager, the
/run/hyperhive/manager/ socket path) — renaming those would diverge from
the source (de-hardcoding is its own backend cleanup).
2026-06-23 21:06:30 +02:00