feat(ai): add the storage for an OpenAI-compatible gateway provider

Three dedicated User columns — base URL, optional bearer, model — for a
provider whose endpoint the user chooses. They are separate from the
OpenAI columns on purpose: the OpenAI arm pins api.openai.com, so it must
share no column with a user-supplied host, and a gateway must never
receive the key issued for OpenAI.

The bearer joins the encrypted-column registry and the rotation script;
the three columns join the account-wipe reset set.
This commit is contained in:
Marc-André Bombeck committed 2026-07-26 22:27:48 +02:00
1 parent d10ae9e71c
commit d11019aebc
5 files changed
+40 -1

No files matched your search

+4
View File
@@ -81,6 +81,10 @@ export const ENCRYPTED_COLUMNS: readonly EncryptedColumn[] = [
{ model: "User", field: "aiAnthropicKeyEncrypted", kind: "string" },
{ model: "User", field: "aiLocalKeyEncrypted", kind: "string" },
{ model: "User", field: "aiOpenaiKeyEncrypted", kind: "string" },
// v1.33.1 (#470) — the OpenAI-compatible gateway provider's optional bearer.
// A dedicated column, never the OpenAI key: the gateway host is user-chosen,
// so the credential that reaches it must be one the user issued for it.
{ model: "User", field: "aiCompatKeyEncrypted", kind: "string" },
{ model: "User", field: "insuranceNumberEncrypted", kind: "string" },
// v1.23 — TOTP shared secret (second factor). String ciphertext like the
// other User credential columns.
+3
View File
@@ -262,6 +262,9 @@ export const USER_RESET = {
aiAnthropicKeyEncrypted: null,
aiLocalKeyEncrypted: null,
aiOpenaiKeyEncrypted: null,
aiCompatBaseUrl: null,
aiCompatKeyEncrypted: null,
aiCompatModel: null,
aiProviderChain: Prisma.DbNull,
aiResponseTimeoutSeconds: null,
disableCoach: false,