docs(augment): add OpenSpec proposal for per-user Kagenti token exchange#3330
docs(augment): add OpenSpec proposal for per-user Kagenti token exchange#3330gabemontero wants to merge 6 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3330 +/- ##
=======================================
Coverage 50.28% 50.28%
=======================================
Files 2260 2260
Lines 85603 85603
Branches 24211 24211
=======================================
Hits 43044 43044
Misses 42058 42058
Partials 501 501
*This pull request uses carry forward flags. Click here to find out more. Continue to review full report in Codecov by Harness.
🚀 New features to boost your workflow:
|
|
thanks for the thorough review @pkliczewski I've pushed the new commit with changes stemming from your comments I've refrained from resolving any conversations .... certainly at least some of them will require more iteration on our part (and possibly non-trivial adjustments) after you see the updates |
|
@gabemontero thanks, resolved most of the comments |
c607ed5 to
104bea5
Compare
thanks @pkliczewski - remaining comment addressed and commit pushed |
|
/lgtm |
|
fyi @pkliczewski I've gotten agreement from @PatAKnight to review this proposal as well |
Code Review by Qodo
1. Frontend scope mismatch
|
|
/assign @PatAKnight |
PR Summary by QodoAdd OpenSpec proposal for per-user Kagenti OAuth2 token exchange WalkthroughsDescription• Add OpenSpec proposal/design for per-user Kagenti RFC 8693 token exchange. • Specify token-exchange and user-token-routing requirements, scenarios, and fallback behavior. • Provide an implementation task breakdown and preliminary plan as source material. Diagramgraph TD
FE["Frontend (Augment)"] --> RT["Backend routes"] --> TEM["TokenExchangeManager"] --> IDP[("IdP token endpoint")]
TEM --> KAG["Kagenti API"]
RT --> SA["Service-account token"] --> KAG
High-Level AssessmentThe following are alternative approaches to this PR: 1. Move the preliminary implementation plan out of OpenSpec
2. Split design decisions into separate ADR files
3. Consolidate into a single spec with sections (instead of two specs)
Recommendation: Keep the current multi-document OpenSpec structure (proposal/design/specs/tasks), but consider relocating or rewording the preliminary plan so it can’t be mistaken for already-merged implementation (e.g., remove/adjust any ‘implementation complete’ phrasing). The split into token-exchange vs user-token-routing is a good boundary for future implementation and review. File ChangesDocumentation (6)
Other (1)
|
PatAKnight
left a comment
There was a problem hiding this comment.
I don't have the most solid grasp on Auth in this context so I might not be able to catch the more minor details but overall it looks fine to me. I did notice that in the middle you were talking about using the frontend with useApiHolder but the proposal.md and tasks.md all mention backend specific work.
|
Thanks for the review @PatAKnight! Good catch on the frontend/backend disconnect — the design.md was updated to include frontend OIDC discovery via I've clarified the phasing: this change covers the backend-only implementation (header-based OIDC token acquisition). Frontend OIDC discovery via Also addressed your inline comment about configurable fallback — see the reply there. |
104bea5 to
9ace505
Compare
|
New changes are detected. LGTM label has been removed. |
|
@PatAKnight @pkliczewski @rrbanda so after another round of deciding whether this current proposal is truly viable, I think I've convinced myself that this staged approach of depending on a 3rd party to inject the user's OIDC access token is not sufficient (i.e. customers won't want to set that up, don't already have it), and we need to bring in user OIDC discovery back to the augment frontend. About to push a couple a commit that does that This also makes me wonder if we go ahead and pursue #3331 (finer grained RBAC) beforehand and independent of this change. |
Add OpenSpec artifacts for the kagenti-user-level-token-exchange change, which implements RFC 8693 OAuth2 Token Exchange for the Kagenti provider enabling per-user authorization instead of shared service-account tokens. Artifacts created: - proposal.md: motivation, capabilities (token-exchange, user-token-routing), impact - design.md: 5 architectural decisions with alternatives, risks, and constraints - specs/token-exchange/spec.md: 7 requirements, 15 scenarios (config, RFC 8693 execution, caching, dedup, streaming, fallback, no-impact guarantee) - specs/user-token-routing/spec.md: 6 requirements, 8 scenarios (header routing, route extraction, interface widening, backward compatibility) - tasks.md: 6 task groups, 19 implementation tasks ordered by dependency Includes the preliminary implementation plan used as source material. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: gabemontero <gmontero@redhat.com>
…roposal - List supported audience values (Kagenti API client ID, RHDH client ID, or any Keycloak client with exchange permissions) - Use fully qualified `auth.tokenEndpoint` consistently - Add note explaining unsupported_grant_type is a defensive fallback, broaden language from Keycloak to IdP - Defer refresh token support with rationale for re-exchange-on-expiry - Remove duplicate "token exchange disabled" scenario, merge into single "disabled or not configured" scenario - Add inline examples to userTokenHeader in user-token-routing spec - Clarify custom auth mechanism support in Decision 1 - Add log severity levels to Decision 3 fallback cases, document fail-hard as considered-and-rejected alternative - Add Prerequisites section documenting deployment requirements - Explain OIDC token refresh responsibility lies with injection layer Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: gabemontero <gmontero@redhat.com>
…on path Adopt the orchestrator's useApiHolder() pattern for runtime OIDC provider discovery, making it the primary path for acquiring the user's OIDC token for RFC 8693 exchange. The header-based approach becomes the fallback for non-OIDC deployments where frontend discovery is not available. - Rewrite Decision 1 from "backend-only with configurable header" to "frontend OIDC discovery with header-based fallback" - Add new user-token-routing requirement for frontend OIDC token acquisition via useApiHolder() and the orchestrator's findCustomProvider pattern, with scenarios for first-time login, existing session, and provider-not-discoverable - Update chat route token extraction to account for both frontend-acquired and header-based token sources - Add risk for useApiHolder() private API fragility (apiHolder.apis accessed via @ts-ignore), mitigated by orchestrator already shipping this pattern in production RHDH - Update prerequisites, goals, and config documentation to reflect dual-path acquisition Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: gabemontero <gmontero@redhat.com>
…rable fallback - Clarify phasing: this change is backend-only (header-based OIDC token acquisition); frontend OIDC discovery via useApiHolder() is a planned follow-up - Add fallbackToServiceAccount config option (default: true) so strict security environments can opt out of silent fallback to service-account token - Update design.md, proposal.md, specs, and tasks.md for consistency Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: gabemontero <gmontero@redhat.com>
Header-only token acquisition is insufficient for the common RHDH deployment pattern where users log in via Backstage's built-in Keycloak auth — Backstage replaces the user's OIDC token with its own JWT, and these deployments typically don't have an auth proxy injecting the original token into a header. Frontend OIDC discovery via useApiHolder() (modeled on the orchestrator's findCustomProvider pattern) is now the primary token acquisition path, with header-based extraction as the fallback for non-OIDC deployments and headless environments. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: gabemontero <gmontero@redhat.com>
…olutions - Transport: frontend sets same userTokenHeader that backend already reads - File paths: added useKagentiOidcToken.ts hook, AugmentApi.ts modifications - UX trigger: discover on mount, acquire token lazily on first interaction - Fixed getIdToken() -> getAccessToken() (OAuthApi for RFC 8693 access_token) - Token lifecycle: provider handles refresh, hook caches provider reference - Config visibility: tokenExchange.enabled marked @visibility frontend - Dynamic plugin: no export/wiring changes needed, hook is internal - Task specificity: section 6 now has file paths and detailed descriptions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
25931fb to
0358fc7
Compare
|



Hey, I just made a Pull Request!
Add OpenSpec artifacts for the kagenti-user-level-token-exchange change, which implements RFC 8693 OAuth2 Token Exchange for the Kagenti provider enabling per-user authorization instead of shared service-account tokens.
Artifacts created:
Includes the preliminary implementation plan used as source material.
✔️ Checklist