@undefineds.co/xpod 0.4.29 → 0.4.30

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.
Files changed (179) hide show
  1. package/dist/api/ApiServer.js +4 -0
  2. package/dist/api/ai-gateway/AiGatewayService.d.ts +55 -0
  3. package/dist/api/ai-gateway/AiGatewayService.js +145 -6
  4. package/dist/api/ai-gateway/auth/AiConnectionsInvocationKeyIssuer.js +5 -3
  5. package/dist/api/ai-gateway/auth/GatewayApiKeyAuthenticator.d.ts +16 -49
  6. package/dist/api/ai-gateway/auth/GatewayApiKeyAuthenticator.js +6 -71
  7. package/dist/api/ai-gateway/auth/InvocationTokenAuthenticator.js +1 -0
  8. package/dist/api/ai-gateway/auth/InvocationTokenCodec.d.ts +4 -0
  9. package/dist/api/ai-gateway/auth/InvocationTokenCodec.js +8 -1
  10. package/dist/api/ai-gateway/connect/FileSessionImportAdapter.d.ts +3 -0
  11. package/dist/api/ai-gateway/connect/FileSessionImportAdapter.js +23 -3
  12. package/dist/api/ai-gateway/connect/SessionImportProfiles.d.ts +9 -1
  13. package/dist/api/ai-gateway/connect/SessionImportProfiles.js +4 -3
  14. package/dist/api/ai-gateway/connect/index.d.ts +40 -0
  15. package/dist/api/ai-gateway/connect/index.js +194 -4
  16. package/dist/api/ai-gateway/models/PodModelSelectionRepository.js +1 -1
  17. package/dist/api/ai-gateway/pod/OwnerPodAccess.js +5 -0
  18. package/dist/api/ai-gateway/pod/PodBaseUrlResolver.d.ts +11 -2
  19. package/dist/api/ai-gateway/pod/PodBaseUrlResolver.js +72 -10
  20. package/dist/api/ai-gateway/quota/ProviderQuotaAdapter.js +1 -1
  21. package/dist/api/ai-gateway/routing/ModelRouter.d.ts +7 -0
  22. package/dist/api/ai-gateway/routing/ModelRouter.js +13 -10
  23. package/dist/api/ai-gateway/service-access/AiConnectionsServiceAccess.d.ts +1 -5
  24. package/dist/api/ai-gateway/service-access/AiConnectionsServiceAccess.js +8 -63
  25. package/dist/api/auth/AuthContext.d.ts +4 -0
  26. package/dist/api/auth/ClientCredentialsAuthenticator.js +11 -5
  27. package/dist/api/auth/SolidSessionFactory.d.ts +50 -4
  28. package/dist/api/auth/SolidSessionFactory.js +114 -4
  29. package/dist/api/chatkit/pod-store.d.ts +8 -1
  30. package/dist/api/chatkit/pod-store.js +54 -3
  31. package/dist/api/container/common.js +34 -60
  32. package/dist/api/container/index.js +0 -3
  33. package/dist/api/container/routes.js +1 -8
  34. package/dist/api/container/types.d.ts +2 -9
  35. package/dist/api/container/types.js +0 -5
  36. package/dist/api/handlers/AiGatewayManagementHandler.d.ts +4 -12
  37. package/dist/api/handlers/AiGatewayManagementHandler.js +18 -258
  38. package/dist/api/middleware/AuthMiddleware.js +29 -1
  39. package/dist/api/runs/PiAgentRuntimeDriver.js +6 -1
  40. package/dist/cli/index.js +2 -1
  41. package/dist/identity/oidc/PodOwnershipResolver.js +16 -6
  42. package/dist/runtime/ingress-port.d.ts +9 -2
  43. package/dist/runtime/ingress-port.js +7 -2
  44. package/dist/runtime/local-secret-file.d.ts +1 -1
  45. package/dist/runtime/runner/node/CommunitySolidServerCssRunner.d.ts +3 -1
  46. package/dist/runtime/runner/node/CommunitySolidServerCssRunner.js +31 -1
  47. package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsPanel.d.ts +3 -1
  48. package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsPanel.js +96 -67
  49. package/node_modules/@undefineds.co/ai-connections/dist/AiCredentialPoolSection.d.ts +2 -1
  50. package/node_modules/@undefineds.co/ai-connections/dist/AiCredentialPoolSection.js +2 -2
  51. package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayKeyRow.d.ts +1 -2
  52. package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayKeyRow.js +2 -2
  53. package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayKeysSection.js +81 -23
  54. package/node_modules/@undefineds.co/ai-connections/dist/AiOfferingDetails.d.ts +2 -1
  55. package/node_modules/@undefineds.co/ai-connections/dist/AiOfferingDetails.js +2 -2
  56. package/node_modules/@undefineds.co/ai-connections/dist/AiProviderCard.d.ts +2 -1
  57. package/node_modules/@undefineds.co/ai-connections/dist/AiProviderCard.js +2 -2
  58. package/node_modules/@undefineds.co/ai-connections/dist/AiProviderHeader.js +1 -1
  59. package/node_modules/@undefineds.co/ai-connections/dist/contract/client/fingerprint.d.ts +1 -0
  60. package/node_modules/@undefineds.co/ai-connections/dist/contract/client/fingerprint.js +7 -0
  61. package/node_modules/@undefineds.co/ai-connections/dist/contract/client/normalize.d.ts +1 -2
  62. package/node_modules/@undefineds.co/ai-connections/dist/contract/client/normalize.js +0 -33
  63. package/node_modules/@undefineds.co/ai-connections/dist/contract/client/request.d.ts +1 -1
  64. package/node_modules/@undefineds.co/ai-connections/dist/contract/client/request.js +68 -22
  65. package/node_modules/@undefineds.co/ai-connections/dist/contract/client/types.d.ts +37 -10
  66. package/node_modules/@undefineds.co/ai-connections/dist/controller.js +5 -54
  67. package/node_modules/@undefineds.co/ai-connections/dist/error-wording.js +7 -2
  68. package/node_modules/@undefineds.co/ai-connections/dist/service-access-resources.cjs +405 -0
  69. package/node_modules/@undefineds.co/ai-connections/dist/service-access-resources.d.ts +14 -0
  70. package/node_modules/@undefineds.co/ai-connections/dist/service-access-resources.js +36 -0
  71. package/node_modules/@undefineds.co/ai-connections/dist/service-access.js +5 -26
  72. package/node_modules/@undefineds.co/ai-connections/package.json +10 -2
  73. package/node_modules/@undefineds.co/extension-sdk/dist/solid-permissions.js +131 -13
  74. package/node_modules/@undefineds.co/extension-sdk/dist/web.d.ts +7 -1
  75. package/node_modules/@undefineds.co/extension-sdk/package.json +1 -1
  76. package/node_modules/@undefineds.co/pod-collections/dist/index.cjs +38 -5
  77. package/node_modules/@undefineds.co/pod-collections/dist/mapping.d.ts +8 -0
  78. package/node_modules/@undefineds.co/pod-collections/dist/mapping.js +34 -0
  79. package/node_modules/@undefineds.co/pod-collections/dist/mutations.d.ts +2 -1
  80. package/node_modules/@undefineds.co/pod-collections/dist/mutations.js +6 -4
  81. package/node_modules/@undefineds.co/pod-collections/dist/sync.js +4 -3
  82. package/node_modules/@undefineds.co/pod-collections/package.json +1 -1
  83. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/IdpChrome.d.ts +1 -1
  84. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/IdpChrome.js +2 -2
  85. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/IdpViews.js +2 -2
  86. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/PodSignInFrame.d.ts +3 -3
  87. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/PodSignInFrame.js +5 -5
  88. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/parts.d.ts +5 -5
  89. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/parts.js +5 -5
  90. package/node_modules/@undefineds.co/shared-ui/dist/theme.css +32 -5
  91. package/node_modules/@undefineds.co/shared-ui/package.json +1 -1
  92. package/package.json +2 -2
  93. package/static/app/assets/main.css +1 -1
  94. package/static/app/assets/main.js +18 -18
  95. package/static/dashboard/assets/{AccountAuthBoundary-Dv52SZc6.js → AccountAuthBoundary-CuqXFEW4.js} +1 -1
  96. package/static/dashboard/assets/{DesktopOidcCallback-DaT_Rumf.js → DesktopOidcCallback-7i-yOvPW.js} +1 -1
  97. package/static/dashboard/assets/DevicePages-D1m_BNtX.js +2 -0
  98. package/static/dashboard/assets/ModelsPage-0qWGa5Y6.js +12 -0
  99. package/static/dashboard/assets/{PaneListHeader-DtvnRmFq.js → PaneListHeader-uWdPgJ0E.js} +1 -1
  100. package/static/dashboard/assets/{PodDeletionAuthorizationPanel-BJk_8rJq.js → PodDeletionAuthorizationPanel-C22bhZeD.js} +3 -3
  101. package/static/dashboard/assets/{PodPage-C4gzEspV.js → PodPage-Dyo3yCb-.js} +1 -1
  102. package/static/dashboard/assets/{SystemSettingsPage-HaNrP1H1.js → SystemSettingsPage-CeX-oG_a.js} +1 -1
  103. package/static/dashboard/assets/{TasksPage-BdO5K2L7.js → TasksPage-B0EoyRYT.js} +1 -1
  104. package/static/dashboard/assets/{WebDesktopEntry-Cj9_ZfJU.js → WebDesktopEntry-DT44RrTa.js} +1 -1
  105. package/static/dashboard/assets/XpodAiConnectionsPodStore-EXCqZPmb.js +3 -0
  106. package/static/dashboard/assets/XpodShellApp-BEzi4f1j.css +1 -0
  107. package/static/dashboard/assets/XpodShellApp-DAFsxamX.js +4 -0
  108. package/static/dashboard/assets/{account-session-DlcKNG7k.js → account-session-rRAOF7nF.js} +1 -1
  109. package/static/dashboard/assets/{button-wslF55uZ.js → button-WVnQUNG-.js} +1 -1
  110. package/static/dashboard/assets/{collection-runtime-uxxgEu13.js → collection-runtime-BAJQ8Qub.js} +1 -1
  111. package/static/dashboard/assets/{createLucideIcon-BJQl82Qk.js → createLucideIcon-BWelSi3L.js} +1 -1
  112. package/static/dashboard/assets/dashboard-hSOBxPcP.css +1 -0
  113. package/static/dashboard/assets/{dashboard-Or0gnkou.js → dashboard-vmne1ZE0.js} +2 -2
  114. package/static/dashboard/assets/{index-BqFeOML9.js → index-HDQQ8asz.js} +1 -1
  115. package/static/dashboard/assets/{index-DgKn1twH.js → index-gtv-MAHl.js} +1 -1
  116. package/static/dashboard/assets/{label-CS6Sx6Zb.js → label-tKuCTJm2.js} +1 -1
  117. package/static/dashboard/assets/{list-UyhlCFKk.js → list-CKq3KHke.js} +1 -1
  118. package/static/dashboard/assets/{nav-item-style-CW1Nnorq.js → nav-item-style-B2gI7c52.js} +1 -1
  119. package/static/dashboard/assets/pod-collections-host-BqOAkacM.js +8 -0
  120. package/static/dashboard/assets/{safe-continuation-ClWAhcma.js → safe-continuation-BsKjDpAA.js} +1 -1
  121. package/static/dashboard/assets/{section-header-CEIEcco-.js → section-header-DM0JU-wk.js} +1 -1
  122. package/static/dashboard/assets/{setting-row-CaYv3dfF.js → setting-row-XiH7UjWy.js} +1 -1
  123. package/static/dashboard/assets/{xpod-remembered-login-BUF9fin1.js → xpod-remembered-login-nv1g1sfC.js} +4 -4
  124. package/static/dashboard/dashboard.html +2 -2
  125. package/static/settings/assets/{AccountAuthBoundary-Chqd38oU.js → AccountAuthBoundary-DAUR0omy.js} +1 -1
  126. package/static/settings/assets/{DesktopOidcCallback-VUrOSM_q.js → DesktopOidcCallback-BNZAZMWY.js} +1 -1
  127. package/static/settings/assets/DevicePages-BO9SrXRp.js +2 -0
  128. package/static/settings/assets/ModelsPage-DREEXdf3.js +12 -0
  129. package/static/settings/assets/{PaneListHeader-B5RkRqr4.js → PaneListHeader-CeUH0JjQ.js} +1 -1
  130. package/static/settings/assets/{PodDeletionAuthorizationPanel-DPM-5Izt.js → PodDeletionAuthorizationPanel-Ch4--l4b.js} +3 -3
  131. package/static/settings/assets/{PodPage-CxND6wwc.js → PodPage-CqJBj3GJ.js} +1 -1
  132. package/static/settings/assets/{SystemSettingsPage-C8EdMkW7.js → SystemSettingsPage-2LSjpqUa.js} +1 -1
  133. package/static/settings/assets/{TasksPage-DuqptEm8.js → TasksPage-DA5IRxlP.js} +1 -1
  134. package/static/settings/assets/{WebDesktopEntry-BRcyktkv.js → WebDesktopEntry-BVelF1q0.js} +1 -1
  135. package/static/settings/assets/XpodAiConnectionsPodStore-O5-2qBsx.js +3 -0
  136. package/static/settings/assets/XpodShellApp-BEzi4f1j.css +1 -0
  137. package/static/settings/assets/XpodShellApp-D1b3kqD0.js +4 -0
  138. package/static/settings/assets/XpodThemeProvider-hSOBxPcP.css +1 -0
  139. package/static/settings/assets/{XpodThemeProvider-DK3pIdRG.js → XpodThemeProvider-rUdAw66p.js} +2 -2
  140. package/static/settings/assets/{account-session-DJOZ03xr.js → account-session-BD1q8D_o.js} +1 -1
  141. package/static/settings/assets/auth-callback-PWS7okI8.js +1 -0
  142. package/static/settings/assets/{button-D3yW-2o1.js → button-ZJYFB218.js} +1 -1
  143. package/static/settings/assets/{collection-runtime-DfGo25mh.js → collection-runtime-C2FHCCXJ.js} +1 -1
  144. package/static/settings/assets/{createLucideIcon-CacwLsmB.js → createLucideIcon-B2wXvYTD.js} +1 -1
  145. package/static/settings/assets/{index-r5KRYsKC.js → index-JFAkaKZH.js} +1 -1
  146. package/static/settings/assets/{label-MJjUmvzG.js → label-BLrTAmGy.js} +1 -1
  147. package/static/settings/assets/{list-Ce-5k1MX.js → list-Cm96vvJO.js} +1 -1
  148. package/static/settings/assets/{nav-item-style-ZUbL8KOZ.js → nav-item-style-C2upI7sr.js} +1 -1
  149. package/static/settings/assets/pod-collections-host-BqOAkacM.js +8 -0
  150. package/static/settings/assets/{safe-continuation-vlBZFSlU.js → safe-continuation-CYaRj3rj.js} +1 -1
  151. package/static/settings/assets/{section-header-DGJdEvQw.js → section-header-BviL5H8E.js} +1 -1
  152. package/static/settings/assets/{setting-row-C7tuFiho.js → setting-row-BYikj0YO.js} +1 -1
  153. package/static/settings/assets/{settings-CyQPih1O.js → settings-CpoDG_Qr.js} +1 -1
  154. package/static/settings/assets/{xpod-remembered-login-D-TzzT5K.js → xpod-remembered-login-BJ4QUSXy.js} +4 -4
  155. package/static/settings/auth-callback.html +3 -3
  156. package/static/settings/settings.html +3 -3
  157. package/dist/api/ai-gateway/auth/GatewayApiKey.d.ts +0 -28
  158. package/dist/api/ai-gateway/auth/GatewayApiKey.js +0 -162
  159. package/dist/api/ai-gateway/auth/GatewayKeyLocatorCodec.d.ts +0 -26
  160. package/dist/api/ai-gateway/auth/GatewayKeyLocatorCodec.js +0 -97
  161. package/dist/api/ai-gateway/auth/PodGatewayAccessKeyRepository.d.ts +0 -67
  162. package/dist/api/ai-gateway/auth/PodGatewayAccessKeyRepository.js +0 -340
  163. package/dist/runtime/gateway-locator-secret.d.ts +0 -5
  164. package/dist/runtime/gateway-locator-secret.js +0 -30
  165. package/static/dashboard/assets/DevicePages-HjclpIVm.js +0 -2
  166. package/static/dashboard/assets/ModelsPage-Be2TPd-x.js +0 -11
  167. package/static/dashboard/assets/XpodAiConnectionsPodStore-B7gmXBmC.js +0 -3
  168. package/static/dashboard/assets/XpodShellApp-Bwom2xL3.css +0 -1
  169. package/static/dashboard/assets/XpodShellApp-D_KY4nCW.js +0 -4
  170. package/static/dashboard/assets/dashboard-CbJ-JkrI.css +0 -1
  171. package/static/dashboard/assets/pod-collections-host-DjK2xf-b.js +0 -8
  172. package/static/settings/assets/DevicePages-C6qwvWwu.js +0 -2
  173. package/static/settings/assets/ModelsPage-Ry_dObRQ.js +0 -11
  174. package/static/settings/assets/XpodAiConnectionsPodStore-CyA_BJVC.js +0 -3
  175. package/static/settings/assets/XpodShellApp-Bwom2xL3.css +0 -1
  176. package/static/settings/assets/XpodShellApp-CsivHJl0.js +0 -4
  177. package/static/settings/assets/XpodThemeProvider-CbJ-JkrI.css +0 -1
  178. package/static/settings/assets/auth-callback-GIBYEz_7.js +0 -1
  179. package/static/settings/assets/pod-collections-host-DjK2xf-b.js +0 -8
