refactor(database): the key store's primary key includes kind

Merged
CH
5d ago
+15043-154

P04c of the "Bringing Codex or Claude Code Max plans into Luke" rollout (plan). This is the second step of the split that started in #4205.

What changes

  • Migration 20261020212152_account_provider_key_primary_key_kind: a single ALTER TABLE drops the old (user_id, provider) primary key and adds account_provider_key_pkey with PRIMARY KEY USING INDEX on #4180's unique index account_provider_key_user_provider_kind_idx. Nothing is rebuilt, and the table always has a key. The statement is wrapped in a DO block that checks for the old constraint, so it is idempotent. It was generated with pnpm --filter @luke/database db:generate --hints '[{"type":"create","kind":"primary_key",…}]' as #4205 describes, then the SQL was replaced with the swap. The snapshot now has the three-column PK and no separate index.
  • Store (provider-key-store.ts): upsertRow no longer has the setWhere kind match, and saveProviderKey no longer has the UniqueViolation catch. saveProviderKey now returns void, because it always keeps the row. The rewrap's where and the full-table read now include kind.
  • Procedures (provider-keys-procedures.ts): the subscriptionHeld pre-check and both other_kind_held answers are removed. An Anthropic API key and a claude_setup_token for the same account and provider now sit side by side. Each is saved and removed by its own kind.
  • Wire: the other_kind_held rejection literal is removed, along with its Settings wording and the two JSON-schema goldens (regenerated with LUKE_UPDATE_FIXTURES=1; the diff is only the dropped enum member). Clients that already shipped still decode every answer. No server answers that rejection any more.

Safety

The deployment before this one must upsert on the three columns. That is #4205 (e22ea70eb), merged at 21:15 UTC. This PR is merged only after production includes that commit.

Tests

  • Store: an API key and a setup-token coexist for one account and provider. Each is replaced by its own kind. Removing one kind leaves the other. Another account's rows are untouched.
  • Procedures: a token saved beside a key, and a key beside a token. Neither is rejected, and only the key is checked with the provider. Removing either one leaves the other.
  • Rewrap: one account holds both kinds for Anthropic, and both move onto the new version.
  • check:migrations and check:contractions pass. The PGlite store tests apply the swap.

The developer waived WORKFLOW.md's Preview/Mac runs for this rollout. Nothing here is user-visible.

Made with Luke


Devin Review