get_run_logs/get_job_logs: 404 on Forgejo v14 — token auth rejected by web log route (needs artifact path or v16 REST API) #9

Open
opened 2026-06-17 09:07:50 +00:00 by Phil · 2 comments
Owner

Severity: HIGH impact, but this is a Forgejo v14 limitation — NOT a forgejo-mcp bug

Symptom (recurring across repos & months)

get_run_logs(run_id=<run_number>, job_index=0)

MCP error -32603: logs 404 at /<owner>/<repo>/actions/runs/<N>/jobs/0/attempt/1/logs.

Recurs in flow.raven (2026-06-17), flow.RagIO (2026-05-27), flow.raven-deployment (2026-05-20/21).

Root cause (independently curl-verified 2026-05-21)

Forgejo v14 serves Action-run logs only via web routes that require a session cookie; the bearer-token auth this MCP holds (ADR-KV-018 token discipline) is rejected — every log URL returns 404 Not found. with token auth alone. There is no token-capable REST endpoint for run logs before Forgejo v16 (forgejo#12140).

The existing 3-mode 404 message (commit 21dda4b) already explains this well; this issue tracks the actual remediation.

Options (pick one)

  1. Artifact path: ship a helper/workflow pattern that uploads the job log as an actions/upload-artifact → attaches it as an issue attachment (which IS token-readable via download_issue_attachment). Requires a workflow-side step, so it's opt-in.
  2. Wait for Forgejo v16 REST log API (forgejo#12140) and switch to it natively.

Not in scope for the pagination/dispatch release; tracked separately because it needs workflow changes, not just MCP code.

Found by the forgejo-mcp tool-call forensic audit, 2026-06-17.

## Severity: HIGH impact, but this is a Forgejo v14 limitation — NOT a forgejo-mcp bug ## Symptom (recurring across repos & months) `get_run_logs(run_id=<run_number>, job_index=0)` → ``` MCP error -32603: logs 404 at /<owner>/<repo>/actions/runs/<N>/jobs/0/attempt/1/logs. ``` Recurs in flow.raven (2026-06-17), flow.RagIO (2026-05-27), flow.raven-deployment (2026-05-20/21). ## Root cause (independently curl-verified 2026-05-21) Forgejo v14 serves Action-run logs **only** via web routes that require a **session cookie**; the bearer-token auth this MCP holds (ADR-KV-018 token discipline) is rejected — every log URL returns `404 Not found.` with token auth alone. There is no token-capable REST endpoint for run logs before Forgejo v16 (forgejo#12140). The existing 3-mode 404 message (commit 21dda4b) already explains this well; this issue tracks the actual remediation. ## Options (pick one) 1. **Artifact path:** ship a helper/workflow pattern that uploads the job log as an `actions/upload-artifact` → attaches it as an issue attachment (which IS token-readable via `download_issue_attachment`). Requires a workflow-side step, so it's opt-in. 2. **Wait for Forgejo v16** REST log API (forgejo#12140) and switch to it natively. Not in scope for the pagination/dispatch release; tracked separately because it needs workflow changes, not just MCP code. Found by the forgejo-mcp tool-call forensic audit, 2026-06-17.
Author
Owner

Remediation recommendation (evidence-backed)

Server version — confirmed Forgejo 14.0.3

flow.raven-deployment/k8s/forgejo/values.yaml:3# Chart: forgejo-helm/forgejo v16.2.1 (appVersion: Forgejo 14.0.3). The Helm chart is 16.2.1; the appVersion (the actual Forgejo binary) is 14.0.3. So the token-capable REST log API (forgejo#12140, lands in Forgejo v16) is not present — your root-cause analysis holds exactly.

The whole log path is one raw-HTTP call with token-only auth:

  • operation/actions/run_logs.go:158 fetchJobLogs → calls DoRaw against the web route /{owner}/{repo}/actions/runs/{run}/jobs/{job}/attempt/{attempt}/logs (run_logs.go:26, comment) — the cookie-gated UI route.
  • pkg/forgejo/rawhttp.go:280 and :327 (DoRaw/DoRawToFile) set only req.Header.Set("Authorization", "token "+flag.Token). There is no http.CookieJar on rawHTTPClient (rawhttp.go:55).

So option (b) = add a login → CSRF-token → session-cookie flow + a cookie jar entirely inside pkg/forgejo. Self-contained in the MCP, but it requires storing a Forgejo username + password (session login isn't token-based) — which directly conflicts with the ADR-KV-018 token-discipline invariant (the server holds only a scoped token; agents never see creds). It also re-implements browser auth that breaks on every Forgejo CSRF/session change. Net: technically feasible, but it trades the single auditable token surface for a username/password — a real regression on the very property the MCP was hardened around.

Ranked recommendation

#1 — Option (a): wait for the Forgejo v16 REST log API (forgejo#12140), switch natively.
The current 3-mode 404 message (commit 21dda4b) already degrades gracefully and tells the caller exactly why. The upstream is moving (chart already at 16.2.1; only the app binary lags at 14.0.3), so the clean fix is a server bump, not MCP code that fights the auth model. Zero token-discipline cost, zero new code surface. Track the v16 bump and flip DoRaw → the /api/v1/.../logs endpoint when it exists.

#2 — Option (c): opt-in artifact upload (actions/upload-artifact → issue attachment, pulled via download_issue_attachment, which is token-readable). This is the right stopgap if a specific workflow genuinely needs token-readable logs before v16. It stays inside token-auth, but it's cross-repo (needs a workflow-side step in each repo that wants it) and per-workflow opt-in, so it's effort-per-consumer, not a platform fix.

#3 (do not) — Option (b): session-cookie auth in the MCP. Rejected: it forces username/password storage, breaking ADR-KV-018, to work around a limitation that v16 removes anyway.

TL;DR: keep the current graceful 404 (it's correct), wait for the v16 REST endpoint (#1), and only reach for the artifact-upload workaround (#2) if a concrete workflow needs token-readable logs before the bump. Don't wire cookie auth into the MCP.

Found via the forgejo-mcp follow-up audit, 2026-06-17.

## Remediation recommendation (evidence-backed) ### Server version — confirmed Forgejo **14.0.3** `flow.raven-deployment/k8s/forgejo/values.yaml:3` → `# Chart: forgejo-helm/forgejo v16.2.1 (appVersion: Forgejo 14.0.3)`. The Helm *chart* is 16.2.1; the *appVersion* (the actual Forgejo binary) is **14.0.3**. So the token-capable REST log API (forgejo#12140, lands in Forgejo **v16**) is **not** present — your root-cause analysis holds exactly. ### Where option (b) would live (grounding the cookie-auth feasibility) The whole log path is one raw-HTTP call with token-only auth: - `operation/actions/run_logs.go:158` `fetchJobLogs` → calls `DoRaw` against the web route `/{owner}/{repo}/actions/runs/{run}/jobs/{job}/attempt/{attempt}/logs` (`run_logs.go:26`, comment) — the cookie-gated UI route. - `pkg/forgejo/rawhttp.go:280` and `:327` (`DoRaw`/`DoRawToFile`) set **only** `req.Header.Set("Authorization", "token "+flag.Token)`. There is no `http.CookieJar` on `rawHTTPClient` (`rawhttp.go:55`). So option (b) = add a login → CSRF-token → session-cookie flow + a cookie jar entirely inside `pkg/forgejo`. Self-contained in the MCP, **but** it requires storing a Forgejo **username + password** (session login isn't token-based) — which directly conflicts with the ADR-KV-018 token-discipline invariant (the server holds only a scoped token; agents never see creds). It also re-implements browser auth that breaks on every Forgejo CSRF/session change. Net: technically feasible, but it trades the single auditable token surface for a username/password — a real regression on the very property the MCP was hardened around. ## Ranked recommendation **#1 — Option (a): wait for the Forgejo v16 REST log API (forgejo#12140), switch natively.** The current 3-mode 404 message (commit 21dda4b) already degrades gracefully and tells the caller exactly why. The upstream is moving (chart already at 16.2.1; only the app binary lags at 14.0.3), so the clean fix is a server bump, not MCP code that fights the auth model. Zero token-discipline cost, zero new code surface. Track the v16 bump and flip `DoRaw` → the `/api/v1/.../logs` endpoint when it exists. **#2 — Option (c): opt-in artifact upload** (`actions/upload-artifact` → issue attachment, pulled via `download_issue_attachment`, which *is* token-readable). This is the right stopgap **if** a specific workflow genuinely needs token-readable logs before v16. It stays inside token-auth, but it's cross-repo (needs a workflow-side step in each repo that wants it) and per-workflow opt-in, so it's effort-per-consumer, not a platform fix. **#3 (do not) — Option (b): session-cookie auth in the MCP.** Rejected: it forces username/password storage, breaking ADR-KV-018, to work around a limitation that v16 removes anyway. **TL;DR:** keep the current graceful 404 (it's correct), wait for the v16 REST endpoint (#1), and only reach for the artifact-upload workaround (#2) if a concrete workflow needs token-readable logs before the bump. Don't wire cookie auth into the MCP. Found via the forgejo-mcp follow-up audit, 2026-06-17.
Author
Owner

The existing self-hosted-Forgejo upgrade issue is Philflow/flow.raven-deployment#267 (chore(forgejo): upgrade self-hosted instance v14.0.3 → v15.0, open).

Important: that upgrade does NOT unblock this issue. #267 targets v15.0, and v15 does not add the token-capable Action-log REST API — #267 even lists "Forgejo v16+" as explicitly out of scope. The fix this issue needs (forgejo#12140) lands in v16.

So the dependency chain is: this issue stays blocked until a v16 upgrade exists and is tracked — not v15. When a v16 bump is planned, flip DoRaw in pkg/forgejo/rawhttp.go over to the /api/v1/.../logs endpoint. No MCP-side action until then; the current graceful 3-mode 404 (commit 21dda4b) is the correct interim behaviour.

## Cross-link to the Forgejo upgrade tracker — but note the version gap The existing self-hosted-Forgejo upgrade issue is **`Philflow/flow.raven-deployment#267`** (`chore(forgejo): upgrade self-hosted instance v14.0.3 → v15.0`, open). **Important: that upgrade does NOT unblock this issue.** #267 targets **v15.0**, and v15 does not add the token-capable Action-log REST API — #267 even lists "Forgejo v16+" as explicitly *out of scope*. The fix this issue needs (forgejo#12140) lands in **v16**. So the dependency chain is: this issue stays blocked until a **v16** upgrade exists and is tracked — not v15. When a v16 bump is planned, flip `DoRaw` in `pkg/forgejo/rawhttp.go` over to the `/api/v1/.../logs` endpoint. No MCP-side action until then; the current graceful 3-mode 404 (commit 21dda4b) is the correct interim behaviour.
Sign in to join this conversation.
No labels
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
Phil/forgejo-mcp#9
No description provided.