@@ -6,9 +6,9 @@
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <script src="/settings/theme-init.js"></script>
8
8
  <title>正在完成 Xpod 登录</title>
9
- <script type="module" crossorigin src="/settings/assets/auth-callback-GIBYEz_7.js"></script>
10
- <link rel="modulepreload" crossorigin href="/settings/assets/XpodThemeProvider-DK3pIdRG.js">
11
- <link rel="stylesheet" crossorigin href="/settings/assets/XpodThemeProvider-CbJ-JkrI.css">
9
+ <script type="module" crossorigin src="/settings/assets/auth-callback-PWS7okI8.js"></script>
10
+ <link rel="modulepreload" crossorigin href="/settings/assets/XpodThemeProvider-rUdAw66p.js">
11
+ <link rel="stylesheet" crossorigin href="/settings/assets/XpodThemeProvider-hSOBxPcP.css">
12
12
  </head>
13
13
  <body class="bg-background text-foreground">
14
14
  <div id="root"></div>
@@ -6,9 +6,9 @@
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <script src="/settings/theme-init.js"></script>
8
8
  <title>Xpod · 工作台</title>
9
- <script type="module" crossorigin src="/settings/assets/settings-CyQPih1O.js"></script>
10
- <link rel="modulepreload" crossorigin href="/settings/assets/XpodThemeProvider-DK3pIdRG.js">
11
- <link rel="stylesheet" crossorigin href="/settings/assets/XpodThemeProvider-CbJ-JkrI.css">
9
+ <script type="module" crossorigin src="/settings/assets/settings-CpoDG_Qr.js"></script>
10
+ <link rel="modulepreload" crossorigin href="/settings/assets/XpodThemeProvider-rUdAw66p.js">
11
+ <link rel="stylesheet" crossorigin href="/settings/assets/XpodThemeProvider-hSOBxPcP.css">
12
12
  </head>
