feat(pr): name the scopes behind a compare 404 #85

Merged
Claude-Run merged 1 commit from feat/pr-compare-scope-error into main 2026-08-01 03:32:24 +02:00
Member

Forgejo's compare handler answers a scope-reduced token with a bare 404 carrying Can't read pulls or can't read UnitTypeCode (base repo) or Can't read headRepo UnitTypeCode (head repo), because parseCompareInfo requires pull read AND code read, each reduced by the token's scopes. fj pr create compares before creating (to guess a title and body when the repo has no PR template), so a token with an issue scope but no repository scope failed with a raw "not found" that named neither the token, the repo, nor the missing scope, and read like an authentication failure. fj pr search on the same repo succeeded, which made the failure look impossible to explain by scopes.

fj_core::prs::compare now maps both of those 404 bodies to an error naming the two scopes (read:issue and read:repository), the repo, and the refs being compared, keeping the server's own text as context. Every compare call site (the CLI's pr create, the new pr compare, and the MCP compare_refs tool) routes through that one function, so all three get the mapped error. Any other error, including an unrelated 404, passes through unchanged.

Add fj pr compare <base...head>, which runs exactly that call, so a caller can pre-flight the credential pr create will use without falling back to raw HTTP against /api/v1/.... It renders a commit/file summary as text and the full comparison under --json.

fj pr create also skips the compare entirely when both a title and a body are supplied: the compare exists only to guess them, so the scripted case no longer needs the repository scope for that call.

Covered by unit tests that build the error from stubbed 404 bodies (base denial, head denial, and an unrelated 404 that must pass through) and by a test that formats the new Fluent messages.

#FJ-64

Forgejo's compare handler answers a scope-reduced token with a bare `404` carrying `Can't read pulls or can't read UnitTypeCode` (base repo) or `Can't read headRepo UnitTypeCode` (head repo), because `parseCompareInfo` requires pull read AND code read, each reduced by the token's scopes. `fj pr create` compares before creating (to guess a title and body when the repo has no PR template), so a token with an issue scope but no repository scope failed with a raw "not found" that named neither the token, the repo, nor the missing scope, and read like an authentication failure. `fj pr search` on the same repo succeeded, which made the failure look impossible to explain by scopes. `fj_core::prs::compare` now maps both of those 404 bodies to an error naming the two scopes (`read:issue` and `read:repository`), the repo, and the refs being compared, keeping the server's own text as context. Every compare call site (the CLI's `pr create`, the new `pr compare`, and the MCP `compare_refs` tool) routes through that one function, so all three get the mapped error. Any other error, including an unrelated 404, passes through unchanged. Add `fj pr compare <base...head>`, which runs exactly that call, so a caller can pre-flight the credential `pr create` will use without falling back to raw HTTP against `/api/v1/...`. It renders a commit/file summary as text and the full comparison under `--json`. `fj pr create` also skips the compare entirely when both a title and a body are supplied: the compare exists only to guess them, so the scripted case no longer needs the repository scope for that call. Covered by unit tests that build the error from stubbed 404 bodies (base denial, head denial, and an unrelated 404 that must pass through) and by a test that formats the new Fluent messages. #FJ-64
feat(pr): name the scopes behind a compare 404
All checks were successful
Check / fmt + clippy + build + tests (pull_request) Successful in 1m1s
Create release / Create release from merged PR (pull_request) Has been skipped
7ef0a4a36f
Forgejo's compare handler answers a scope-reduced token with a bare `404` carrying `Can't read pulls or can't read UnitTypeCode` (base repo) or `Can't read headRepo UnitTypeCode` (head repo), because `parseCompareInfo` requires pull read AND code read, each reduced by the token's scopes. `fj pr create` compares before creating (to guess a title and body when the repo has no PR template), so a token with an issue scope but no repository scope failed with a raw "not found" that named neither the token, the repo, nor the missing scope, and read like an authentication failure. `fj pr search` on the same repo succeeded, which made the failure look impossible to explain by scopes.

`fj_core::prs::compare` now maps both of those 404 bodies to an error naming the two scopes (`read:issue` and `read:repository`), the repo, and the refs being compared, keeping the server's own text as context. Every compare call site (the CLI's `pr create`, the new `pr compare`, and the MCP `compare_refs` tool) routes through that one function, so all three get the mapped error. Any other error, including an unrelated 404, passes through unchanged.

Add `fj pr compare <base...head>`, which runs exactly that call, so a caller can pre-flight the credential `pr create` will use without falling back to raw HTTP against `/api/v1/...`. It renders a commit/file summary as text and the full comparison under `--json`.

`fj pr create` also skips the compare entirely when both a title and a body are supplied: the compare exists only to guess them, so the scripted case no longer needs the repository scope for that call.

Covered by unit tests that build the error from stubbed 404 bodies (base denial, head denial, and an unrelated 404 that must pass through) and by a test that formats the new Fluent messages.

#FJ-64
Claude-Run deleted branch feat/pr-compare-scope-error 2026-08-01 03:32:24 +02:00
Sign in to join this conversation.
No reviewers
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
pandoras-box/forgejo-cli!85
No description provided.