feat: add DeepSeek API provider and missing Mistral model prefixes#2
Merged
feat: add DeepSeek API provider and missing Mistral model prefixes#2
Conversation
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
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
16 tasks
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.