Skip to content

refactor(ai-gateway): share BYOK owner lookups and inline the direct BYOK dedupe - #8348

Merged
iscekic merged 1 commit into
mainfrom
drain/byok-owner-lookups-dedupe
Oct 21, 2026
Merged

iscekic merged 1 commit into
mainfrom
drain/byok-owner-lookups-dedupe

Conversation

@iscekic

@iscekic iscekic commented Oct 20, 2026

Copy link
Copy Markdown
Collaborator

What changed

packages/web-shared/src/lib/ai-gateway/byok/index.ts

  • The user and organization BYOK lookups now share one private query body
    parameterized by the owning column (byok_api_keys.kilo_user_id or
    byok_api_keys.organization_id): getByokRowsForOwner for decrypted rows and
    getEnabledByokProviderIds for provider-id lists.
  • The four exported functions keep their names, argument order, return types,
    and behavior: null for an empty provider list and for zero rows, ascending
    created_at order, is_enabled = true, and the same provider-id parsing.
    getBYOKforUser stays typed typeof db; getBYOKforOrganization keeps
    accepting a transaction.

packages/web-shared/src/lib/ai-gateway/providers/direct-byok/model-list.ts

  • The dedupe filter is an explicit body (if (seenIds.has(id)) return false; seenIds.add(id); return true;) instead of a comma-operator side effect inside
    a ternary. First occurrence still wins; the recommended flag merge and the
    reasoning_options fallback are unchanged.

Test added

packages/web-shared/src/lib/ai-gateway/byok/index.test.ts (DB-backed, runs
under the apps/web Jest config). It seeds two users and two organizations with
distinct created_at values and asserts, for both owner kinds:

  • each lookup returns only its own owner's keys (no cross-owner reads),
  • results follow ascending creation order,
  • disabled keys are excluded from both the decrypted rows and the provider-id
    list,
  • the decrypted secret belongs to the right provider,
  • an empty provider list and an owner without matching keys both yield null,
  • getBYOKforOrganization works inside a transaction.

End-to-end evidence

Local PostgreSQL from dev/docker-compose.yml (pnpm test:db, migrations
applied), real queries through the changed helpers, no mocks of the database:

pnpm --filter @kilocode/web-shared typecheck            # passed
NODE_ENV=test pnpm exec jest ../../packages/web-shared/src/lib/ai-gateway/byok/index.test.ts
  # 1 suite, 4 tests passed
NODE_ENV=test pnpm exec jest ../../packages/web-shared/src/lib/ai-gateway/providers/direct-byok \
  ../../packages/web-shared/src/lib/ai-gateway/byok src/lib/byok src/lib/providers/direct-byok
  # 11 suites, 104 tests passed
NODE_ENV=test pnpm exec jest ../../packages/web-shared/src/lib/ai-gateway/handlers \
  ../../packages/web-shared/src/lib/cloud-agent-next/balance-check-eligibility.test.ts \
  ../ai-gateway/src/app/api/v1/audience-auth.integration.test.ts \
  ../ai-gateway/src/app/api/v1/model-validation.integration.test.ts
  # 14 suites, 230 tests passed
pnpm -w exec oxlint ...                                  # 0 warnings, 0 errors
pnpm -w exec oxfmt ...                                   # formatted
git diff --check                                         # clean

The change is server-side query plumbing with no user-visible surface, so there
is no screenshot to publish. Behavior is observed through the real database
queries above, including the direct-byok merge output pinned by
model-list.test.ts (order, flags, reasoning options).

Proxy answers

The owner's proxy gave these answers in the owner's place.

  1. Question: Signature: getBYOKforUser is typed typeof db while getBYOKforOrganization accepts typeof db | DrizzleTransaction — the accidental divergence the finding names. How should the shared helper's signatures settle?
    Answer: Keep the user path narrow (typeof db)
    Confidence: 0.60 · Precedent: No profile rule decides this. The work item says to keep the exported signatures, so share only the query body and leave getBYOKforUser typed typeof db. Nearest rule, 'Put each separate concern in its own PR', keeps the widening out of this refactor.
  2. Question: Tests: Both findings are pure refactors with no intended behavior change. What test shape should accompany them?
    Answer: Add a permanent DB-backed test for the shared owner lookups
    Confidence: 0.55 · Precedent: Rule 'If you see a gap or an error, fix it'. Rule 'Keep CI checks that catch real errors in PRs'. No unmocked test covers the org path, and this refactor touches that path.

getBYOKforUser/getBYOKforOrganization and the two provider-id lookups now
delegate to one private query body parameterized by the owning column
(kilo_user_id or organization_id). Contract unchanged: null for an empty
provider list and for zero rows, created_at ordering, and the same
exported signatures. The organization lookup still accepts a transaction.

enhanceDirectByokModelList replaces the comma-operator dedupe with an
explicit filter body; first occurrence still wins.

Adds a DB-backed test covering owner scoping, created_at order, disabled
keys, empty-provider and no-key null results, and the provider-id lookups.
@iscekic iscekic added drain Work item from the findings drain janitor:maintainability Maintainability finding from the janitor labels Oct 20, 2026
@kilo-code-bot

kilo-code-bot Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

The refactor is behavior-preserving for both BYOK owner lookups and the direct-BYOK dedupe, and the new DB-backed test verifies owner scoping, ordering, disabled-key exclusion, null results, and transaction support with high confidence.

Files Reviewed (3 files)
  • packages/web-shared/src/lib/ai-gateway/byok/index.ts
  • packages/web-shared/src/lib/ai-gateway/byok/index.test.ts
  • packages/web-shared/src/lib/ai-gateway/providers/direct-byok/model-list.ts

Notes: verified the shared getByokRowsForOwner/getEnabledByokProviderIds bodies against the pre-PR implementation — owner column, is_enabled = true, inArray provider filter, created_at ordering, and null/empty-list handling are identical, and the exported signatures are unchanged. The explicit dedupe filter preserves first-occurrence-wins semantics. The test's cleanup relies on foreign-key cascade for byok_api_keys, matching the existing pattern in sibling DB-backed tests.


Reviewed by deepseek-v4.1-flash-1017 · Input: 65K · Output: 11.5K · Cached: 1.3M

Review guidance: REVIEW.md from base branch main

@iscekic iscekic added the merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. label Oct 20, 2026
@iscekic
iscekic added this pull request to the merge queue Oct 21, 2026
Merged via the queue into main with commit 9f6d08d Oct 21, 2026
56 checks passed
@iscekic
iscekic deleted the drain/byok-owner-lookups-dedupe branch October 21, 2026 16:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

drain Work item from the findings drain janitor:maintainability Maintainability finding from the janitor merge:bot Bot-owned review; merge when ready once readiness passes and a review approves.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants