Skip to content

feat: add DeepSeek API provider and missing Mistral model prefixes#2

Merged
kaiweijw merged 1 commit intomainfrom
feat/add-deepseek-provider
Feb 13, 2026
Merged

feat: add DeepSeek API provider and missing Mistral model prefixes#2
kaiweijw merged 1 commit intomainfrom
feat/add-deepseek-provider

Conversation

@kaiweijw
Copy link
Copy Markdown
Collaborator

Add DeepSeek as a new LLM provider (OpenAI-compatible, passthrough proxy to https://api.deepseek.com/v1 with Bearer auth). Also add missing Mistral model prefixes (devstral-, magistral-) to the gateway model resolver.

Add DeepSeek as a new LLM provider (OpenAI-compatible, passthrough
proxy to https://api.deepseek.com/v1 with Bearer auth). Also add
missing Mistral model prefixes (devstral-*, magistral-*) to the
gateway model resolver.
@kaiweijw kaiweijw merged commit 4914c4c into main Feb 13, 2026
@kaiweijw kaiweijw deleted the feat/add-deepseek-provider branch February 13, 2026 06:03
kaiweijw added a commit that referenced this pull request Apr 9, 2026
…ascade refresh tokens

[High] Refresh tokens minted by an org-owned developer app survived
       org deletion and could keep minting access tokens

The PR explicitly allows org-owned developer OAuth clients
(developer_apps.rs:220), and delete_org_user blocks active
oauth_clients + cascades inactive ones (org_service.rs). But the OAuth
issuance and refresh paths never re-validated the client:

- `oauth_service::exchange_authorization_code` (line 256) loaded the
  OauthClient by id with NO `is_active` filter, so an already-issued
  auth code could still be exchanged after the developer app was
  soft-deleted (window = auth-code TTL).
- `token_service::refresh_tokens` (line 300) only checked the stored
  refresh-token row -- never the issuing client. Once an org-owned
  developer app minted a refresh token, deleting the app to clear the
  org blocker and then deleting the org still left those refresh
  tokens valid for the rest of their JWT TTL.

Fix has three layers:

1. **`exchange_authorization_code`**: filter the OauthClient lookup by
   `_id, is_active: true`. Auth codes against soft-deleted clients
   can't be exchanged.

2. **`refresh_tokens`**: after loading the stored refresh-token row,
   when `stored.client_id != Uuid::nil()` (the first-party login
   sentinel from auth_service / token_service), look up the
   OauthClient by id with `is_active: true`. If missing or inactive:
   flip the stored row to `revoked: true` so subsequent retries hit
   the existing reuse-detection path, then return `Unauthorized`.
   First-party login refresh flows skip the lookup entirely (no
   OauthClient row exists for them).

3. **`delete_org_user`**: snapshot the org's owned `oauth_clients._id`
   set BEFORE deleting the soft-deleted client tombstones, then
   `delete_many({ client_id: $in: [...] })` against `refresh_tokens`.
   With #2 in place this is belt-and-suspenders cleanup -- the
   refresh would already fail validation -- but it stops the
   collection from accumulating dead rows referencing a deleted
   client. Mirrors the existing service_account_tokens snapshot
   pattern.

End result: refresh tokens minted by an org-owned developer app stop
working **immediately** when the app or its owning org is deleted,
instead of remaining usable for the rest of the JWT TTL.

Doc updates
- `docs/ORG_MODEL.md` -- "Cascade-deleted" list adds refresh_tokens.
  Narrative now enumerates FIVE snapshot-then-delete cases (the new
  refresh_tokens-by-client_id case alongside the existing four). New
  "OAuth refresh-token validation" subsection documents the live
  is_active checks in exchange_authorization_code and refresh_tokens
  and explains the first-party login bypass via the nil-uuid
  sentinel.

Verification
- cargo test -p nyxid: 1163 passed
- cargo clippy --workspace --all-targets -- -D warnings: clean
- cargo fmt --all: clean
- frontend untouched
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.

1 participant