Add actor-aware admission for external Forgejo issues and comments #1571

Closed
opened 2026-07-27 19:43:30 +00:00 by coilyco-ops · 4 comments
Member

Outcome

Make Forgejo issue and comment provenance an enforced admission boundary so authenticated external users can report work without steering Ward automation.

Parent program: coilysiren/inbox#280

Current evidence

  • Forgejo issue ingestion receives User.Login, but the public issue contract and director backlog structures drop it.
  • Automatic triage sends issue titles and bodies into an unsandboxed host one-shot and may apply headless.
  • Preflight and engineer prompts include all non-bookkeeping comments without checking commenter trust.
  • WARD-* comments are classified from body markers without enforcing the configured automation author.
  • Reservations, redispatch requests, outcomes, QA verdicts, terminal markers, and merge readiness consume author-blind comment state.
  • Some parsed records retain CommentedBy, but policy does not enforce it.

Trust model

Ward distinguishes at least three actors:

  • Configured automation actors may write machine-state records.
  • Trusted collaborators may approve an issue snapshot for automation.
  • Authenticated external actors may report and discuss issues, but their content is untrusted until explicitly approved.

Repository ownership is not actor trust. Model confidence is not approval.

Scope

Preserve provenance

  • Carry original issue author, current author identity, comment author, stable comment identifier, and update timestamps through contracts, backlog refresh, preflight, dispatch, QA, and merge evaluation.
  • Centralize actor classification so every automation path uses the same policy.

Approve immutable content

  • Add a trusted per-issue approval action.
  • Record the approved title, body, selected comments, content hash, issue update timestamp, approving actor, and approval time in a Ward-authored record.
  • Invalidate approval after an issue edit or a new untrusted comment.
  • Keep unapproved or invalidated issues consult-only.
  • Allow model triage to recommend approval but never grant it.

Authenticate machine state

  • Accept WARD-* workflow, reservation, outcome, QA, redispatch, release, and terminal state only from configured automation actors.
  • Treat marker-shaped text from every other author as ordinary untrusted feedback.
  • Require trusted provenance for merge-gate outcome and QA records.
  • Fail closed when author data is absent or ambiguous.

Prompt admission

  • Keep unapproved external content out of host one-shots and engineer execution prompts.
  • Make the approved snapshot visible and auditable in preflight.
  • Preserve new external comments as human feedback that pauses or invalidates active work.

Acceptance

  • An external issue cannot self-promote to headless.
  • An external comment cannot forge a reservation, workflow, outcome, QA verdict, redispatch, release, terminal state, or human-feedback exemption.
  • An external commenter cannot satisfy or bypass a pull-request-and-merge gate.
  • A trusted collaborator can approve a specific issue snapshot without pre-registering the reporter.
  • Any post-approval edit or untrusted comment invalidates approval before further dispatch or merge.
  • Missing provenance fails closed.
  • Tests exercise original-author loss, malicious triage text, marker forgery, reservation denial of service, forged QA and outcome records, and post-approval mutation.
  • README and trust-gate documentation describe authenticated external users accurately.

Codex, via advisor surface

