Add actor-aware admission for external Forgejo issues and comments #1583
No reviewers
Labels
No labels
burndown-2026-06
pressure-test
sunday-sprint
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
coherence-core
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
qa-fixture
role/ai
role/creator
role/design
role/director
role/engineer
role/exec
role/human
role/ops
role/qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-flight-deck/ward!1583
Loading…
Reference in a new issue
No description provided.
Delete branch "issue-1571"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
External Forgejo issues and comments are now gated by actor-aware admission so unapproved reporter content stays consult-only until a Ward-authored approval snapshot exists. Machine-state markers only count from Ward automation identities, and the director/preflight paths now carry provenance through the queue, reservation, QA, and merge gates.
Tests:
go test ./cmd/ward -count=1closes #1571
Blocking admission review at head
107267e7bf. Do not merge this head. First, issueRequiresApproval returns false when the issue author is empty, so missing provenance bypasses approval and admits raw content. The Shortcut adapter explicitly sets Author empty, making this reachable. Missing or ambiguous provenance must fail closed. Second, latestIssueSnapshotApproval treats content hash and issue update time as optional. An automation-authored marker with omitted fields can become a valid approval. Require every immutable field and exact match. Third, the approval hash covers only the selected comment IDs. A later untrusted comment does not invalidate the approval, and resolveAgentWork retains the full current comment list once any approval summary exists, so that later comment reaches preflight and the engineer prompt. Reject approval when any non-Ward comment is newer or not present in the approved snapshot, and pass only the approved comment set into execution. Fourth, the approval command accepts an arbitrary approved-by string without binding it to an authenticated trusted collaborator, which weakens the audit record. Add adversarial tests for missing author, incomplete approval fields, a later untrusted comment, and an exact-current-SHA forged approval record. The host-context test change also belongs to #1565 and should be linked or split from this security PR.Additional blocking path in humanFeedbackRules.wardAuthoredComment: the current code returns true for any comment from an ignored author even when the body is ordinary feedback, and it returns true for any configured automation-marker prefix without checking the comment author. That is still an author-blind human-feedback exemption. Machine-state classification must require both an approved automation actor and a recognized machine marker. A custom marker from an external author must remain ordinary untrusted feedback, and an ordinary unmarked comment must not become machine state merely because an ignored or bot login wrote it. Add both adversarial fixtures and keep this in the #1584 correction.
Approval authority is also not enforced at the command boundary. runDirectorApprove checks the repository owner and then posts with whichever tracker client currentAgentMode provides, but it never proves that the caller is a director or a trusted human operator. An engineer container carrying the normal push credential can invoke the subcommand and supply any approved-by string, allowing automation to self-grant the snapshot that is supposed to require collaborator approval. The fix must enforce the role and broker authority at execution time, not only place the command under a director-shaped CLI path, and the recorded approver must come from authenticated authority rather than free text. Add a negative engineer-mode invocation test and a positive authorized-director test.
The prompt gate is also skipped for pull-request refs. resolveAgentWork applies issueRequiresApproval only in the non-merge-request branch. resolveAgentPullRequestWork can therefore place an external PR title, body, PR comments, linked issue body, and linked issue comments into preflight and execution without any approved snapshot. Carry PR author provenance and require approval for every untrusted source object before a PR-ref engineer or QA run sees its content. Add an external-PR fixture with a malicious body and later comment, plus a linked external-issue fixture, and prove both stay out of host one-shots and agent prompts until the exact snapshots are approved.
The approval record is not yet an immutable content record. issueSnapshotApprovalComment stores the title, issue author, selected comment IDs, timestamps, and one hash, but it does not store the approved issue body or the selected comment text and authors. After an edit, the old approved content cannot be reconstructed or audited from that record. The #1571 contract explicitly requires the approved title, body, selected comments, content hash, issue update timestamp, approving actor, and approval time. Persist the exact approved snapshot in the Ward-authored record or another immutable Ward-owned artifact, then have execution consume that snapshot rather than re-reading mutable current text.
Final disposition: this PR is closed without merge. Its branch is retained. The reviewed implementation is superseded by the complete P0 replacement contract at #1586. PR #1585 also failed review and was closed. Containment remains active.
Pull request closed