feat(providers): expose actionable OAuth refresh failures - #2887
Conversation
Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
johntmyers
left a comment
There was a problem hiding this comment.
gator-agent
PR Review Status
This PR is project-valid through accepted issue #2886. The initial review found one blocking OAuth error-classification defect; the provider docs and CLI skill updates otherwise cover the direct UX contract.
Action required: @mrunalp, preserve recognized top-level OAuth classifications when an optional subtype has an unexpected JSON type, and add the malformed-subtype regression case.
Blocking findings:
GATOR-88e83828-01: a non-string optional subtype discards a recognizedinvalid_grantclassification
Carried findings:
- None
Non-blocking suggestions:
- None
Gator metadata
- Validation: Implements accepted issue #2886 across the existing provider-refresh boundary
- Docs: Fern provider docs, gateway architecture, protobuf comments, and CLI skill updated
- Checks: DCO and vouch are green; required branch and E2E workflows are not dispatched for this head yet
- E2E:
test:e2erequired for provider credential flow; dispatch deferred until blocking review feedback is resolved - Head SHA:
88e8382897a857893f1a9dbba824e3a486819960 - Base SHA:
2f7fb65591ee5746217ace154afc0aa6bf1afc6d - Merge base SHA:
2f7fb65591ee5746217ace154afc0aa6bf1afc6d - Patch ID:
9f514aa29504caf111a75d371d6c06023ccbea9d - Gator payload:
6 - Review mode:
initial - Previous reviewed SHA: none
- Review budget exhausted: no
- Maintainer decision required: no
- Next state:
gator:in-review
| @@ -403,6 +414,121 @@ struct TokenResponse { | |||
| refresh_token: Option<String>, | |||
| } | |||
|
|
|||
There was a problem hiding this comment.
gator-agent
Warning — GATOR-88e83828-01 · Preserve recognized OAuth errors when subtype shape is unknown
Summary: When a configured issuer returns a recognized invalid_grant with a non-string error_subtype, deserializing the optional subtype rejects the entire response. Clients then receive investigate, and the worker retries every minute, instead of reporting reauthorize and parking the terminal user grant.
Fix: Parse the required top-level error independently, decode the subtype permissively, retain only recognized string values, and cover a malformed or unknown subtype.
Verify: Return HTTP 400 with {"error":"invalid_grant","error_subtype":{"vendor":"value"}} for a user refresh. The current result is Investigate/Short; it must be Reauthorize/Parked.
Agent context
- Location:
crates/openshell-server/src/provider_refresh.rs:416 - Ownership: This PR makes the new provider-controlled subtype parser authoritative for structured recovery.
Summary
Expose structured, provider-neutral recovery guidance for OAuth refresh failures so consumers can distinguish transient retries, operator configuration problems, and user reauthorization without parsing provider error text. Preserve safe diagnostics, stop rapid retries for terminal grants, and keep the existing credential-driver storage boundary unchanged.
Related Issue
Closes #2886
Changes
Testing
mise run pre-commitpassescargo test -p openshell-server --lib(1,430 passed, 8 ignored)mise run go:cimise run e2e:provider-refresh-keycloakChecklist