13
13
  <body class="bg-background text-foreground">
14
14
  <div id="root"></div>
@@ -1,28 +0,0 @@
1
- export type GatewayDeployment = 'local' | 'cloud';
2
- export interface ParsedGatewayApiKey {
3
- version: 'v1';
4
- deployment: GatewayDeployment;
5
- keyId: string;
6
- secret: string;
7
- }
8
- export interface GatewayApiKeyRecordInput {
9
- id: string;
10
- secretHash: string;
11
- deployment: GatewayDeployment;
12
- }
13
- export interface CreatedGatewayApiKey {
14
- plaintext: string;
15
- secret: string;
16
- record: GatewayApiKeyRecordInput;
17
- }
18
- export interface CreateGatewayApiKeyInput {
19
- deployment: GatewayDeployment;
20
- keyId?: string;
21
- secret?: string;
22
- }
23
- export declare function createGatewayApiKey(input: CreateGatewayApiKeyInput): Promise<CreatedGatewayApiKey>;
24
- export declare function createGatewayKeyId(): string;
25
- export declare function formatGatewayApiKey(parsed: ParsedGatewayApiKey): string;
26
- export declare function parseGatewayApiKey(value: string): ParsedGatewayApiKey | undefined;
27
- export declare function hashGatewayApiKeySecret(secret: string): Promise<string>;
28
- export declare function verifyGatewayApiKeySecret(secret: string, encodedHash: string): Promise<boolean>;
@@ -1,162 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createGatewayApiKey = createGatewayApiKey;
4
- exports.createGatewayKeyId = createGatewayKeyId;
5
- exports.formatGatewayApiKey = formatGatewayApiKey;
6
- exports.parseGatewayApiKey = parseGatewayApiKey;
7
- exports.hashGatewayApiKeySecret = hashGatewayApiKeySecret;
8
- exports.verifyGatewayApiKeySecret = verifyGatewayApiKeySecret;
9
- const node_crypto_1 = require("node:crypto");
10
- const PREFIX = 'xpod_gw';
11
- const VERSION = 'v1';
12
- const SECRET_BYTES = 32;
13
- const KEY_ID_BYTES = 18;
14
- const SCRYPT_KEY_BYTES = 32;
15
- const SCRYPT_N = 16_384;
16
- const SCRYPT_R = 8;
17
- const SCRYPT_P = 1;
18
- const SCRYPT_MAXMEM = 32 * 1024 * 1024;
19
- async function createGatewayApiKey(input) {
20
- const keyId = input.keyId ?? createGatewayKeyId();
21
- const secret = input.secret ?? randomBase64Url(SECRET_BYTES);
22
- const plaintext = formatGatewayApiKey({
23
- version: VERSION,
24
- deployment: input.deployment,
25
- keyId,
26
- secret,
27
- });
28
- return {
29
- plaintext,
30
- secret,
31
- record: {
32
- id: keyId,
33
- deployment: input.deployment,
34
- secretHash: await hashGatewayApiKeySecret(secret),
35
- },
36
- };
37
- }
38
- function createGatewayKeyId() {
39
- return `gak_${randomBase64Url(KEY_ID_BYTES)}`;
40
- }
41
- function formatGatewayApiKey(parsed) {
42
- assertDeployment(parsed.deployment);
43
- if (!parsed.keyId || parsed.keyId.includes(' ') || parsed.keyId.includes('/')) {
44
- throw new Error('Invalid Gateway API key id');
45
- }
46
- if (!parsed.secret || !/^[A-Za-z0-9-]+$/.test(parsed.secret)) {
47
- throw new Error('Invalid Gateway API key secret');
48
- }
49
- return `${PREFIX}_${parsed.version}_${parsed.deployment}_${parsed.keyId}_${parsed.secret}`;
50
- }
51
- function parseGatewayApiKey(value) {
52
- const parts = value.split('_');
53
- if (parts.length < 6 || parts[0] !== 'xpod' || parts[1] !== 'gw' || parts[2] !== VERSION) {
54
- return undefined;
55
- }
56
- const deployment = parts[3];
57
- if (deployment !== 'local' && deployment !== 'cloud') {
58
- return undefined;
59
- }
60
- const secret = parts[parts.length - 1];
61
- const keyId = parts.slice(4, -1).join('_');
62
- if (!keyId || !secret || !/^[A-Za-z0-9-]+$/.test(secret)) {
63
- return undefined;
64
- }
65
- return {
66
- version: VERSION,
67
- deployment,
68
- keyId,
69
- secret,
70
- };
71
- }
72
- async function hashGatewayApiKeySecret(secret) {
73
- const salt = randomBase64Url(16);
74
- const key = await deriveScrypt(secret, salt, SCRYPT_N, SCRYPT_R, SCRYPT_P);
75
- return [
76
- 'scrypt',
77
- 'v=1',
78
- `N=${SCRYPT_N}`,
79
- `r=${SCRYPT_R}`,
80
- `p=${SCRYPT_P}`,
81
- `salt=${salt}`,
82
- `key=${key.toString('base64url')}`,
83
- ].join('$');
84
- }
85
- async function verifyGatewayApiKeySecret(secret, encodedHash) {
86
- const parsed = parseScryptHash(encodedHash);
87
- if (!parsed) {
88
- return false;
89
- }
90
- let actual;
91
- try {
92
- actual = await deriveScrypt(secret, parsed.salt, parsed.N, parsed.r, parsed.p);
93
- }
94
- catch {
95
- return false;
96
- }
97
- const expected = Buffer.from(parsed.key, 'base64url');
98
- if (actual.byteLength !== expected.byteLength) {
99
- const paddedActual = Buffer.alloc(SCRYPT_KEY_BYTES);
100
- const paddedExpected = Buffer.alloc(SCRYPT_KEY_BYTES);
101
- actual.copy(paddedActual, 0, 0, Math.min(actual.byteLength, SCRYPT_KEY_BYTES));
102
- expected.copy(paddedExpected, 0, 0, Math.min(expected.byteLength, SCRYPT_KEY_BYTES));
103
- (0, node_crypto_1.timingSafeEqual)(paddedActual, paddedExpected);
104
- return false;
105
- }
106
- return (0, node_crypto_1.timingSafeEqual)(actual, expected);
107
- }
108
- function parseScryptHash(encodedHash) {
109
- const parts = encodedHash.split('$');
110
- if (parts.length !== 7
111
- || parts[0] !== 'scrypt'
112
- || parts[1] !== 'v=1'
113
- || parts[2] !== `N=${SCRYPT_N}`
114
- || parts[3] !== `r=${SCRYPT_R}`
115
- || parts[4] !== `p=${SCRYPT_P}`
116
- || !parts[5]?.startsWith('salt=')
117
- || !parts[6]?.startsWith('key=')) {
118
- return undefined;
119
- }
120
- const salt = parts[5].slice('salt='.length);
121
- const key = parts[6].slice('key='.length);
122
- if (!isBase64UrlBytes(salt, 16) || !isBase64UrlBytes(key, SCRYPT_KEY_BYTES)) {
123
- return undefined;
124
- }
125
- return { N: SCRYPT_N, r: SCRYPT_R, p: SCRYPT_P, salt, key };
126
- }
127
- function isBase64UrlBytes(value, bytes) {
128
- if (!/^[A-Za-z0-9_-]+$/.test(value)) {
129
- return false;
130
- }
131
- try {
132
- return Buffer.from(value, 'base64url').byteLength === bytes;
133
- }
134
- catch {
135
- return false;
136
- }
137
- }
138
- async function deriveScrypt(secret, salt, N, r, p) {
139
- return await new Promise((resolve, reject) => {
140
- (0, node_crypto_1.scrypt)(secret, salt, SCRYPT_KEY_BYTES, {
141
- N,
142
- r,
143
- p,
144
- maxmem: SCRYPT_MAXMEM,
145
- }, (error, derivedKey) => {
146
- if (error) {
147
- reject(error);
148
- return;
149
- }
150
- resolve(derivedKey);
151
- });
152
- });
153
- }
154
- function randomBase64Url(bytes) {
155
- return (0, node_crypto_1.randomBytes)(bytes).toString('base64url').replaceAll('_', '-');
156
- }
157
- function assertDeployment(deployment) {
158
- if (deployment !== 'local' && deployment !== 'cloud') {
159
- throw new Error(`Invalid Gateway API key deployment: ${deployment}`);
160
- }
161
- }
162
- //# sourceMappingURL=GatewayApiKey.js.map
@@ -1,26 +0,0 @@
1
- import type { GatewayDeployment } from './GatewayApiKey';
2
- export interface GatewayKeyLocatorPayload {
3
- owner: string;
4
- keyId: string;
5
- deployment: GatewayDeployment;
6
- }
7
- export interface GatewayKeyLocatorCodec {
8
- encode(payload: GatewayKeyLocatorPayload): string;
9
- decode(locator: string): GatewayKeyLocatorPayload | undefined;
10
- }
11
- export interface GatewayKeyLocatorSecret {
12
- kid: string;
13
- secret: string;
14
- }
15
- export interface AesGatewayKeyLocatorCodecOptions {
16
- active: GatewayKeyLocatorSecret;
17
- previous?: GatewayKeyLocatorSecret[];
18
- }
19
- export declare class AesGatewayKeyLocatorCodec implements GatewayKeyLocatorCodec {
20
- private readonly active;
21
- private readonly ring;
22
- constructor(secretOrOptions: string | AesGatewayKeyLocatorCodecOptions);
23
- encode(payload: GatewayKeyLocatorPayload): string;
24
- decode(locator: string): GatewayKeyLocatorPayload | undefined;
25
- }
26
- export declare function createGatewayKeyLocator(owner: string, deployment: GatewayDeployment, codec: GatewayKeyLocatorCodec): string;
@@ -1,97 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AesGatewayKeyLocatorCodec = void 0;
4
- exports.createGatewayKeyLocator = createGatewayKeyLocator;
5
- const node_crypto_1 = require("node:crypto");
6
- const PREFIX = 'gakv1';
7
- const NONCE_BYTES = 12;
8
- const KEY_BYTES = 32;
9
- class AesGatewayKeyLocatorCodec {
10
- constructor(secretOrOptions) {
11
- this.ring = new Map();
12
- const options = typeof secretOrOptions === 'string'
13
- ? { active: { kid: 'default', secret: secretOrOptions } }
14
- : secretOrOptions;
15
- this.active = normalizeSecret(options.active);
16
- this.ring.set(this.active.kid, this.active.key);
17
- for (const previous of options.previous ?? []) {
18
- const normalized = normalizeSecret(previous);
19
- if (this.ring.has(normalized.kid)) {
20
- throw new Error(`Duplicate Gateway key locator key id: ${normalized.kid}`);
21
- }
22
- this.ring.set(normalized.kid, normalized.key);
23
- }
24
- }
25
- encode(payload) {
26
- const nonce = (0, node_crypto_1.randomBytes)(NONCE_BYTES);
27
- const aad = Buffer.from(`${PREFIX}.${this.active.kid}`);
28
- const cipher = (0, node_crypto_1.createCipheriv)('aes-256-gcm', this.active.key, nonce);
29
- cipher.setAAD(aad);
30
- const plaintext = Buffer.from(JSON.stringify(payload), 'utf8');
31
- const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
32
- const tag = cipher.getAuthTag();
33
- return [
34
- PREFIX,
35
- this.active.kid,
36
- nonce.toString('base64url'),
37
- ciphertext.toString('base64url'),
38
- tag.toString('base64url'),
39
- ].join('.');
40
- }
41
- decode(locator) {
42
- const parts = locator.split('.');
43
- if (parts.length !== 5 || parts[0] !== PREFIX) {
44
- return undefined;
45
- }
46
- const kid = parts[1];
47
- const key = this.ring.get(kid);
48
- if (!key) {
49
- return undefined;
50
- }
51
- try {
52
- const nonce = Buffer.from(parts[2], 'base64url');
53
- const ciphertext = Buffer.from(parts[3], 'base64url');
54
- const tag = Buffer.from(parts[4], 'base64url');
55
- const decipher = (0, node_crypto_1.createDecipheriv)('aes-256-gcm', key, nonce);
56
- decipher.setAAD(Buffer.from(`${PREFIX}.${kid}`));
57
- decipher.setAuthTag(tag);
58
- const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
59
- const parsed = JSON.parse(plaintext.toString('utf8'));
60
- if (typeof parsed.owner !== 'string'
61
- || typeof parsed.keyId !== 'string'
62
- || (parsed.deployment !== 'local' && parsed.deployment !== 'cloud')) {
63
- return undefined;
64
- }
65
- return {
66
- owner: parsed.owner,
67
- keyId: parsed.keyId,
68
- deployment: parsed.deployment,
69
- };
70
- }
71
- catch {
72
- return undefined;
73
- }
74
- }
75
- }
76
- exports.AesGatewayKeyLocatorCodec = AesGatewayKeyLocatorCodec;
77
- function normalizeSecret(input) {
78
- const kid = input.kid.trim();
79
- if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(kid)) {
80
- throw new Error('Gateway key locator key id is invalid');
81
- }
82
- if (!input.secret.trim()) {
83
- throw new Error('Gateway key locator secret is required');
84
- }
85
- return {
86
- kid,
87
- key: (0, node_crypto_1.createHash)('sha256').update(input.secret).digest().subarray(0, KEY_BYTES),
88
- };
89
- }
90
- function createGatewayKeyLocator(owner, deployment, codec) {
91
- return codec.encode({
92
- owner,
93
- deployment,
94
- keyId: `gak_${(0, node_crypto_1.randomBytes)(18).toString('base64url')}`,
95
- });
96
- }
97
- //# sourceMappingURL=GatewayKeyLocatorCodec.js.map
@@ -1,67 +0,0 @@
1
- import { credentialResource, gatewayAccessKeyResource, type GatewayAccessKeyRow } from '@undefineds.co/models';
2
- import type { AuthContext } from '../../auth/AuthContext';
3
- import { type PodAccessFetchProvider } from '../pod/OwnerPodAccess';
4
- import { type PodBaseUrlResolver } from '../pod/PodBaseUrlResolver';
5
- import { type GatewayKeyLocatorCodec } from './GatewayKeyLocatorCodec';
6
- import { type GatewayAccessKeyRecord, type GatewayAccessKeyRepository, type GatewayAccessKeyRepositoryContext } from './GatewayApiKeyAuthenticator';
7
- import type { GatewayDeployment } from './GatewayApiKey';
8
- /** Schema resources this repository reads and writes in the owner's Pod. */
9
- type PodSchemaResource = typeof gatewayAccessKeyResource | typeof credentialResource;
10
- type GatewayAccessKeyDb = {
11
- init?: (...resources: unknown[]) => Promise<void>;
12
- insert(resource: PodSchemaResource): {
13
- values(value: unknown): {
14
- execute(): Promise<unknown[]>;
15
- };
16
- };
17
- select(): {
18
- from(resource: PodSchemaResource): {
19
- where(condition: unknown): {
20
- execute(): Promise<GatewayAccessKeyRow[]>;
21
- };
22
- };
23
- };
24
- findById<TRow>(resource: PodSchemaResource, id: string): Promise<TRow | null>;
25
- findByIri<TRow>(resource: PodSchemaResource, iri: string): Promise<TRow | null>;
26
- updateById<TRow>(resource: PodSchemaResource, id: string, patch: unknown): Promise<TRow | null>;
27
- updateByIri?<TRow>(resource: PodSchemaResource, iri: string, patch: unknown): Promise<TRow | null>;
28
- deleteById?(resource: PodSchemaResource, id: string): Promise<unknown>;
29
- };
30
- type GatewayAccessKeyResource = typeof gatewayAccessKeyResource;
31
- export interface PodGatewayAccessKeyRepositoryOptions {
32
- locatorCodec: GatewayKeyLocatorCodec;
33
- podAccess?: PodAccessFetchProvider;
34
- podBaseUrlResolver?: PodBaseUrlResolver;
35
- dbFactory?: (input: {
36
- owner: string;
37
- auth?: AuthContext;
38
- fetch: typeof fetch;
39
- podUrl: string;
40
- resource?: GatewayAccessKeyResource;
41
- listResource?: GatewayAccessKeyResource;
42
- credentialListResource?: typeof credentialResource;
43
- }) => Promise<GatewayAccessKeyDb>;
44
- }
45
- export declare class PodGatewayAccessKeyRepository implements GatewayAccessKeyRepository {
46
- private readonly dbFactory;
47
- private readonly locatorCodec;
48
- private readonly podAccess?;
49
- private readonly podBaseUrlResolver?;
50
- private readonly usesDefaultDbFactory;
51
- constructor(options: PodGatewayAccessKeyRepositoryOptions);
52
- createKeyId(owner: string, deployment: GatewayDeployment): string;
53
- create(record: GatewayAccessKeyRecord, context?: GatewayAccessKeyRepositoryContext): Promise<GatewayAccessKeyRecord>;
54
- findById(id: string, context?: GatewayAccessKeyRepositoryContext): Promise<GatewayAccessKeyRecord | undefined>;
55
- listByOwner(owner: string, context?: GatewayAccessKeyRepositoryContext): Promise<GatewayAccessKeyRecord[]>;
56
- setEnabled(id: string, enabled: boolean, changedAt: Date, context?: GatewayAccessKeyRepositoryContext): Promise<GatewayAccessKeyRecord | undefined>;
57
- revoke(id: string, revokedAt: Date, context?: GatewayAccessKeyRepositoryContext): Promise<GatewayAccessKeyRecord | undefined>;
58
- delete(id: string, context?: GatewayAccessKeyRepositoryContext): Promise<boolean>;
59
- revealPlaintext(id: string, context?: GatewayAccessKeyRepositoryContext): Promise<string | undefined>;
60
- touchLastUsed(id: string, lastUsedAt: Date, context?: GatewayAccessKeyRepositoryContext): Promise<void>;
61
- private dbForOwner;
62
- private resolveTrustedFetch;
63
- private wrapPodFetch;
64
- }
65
- /** Derived provider id of the built-in Xpod gateway provider; no provider row is persisted. */
66
- export declare function clientCredentialProviderId(): string;
67
- export {};