cartethyia 2.7.2 → 2.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +2 -0
- package/dist/dashboard/assets/{BannedPage-XaUmiBrC.js → BannedPage-2TJD37Hb.js} +1 -1
- package/dist/dashboard/assets/BannedPage-2TJD37Hb.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-xefJNRmJ.js +1 -0
- package/dist/dashboard/assets/CliToolDetailPage-xefJNRmJ.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-Rj9iHQ3F.js +1 -0
- package/dist/dashboard/assets/CliToolsPage-Rj9iHQ3F.js.gz +0 -0
- package/dist/dashboard/assets/{CombosPage-CXGS_Ct-.js → CombosPage-JEbYJFxw.js} +1 -1
- package/dist/dashboard/assets/CombosPage-JEbYJFxw.js.gz +0 -0
- package/dist/dashboard/assets/{ConsoleLogPage-DGnGNYnM.js → ConsoleLogPage-C3xx_inM.js} +1 -1
- package/dist/dashboard/assets/ConsoleLogPage-C3xx_inM.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-Dw306gJU.js +1 -0
- package/dist/dashboard/assets/CustomizationPage-Dw306gJU.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-jaBo1TWV.js +1 -0
- package/dist/dashboard/assets/HealthEventsModal-jaBo1TWV.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-BdmRLnq2.js → LoginPage-C4w7vea-.js} +1 -1
- package/dist/dashboard/assets/LoginPage-C4w7vea-.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-BH8Tehdi.js → ModelPicker-BtPcAfot.js} +1 -1
- package/dist/dashboard/assets/ModelPicker-BtPcAfot.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-CGC5gNs1.js +1 -0
- package/dist/dashboard/assets/OverviewPage-CGC5gNs1.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-DQcthNGt.js +4 -0
- package/dist/dashboard/assets/ProviderDetailPage-DQcthNGt.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-0OsXRGXe.js +1 -0
- package/dist/dashboard/assets/ProvidersPage-0OsXRGXe.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-DdPc8slb.js +9 -0
- package/dist/dashboard/assets/ProxyPage-DdPc8slb.js.gz +0 -0
- package/dist/dashboard/assets/{QuotaPage-7P2n--Fv.js → QuotaPage-Ci5O4BnH.js} +1 -1
- package/dist/dashboard/assets/QuotaPage-Ci5O4BnH.js.gz +0 -0
- package/dist/dashboard/assets/{SettingsPage-CxZ1fTkN.js → SettingsPage-CDZjTt87.js} +1 -1
- package/dist/dashboard/assets/SettingsPage-CDZjTt87.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-BQS0Rx_u.js +1 -0
- package/dist/dashboard/assets/SetupPage-BQS0Rx_u.js.gz +0 -0
- package/dist/dashboard/assets/{SortableList-Dqf4zpS-.js → SortableList-BAL5npBC.js} +1 -1
- package/dist/dashboard/assets/SortableList-BAL5npBC.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-Byj2lAEm.js → StudioPage-TP7voAQ0.js} +3 -3
- package/dist/dashboard/assets/StudioPage-TP7voAQ0.js.gz +0 -0
- package/dist/dashboard/assets/{UsagePage-CTkLAuRc.js → UsagePage-Cj_fEzhg.js} +13 -13
- package/dist/dashboard/assets/UsagePage-Cj_fEzhg.js.gz +0 -0
- package/dist/dashboard/assets/{api-keys-CUi6UXsR.js → api-keys-MbI7e7rt.js} +1 -1
- package/dist/dashboard/assets/api-keys-MbI7e7rt.js.gz +0 -0
- package/dist/dashboard/assets/app-B2vyPoII.css +2 -0
- package/dist/dashboard/assets/app-B2vyPoII.css.gz +0 -0
- package/dist/dashboard/assets/arrow-up-59ms1iiT.js +1 -0
- package/dist/dashboard/assets/arrow-up-59ms1iiT.js.gz +0 -0
- package/dist/dashboard/assets/{assert-67xXH5rf.js → assert-C0YYuZJ4.js} +1 -1
- package/dist/dashboard/assets/assert-C0YYuZJ4.js.gz +0 -0
- package/dist/dashboard/assets/{badge-DC2L43Mj.js → badge-B_DMpMJN.js} +1 -1
- package/dist/dashboard/assets/badge-B_DMpMJN.js.gz +0 -0
- package/dist/dashboard/assets/{banner-BBVcb0J3.js → banner-DMrMPmth.js} +1 -1
- package/dist/dashboard/assets/banner-DMrMPmth.js.gz +0 -0
- package/dist/dashboard/assets/{card-Cca1XC6G.js → card-Be5Uzamx.js} +1 -1
- package/dist/dashboard/assets/card-Be5Uzamx.js.gz +0 -0
- package/dist/dashboard/assets/{cli-tools-KvsWa1Jl.js → cli-tools-muFRphDu.js} +1 -1
- package/dist/dashboard/assets/cli-tools-muFRphDu.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-DUzEbynq.js → clipboard-button-DOfrVmsi.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-DOfrVmsi.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-DFvWhwTa.js → dialog-C9omdjQt.js} +1 -1
- package/dist/dashboard/assets/dialog-C9omdjQt.js.gz +0 -0
- package/dist/dashboard/assets/drawer-Bm8WKaGY.js +1 -0
- package/dist/dashboard/assets/drawer-Bm8WKaGY.js.gz +0 -0
- package/dist/dashboard/assets/{entry-_xHo5x6r.js → entry-DS90gUks.js} +1 -1
- package/dist/dashboard/assets/entry-DS90gUks.js.gz +0 -0
- package/dist/dashboard/assets/{entry-ClCMCWWQ.js → entry-j40LJotO.js} +3 -3
- package/dist/dashboard/assets/entry-j40LJotO.js.gz +0 -0
- package/dist/dashboard/assets/{entry-Bqy8RFvM.js → entry-q5HwZ8nN.js} +1 -1
- package/dist/dashboard/assets/entry-q5HwZ8nN.js.gz +0 -0
- package/dist/dashboard/assets/{concurrency-BDF0ok7y.js → fingerprint-pattern-BWuHtbW4.js} +1 -1
- package/dist/dashboard/assets/fingerprint-pattern-BWuHtbW4.js.gz +0 -0
- package/dist/dashboard/assets/{formatters-CWWZ-uCZ.js → formatters-BTScrQpe.js} +1 -1
- package/dist/dashboard/assets/formatters-BTScrQpe.js.gz +0 -0
- package/dist/dashboard/assets/{github-badge-C9e8Ts7e.js → github-badge-Orjuzemr.js} +1 -1
- package/dist/dashboard/assets/github-badge-Orjuzemr.js.gz +0 -0
- package/dist/dashboard/assets/{index-DFVFrnWW.js → index-cPrX5vn6.js} +2 -2
- package/dist/dashboard/assets/index-cPrX5vn6.js.gz +0 -0
- package/dist/dashboard/assets/{inline-BFUcvllj.js → inline-Dvux8w-0.js} +1 -1
- package/dist/dashboard/assets/inline-Dvux8w-0.js.gz +0 -0
- package/dist/dashboard/assets/{input-C_ILAvBb.js → input-CU1Rgf3p.js} +1 -1
- package/dist/dashboard/assets/input-CU1Rgf3p.js.gz +0 -0
- package/dist/dashboard/assets/{layout-CBIyT6Rt.js → layout-C_7A6H55.js} +1 -1
- package/dist/dashboard/assets/layout-C_7A6H55.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-ebJ_-Nsb.js → list-row-CzFvogbj.js} +1 -1
- package/dist/dashboard/assets/list-row-CzFvogbj.js.gz +0 -0
- package/dist/dashboard/assets/{live-D0mm--ME.js → live-KaG15HLQ.js} +1 -1
- package/dist/dashboard/assets/live-KaG15HLQ.js.gz +0 -0
- package/dist/dashboard/assets/{mutation-sMD965oO.js → mutation-JJGQm8TD.js} +1 -1
- package/dist/dashboard/assets/mutation-JJGQm8TD.js.gz +0 -0
- package/dist/dashboard/assets/{numbers-BO9dKaFr.js → numbers-BNDZnsUE.js} +1 -1
- package/dist/dashboard/assets/numbers-BNDZnsUE.js.gz +0 -0
- package/dist/dashboard/assets/{query-keys-CfL_Zdoh.js → query-keys-CLaNz8Xz.js} +1 -1
- package/dist/dashboard/assets/query-keys-CLaNz8Xz.js.gz +0 -0
- package/dist/dashboard/assets/{routing-BnIpi1IJ.js → routing-BEH32QOC.js} +1 -1
- package/dist/dashboard/assets/routing-BEH32QOC.js.gz +0 -0
- package/dist/dashboard/assets/{select-DBNVLdUu.js → select-B3iTetHN.js} +1 -1
- package/dist/dashboard/assets/select-B3iTetHN.js.gz +0 -0
- package/dist/dashboard/assets/settings-2-Ds9DQp0t.js +1 -0
- package/dist/dashboard/assets/settings-2-Ds9DQp0t.js.gz +0 -0
- package/dist/dashboard/assets/{settings-BAFhDgX8.js → settings-Dt3Eqbnq.js} +1 -1
- package/dist/dashboard/assets/settings-Dt3Eqbnq.js.gz +0 -0
- package/dist/dashboard/assets/{stack-EMrOMt4I.js → stack-KrOrm7JZ.js} +1 -1
- package/dist/dashboard/assets/stack-KrOrm7JZ.js.gz +0 -0
- package/dist/dashboard/assets/{state-CWoo7ty5.js → state-DLS7IDMy.js} +1 -1
- package/dist/dashboard/assets/state-DLS7IDMy.js.gz +0 -0
- package/dist/dashboard/assets/{switch-CCjT6IkF.js → switch-42ItvbAs.js} +1 -1
- package/dist/dashboard/assets/switch-42ItvbAs.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-DjkLHUcE.js → useMutation-Dmnfh1Ue.js} +1 -1
- package/dist/dashboard/assets/useMutation-Dmnfh1Ue.js.gz +0 -0
- package/dist/dashboard/index.html +3 -2
- package/dist/dashboard/index.html.gz +0 -0
- package/dist/dashboard/precompressed-assets.json +117 -115
- package/migrations/full-postgres/0026_add_qoder_native_identity.sql +20 -0
- package/migrations/full-postgres/0027_qoder_identity_genuine_seed.sql +22 -0
- package/migrations/full-postgres/0028_add_family_template_key_telemetry.sql +40 -0
- package/migrations/full-postgres/0029_null_share_child_policy_columns.sql +38 -0
- package/migrations/full-postgres/0030_add_api_key_max_children.sql +10 -0
- package/migrations/full-postgres/0031_tenant_system_prompts.sql +16 -0
- package/migrations/lite-sqlite3/0026_add_qoder_native_identity.sql +15 -0
- package/migrations/lite-sqlite3/0027_qoder_identity_genuine_seed.sql +22 -0
- package/migrations/lite-sqlite3/0028_add_family_template_key_telemetry.sql +40 -0
- package/migrations/lite-sqlite3/0029_null_share_child_policy_columns.sql +38 -0
- package/migrations/lite-sqlite3/0030_add_api_key_max_children.sql +10 -0
- package/migrations/lite-sqlite3/0031_tenant_system_prompts.sql +10 -0
- package/package.json +1 -1
- package/src/config/network.ts +1 -1
- package/src/console/api-keys/bucket-spend.ts +7 -7
- package/src/console/api-keys/contracts.ts +423 -410
- package/src/console/api-keys/routes.ts +118 -19
- package/src/console/backup/export-endpoint.ts +8 -11
- package/src/console/backup/routes.ts +40 -8
- package/src/console/backup/service.ts +11 -6
- package/src/console/backup/store.ts +384 -88
- package/src/console/dashboard-assets.ts +16 -1
- package/src/console/domain-registration.ts +2 -0
- package/src/console/quota/account-quota-tenant.ts +8 -1
- package/src/console/quota/account-quota.ts +4 -1
- package/src/console/quota/native-identity.ts +189 -0
- package/src/console/remote-support/contracts.ts +12 -6
- package/src/console/remote-support/service.ts +2 -2
- package/src/console/share/share-router.ts +39 -6
- package/src/console/share/share-stats.ts +64 -25
- package/src/console/share/share-usage.ts +24 -7
- package/src/console/system-prompt/contracts.ts +102 -0
- package/src/console/system-prompt/routes.ts +165 -0
- package/src/main.ts +11 -0
- package/src/observability/event-query.ts +118 -7
- package/src/persistence/db-pg.ts +42 -0
- package/src/persistence/schema.ts +102 -0
- package/src/persistence/stores/api-key-store.ts +753 -581
- package/src/persistence/stores/share-store.ts +65 -13
- package/src/persistence/stores/telemetry-store.ts +57 -1
- package/src/persistence/system-prompt-store.ts +104 -0
- package/src/protocol/reasoning.ts +65 -1
- package/src/protocol/request/chat.ts +1 -0
- package/src/providers/integrations/antigravity/antigravity.ts +20 -23
- package/src/providers/integrations/buddy/buddy-chat-shared.ts +30 -2
- package/src/providers/integrations/buddy/buddy-media.ts +5 -1
- package/src/providers/integrations/buddy/codebuddy/provider.ts +5 -1
- package/src/providers/integrations/buddy/workbuddy/provider.ts +5 -1
- package/src/providers/integrations/cline/cline.ts +7 -0
- package/src/providers/integrations/github/github.ts +20 -1
- package/src/providers/integrations/hermes.ts +5 -1
- package/src/providers/integrations/kilo/kilo.ts +4 -0
- package/src/providers/integrations/openrouter/provider.ts +4 -0
- package/src/providers/integrations/qoder/qoder-checkin.ts +224 -51
- package/src/providers/integrations/qoder/qoder-native-identity-store.ts +156 -0
- package/src/providers/integrations/qoder/qoder-oauth.ts +12 -3
- package/src/providers/integrations/qoder/qoder-umid.ts +288 -0
- package/src/providers/integrations/qoder/qoder.ts +5 -3
- package/src/providers/operations/account-error-classification.ts +6 -8
- package/src/providers/operations/account-health-service.ts +14 -16
- package/src/providers/operations/client-versions.ts +37 -22
- package/src/providers/provider-contracts.ts +8 -0
- package/src/security/access-control.ts +19 -0
- package/src/security/api-key-auth.ts +14 -1
- package/src/transport/dispatch/proxy-request.ts +31 -2
- package/src/transport/dispatch/streaming/stream.ts +16 -1
- package/src/transport/dispatch/upstream.ts +10 -0
- package/src/transport/request/preparer.ts +17 -1
- package/src/transport/request/system-prompt-injection.ts +89 -0
- package/src/transport/request/tenant-preferences.ts +43 -0
- package/src/transport/routing/admission.ts +13 -3
- package/src/transport/routing/route-catalog.ts +7 -0
- package/src/transport/routing/route-model.ts +53 -0
- package/src/transport/routing/router.ts +306 -256
- package/src/workers/daily-checkin.ts +2 -0
- package/dist/dashboard/assets/BannedPage-XaUmiBrC.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-CqD7QiLM.js +0 -1
- package/dist/dashboard/assets/CliToolDetailPage-CqD7QiLM.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-0XUo4UMn.js +0 -1
- package/dist/dashboard/assets/CliToolsPage-0XUo4UMn.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-CXGS_Ct-.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-DGnGNYnM.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-DAG5J9EY.js +0 -1
- package/dist/dashboard/assets/CustomizationPage-DAG5J9EY.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-BKtAPYVF.js +0 -1
- package/dist/dashboard/assets/HealthEventsModal-BKtAPYVF.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-BdmRLnq2.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-BH8Tehdi.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-CqMxibJB.js +0 -1
- package/dist/dashboard/assets/OverviewPage-CqMxibJB.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-CqMh2NRX.js +0 -4
- package/dist/dashboard/assets/ProviderDetailPage-CqMh2NRX.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-B9uWu4Nz.js +0 -1
- package/dist/dashboard/assets/ProvidersPage-B9uWu4Nz.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-BoWOhpDO.js +0 -9
- package/dist/dashboard/assets/ProxyPage-BoWOhpDO.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-7P2n--Fv.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-CxZ1fTkN.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-Co12Zzaw.js +0 -1
- package/dist/dashboard/assets/SetupPage-Co12Zzaw.js.gz +0 -0
- package/dist/dashboard/assets/SortableList-Dqf4zpS-.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-Byj2lAEm.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-CTkLAuRc.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-CUi6UXsR.js.gz +0 -0
- package/dist/dashboard/assets/app-KvsUJUMF.css +0 -2
- package/dist/dashboard/assets/app-KvsUJUMF.css.gz +0 -0
- package/dist/dashboard/assets/assert-67xXH5rf.js.gz +0 -0
- package/dist/dashboard/assets/badge-DC2L43Mj.js.gz +0 -0
- package/dist/dashboard/assets/banner-BBVcb0J3.js.gz +0 -0
- package/dist/dashboard/assets/card-Cca1XC6G.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-KvsWa1Jl.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-DUzEbynq.js.gz +0 -0
- package/dist/dashboard/assets/concurrency-BDF0ok7y.js.gz +0 -0
- package/dist/dashboard/assets/dialog-DFvWhwTa.js.gz +0 -0
- package/dist/dashboard/assets/drawer-CFM2sMX1.js +0 -1
- package/dist/dashboard/assets/drawer-CFM2sMX1.js.gz +0 -0
- package/dist/dashboard/assets/entry-Bqy8RFvM.js.gz +0 -0
- package/dist/dashboard/assets/entry-ClCMCWWQ.js.gz +0 -0
- package/dist/dashboard/assets/entry-_xHo5x6r.js.gz +0 -0
- package/dist/dashboard/assets/formatters-CWWZ-uCZ.js.gz +0 -0
- package/dist/dashboard/assets/github-badge-C9e8Ts7e.js.gz +0 -0
- package/dist/dashboard/assets/index-DFVFrnWW.js.gz +0 -0
- package/dist/dashboard/assets/inline-BFUcvllj.js.gz +0 -0
- package/dist/dashboard/assets/input-C_ILAvBb.js.gz +0 -0
- package/dist/dashboard/assets/layout-CBIyT6Rt.js.gz +0 -0
- package/dist/dashboard/assets/list-row-ebJ_-Nsb.js.gz +0 -0
- package/dist/dashboard/assets/live-D0mm--ME.js.gz +0 -0
- package/dist/dashboard/assets/mutation-sMD965oO.js.gz +0 -0
- package/dist/dashboard/assets/numbers-BO9dKaFr.js.gz +0 -0
- package/dist/dashboard/assets/query-keys-CfL_Zdoh.js.gz +0 -0
- package/dist/dashboard/assets/routing-BnIpi1IJ.js.gz +0 -0
- package/dist/dashboard/assets/select-DBNVLdUu.js.gz +0 -0
- package/dist/dashboard/assets/settings-BAFhDgX8.js.gz +0 -0
- package/dist/dashboard/assets/stack-EMrOMt4I.js.gz +0 -0
- package/dist/dashboard/assets/state-CWoo7ty5.js.gz +0 -0
- package/dist/dashboard/assets/switch-CCjT6IkF.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-DjkLHUcE.js.gz +0 -0
- /package/dist/dashboard/assets/{app-BaWd0puM.js → app-wvwCi4Eh.js} +0 -0
- /package/dist/dashboard/assets/{app-BaWd0puM.js.gz → app-wvwCi4Eh.js.gz} +0 -0
|
@@ -1,120 +1,122 @@
|
|
|
1
1
|
{
|
|
2
|
-
"count":
|
|
2
|
+
"count": 117,
|
|
3
3
|
"assets": [
|
|
4
|
-
"assets
|
|
5
|
-
"assets
|
|
6
|
-
"assets
|
|
7
|
-
"assets
|
|
8
|
-
"assets
|
|
9
|
-
"assets
|
|
10
|
-
"assets
|
|
11
|
-
"assets
|
|
12
|
-
"assets
|
|
13
|
-
"assets
|
|
14
|
-
"assets
|
|
15
|
-
"assets
|
|
16
|
-
"assets
|
|
17
|
-
"assets
|
|
18
|
-
"assets
|
|
19
|
-
"assets
|
|
20
|
-
"assets
|
|
21
|
-
"assets
|
|
22
|
-
"assets
|
|
23
|
-
"assets
|
|
24
|
-
"assets
|
|
25
|
-
"assets
|
|
26
|
-
"assets
|
|
27
|
-
"assets
|
|
28
|
-
"assets
|
|
29
|
-
"assets
|
|
30
|
-
"assets
|
|
31
|
-
"assets
|
|
32
|
-
"assets
|
|
33
|
-
"assets
|
|
34
|
-
"assets
|
|
35
|
-
"assets
|
|
36
|
-
"assets
|
|
37
|
-
"assets
|
|
38
|
-
"assets
|
|
39
|
-
"assets
|
|
40
|
-
"assets
|
|
41
|
-
"assets
|
|
42
|
-
"assets
|
|
43
|
-
"assets
|
|
44
|
-
"assets
|
|
45
|
-
"assets
|
|
46
|
-
"assets
|
|
47
|
-
"assets
|
|
48
|
-
"assets
|
|
49
|
-
"assets
|
|
50
|
-
"assets
|
|
51
|
-
"assets
|
|
52
|
-
"assets
|
|
53
|
-
"assets
|
|
54
|
-
"assets
|
|
55
|
-
"assets
|
|
56
|
-
"assets
|
|
57
|
-
"assets
|
|
58
|
-
"assets
|
|
59
|
-
"assets
|
|
60
|
-
"assets
|
|
61
|
-
"assets
|
|
62
|
-
"assets
|
|
63
|
-
"assets
|
|
64
|
-
"assets
|
|
65
|
-
"assets
|
|
66
|
-
"assets
|
|
67
|
-
"assets
|
|
68
|
-
"assets
|
|
69
|
-
"assets
|
|
70
|
-
"assets
|
|
71
|
-
"assets
|
|
72
|
-
"assets
|
|
73
|
-
"assets
|
|
74
|
-
"assets
|
|
75
|
-
"assets
|
|
76
|
-
"assets
|
|
77
|
-
"assets
|
|
78
|
-
"assets
|
|
79
|
-
"assets
|
|
80
|
-
"assets
|
|
81
|
-
"assets
|
|
82
|
-
"assets
|
|
83
|
-
"assets
|
|
84
|
-
"assets
|
|
85
|
-
"assets
|
|
86
|
-
"assets
|
|
87
|
-
"assets
|
|
88
|
-
"assets
|
|
89
|
-
"assets
|
|
90
|
-
"assets
|
|
91
|
-
"assets
|
|
92
|
-
"assets
|
|
93
|
-
"assets
|
|
94
|
-
"assets
|
|
95
|
-
"assets
|
|
96
|
-
"assets
|
|
97
|
-
"assets
|
|
98
|
-
"assets
|
|
99
|
-
"assets
|
|
100
|
-
"assets
|
|
101
|
-
"assets
|
|
102
|
-
"assets
|
|
103
|
-
"assets
|
|
104
|
-
"assets
|
|
105
|
-
"assets
|
|
106
|
-
"assets
|
|
107
|
-
"assets
|
|
108
|
-
"assets
|
|
109
|
-
"assets
|
|
110
|
-
"assets
|
|
111
|
-
"assets
|
|
112
|
-
"assets
|
|
113
|
-
"assets
|
|
114
|
-
"assets
|
|
115
|
-
"assets
|
|
116
|
-
"assets
|
|
117
|
-
"assets
|
|
4
|
+
"assets/AccountCooldown-Bjo92Qat.js",
|
|
5
|
+
"assets/BannedPage-2TJD37Hb.js",
|
|
6
|
+
"assets/CliToolDetailPage-xefJNRmJ.js",
|
|
7
|
+
"assets/CliToolsPage-Rj9iHQ3F.js",
|
|
8
|
+
"assets/CombosPage-JEbYJFxw.js",
|
|
9
|
+
"assets/ConsoleLogPage-C3xx_inM.js",
|
|
10
|
+
"assets/CustomizationPage-Dw306gJU.js",
|
|
11
|
+
"assets/HealthEventsModal-jaBo1TWV.js",
|
|
12
|
+
"assets/LoginPage-C4w7vea-.js",
|
|
13
|
+
"assets/ModelPicker-BtPcAfot.js",
|
|
14
|
+
"assets/OverviewPage-CGC5gNs1.js",
|
|
15
|
+
"assets/ProviderDetailPage-DQcthNGt.js",
|
|
16
|
+
"assets/ProviderIcon-FB6yS4v1.js",
|
|
17
|
+
"assets/ProvidersPage-0OsXRGXe.js",
|
|
18
|
+
"assets/ProxyPage-DdPc8slb.js",
|
|
19
|
+
"assets/QuotaPage-Ci5O4BnH.js",
|
|
20
|
+
"assets/SettingsPage-CDZjTt87.js",
|
|
21
|
+
"assets/SetupPage-BQS0Rx_u.js",
|
|
22
|
+
"assets/SortableList-BAL5npBC.js",
|
|
23
|
+
"assets/StudioPage-TP7voAQ0.js",
|
|
24
|
+
"assets/ToolIcon-K1ckcDKg.js",
|
|
25
|
+
"assets/UsagePage-Cj_fEzhg.js",
|
|
26
|
+
"assets/api-keys-MbI7e7rt.js",
|
|
27
|
+
"assets/app-B2vyPoII.css",
|
|
28
|
+
"assets/app-wvwCi4Eh.js",
|
|
29
|
+
"assets/arrow-left-CpBxkoxI.js",
|
|
30
|
+
"assets/arrow-right-Dl5yKnp8.js",
|
|
31
|
+
"assets/arrow-up-59ms1iiT.js",
|
|
32
|
+
"assets/assert-C0YYuZJ4.js",
|
|
33
|
+
"assets/backup-file-gdKIlg8U.js",
|
|
34
|
+
"assets/badge-B_DMpMJN.js",
|
|
35
|
+
"assets/banner-DMrMPmth.js",
|
|
36
|
+
"assets/brain-Cwed_72z.js",
|
|
37
|
+
"assets/card-Be5Uzamx.js",
|
|
38
|
+
"assets/chevron-right-BXIy5l3h.js",
|
|
39
|
+
"assets/circle-alert-CntYHV5v.js",
|
|
40
|
+
"assets/circle-check-BU3v_mFW.js",
|
|
41
|
+
"assets/cli-tools-muFRphDu.js",
|
|
42
|
+
"assets/clipboard-button-DOfrVmsi.js",
|
|
43
|
+
"assets/database-Dz9N3zGd.js",
|
|
44
|
+
"assets/dialog-C9omdjQt.js",
|
|
45
|
+
"assets/dialog-actions-B1axpEg7.js",
|
|
46
|
+
"assets/download-dRFo5_Wu.js",
|
|
47
|
+
"assets/drawer-Bm8WKaGY.js",
|
|
48
|
+
"assets/entry-DS90gUks.js",
|
|
49
|
+
"assets/entry-j40LJotO.js",
|
|
50
|
+
"assets/entry-q5HwZ8nN.js",
|
|
51
|
+
"assets/eye-C_hawfH4.js",
|
|
52
|
+
"assets/eye-off-Bk5g2luF.js",
|
|
53
|
+
"assets/fingerprint-pattern-BWuHtbW4.js",
|
|
54
|
+
"assets/formatters-BTScrQpe.js",
|
|
55
|
+
"assets/gauge-BbIMy7MB.js",
|
|
56
|
+
"assets/github-badge-Orjuzemr.js",
|
|
57
|
+
"assets/image-BPaouViG.js",
|
|
58
|
+
"assets/index-cPrX5vn6.js",
|
|
59
|
+
"assets/inline-Dvux8w-0.js",
|
|
60
|
+
"assets/input-CU1Rgf3p.js",
|
|
61
|
+
"assets/jsx-runtime-CXUMngI_.js",
|
|
62
|
+
"assets/key-round-UkavsGxp.js",
|
|
63
|
+
"assets/layers-2-glBbjl.js",
|
|
64
|
+
"assets/layout-C_7A6H55.js",
|
|
65
|
+
"assets/list-row-CzFvogbj.js",
|
|
66
|
+
"assets/live-KaG15HLQ.js",
|
|
67
|
+
"assets/log-in-BmRjy60c.js",
|
|
68
|
+
"assets/message-circle-CCxGwRvv.js",
|
|
69
|
+
"assets/minimize-2-D-MN8W8a.js",
|
|
70
|
+
"assets/mutation-JJGQm8TD.js",
|
|
71
|
+
"assets/numbers-BNDZnsUE.js",
|
|
72
|
+
"assets/pencil-768ysRAr.js",
|
|
73
|
+
"assets/plus-DIdX_g-x.js",
|
|
74
|
+
"assets/power-off-Yjw9GMJh.js",
|
|
75
|
+
"assets/privacy-mode-GM8bej85.js",
|
|
76
|
+
"assets/providers/agentrouter.svg",
|
|
77
|
+
"assets/providers/aihubmix.svg",
|
|
78
|
+
"assets/providers/alibaba-coding-plan.svg",
|
|
79
|
+
"assets/providers/alibaba.svg",
|
|
80
|
+
"assets/providers/antigravity.svg",
|
|
81
|
+
"assets/providers/bai.svg",
|
|
82
|
+
"assets/providers/blackbox.svg",
|
|
83
|
+
"assets/providers/claude-code.svg",
|
|
84
|
+
"assets/providers/exa.svg",
|
|
85
|
+
"assets/providers/gmi-cloud.svg",
|
|
86
|
+
"assets/providers/inception.svg",
|
|
87
|
+
"assets/providers/inferhub.svg",
|
|
88
|
+
"assets/providers/muse.svg",
|
|
89
|
+
"assets/providers/nous-research.svg",
|
|
90
|
+
"assets/providers/openai-light.svg",
|
|
91
|
+
"assets/providers/parallel.svg",
|
|
92
|
+
"assets/providers/tokenharbor.svg",
|
|
93
|
+
"assets/providers/zai-coding-plan.svg",
|
|
94
|
+
"assets/query-keys-CLaNz8Xz.js",
|
|
95
|
+
"assets/quota-DZGyp0N5.js",
|
|
96
|
+
"assets/refresh-cw-BqJFk4sU.js",
|
|
97
|
+
"assets/rotate-ccw-CufcqITi.js",
|
|
98
|
+
"assets/route-CNSNj9Zm.js",
|
|
99
|
+
"assets/routing-BEH32QOC.js",
|
|
100
|
+
"assets/scaling-nWE4Cx8f.js",
|
|
101
|
+
"assets/search-JOKus9rb.js",
|
|
102
|
+
"assets/select-B3iTetHN.js",
|
|
103
|
+
"assets/settings-2-Ds9DQp0t.js",
|
|
104
|
+
"assets/settings-Dt3Eqbnq.js",
|
|
105
|
+
"assets/shield-check-DVS0Foqh.js",
|
|
106
|
+
"assets/stack-KrOrm7JZ.js",
|
|
107
|
+
"assets/state-DLS7IDMy.js",
|
|
108
|
+
"assets/stream-retry-5QnVuSSo.js",
|
|
109
|
+
"assets/switch-42ItvbAs.js",
|
|
110
|
+
"assets/terminal-0_IjPWTk.js",
|
|
111
|
+
"assets/tokens-COzario9.js",
|
|
112
|
+
"assets/trash-Cppn5c3R.js",
|
|
113
|
+
"assets/use-clipboard-B0Sy03fE.js",
|
|
114
|
+
"assets/use-modal-focus-By7oJoGd.js",
|
|
115
|
+
"assets/use-reduced-motion-C4B0R6Sz.js",
|
|
116
|
+
"assets/use-timeout-BwcBBRrT.js",
|
|
117
|
+
"assets/useMutation-Dmnfh1Ue.js",
|
|
118
|
+
"assets/wrench-B6E1oEuY.js",
|
|
119
|
+
"assets/zap-C4EeVW4q.js",
|
|
118
120
|
"index.html"
|
|
119
121
|
]
|
|
120
122
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
-- Qoder native machine identity (UMID) bound to one account.
|
|
2
|
+
--
|
|
3
|
+
-- The daily 100-credit check-in campaign appears only when the request
|
|
4
|
+
-- carries a genuine, non-VM device identity. That identity is a
|
|
5
|
+
-- deterministic function of a seed file (`~/.config/.locale_cfg`): the
|
|
6
|
+
-- `runtime-info` bridge derives machineToken/machineType/machineCode from the
|
|
7
|
+
-- seed. Each account gets its own minted seed, so it looks like its own
|
|
8
|
+
-- device to the server.
|
|
9
|
+
--
|
|
10
|
+
-- The identity is not a credential (it travels in plaintext `cosy-machine*`
|
|
11
|
+
-- headers), so it lives unsealed as a JSON object. The partial unique index
|
|
12
|
+
-- on the extracted `machineToken` enforces "one device per account" at the
|
|
13
|
+
-- database level: two accounts sharing a token would claim as the same
|
|
14
|
+
-- device and the second would lose the grant for the day.
|
|
15
|
+
ALTER TABLE "provider_accounts"
|
|
16
|
+
ADD COLUMN "native_identity" jsonb;
|
|
17
|
+
|
|
18
|
+
CREATE UNIQUE INDEX "provider_accounts_native_identity_token_uidx"
|
|
19
|
+
ON "provider_accounts" ((native_identity ->> 'machineToken'))
|
|
20
|
+
WHERE native_identity IS NOT NULL;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
-- Qoder native identity: genuine SG identity + per-account seed replay.
|
|
2
|
+
--
|
|
3
|
+
-- Research (2026-10-30, see documentation/research/qoder-identity-gate-
|
|
4
|
+
-- postmortem.md and qoder-umid-reverse.md) established that the daily-credit
|
|
5
|
+
-- campaign gates its CREDITS grant on a *genuine* Alibaba SG-produced
|
|
6
|
+
-- identity: generated/deterministic tokens do not reveal the grant on a
|
|
7
|
+
-- fresh account, while the `runtime-info` bridge (SG-signed) does.
|
|
8
|
+
--
|
|
9
|
+
-- Migration 0026 already added `native_identity` (the token triple + optional
|
|
10
|
+
-- seed) with a partial unique index on the extracted machineToken — the
|
|
11
|
+
-- "one device per account" invariant. This migration does not change that
|
|
12
|
+
-- schema; it only documents the contract change on the same column:
|
|
13
|
+
--
|
|
14
|
+
-- `seed` is now REQUIRED for a claim-capable identity (the seed is the
|
|
15
|
+
-- device material; the token can be re-derived from it, never the reverse).
|
|
16
|
+
-- Rows minted by the retired generated path carry `seed = ""` — they stay
|
|
17
|
+
-- valid records but must be re-minted through the bridge before the next
|
|
18
|
+
-- claim; the store treats a missing/empty seed as "not replay-capable".
|
|
19
|
+
--
|
|
20
|
+
-- No DDL is needed: the JSON shape already carries everything. Kept as an
|
|
21
|
+
-- empty migration so the migration numbering records the policy change.
|
|
22
|
+
SELECT 1;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
-- Denormalizes the share-template family onto every telemetry event.
|
|
2
|
+
--
|
|
3
|
+
-- The share page's family rollup used to scope by an `EXISTS` against
|
|
4
|
+
-- `api_keys` (the template plus every child it issued). That made history
|
|
5
|
+
-- depend on the key row surviving: revoking/removing a key silently dropped
|
|
6
|
+
-- its events out of the family totals. This column pins the template on the
|
|
7
|
+
-- event at write time, so usage outlives the key.
|
|
8
|
+
--
|
|
9
|
+
-- Backfill is idempotent: it only fills NULL rows (the column is new, so
|
|
10
|
+
-- every existing row is NULL) and never overwrites a value. Events whose key
|
|
11
|
+
-- was already hard-deleted before this migration cannot be attributed and stay
|
|
12
|
+
-- NULL; the soft-delete change shipped alongside this prevents future loss.
|
|
13
|
+
|
|
14
|
+
ALTER TABLE "telemetry_events" ADD COLUMN IF NOT EXISTS "family_template_key_id" uuid;
|
|
15
|
+
|
|
16
|
+
CREATE INDEX IF NOT EXISTS "telemetry_events_tenant_family_created_id_idx"
|
|
17
|
+
ON "telemetry_events" ("tenant_id", "family_template_key_id", "created_at" DESC, "id" DESC);
|
|
18
|
+
|
|
19
|
+
ALTER TABLE "telemetry_usage_totals" ADD COLUMN IF NOT EXISTS "family_template_key_id" uuid;
|
|
20
|
+
|
|
21
|
+
CREATE INDEX IF NOT EXISTS "telemetry_usage_totals_tenant_family_idx"
|
|
22
|
+
ON "telemetry_usage_totals" ("tenant_id", "family_template_key_id");
|
|
23
|
+
|
|
24
|
+
UPDATE "telemetry_events" AS e
|
|
25
|
+
SET "family_template_key_id" = (
|
|
26
|
+
SELECT COALESCE(k."parent_key_id", k."id")
|
|
27
|
+
FROM "api_keys" k
|
|
28
|
+
WHERE k."id" = e."api_key_id"
|
|
29
|
+
)
|
|
30
|
+
WHERE e."family_template_key_id" IS NULL AND e."api_key_id" IS NOT NULL;
|
|
31
|
+
|
|
32
|
+
UPDATE "telemetry_usage_totals" AS t
|
|
33
|
+
SET "family_template_key_id" = (
|
|
34
|
+
SELECT COALESCE(k."parent_key_id", k."id")
|
|
35
|
+
FROM "api_keys" k
|
|
36
|
+
WHERE k."id" = t."entity_id"
|
|
37
|
+
)
|
|
38
|
+
WHERE t."family_template_key_id" IS NULL
|
|
39
|
+
AND t."identity_type" = 'api_key'
|
|
40
|
+
AND t."entity_id" IS NOT NULL;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
-- One-time row-data optimization for share children.
|
|
2
|
+
--
|
|
3
|
+
-- Every minted share child used to copy the template's policy columns
|
|
4
|
+
-- (notes, limits, model_list, denylist, …). Auth never reads those from the
|
|
5
|
+
-- child — it resolves `policy = parent ?? row` — so the copies were pure
|
|
6
|
+
-- write-amplification. This UPDATE nulls the 11 nullable policy columns on
|
|
7
|
+
-- every child (`parent_key_id IS NOT NULL`). `scopes` stays (NOT NULL, and
|
|
8
|
+
-- required by backup restore); `model_access_mode` stays (NOT NULL default
|
|
9
|
+
-- 'whitelist'). Schema shape is unchanged — no DROP COLUMN — so backup/
|
|
10
|
+
-- restore remains compatible both directions.
|
|
11
|
+
--
|
|
12
|
+
-- Idempotent: the OR-of-IS-NOT-NULL predicate matches nothing on a re-run,
|
|
13
|
+
-- and the migration ledger skips the file after the first apply.
|
|
14
|
+
--
|
|
15
|
+
-- Keep in sync with `normalizeShareChildPolicy` in
|
|
16
|
+
-- `src/console/backup/store.ts` (post-restore re-applies the same null-out
|
|
17
|
+
-- for a tenant, because restore does not re-run numbered migrations).
|
|
18
|
+
|
|
19
|
+
UPDATE "api_keys"
|
|
20
|
+
SET "notes_title" = NULL,
|
|
21
|
+
"notes_subtitle" = NULL,
|
|
22
|
+
"notes_body" = NULL,
|
|
23
|
+
"requests_per_minute" = NULL,
|
|
24
|
+
"daily_token_limit" = NULL,
|
|
25
|
+
"monthly_token_limit" = NULL,
|
|
26
|
+
"lifetime_token_budget" = NULL,
|
|
27
|
+
"max_concurrent_requests" = NULL,
|
|
28
|
+
"model_prefix" = NULL,
|
|
29
|
+
"model_list" = NULL,
|
|
30
|
+
"client_router_denylist" = NULL
|
|
31
|
+
WHERE "parent_key_id" IS NOT NULL
|
|
32
|
+
AND ( "notes_title" IS NOT NULL OR "notes_subtitle" IS NOT NULL
|
|
33
|
+
OR "notes_body" IS NOT NULL OR "requests_per_minute" IS NOT NULL
|
|
34
|
+
OR "daily_token_limit" IS NOT NULL OR "monthly_token_limit" IS NOT NULL
|
|
35
|
+
OR "lifetime_token_budget" IS NOT NULL
|
|
36
|
+
OR "max_concurrent_requests" IS NOT NULL OR "model_prefix" IS NOT NULL
|
|
37
|
+
OR "model_list" IS NOT NULL
|
|
38
|
+
OR "client_router_denylist" IS NOT NULL );
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
-- Add a share-template child slot cap.
|
|
2
|
+
--
|
|
3
|
+
-- Share enrollment links are public, and an attacker minting child rows is
|
|
4
|
+
-- only bounded by the per-IP dedupe, which IP rotation (CDN edges, cloud
|
|
5
|
+
-- egress, residential proxies) defeats. `max_children` lets an operator cap
|
|
6
|
+
-- how many concurrently-active child keys a template may mint; NULL keeps the
|
|
7
|
+
-- legacy unlimited behavior. Enforced at mint time (not a database
|
|
8
|
+
-- constraint) so the error path is a clean 429/409.
|
|
9
|
+
|
|
10
|
+
ALTER TABLE "api_keys" ADD COLUMN "max_children" integer;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
-- Tenant-scoped system prompt injection (append/override).
|
|
2
|
+
--
|
|
3
|
+
-- Resolution is most-specific-wins: model > provider > global. A provider
|
|
4
|
+
-- either follows the tenant's global prompt (`providers` entry
|
|
5
|
+
-- followGlobal = true, its own setting is ignored) or carries a custom one.
|
|
6
|
+
-- Text is capped at 5 MB per scope in the console route; the dispatch-path
|
|
7
|
+
-- reader is revision-keyed cached, so a mutation converges within the
|
|
8
|
+
-- settings-revision bump. `global` NULL means never configured — distinct
|
|
9
|
+
-- from an explicit `{"enabled": false}` row.
|
|
10
|
+
CREATE TABLE IF NOT EXISTS "tenant_system_prompts" (
|
|
11
|
+
"tenant_id" uuid PRIMARY KEY REFERENCES "tenants" ("id") ON DELETE CASCADE,
|
|
12
|
+
"global" jsonb,
|
|
13
|
+
"providers" jsonb NOT NULL DEFAULT '{}',
|
|
14
|
+
"models" jsonb NOT NULL DEFAULT '{}',
|
|
15
|
+
"updated_at" timestamptz NOT NULL DEFAULT now()
|
|
16
|
+
);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
-- Qoder native machine identity (UMID) bound to one account.
|
|
2
|
+
--
|
|
3
|
+
-- SQLite mirror of `full-postgres/0026_add_qoder_native_identity.sql`:
|
|
4
|
+
-- the column is `text` (the SQLite representation of jsonb) and the unique
|
|
5
|
+
-- index extracts the `machineToken` the same way the application reads it.
|
|
6
|
+
--
|
|
7
|
+
-- The partial unique index enforces "one device per account" at the database
|
|
8
|
+
-- level. SQLite supports expression indexes (3.38+); a bound identity is a
|
|
9
|
+
-- non-null JSON object whose `$.machineToken` is the device key.
|
|
10
|
+
ALTER TABLE "provider_accounts"
|
|
11
|
+
ADD COLUMN "native_identity" text;
|
|
12
|
+
|
|
13
|
+
CREATE UNIQUE INDEX "provider_accounts_native_identity_token_uidx"
|
|
14
|
+
ON "provider_accounts" (json_extract(native_identity, '$.machineToken'))
|
|
15
|
+
WHERE native_identity IS NOT NULL;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
-- Qoder native identity: genuine SG identity + per-account seed replay.
|
|
2
|
+
--
|
|
3
|
+
-- Research (2026-10-30, see documentation/research/qoder-identity-gate-
|
|
4
|
+
-- postmortem.md and qoder-umid-reverse.md) established that the daily-credit
|
|
5
|
+
-- campaign gates its CREDITS grant on a *genuine* Alibaba SG-produced
|
|
6
|
+
-- identity: generated/deterministic tokens do not reveal the grant on a
|
|
7
|
+
-- fresh account, while the `runtime-info` bridge (SG-signed) does.
|
|
8
|
+
--
|
|
9
|
+
-- Migration 0026 already added `native_identity` (the token triple + optional
|
|
10
|
+
-- seed) with a partial unique index on the extracted machineToken — the
|
|
11
|
+
-- "one device per account" invariant. This migration does not change that
|
|
12
|
+
-- schema; it only documents the contract change on the same column:
|
|
13
|
+
--
|
|
14
|
+
-- `seed` is now REQUIRED for a claim-capable identity (the seed is the
|
|
15
|
+
-- device material; the token can be re-derived from it, never the reverse).
|
|
16
|
+
-- Rows minted by the retired generated path carry `seed = ""` — they stay
|
|
17
|
+
-- valid records but must be re-minted through the bridge before the next
|
|
18
|
+
-- claim; the store treats a missing/empty seed as "not replay-capable".
|
|
19
|
+
--
|
|
20
|
+
-- No DDL is needed: the JSON shape already carries everything. Kept as an
|
|
21
|
+
-- empty migration so the migration numbering records the policy change.
|
|
22
|
+
SELECT 1;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
-- Denormalizes the share-template family onto every telemetry event.
|
|
2
|
+
--
|
|
3
|
+
-- The share page's family rollup used to scope by an `EXISTS` against
|
|
4
|
+
-- `api_keys` (the template plus every child it issued). That made history
|
|
5
|
+
-- depend on the key row surviving: revoking/removing a key silently dropped
|
|
6
|
+
-- its events out of the family totals. This column pins the template on the
|
|
7
|
+
-- event at write time, so usage outlives the key.
|
|
8
|
+
--
|
|
9
|
+
-- Backfill is idempotent: it only fills NULL rows (the column is new, so
|
|
10
|
+
-- every existing row is NULL) and never overwrites a value. Events whose key
|
|
11
|
+
-- was already hard-deleted before this migration cannot be attributed and stay
|
|
12
|
+
-- NULL; the soft-delete change shipped alongside this prevents future loss.
|
|
13
|
+
|
|
14
|
+
ALTER TABLE "telemetry_events" ADD COLUMN "family_template_key_id" text;
|
|
15
|
+
|
|
16
|
+
CREATE INDEX IF NOT EXISTS "telemetry_events_tenant_family_created_id_idx"
|
|
17
|
+
ON "telemetry_events" ("tenant_id", "family_template_key_id", "created_at" DESC, "id" DESC);
|
|
18
|
+
|
|
19
|
+
ALTER TABLE "telemetry_usage_totals" ADD COLUMN "family_template_key_id" text;
|
|
20
|
+
|
|
21
|
+
CREATE INDEX IF NOT EXISTS "telemetry_usage_totals_tenant_family_idx"
|
|
22
|
+
ON "telemetry_usage_totals" ("tenant_id", "family_template_key_id");
|
|
23
|
+
|
|
24
|
+
UPDATE "telemetry_events" AS e
|
|
25
|
+
SET "family_template_key_id" = (
|
|
26
|
+
SELECT COALESCE(k."parent_key_id", k."id")
|
|
27
|
+
FROM "api_keys" k
|
|
28
|
+
WHERE k."id" = e."api_key_id"
|
|
29
|
+
)
|
|
30
|
+
WHERE e."family_template_key_id" IS NULL AND e."api_key_id" IS NOT NULL;
|
|
31
|
+
|
|
32
|
+
UPDATE "telemetry_usage_totals" AS t
|
|
33
|
+
SET "family_template_key_id" = (
|
|
34
|
+
SELECT COALESCE(k."parent_key_id", k."id")
|
|
35
|
+
FROM "api_keys" k
|
|
36
|
+
WHERE k."id" = t."entity_id"
|
|
37
|
+
)
|
|
38
|
+
WHERE t."family_template_key_id" IS NULL
|
|
39
|
+
AND t."identity_type" = 'api_key'
|
|
40
|
+
AND t."entity_id" IS NOT NULL;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
-- One-time row-data optimization for share children.
|
|
2
|
+
--
|
|
3
|
+
-- Every minted share child used to copy the template's policy columns
|
|
4
|
+
-- (notes, limits, model_list, denylist, …). Auth never reads those from the
|
|
5
|
+
-- child — it resolves `policy = parent ?? row` — so the copies were pure
|
|
6
|
+
-- write-amplification. This UPDATE nulls the 11 nullable policy columns on
|
|
7
|
+
-- every child (`parent_key_id IS NOT NULL`). `scopes` stays (NOT NULL, and
|
|
8
|
+
-- required by backup restore); `model_access_mode` stays (NOT NULL default
|
|
9
|
+
-- 'whitelist'). Schema shape is unchanged — no DROP COLUMN — so backup/
|
|
10
|
+
-- restore remains compatible both directions.
|
|
11
|
+
--
|
|
12
|
+
-- Idempotent: the OR-of-IS-NOT-NULL predicate matches nothing on a re-run,
|
|
13
|
+
-- and the migration ledger skips the file after the first apply.
|
|
14
|
+
--
|
|
15
|
+
-- Keep in sync with `normalizeShareChildPolicy` in
|
|
16
|
+
-- `src/console/backup/store.ts` (post-restore re-applies the same null-out
|
|
17
|
+
-- for a tenant, because restore does not re-run numbered migrations).
|
|
18
|
+
|
|
19
|
+
UPDATE "api_keys"
|
|
20
|
+
SET "notes_title" = NULL,
|
|
21
|
+
"notes_subtitle" = NULL,
|
|
22
|
+
"notes_body" = NULL,
|
|
23
|
+
"requests_per_minute" = NULL,
|
|
24
|
+
"daily_token_limit" = NULL,
|
|
25
|
+
"monthly_token_limit" = NULL,
|
|
26
|
+
"lifetime_token_budget" = NULL,
|
|
27
|
+
"max_concurrent_requests" = NULL,
|
|
28
|
+
"model_prefix" = NULL,
|
|
29
|
+
"model_list" = NULL,
|
|
30
|
+
"client_router_denylist" = NULL
|
|
31
|
+
WHERE "parent_key_id" IS NOT NULL
|
|
32
|
+
AND ( "notes_title" IS NOT NULL OR "notes_subtitle" IS NOT NULL
|
|
33
|
+
OR "notes_body" IS NOT NULL OR "requests_per_minute" IS NOT NULL
|
|
34
|
+
OR "daily_token_limit" IS NOT NULL OR "monthly_token_limit" IS NOT NULL
|
|
35
|
+
OR "lifetime_token_budget" IS NOT NULL
|
|
36
|
+
OR "max_concurrent_requests" IS NOT NULL OR "model_prefix" IS NOT NULL
|
|
37
|
+
OR "model_list" IS NOT NULL
|
|
38
|
+
OR "client_router_denylist" IS NOT NULL );
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
-- Add a share-template child slot cap.
|
|
2
|
+
--
|
|
3
|
+
-- Share enrollment links are public, and an attacker minting child rows is
|
|
4
|
+
-- only bounded by the per-IP dedupe, which IP rotation (CDN edges, cloud
|
|
5
|
+
-- egress, residential proxies) defeats. `max_children` lets an operator cap
|
|
6
|
+
-- how many concurrently-active child keys a template may mint; NULL keeps the
|
|
7
|
+
-- legacy unlimited behavior. Enforced at mint time (not a database
|
|
8
|
+
-- constraint) so the error path is a clean 429/409.
|
|
9
|
+
|
|
10
|
+
ALTER TABLE "api_keys" ADD COLUMN "max_children" integer;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
-- Tenant-scoped system prompt injection (append/override).
|
|
2
|
+
--
|
|
3
|
+
-- Mirror of the Postgres migration; see that file for rationale.
|
|
4
|
+
CREATE TABLE IF NOT EXISTS "tenant_system_prompts" (
|
|
5
|
+
"tenant_id" TEXT PRIMARY KEY REFERENCES "tenants" ("id") ON DELETE CASCADE,
|
|
6
|
+
"global" TEXT,
|
|
7
|
+
"providers" TEXT NOT NULL DEFAULT '{}',
|
|
8
|
+
"models" TEXT NOT NULL DEFAULT '{}',
|
|
9
|
+
"updated_at" TEXT NOT NULL DEFAULT (datetime('now'))
|
|
10
|
+
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cartethyia",
|
|
3
|
-
"version": "2.7.
|
|
3
|
+
"version": "2.7.3",
|
|
4
4
|
"description": "A powerful, self-hosted reverse proxy for OpenAI- and Anthropic-compatible AI clients, powered by native Bun and Elysia. It serves both protocols from a single server, routes every model across any configured provider, and translates requests and responses in real time — streaming and prompt caching included. Underneath it runs a full delivery engine: per-account health tracking, quota and cooldown enforcement, automatic failover across pools and providers, usage accounting, and telemetry. Point OpenCode, Cline, Claude Code, Codex, or any compatible client at Cartethyia and it keeps its native protocol while the gateway absorbs every provider-specific difference behind it. Runs on embedded SQLite or external PostgreSQL with optional Redis coordination, ships as a global CLI with a system-tray console, and needs only Bun 1.4+ alongside Node.js/npm.",
|
|
5
5
|
"license": "GPL-3.0-only",
|
|
6
6
|
"type": "module",
|
package/src/config/network.ts
CHANGED
|
@@ -20,7 +20,12 @@ import { utcDayStart, utcMonthStart } from "../shared/day";
|
|
|
20
20
|
*
|
|
21
21
|
* A share template's recipients admit under the parent id, and their spend is
|
|
22
22
|
* attributed to their own child row, so the family is summed — otherwise
|
|
23
|
-
* seeding a template would miss everything its recipients already used.
|
|
23
|
+
* seeding a template would miss everything its recipients already used. The
|
|
24
|
+
* family is passed to the reader as the template's id, which the query
|
|
25
|
+
* resolves with an `EXISTS` against `api_keys`: a family that has minted tens
|
|
26
|
+
* of thousands of children must not expand them into bind parameters on the
|
|
27
|
+
* key-creation path, which is where an old id-list version crashed the
|
|
28
|
+
* process.
|
|
24
29
|
*/
|
|
25
30
|
export async function familyBucketSpend(
|
|
26
31
|
db: CartethyiaDatabase,
|
|
@@ -36,15 +41,10 @@ export async function familyBucketSpend(
|
|
|
36
41
|
.limit(1);
|
|
37
42
|
const tenantId = parent?.tenantId;
|
|
38
43
|
if (tenantId === undefined) return { daily: 0, monthly: 0 };
|
|
39
|
-
const children = await db
|
|
40
|
-
.select({ id: apiKeys.id })
|
|
41
|
-
.from(apiKeys)
|
|
42
|
-
.where(eq(apiKeys.parentKeyId, keyId));
|
|
43
|
-
const keyIds = [keyId, ...children.map((child) => child.id)];
|
|
44
44
|
// Two SQL sums instead of reading every event of the family: the bucket
|
|
45
45
|
// spend only needs a total, and this runs on the key-creation path.
|
|
46
46
|
const spentSince = async (start: Date): Promise<number> =>
|
|
47
|
-
sumTelemetryTokens(db, tenantId, {
|
|
47
|
+
sumTelemetryTokens(db, tenantId, { familyKeyId: keyId, since: start });
|
|
48
48
|
const [daily, monthly] = await Promise.all([
|
|
49
49
|
spentSince(utcDayStart(now)),
|
|
50
50
|
spentSince(utcMonthStart(now)),
|