fix: decode Forgejo negative system-actor user ids in pr list/view #231

Merged
stephen merged 1 commit from fix/pr-decode-negative-user-id into main 2026-07-25 01:02:20 +00:00
Owner

Problem

fj pr list / fj pr view fail on any repo where a Forgejo system actor appears as a reviewer, assignee, poster, or author:

error: decoding JSON list response
  caused by: invalid value: integer `-2`, expected u64

Forgejo uses negative sentinel user ids for system actors: -1 for Ghost (deleted user) and -2 for the forgejo-actions bot. rasterstate/fj#230 has forgejo-actions in requested_reviewers, so "id":-2 is in the pulls payload. The canonical User model decoded id as u64, so serde rejected the value and the whole list/detail decode failed. This red-lit the release live-e2e smoke, which runs fj pr list -R rasterstate/fj --state all.

Fix

Change the Forgejo User.id field from u64 to i64 in src/api/user.rs. This is the single user shape reused across pulls, issues, reviews, comments, repo owner, requested reviewers, and assignees (it is the only struct in the models with a login field), so one change covers every actor field. Non-user ids (repo, PR, review, issue, milestone, label) are left unsigned; Forgejo only uses negatives for user/actor rows.

Test

Added api::user::tests::deserializes_negative_system_actor_id: deserializes {"id":-2,"login":"forgejo-actions"} and asserts the signed id and login decode.

Verify

  • cargo test: 683 passed, 2 ignored, 0 failed (includes the new test).
  • cargo build --release && ./target/release/fj pr list -R rasterstate/fj --state all decodes cleanly (exit 0), including #230; fj pr view 230 -R rasterstate/fj also decodes.

Operator-merge only.

## Problem `fj pr list` / `fj pr view` fail on any repo where a Forgejo system actor appears as a reviewer, assignee, poster, or author: ``` error: decoding JSON list response caused by: invalid value: integer `-2`, expected u64 ``` Forgejo uses negative sentinel user ids for system actors: `-1` for Ghost (deleted user) and `-2` for the `forgejo-actions` bot. rasterstate/fj#230 has `forgejo-actions` in `requested_reviewers`, so `"id":-2` is in the pulls payload. The canonical `User` model decoded `id` as `u64`, so serde rejected the value and the whole list/detail decode failed. This red-lit the release `live-e2e` smoke, which runs `fj pr list -R rasterstate/fj --state all`. ## Fix Change the Forgejo `User.id` field from `u64` to `i64` in `src/api/user.rs`. This is the single user shape reused across pulls, issues, reviews, comments, repo owner, requested reviewers, and assignees (it is the only struct in the models with a `login` field), so one change covers every actor field. Non-user ids (repo, PR, review, issue, milestone, label) are left unsigned; Forgejo only uses negatives for user/actor rows. ## Test Added `api::user::tests::deserializes_negative_system_actor_id`: deserializes `{"id":-2,"login":"forgejo-actions"}` and asserts the signed id and login decode. ## Verify - `cargo test`: 683 passed, 2 ignored, 0 failed (includes the new test). - `cargo build --release && ./target/release/fj pr list -R rasterstate/fj --state all` decodes cleanly (exit 0), including #230; `fj pr view 230 -R rasterstate/fj` also decodes. Operator-merge only.
fix(api): decode Forgejo user id as i64 so negative system-actor ids (Ghost, forgejo-actions) don't break pr list/view
All checks were successful
Forseti review / forseti review (advisory) (pull_request_target) Successful in 9s
ci / check (pull_request) Successful in 10m26s
ci / coverage (pull_request) Successful in 1m58s
ci / live-e2e (pull_request) Successful in 1m58s
49bde47abc

Forseti review

No blocking findings from the lead reviewer.

No inline findings.

  • PR: rasterstate/fj#231
  • Head SHA: 49bde47abc87
  • Review job: sha256:0ca9d499ff5e94d2bcc6d183f51106805a2c0128c58c1c17b231688bb5633a00
  • Provider pair: openai:gpt-5.5+anthropic:claude-haiku-4-5-20251001
  • Blocking findings: 0
  • Inline findings: 0
  • Token source: GITHUB_TOKEN
  • Runner: e675d37c9729
  • Run: https://rasterhub.com/rasterstate/fj/actions/runs/394
<!-- forseti:review {"version":2,"repo":"rasterstate/fj","pr":231,"head_sha":"49bde47abc873490bda46231de1457e289c9134e","provider_pair":"openai:gpt-5.5+anthropic:claude-haiku-4-5-20251001","policy_version":"stub-policy-v1","prompt_version":"prompt-v2","context_fingerprint":"fnv64:7265389ada6127a9","review_job_key":"sha256:0ca9d499ff5e94d2bcc6d183f51106805a2c0128c58c1c17b231688bb5633a00","base_sha":"62d4d7f670add61e8466cec0604c7aab6428d581","role":"summary","status":"current"} --> ## Forseti review No blocking findings from the lead reviewer. _No inline findings._ - PR: `rasterstate/fj#231` - Head SHA: `49bde47abc87` - Review job: `sha256:0ca9d499ff5e94d2bcc6d183f51106805a2c0128c58c1c17b231688bb5633a00` - Provider pair: `openai:gpt-5.5+anthropic:claude-haiku-4-5-20251001` - Blocking findings: `0` - Inline findings: `0` - Token source: `GITHUB_TOKEN` - Runner: `e675d37c9729` - Run: https://rasterhub.com/rasterstate/fj/actions/runs/394
forgejo-actions left a comment

Forseti review

No blocking findings from the lead reviewer.

No inline findings.

  • PR: rasterstate/fj#231
  • Head SHA: 49bde47abc87
  • Review job: sha256:0ca9d499ff5e94d2bcc6d183f51106805a2c0128c58c1c17b231688bb5633a00
  • Provider pair: openai:gpt-5.5+anthropic:claude-haiku-4-5-20251001
  • Blocking findings: 0
  • Inline findings: 0
  • Token source: GITHUB_TOKEN
  • Runner: e675d37c9729
  • Run: https://rasterhub.com/rasterstate/fj/actions/runs/394
<!-- forseti:review {"version":2,"repo":"rasterstate/fj","pr":231,"head_sha":"49bde47abc873490bda46231de1457e289c9134e","provider_pair":"openai:gpt-5.5+anthropic:claude-haiku-4-5-20251001","policy_version":"stub-policy-v1","prompt_version":"prompt-v2","context_fingerprint":"fnv64:7265389ada6127a9","review_job_key":"sha256:0ca9d499ff5e94d2bcc6d183f51106805a2c0128c58c1c17b231688bb5633a00","base_sha":"62d4d7f670add61e8466cec0604c7aab6428d581","role":"summary","status":"current"} --> ## Forseti review No blocking findings from the lead reviewer. _No inline findings._ - PR: `rasterstate/fj#231` - Head SHA: `49bde47abc87` - Review job: `sha256:0ca9d499ff5e94d2bcc6d183f51106805a2c0128c58c1c17b231688bb5633a00` - Provider pair: `openai:gpt-5.5+anthropic:claude-haiku-4-5-20251001` - Blocking findings: `0` - Inline findings: `0` - Token source: `GITHUB_TOKEN` - Runner: `e675d37c9729` - Run: https://rasterhub.com/rasterstate/fj/actions/runs/394
stephen deleted branch fix/pr-decode-negative-user-id 2026-07-25 01:02:20 +00:00
Sign in to join this conversation.
No description provided.