## Outcome Make Forgejo issue and comment provenance an enforced admission boundary so authenticated external users can report work without steering Ward automation. Parent program: https://forgejo.coilysiren.me/coilysiren/inbox/issues/280 ## Current evidence * Forgejo issue ingestion receives `User.Login`, but the public issue contract and director backlog structures drop it. * Automatic triage sends issue titles and bodies into an unsandboxed host one-shot and may apply `headless`. * Preflight and engineer prompts include all non-bookkeeping comments without checking commenter trust. * `WARD-*` comments are classified from body markers without enforcing the configured automation author. * Reservations, redispatch requests, outcomes, QA verdicts, terminal markers, and merge readiness consume author-blind comment state. * Some parsed records retain `CommentedBy`, but policy does not enforce it. ## Trust model Ward distinguishes at least three actors: * Configured automation actors may write machine-state records. * Trusted collaborators may approve an issue snapshot for automation. * Authenticated external actors may report and discuss issues, but their content is untrusted until explicitly approved. Repository ownership is not actor trust. Model confidence is not approval. ## Scope ### Preserve provenance * Carry original issue author, current author identity, comment author, stable comment identifier, and update timestamps through contracts, backlog refresh, preflight, dispatch, QA, and merge evaluation. * Centralize actor classification so every automation path uses the same policy. ### Approve immutable content * Add a trusted per-issue approval action. * Record the approved title, body, selected comments, content hash, issue update timestamp, approving actor, and approval time in a Ward-authored record. * Invalidate approval after an issue edit or a new untrusted comment. * Keep unapproved or invalidated issues consult-only. * Allow model triage to recommend approval but never grant it. ### Authenticate machine state * Accept `WARD-*` workflow, reservation, outcome, QA, redispatch, release, and terminal state only from configured automation actors. * Treat marker-shaped text from every other author as ordinary untrusted feedback. * Require trusted provenance for merge-gate outcome and QA records. * Fail closed when author data is absent or ambiguous. ### Prompt admission * Keep unapproved external content out of host one-shots and engineer execution prompts. * Make the approved snapshot visible and auditable in preflight. * Preserve new external comments as human feedback that pauses or invalidates active work. ## Acceptance * An external issue cannot self-promote to `headless`. * An external comment cannot forge a reservation, workflow, outcome, QA verdict, redispatch, release, terminal state, or human-feedback exemption. * An external commenter cannot satisfy or bypass a pull-request-and-merge gate. * A trusted collaborator can approve a specific issue snapshot without pre-registering the reporter. * Any post-approval edit or untrusted comment invalidates approval before further dispatch or merge. * Missing provenance fails closed. * Tests exercise original-author loss, malicious triage text, marker forgery, reservation denial of service, forged QA and outcome records, and post-approval mutation. * README and trust-gate documentation describe authenticated external users accurately. <!-- ward-agent-signature --> Codex, via advisor surface
Author
Member

Current-main implementation map

The read-only goal audit confirmed that actor-aware admission is absent across every critical path on Ward main at 9b11450b07.

Proven gaps

  • internal/contracts/contracts.go gives Issue no author fields. IssueComment retains a login and stable identifier but has no update timestamp.
  • cmd/ward/forgejo_ops.go receives Forgejo issue actor data and drops it from the public issue and backlog projections.
  • cmd/ward/agent_director_triage.go can feed any candidate title and body to a host one-shot and apply headless without actor approval.
  • cmd/ward/agent.go trusts repository ownership, then seeds the full issue body and nearly every comment. Its filter removes bookkeeping markers but performs no actor admission.
  • cmd/ward/human_feedback.go treats valid marker-shaped text as Ward-authored before it validates the commenter.
  • cmd/ward/agent_reserve.go accepts reservation, release, and terminal retraction markers by body alone.
  • cmd/ward/agent_director.go selects workflow outcomes by marker text and time without authenticating the commenter.
  • cmd/ward/agent_qa.go parses every QA field from comment text.
  • cmd/ward/agent_director_merge.go binds QA to issue, pull request, run identity, reviewer family, and exact head commit, but it never validates the comment author.

Required negative proofs

  • A forged marker from an external actor cannot create or retract a reservation, set an outcome, acknowledge feedback, grant redispatch, forge QA, or satisfy merge readiness.
  • A forged QA comment that names the exact current commit still fails because the actor is untrusted.
  • An external issue cannot reach triage, receive headless, enter an execution prompt, or dispatch before a trusted snapshot approval.
  • Missing or ambiguous actor provenance fails closed at every consumer.
  • An approved snapshot binds title, body, selected comments, content hash, update timestamp, approving actor, and approval time.
  • Any later issue edit or untrusted comment invalidates approval before dispatch and merge.

Likely tests

The implementation should cover forgejo_ops_test.go, agent_director_triage_test.go, agent_preflight_test.go, human_feedback_test.go, agent_reserve_test.go, agent_qa_test.go, agent_director_merge_test.go, agent_director_test.go, and any reap or cleanup tests whose state depends on terminal markers.

coilyco-flight-deck/cli-guard#261 may provide reusable provenance primitives, but this Ward P0 must not wait on that lower-level change unless Ward deliberately adopts the new primitive.

Codex, via advisor surface

