Both kinds fell through to the spawn branch in renderApprovals, showing
a misleading 'spawn' chip and agent-spawn body text. Mara saw a meta-input
bump render as a spawn card for agent damocles and denied it.
Backend (dashboard.rs):
- Add commit_ref: None to the MergeConfigPr arm (struct was incomplete).
All arms of ApprovalView now initialise every field.
Frontend (call.js):
- Add isUpdateMeta / isSchedule booleans alongside the existing kind flags.
- Glyph: update_meta_inputs gets ↻, schedule_prompt gets ⏱.
- Kind chip: 'meta-update' / 'schedule' (no kind-spawn class for either).
- Body: update_meta_inputs parses commit_ref as JSON Vec<String> and shows
'bump flake inputs: foo, bar' or 'bump all flake inputs'; schedule_prompt
parses SchedulePromptPayload and shows targets + first-fire time + cadence
+ a truncated body excerpt.
- History row: add 'meta-update' and 'schedule' cases (were both 'spawn').
- Import fmtDuration from util.js (needed for schedule cadence display).
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.