Skip to content

fix: token validation performance with cached org names#35

Open
JoshSalway wants to merge 8 commits intolaravel:mainfrom
JoshSalway:fix/token-validation-performance
Open

fix: token validation performance with cached org names#35
JoshSalway wants to merge 8 commits intolaravel:mainfrom
JoshSalway:fix/token-validation-performance

Conversation

@JoshSalway
Copy link

Summary

  • Cache org names with tokens: Auth.php now stores organization_name and organization_id alongside tokens in config.json. resolveApiToken() uses cached metadata for the org picker instead of making sequential API calls per token on every CLI invocation.
  • File-based Saloon cache: Switch Connector cache driver from array (in-memory only, useless across CLI invocations) to file with a 5-minute TTL, so repeated CLI commands don't re-fetch the same API data.
  • Backwards compatible: Legacy plain-string tokens in config.json are auto-normalized via apiTokenEntries(). On first multi-token resolution with legacy data, org names are fetched once and then persisted for future use.

Closes #31

Test plan

  • All 40 existing tests pass (./vendor/bin/pest)
  • Test with single token in config (no org picker shown, no API call for org name)
  • Test with multiple tokens: verify org picker uses cached names without spinner/API calls
  • Test backwards compatibility: manually set api_tokens to ["token1", "token2"] in config.json, run a command, verify it falls back to API calls and then upgrades the format
  • Test cloud auth stores the new format with organization_name and organization_id
  • Verify file cache persists between CLI invocations (check storage/framework/cache/data/)

🤖 Generated with Claude Code

Josh Salway and others added 8 commits March 16, 2026 21:56
When authenticating multiple times, the same API tokens were appended
to config.json without deduplication. Each duplicate token triggered a
separate API call returning the same organization, causing the org
selection prompt to show duplicate entries.

Add unique() to both apiTokens() (to handle existing duplicated configs)
and addApiToken() (to prevent future duplicates).

Fixes laravel#22

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When running `cloud auth` multiple times, old tokens accumulated in
config.json because new tokens were appended without removing previous
ones. Expired/revoked tokens were never cleaned up, causing
`{"message":"Required."}` errors when the CLI tried to use them.

Three fixes:
- Auth command now replaces all tokens with fresh ones from the auth
  session instead of appending, preventing stale token buildup
- Token resolution now validates tokens via API before use and
  automatically removes expired/invalid ones from config
- Added ConfigRepository::setApiTokens() for bulk token replacement

Closes laravel#23

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The isValidToken() check made an unmocked API call to /api/meta/organization
on every command, causing 5 test failures. For a single token, just use it
directly — if expired, the actual command will fail with a clear auth error.
Token validation is only needed when choosing among multiple tokens.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Proves both Issue laravel#22 and laravel#23 fixes with 6 targeted tests:
- addApiToken() no longer accumulates duplicates (was 5, now 1)
- apiTokens() deduplicates existing bloated configs on read
- setApiTokens() atomically replaces all tokens
- setApiTokens() deduplicates input
- removeApiToken() removes specific tokens
- Empty config returns empty collection

All 6 tests FAIL on main branch (confirming the bugs exist) and
PASS on this branch (confirming the fixes work).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ensures setApiTokens correctly handles users with multiple orgs:
- Preserves multiple tokens (one per org)
- Atomically replaces all org tokens on re-auth
- Handles org count changing between auth sessions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Enable non-interactive token authentication for CI/CD pipelines, Docker
containers, and AI assistants. Token resolution priority:
--token flag > LARAVEL_CLOUD_API_TOKEN env var > stored config > prompt.

Tokens passed via flag or env var are used directly without validation
and are not persisted to config.json.

Closes laravel#27

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…cache

Cache organization names alongside tokens in config.json so that
resolveApiToken() can display the org picker without making sequential
API calls on every CLI invocation. Legacy plain-string tokens are
auto-upgraded on first use.

Also switch Saloon cache driver from array (in-memory only, useless
across CLI invocations) to file with a 5-minute TTL.

Closes laravel#31

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…x select() type

- Auth.php: Remove organization_id from token storage since exchangeCode()
  only returns {organization_name, token} — not organization_id
- HasAClient.php: Use ?? for optional organization_id from cached entries,
  use ->all() on select() options to satisfy PHPStan type checking
- ConfigRepository.php: Mark organization_id as optional in docblocks

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Performance: token validation makes O(N) sequential API calls on every command

1 participant