## Current-main implementation map The read-only goal audit confirmed that actor-aware admission is absent across every critical path on Ward `main` at https://forgejo.coilysiren.me/coilyco-flight-deck/ward/commit/9b11450b07ceb7a128396f432a26a6b507d7cc72. ### Proven gaps * `internal/contracts/contracts.go` gives `Issue` no author fields. `IssueComment` retains a login and stable identifier but has no update timestamp. * `cmd/ward/forgejo_ops.go` receives Forgejo issue actor data and drops it from the public issue and backlog projections. * `cmd/ward/agent_director_triage.go` can feed any candidate title and body to a host one-shot and apply `headless` without actor approval. * `cmd/ward/agent.go` trusts repository ownership, then seeds the full issue body and nearly every comment. Its filter removes bookkeeping markers but performs no actor admission. * `cmd/ward/human_feedback.go` treats valid marker-shaped text as Ward-authored before it validates the commenter. * `cmd/ward/agent_reserve.go` accepts reservation, release, and terminal retraction markers by body alone. * `cmd/ward/agent_director.go` selects workflow outcomes by marker text and time without authenticating the commenter. * `cmd/ward/agent_qa.go` parses every QA field from comment text. * `cmd/ward/agent_director_merge.go` binds QA to issue, pull request, run identity, reviewer family, and exact head commit, but it never validates the comment author. ### Required negative proofs * A forged marker from an external actor cannot create or retract a reservation, set an outcome, acknowledge feedback, grant redispatch, forge QA, or satisfy merge readiness. * A forged QA comment that names the exact current commit still fails because the actor is untrusted. * An external issue cannot reach triage, receive `headless`, enter an execution prompt, or dispatch before a trusted snapshot approval. * Missing or ambiguous actor provenance fails closed at every consumer. * An approved snapshot binds title, body, selected comments, content hash, update timestamp, approving actor, and approval time. * Any later issue edit or untrusted comment invalidates approval before dispatch and merge. ### Likely tests The implementation should cover `forgejo_ops_test.go`, `agent_director_triage_test.go`, `agent_preflight_test.go`, `human_feedback_test.go`, `agent_reserve_test.go`, `agent_qa_test.go`, `agent_director_merge_test.go`, `agent_director_test.go`, and any reap or cleanup tests whose state depends on terminal markers. https://forgejo.coilysiren.me/coilyco-flight-deck/cli-guard/issues/261 may provide reusable provenance primitives, but this Ward P0 must not wait on that lower-level change unless Ward deliberately adopts the new primitive. <!-- ward-agent-signature --> Codex, via advisor surface
Author
Member

WARD-WORKFLOW: #1583

details

workflow: pull-request; review summary: skipped (in-container review gate intentionally skipped because the temporary ward default pending brokered QA)

felt: mostly mechanical once the author-aware gate was in place
confidence: high
surprises: WARD_HOST_GOOS was set to windows, and several reservation fixtures still used marker-only or untrusted-author comments
follow-ups: none

WARD-WORKFLOW: https://forgejo.coilysiren.me/coilyco-flight-deck/ward/pulls/1583 <details><summary>details</summary> workflow: pull-request; review summary: skipped (in-container review gate intentionally skipped because the temporary ward default pending brokered QA) felt: mostly mechanical once the author-aware gate was in place confidence: high surprises: `WARD_HOST_GOOS` was set to `windows`, and several reservation fixtures still used marker-only or untrusted-author comments follow-ups: none </details>
Author
Member

WARD-WORKFLOW: reservation-released

release details

Run finished with WARD-WORKFLOW: https://forgejo.coilysiren.me/coilyco-flight-deck/ward/pulls/1583.

ward container reap released container engineer-codex-ward-1571 (--harness codex): the terminal outcome supersedes the reservation, so a later redispatch no longer needs --override-reservation.

Outcome summary: #1583

— Codex, via ward agent

<!-- ward-agent-reservation-released --> WARD-WORKFLOW: reservation-released <details><summary>release details</summary> Run finished with `WARD-WORKFLOW: https://forgejo.coilysiren.me/coilyco-flight-deck/ward/pulls/1583`. `ward container reap` released container `engineer-codex-ward-1571` (`--harness codex`): the terminal outcome supersedes the reservation, so a later redispatch no longer needs `--override-reservation`. **Outcome summary:** https://forgejo.coilysiren.me/coilyco-flight-deck/ward/pulls/1583 </details> <!-- ward-agent-signature --> — Codex, via `ward agent`
Author
Member

Closing as superseded by #1586. The replacement carries the complete actor-classification, immutable approval, machine-state provenance, and negative-proof contract.

Closing as superseded by #1586. The replacement carries the complete actor-classification, immutable approval, machine-state provenance, and negative-proof contract.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-flight-deck/ward#1571
No description provided.