Skip to content

feat: persist authenticated agent task reports#426

Merged
joryirving merged 1 commit into
mainfrom
feat/persist-agent-task-report
Jun 17, 2026
Merged

feat: persist authenticated agent task reports#426
joryirving merged 1 commit into
mainfrom
feat/persist-agent-task-report

Conversation

@joryirving

Copy link
Copy Markdown
Contributor

Persist authenticated agent task reports as AgentRun rows.

Changes

  • Add Bearer token auth to POST /api/agents/[agentName]/tasks/report using existing authorizeRequest helper
  • Persist one AgentRun row per valid report:
    • agentName: from route param
    • runType: from taskType
    • status: derived from outcome (failedfailed, blockedblocked, everything else → completed)
    • startedAt / finishedAt: current timestamp
    • summary: report summary, if provided
    • errorMessage: report error, if provided
    • touchedIssueUrls: built from issue and PR references
    • issueId: resolved from repoFullName + issueNumber when matching Issue exists; otherwise null
  • Response includes { ok, agentName, report, agentRunId }
  • Validation failures and unauthorized requests return early without creating AgentRun
  • All existing validation behavior preserved (400 for invalid types, 401 for unauthenticated)

Validation

  • npm run lint ✅
  • npm run typecheck ✅
  • npm run test (1335 tests) ✅
  • npm run build ✅

Closes #413
Closes #409

Add Bearer token auth to POST /api/agents/[agentName]/tasks/report.
Persist one AgentRun row per valid report with:
- agentName from route param
- runType from taskType
- status derived from outcome (failed->failed, blocked->blocked, else completed)
- issueId resolved from repoFullName + issueNumber when matching Issue exists
- touchedIssueUrls built from issue and PR references
- summary and errorMessage from report fields

Response includes { ok, agentName, report, agentRunId }.
Validation failures and unauthorized requests do not create AgentRun.

Closes #413
Closes #409

@its-saffron its-saffron Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Automated Review

Full PR review.

Analysis engine: MiniMax-M2.7@https://litellm.jory.dev/v1 (anthropic) — routed smart (risk match: public_route_changes)

PR Review: PR 426 — feat: persist authenticated agent task reports

Recommendation: Approve

This PR correctly addresses both linked issues (PR 409, PR 413) by adding Bearer token authentication and persisting AgentRun rows from task reports. The implementation is internally consistent, follows repository conventions, and includes comprehensive test coverage.


Required Checks

✅ verify route access controls are in place

Verified. The route now calls authorizeRequest(request) at the start of the POST handler and returns 401 Unauthorized when authentication fails:

// Authenticate
if (!(await authorizeRequest(request)).authorized) {
  return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}

This uses the shared authorizeRequest helper from @/lib/auth, which is the documented pattern for protecting mutating Dispatch API routes. The auth check occurs before validation or persistence, ensuring no data is written for unauthenticated requests.

Test coverage confirms:

  • returns 401 when no authorization header is provided
  • returns 401 when token is incorrect
  • unauthorized requests do not create AgentRun

✅ check for unintended public endpoints

Verified. The endpoint is not publicly accessible after this change. Anonymous requests without a valid Bearer token receive 401. The DISPATCH_AGENT_TOKEN is required, matching the documented contract for agent API bearer auth.


Change-by-Change Findings

File Finding Severity Category
route.ts Auth added before validation — correctly ordered
route.ts deriveStatus() maps outcomes to statuses: failed→failed, blocked→blocked, else→completed
route.ts resolveIssueId() does two DB lookups (repo, then issue) — graceful null on missing
route.ts buildTouchedUrls() constructs GitHub URLs from report fields
route.ts AgentRun created only after all validation passes
route.ts Response includes agentRunId: run.id for caller traceability
route.test.ts Test file restructured into logical describe blocks: auth, validation, persistence
route.test.ts Auth tests mock isAuthorizedAgentToken / isAuthorizedBearerToken to isolate behavior
route.test.ts No findings — tests are comprehensive and correctly assert 401/400/200 paths

Standards Compliance

Standard Status Evidence
Bearer token auth via DISPATCH_AGENT_TOKEN authorizeRequest(request) from @/lib/auth
Return 401 for unauthenticated Explicit NextResponse.json({ error: "Unauthorized" }, { status: 401 })
Return 400 for validation errors Preserved from original implementation
No secrets in responses Test: "does not echo secrets or auth data"
AuditLog for state changes ⚠️ AgentRun persisted, but no AuditLog entry per issue PR 413's consideration of "both"

Note on AuditLog: Issue PR 413 asks to "decide the persistence model (audit log row, agent run row, both)." The PR chose AgentRun only. Given that POST /api/agent-runs also does not write AuditLog (per repo grep), this is consistent with existing patterns. The audit label on PR 413 suggests future work could add AuditLog, but this is out of scope for the immediate fix.


Linked Issue Fit

Issue Acceptance Criteria Verification
PR 409 (P1): Add authentication or remove endpoint Add authorizeRequest() call ✅ Added; test confirms 401 for missing/invalid token
PR 413 (P2): Decide persistence model and add tests Persist data + tests ✅ AgentRun created per report; comprehensive tests added

Evidence Provider Findings

No evidence providers were configured for this PR.


Tool Harness Findings

The tool harness read route.ts and src/lib/auth.ts to verify the auth implementation. Findings:

  • authorizeRequest is imported from @/lib/auth — correct
  • authorizeRequest returns { authorized: boolean, ... } — route checks .authorized
  • src/lib/auth.ts confirms legacy mode (no DISPATCH_AUTH_MODE set) uses Bearer token checks — consistent with agent API contract

CI Check Results

Check Status
Docker Build ✅ success
Validate ✅ success

Unknowns / Needs Verification

None. The diff, tests, and auth implementation are fully traceable.


Summary

This PR is a clean, well-tested fix that closes both PR 409 (authentication vulnerability) and PR 413 (persistence gap). The route is no longer publicly accessible, and task reports are now persisted as AgentRun rows for operator traceability.

@joryirving joryirving merged commit 2cdda7b into main Jun 17, 2026
3 checks passed
@joryirving joryirving deleted the feat/persist-agent-task-report branch June 17, 2026 15:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant