fix(usage): read the social-login token key in the free credit API path - #2292
Conversation
Design Review (Fable 5) — ✅ PASSAdvisory design-level review of Design-Verdict: PASS Root-cause data fix in the mechanism's designated extension point — new keys in WatchEnd-to-end verification covers only the social path; the Identity Center claim rests on the shared blob shape plus the "kiro-cli's own store needs no profile ARN" trust rule in [DESIGN-REVIEWED] 672738a |
Opus 5 Review — ✅ no blocking findingsReviewed Verdict parsed from the review's SHA-scoped output markers for commit False positive or not applicable? A repository writer can comment: |
GPT 5.6 Review — ✅ no blocking findingsGPT 5.6 completed its review of This comment is updated in place on each push. Review detailsNo findings. False positive or not applicable? A repository writer can comment: |
The kiro_usage_api module's _SQLITE_TOKEN_KEYS tuple only contained the OIDC and legacy CodeWhisperer keys. Users signed in via GitHub social login store their bearer token under kirocli:social:token, which was never searched -- leaving the free GetUsageLimits path non-functional for this login class. Since #2039 made the text scrape opt-in (default off), these users see no credit pill at all. Add kirocli:social:token to the key list. The token blob has the same {access_token, expires_at} shape the existing parser expects; no format change is needed. Verified end-to-end on a real social-login host. Closes #2291
12b7509 to
672738a
Compare
Problem
Users signed in via GitHub/Google social login or Identity Center (org SSO) see no credit pill in the dashboard header. The pill either shows a permanent spinner or hides entirely.
Why it matters
The credit meter is the user's primary visibility into plan usage. With #2039's correct change making the text scrape opt-in (default off), the free API path is the only zero-cost way to surface credits — and it silently fails for two of the four login classes.
Fix (symptoms → root cause → change)
Symptom: Credit pill hidden;
/api/sessions/usagereturns{available: false}.Root cause:
kiro_usage_api.fetch_usage_limits()searches kiro-cli's SQLiteauth_kvtable for bearer tokens, but only under two of the four key names kiro-cli uses:kirocli:odic:tokencodewhisperer:odic:tokenkirocli:social:tokenkirocli:external-idp:tokenKey names confirmed by reverse-engineering kiro-cli binary strings — all four use the same
{access_token, expires_at}blob shape.Change: Add
"kirocli:social:token"and"kirocli:external-idp:token"to_SQLITE_TOKEN_KEYS. No parser or format change needed.This does NOT revert #2039. The text scrape remains opt-in. This fixes the free API path so all login classes get credits without paying for the scrape.
Tests
test_social_login_token_key_is_recognized— social-key token found from kiro-cli storetest_external_idp_token_key_is_recognized— external-idp-key token found from kiro-cli storetest_kiro_usage_api.pytests pass.Manual verification
Verified end-to-end on a real social-login host (GitHub,
kiro-cli whoami→ "Logged in with GitHub"):_candidate_tokens()→ 0 candidates →fetch_usage_limits→ None_candidate_tokens()→ 1 candidate (from_cli_store=True) →GetUsageLimits200 →{credits_used: 2480.54, credits_plan: 5000.0, plan: "KIRO PRO MAX"}Closes #2291