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.
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).
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).
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.
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.
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).
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.