@undefineds.co/xpod 0.3.70 → 0.3.71-rc.2
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/config/cloud.json +3 -0
- package/config/local.json +3 -0
- package/config/resolver.json +7 -0
- package/config/xpod.base.json +20 -0
- package/dist/agents/ClaudeExecutor.js +1 -1
- package/dist/agents/ClaudeExecutor.js.map +1 -1
- package/dist/agents/types.d.ts +5 -5
- package/dist/agents/types.js.map +1 -1
- package/dist/api/ai-gateway/AiGatewayService.d.ts +5 -16
- package/dist/api/ai-gateway/AiGatewayService.js +13 -35
- package/dist/api/ai-gateway/AiGatewayService.js.map +1 -1
- package/dist/api/ai-gateway/auth/AiConnectionInvocationKeyIssuer.d.ts +3 -2
- package/dist/api/ai-gateway/auth/AiConnectionInvocationKeyIssuer.js +37 -12
- package/dist/api/ai-gateway/auth/AiConnectionInvocationKeyIssuer.js.map +1 -1
- package/dist/api/ai-gateway/auth/GatewayPrincipal.d.ts +2 -16
- package/dist/api/ai-gateway/auth/GatewayPrincipal.js +3 -33
- package/dist/api/ai-gateway/auth/GatewayPrincipal.js.map +1 -1
- package/dist/api/ai-gateway/auth/InvocationTokenAuthenticator.d.ts +23 -0
- package/dist/api/ai-gateway/auth/InvocationTokenAuthenticator.js +81 -0
- package/dist/api/ai-gateway/auth/InvocationTokenAuthenticator.js.map +1 -0
- package/dist/api/ai-gateway/auth/InvocationTokenCodec.d.ts +7 -4
- package/dist/api/ai-gateway/auth/InvocationTokenCodec.js.map +1 -1
- package/dist/api/ai-gateway/connect/index.d.ts +7 -26
- package/dist/api/ai-gateway/connect/index.js +40 -67
- package/dist/api/ai-gateway/connect/index.js.map +1 -1
- package/dist/api/ai-gateway/credentials/PlaintextCredentialPayload.d.ts +17 -0
- package/dist/api/ai-gateway/credentials/PlaintextCredentialPayload.js +65 -0
- package/dist/api/ai-gateway/credentials/PlaintextCredentialPayload.js.map +1 -0
- package/dist/api/ai-gateway/pod/HostedPodDataAccess.d.ts +24 -0
- package/dist/api/ai-gateway/pod/HostedPodDataAccess.js +149 -0
- package/dist/api/ai-gateway/pod/HostedPodDataAccess.js.map +1 -0
- package/dist/api/ai-gateway/quota/ProviderQuotaAdapter.d.ts +13 -5
- package/dist/api/ai-gateway/quota/ProviderQuotaAdapter.js +16 -19
- package/dist/api/ai-gateway/quota/ProviderQuotaAdapter.js.map +1 -1
- package/dist/api/ai-gateway/service-access/AiConnectionServiceAccess.d.ts +1 -1
- package/dist/api/ai-gateway/service-access/AiConnectionServiceAccess.js +0 -2
- package/dist/api/ai-gateway/service-access/AiConnectionServiceAccess.js.map +1 -1
- package/dist/api/auth/AuthContext.d.ts +1 -12
- package/dist/api/auth/AuthContext.js +0 -11
- package/dist/api/auth/AuthContext.js.map +1 -1
- package/dist/api/auth/ClientCredentialsAuthenticator.js +4 -11
- package/dist/api/auth/ClientCredentialsAuthenticator.js.map +1 -1
- package/dist/api/chatkit/default-agent.d.ts +2 -2
- package/dist/api/chatkit/default-agent.js +4 -4
- package/dist/api/chatkit/default-agent.js.map +1 -1
- package/dist/api/chatkit/runtime/AcpAgentRuntime.js +1 -1
- package/dist/api/chatkit/runtime/AcpAgentRuntime.js.map +1 -1
- package/dist/api/container/common.js +28 -69
- package/dist/api/container/common.js.map +1 -1
- package/dist/api/container/index.js +5 -6
- package/dist/api/container/index.js.map +1 -1
- package/dist/api/container/routes.js +2 -5
- package/dist/api/container/routes.js.map +1 -1
- package/dist/api/container/types.d.ts +8 -10
- package/dist/api/container/types.js.map +1 -1
- package/dist/api/handlers/AiClientConfigurationHandler.js +3 -3
- package/dist/api/handlers/AiClientConfigurationHandler.js.map +1 -1
- package/dist/api/handlers/AiGatewayHandler.js +2 -2
- package/dist/api/handlers/AiGatewayHandler.js.map +1 -1
- package/dist/api/handlers/AiGatewayManagementHandler.d.ts +2 -10
- package/dist/api/handlers/AiGatewayManagementHandler.js +4 -154
- package/dist/api/handlers/AiGatewayManagementHandler.js.map +1 -1
- package/dist/api/handlers/NetworkSettingsHandler.js +0 -3
- package/dist/api/handlers/NetworkSettingsHandler.js.map +1 -1
- package/dist/api/handlers/PodSettingsHandler.d.ts +5 -2
- package/dist/api/handlers/PodSettingsHandler.js +3 -3
- package/dist/api/handlers/PodSettingsHandler.js.map +1 -1
- package/dist/api/runs/AgentRuntimeTypes.d.ts +3 -3
- package/dist/api/runs/AgentRuntimeTypes.js +10 -10
- package/dist/api/runs/AgentRuntimeTypes.js.map +1 -1
- package/dist/api/runs/InngestRunExecutionBackend.d.ts +15 -9
- package/dist/api/runs/InngestRunExecutionBackend.js +25 -10
- package/dist/api/runs/InngestRunExecutionBackend.js.map +1 -1
- package/dist/api/runs/PiAgentRuntimeDriver.js +2 -2
- package/dist/api/runs/PiAgentRuntimeDriver.js.map +1 -1
- package/dist/api/runs/RunStateCenter.js +1 -1
- package/dist/api/runs/RunStateCenter.js.map +1 -1
- package/dist/api/service/AiClientConfigurationService.d.ts +2 -2
- package/dist/api/service/AiClientConfigurationService.js +11 -11
- package/dist/api/service/AiClientConfigurationService.js.map +1 -1
- package/dist/api/tasks/InngestTaskScheduler.d.ts +16 -10
- package/dist/api/tasks/InngestTaskScheduler.js +24 -12
- package/dist/api/tasks/InngestTaskScheduler.js.map +1 -1
- package/dist/cli/commands/start.js +7 -7
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/components/components.jsonld +1 -0
- package/dist/components/context.jsonld +36 -0
- package/dist/http/InternalPodDataHttpHandler.d.ts +32 -0
- package/dist/http/InternalPodDataHttpHandler.js +258 -0
- package/dist/http/InternalPodDataHttpHandler.js.map +1 -0
- package/dist/http/InternalPodDataHttpHandler.jsonld +201 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/main.js +13 -13
- package/dist/main.js.map +1 -1
- package/dist/runtime/GatewayAdminProxyAuth.d.ts +15 -1
- package/dist/runtime/GatewayAdminProxyAuth.js +57 -2
- package/dist/runtime/GatewayAdminProxyAuth.js.map +1 -1
- package/dist/runtime/bootstrap.js +3 -0
- package/dist/runtime/bootstrap.js.map +1 -1
- package/dist/runtime/css-process.d.ts +1 -1
- package/dist/runtime/css-process.js +4 -1
- package/dist/runtime/css-process.js.map +1 -1
- package/dist/runtime/runner/node/CommunitySolidServerCssRunner.d.ts +2 -0
- package/dist/runtime/runner/node/CommunitySolidServerCssRunner.js +50 -0
- package/dist/runtime/runner/node/CommunitySolidServerCssRunner.js.map +1 -1
- package/node_modules/@undefineds.co/ai-connection/dist/AiClientConfigurationSection.d.ts +5 -5
- package/node_modules/@undefineds.co/ai-connection/dist/AiClientConfigurationSection.js +7 -7
- package/node_modules/@undefineds.co/ai-connection/dist/AiConnectionMain.js +1 -1
- package/node_modules/@undefineds.co/ai-connection/dist/AiConnectionPanel.d.ts +3 -1
- package/node_modules/@undefineds.co/ai-connection/dist/AiConnectionPanel.js +74 -60
- package/node_modules/@undefineds.co/ai-connection/dist/ai-connection-client.d.ts +0 -21
- package/node_modules/@undefineds.co/ai-connection/dist/ai-connection-client.js +0 -41
- package/node_modules/@undefineds.co/ai-connection/dist/client-config/base-adapter.d.ts +1 -0
- package/node_modules/@undefineds.co/ai-connection/dist/client-config/base-adapter.js +7 -2
- package/node_modules/@undefineds.co/ai-connection/dist/client-config/codex.js +3 -3
- package/node_modules/@undefineds.co/ai-connection/dist/client-config/index.cjs +15 -9
- package/node_modules/@undefineds.co/ai-connection/dist/client-config/json-env-adapter.js +4 -4
- package/node_modules/@undefineds.co/ai-connection/dist/client-config/pi.js +3 -3
- package/node_modules/@undefineds.co/ai-connection/dist/client-config/types.d.ts +1 -1
- package/node_modules/@undefineds.co/ai-connection/dist/controller.d.ts +2 -1
- package/node_modules/@undefineds.co/ai-connection/dist/controller.js +1 -0
- package/node_modules/@undefineds.co/ai-connection/dist/service-access.js +0 -1
- package/node_modules/@undefineds.co/extension-sdk/dist/web.d.ts +22 -1
- package/package.json +3 -3
- package/static/app/assets/main.js +7 -7
- package/static/dashboard/assets/NetworkPage-CXjiUMR1.js +2 -0
- package/static/dashboard/assets/{PaneListHeader-57nvMwH6.js → PaneListHeader-BSipfl0W.js} +1 -1
- package/static/dashboard/assets/PodPage-Bd3Xhmp-.js +2 -0
- package/static/dashboard/assets/ServicesPage-CI3jWZGe.js +1 -0
- package/static/dashboard/assets/{card-B9Zjf_2p.js → card-z5BV5hTo.js} +1 -1
- package/static/dashboard/assets/{dashboard-8C6o666W.js → dashboard-CSrqAv2L.js} +2 -2
- package/static/dashboard/assets/{database-DPh9wDY9.js → database-Ct5ZPe6L.js} +1 -1
- package/static/dashboard/assets/{external-link-VbMQvVMz.js → external-link-B7wD1hkm.js} +1 -1
- package/static/dashboard/assets/index-tOBaUnM1.js +44 -0
- package/static/dashboard/assets/{refresh-cw-BxVxNxNr.js → refresh-cw-CFDZPaE8.js} +1 -1
- package/static/dashboard/assets/{services-status-context-DKmJ7ISr.js → services-status-context-DN1Icg4A.js} +1 -1
- package/static/dashboard/dashboard.html +1 -1
- package/static/settings/assets/ModelsPage-D87RrLB0.js +1 -0
- package/static/settings/assets/{PaneListHeader-Bgaze006.js → PaneListHeader-BtON8Z5Q.js} +1 -1
- package/static/settings/assets/PodPage-9LGuOloQ.js +2 -0
- package/static/settings/assets/ServicesPage-ZoT9-B_0.js +1 -0
- package/static/settings/assets/SettingsPage-Bj4lB3mq.js +41 -0
- package/static/settings/assets/{card-B_bXSIn-.js → card-CCGngjas.js} +1 -1
- package/static/settings/assets/{services-status-context-DiX-AbrP.js → services-status-context-CBfImxL_.js} +1 -1
- package/static/settings/assets/{settings-B30oMfZq.js → settings-yUyFIJxi.js} +2 -2
- package/static/settings/assets/{workspace-layout-Dv1Yn9Ci.js → workspace-layout-B0wJpPze.js} +1 -1
- package/static/settings/settings.html +1 -1
- package/dist/api/ai-gateway/auth/ClientCredentialsInternalPodAccessTokenProvider.d.ts +0 -25
- package/dist/api/ai-gateway/auth/ClientCredentialsInternalPodAccessTokenProvider.js +0 -91
- package/dist/api/ai-gateway/auth/ClientCredentialsInternalPodAccessTokenProvider.js.map +0 -1
- package/dist/api/ai-gateway/auth/GatewayApiKey.d.ts +0 -28
- package/dist/api/ai-gateway/auth/GatewayApiKey.js +0 -162
- package/dist/api/ai-gateway/auth/GatewayApiKey.js.map +0 -1
- package/dist/api/ai-gateway/auth/GatewayApiKeyAuthenticator.d.ts +0 -56
- package/dist/api/ai-gateway/auth/GatewayApiKeyAuthenticator.js +0 -143
- package/dist/api/ai-gateway/auth/GatewayApiKeyAuthenticator.js.map +0 -1
- package/dist/api/ai-gateway/auth/GatewayKeyLocatorCodec.d.ts +0 -26
- package/dist/api/ai-gateway/auth/GatewayKeyLocatorCodec.js +0 -97
- package/dist/api/ai-gateway/auth/GatewayKeyLocatorCodec.js.map +0 -1
- package/dist/api/ai-gateway/auth/PodGatewayAccessKeyRepository.d.ts +0 -54
- package/dist/api/ai-gateway/auth/PodGatewayAccessKeyRepository.js +0 -152
- package/dist/api/ai-gateway/auth/PodGatewayAccessKeyRepository.js.map +0 -1
- package/static/dashboard/assets/NetworkPage-Brt79fuQ.js +0 -2
- package/static/dashboard/assets/PodPage-CM6do1vB.js +0 -2
- package/static/dashboard/assets/ServicesPage-BUNxGJRz.js +0 -1
- package/static/dashboard/assets/index-RfiFckzb.js +0 -51
- package/static/settings/assets/ModelsPage-D_IH7AH3.js +0 -1
- package/static/settings/assets/PodPage-Cy1VNObw.js +0 -2
- package/static/settings/assets/ServicesPage-BsFaxVWC.js +0 -1
- package/static/settings/assets/SettingsPage-UafNWE_p.js +0 -48
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InvocationTokenCodec.js","sourceRoot":"","sources":["../../../../src/api/ai-gateway/auth/InvocationTokenCodec.ts"],"names":[],"mappings":"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","sourcesContent":["import { createCipheriv, createDecipheriv, createHash, randomBytes } from 'node:crypto';\nimport type { GatewayDeployment } from './GatewayApiKey';\nimport type { GatewayKeyLocatorSecret } from './GatewayKeyLocatorCodec';\n\nconst PREFIX = 'xpod_inv_v1';\nconst AAD_CONTEXT = 'xpod:gateway:internal-invocation:v1';\nconst NONCE_BYTES = 12;\nconst KEY_BYTES = 32;\nconst MAX_TOKEN_LENGTH = 8_192;\nconst MAX_CIPHERTEXT_BYTES = 4_096;\nconst MAX_TTL_MS = 15 * 60_000;\nconst MAX_SCOPES = 8;\n\nexport interface InvocationTokenClaims {\n version: 1;\n kid: string;\n deployment: GatewayDeployment;\n audience: string;\n issuer: string;\n webId: string;\n scopes: string[];\n issuedAt: Date;\n expiresAt: Date;\n jti: string;\n}\n\nexport interface InvocationTokenInput {\n deployment: GatewayDeployment;\n audience: string;\n issuer: string;\n webId: string;\n scopes: string[];\n issuedAt: Date;\n expiresAt: Date;\n jti?: string;\n}\n\nexport interface InvocationTokenCodec {\n encode(input: InvocationTokenInput): string;\n decode(token: string): InvocationTokenClaims | undefined;\n}\n\nexport interface AesInvocationTokenCodecOptions {\n active: GatewayKeyLocatorSecret;\n previous?: GatewayKeyLocatorSecret[];\n}\n\nexport class AesInvocationTokenCodec implements InvocationTokenCodec {\n private readonly active: { kid: string; key: Buffer };\n private readonly ring = new Map<string, Buffer>();\n\n public constructor(options: AesInvocationTokenCodecOptions) {\n this.active = normalizeSecret(options.active);\n this.ring.set(this.active.kid, this.active.key);\n for (const previous of options.previous ?? []) {\n const normalized = normalizeSecret(previous);\n if (this.ring.has(normalized.kid)) {\n throw new Error(`Duplicate invocation token key id: ${normalized.kid}`);\n }\n this.ring.set(normalized.kid, normalized.key);\n }\n }\n\n public encode(input: InvocationTokenInput): string {\n const webId = requireCanonicalWebId(input.webId);\n const audience = requireCanonicalOrigin(input.audience, 'audience');\n const issuer = requireCanonicalOrigin(input.issuer, 'issuer');\n const scopes = requireScopes(input.scopes);\n const issuedAt = requireTimestamp(input.issuedAt, 'issuedAt');\n const expiresAt = requireTimestamp(input.expiresAt, 'expiresAt');\n if (expiresAt <= issuedAt || expiresAt - issuedAt > MAX_TTL_MS) {\n throw new Error(`Invocation token TTL must be between 1 and ${MAX_TTL_MS} milliseconds`);\n }\n const payload = {\n v: 1,\n kid: this.active.kid,\n deployment: input.deployment,\n aud: audience,\n iss: issuer,\n webId,\n scopes,\n iat: issuedAt,\n exp: expiresAt,\n jti: input.jti ?? randomBytes(18).toString('base64url'),\n };\n const nonce = randomBytes(NONCE_BYTES);\n const aad = Buffer.from(`${AAD_CONTEXT}.${this.active.kid}`);\n const cipher = createCipheriv('aes-256-gcm', this.active.key, nonce);\n cipher.setAAD(aad);\n const ciphertext = Buffer.concat([\n cipher.update(JSON.stringify(payload), 'utf8'),\n cipher.final(),\n ]);\n const tag = cipher.getAuthTag();\n return [\n PREFIX,\n this.active.kid,\n nonce.toString('base64url'),\n ciphertext.toString('base64url'),\n tag.toString('base64url'),\n ].join('.');\n }\n\n public decode(token: string): InvocationTokenClaims | undefined {\n if (token.length > MAX_TOKEN_LENGTH) {\n return undefined;\n }\n const parts = token.split('.');\n if (parts.length !== 5 || parts[0] !== PREFIX) {\n return undefined;\n }\n const kid = parts[1];\n const key = this.ring.get(kid);\n if (\n !key\n || !parts.slice(1).every((part) => /^[A-Za-z0-9_-]+$/u.test(part))\n ) {\n return undefined;\n }\n try {\n const nonce = decodeCanonicalBase64Url(parts[2]);\n const ciphertext = decodeCanonicalBase64Url(parts[3]);\n const tag = decodeCanonicalBase64Url(parts[4]);\n if (!nonce || !ciphertext || !tag) {\n return undefined;\n }\n if (\n nonce.length !== NONCE_BYTES\n || ciphertext.length === 0\n || ciphertext.length > MAX_CIPHERTEXT_BYTES\n || tag.length !== 16\n ) {\n return undefined;\n }\n const decipher = createDecipheriv('aes-256-gcm', key, nonce);\n decipher.setAAD(Buffer.from(`${AAD_CONTEXT}.${kid}`));\n decipher.setAuthTag(tag);\n const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);\n const parsed = JSON.parse(plaintext.toString('utf8')) as Record<string, unknown>;\n const keys = Object.keys(parsed).sort();\n if (\n keys.join(',') !== 'aud,deployment,exp,iat,iss,jti,kid,scopes,v,webId'\n ||\n parsed.v !== 1\n || parsed.kid !== kid\n || (parsed.deployment !== 'local' && parsed.deployment !== 'cloud')\n || typeof parsed.aud !== 'string'\n || typeof parsed.iss !== 'string'\n || typeof parsed.webId !== 'string'\n || !Array.isArray(parsed.scopes)\n || typeof parsed.iat !== 'number'\n || typeof parsed.exp !== 'number'\n || typeof parsed.jti !== 'string'\n || !/^[A-Za-z0-9_-]{16,128}$/u.test(parsed.jti)\n ) {\n return undefined;\n }\n const audience = requireCanonicalOrigin(parsed.aud, 'audience');\n const issuer = requireCanonicalOrigin(parsed.iss, 'issuer');\n const webId = requireCanonicalWebId(parsed.webId);\n const scopes = requireScopes(parsed.scopes);\n const issuedAt = requireEpoch(parsed.iat);\n const expiresAt = requireEpoch(parsed.exp);\n if (expiresAt <= issuedAt || expiresAt - issuedAt > MAX_TTL_MS) {\n return undefined;\n }\n return {\n version: 1,\n kid,\n deployment: parsed.deployment,\n audience,\n issuer,\n webId,\n scopes,\n issuedAt: new Date(issuedAt),\n expiresAt: new Date(expiresAt),\n jti: parsed.jti,\n };\n } catch {\n return undefined;\n }\n }\n}\n\nexport function requireCanonicalOrigin(value: string, name = 'origin'): string {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n throw new Error(`Invocation token ${name} must be a canonical HTTP(S) origin`);\n }\n if (\n (url.protocol !== 'https:' && url.protocol !== 'http:')\n || url.username\n || url.password\n || url.pathname !== '/'\n || url.search\n || url.hash\n || url.origin !== value\n ) {\n throw new Error(`Invocation token ${name} must be a canonical HTTP(S) origin`);\n }\n return url.origin;\n}\n\nfunction decodeCanonicalBase64Url(value: string): Buffer | undefined {\n const decoded = Buffer.from(value, 'base64url');\n return decoded.toString('base64url') === value ? decoded : undefined;\n}\n\nfunction normalizeSecret(input: GatewayKeyLocatorSecret): { kid: string; key: Buffer } {\n const kid = input.kid.trim();\n if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/u.test(kid)) {\n throw new Error('Invocation token key id is invalid');\n }\n if (!input.secret.trim()) {\n throw new Error('Invocation token secret is required');\n }\n return {\n kid,\n key: createHash('sha256')\n .update(`${AAD_CONTEXT}\\0`, 'utf8')\n .update(input.secret, 'utf8')\n .digest()\n .subarray(0, KEY_BYTES),\n };\n}\n\nexport function requireCanonicalWebId(value: string): string {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n throw new Error('Invocation token WebID must be a canonical HTTP(S) URL');\n }\n if (\n (url.protocol !== 'https:' && url.protocol !== 'http:')\n || url.username\n || url.password\n || url.href !== value\n ) {\n throw new Error('Invocation token WebID must be a canonical HTTP(S) URL');\n }\n return url.href;\n}\n\nfunction requireScopes(value: unknown[]): string[] {\n if (\n value.length === 0\n || value.length > MAX_SCOPES\n || value.some((scope) => typeof scope !== 'string' || !/^[a-z][a-z0-9-]*:[a-z][a-z0-9-]*$/u.test(scope))\n || new Set(value).size !== value.length\n ) {\n throw new Error('Invocation token scopes are invalid');\n }\n return [...value] as string[];\n}\n\nfunction requireTimestamp(value: Date, name: string): number {\n const timestamp = value.getTime();\n if (!Number.isSafeInteger(timestamp) || timestamp < 0) {\n throw new Error(`Invocation token ${name} is invalid`);\n }\n return timestamp;\n}\n\nfunction requireEpoch(value: number): number {\n if (!Number.isSafeInteger(value) || value < 0) {\n throw new Error('Invocation token timestamp is invalid');\n }\n return value;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"InvocationTokenCodec.js","sourceRoot":"","sources":["../../../../src/api/ai-gateway/auth/InvocationTokenCodec.ts"],"names":[],"mappings":"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","sourcesContent":["import { createCipheriv, createDecipheriv, createHash, randomBytes } from 'node:crypto';\n\nconst PREFIX = 'xpod_inv_v1';\nconst AAD_CONTEXT = 'xpod:gateway:internal-invocation:v1';\nconst NONCE_BYTES = 12;\nconst KEY_BYTES = 32;\nconst MAX_TOKEN_LENGTH = 8_192;\nconst MAX_CIPHERTEXT_BYTES = 4_096;\nconst MAX_TTL_MS = 15 * 60_000;\nconst MAX_SCOPES = 8;\n\nexport interface InvocationTokenClaims {\n version: 1;\n kid: string;\n deployment: GatewayDeployment;\n audience: string;\n issuer: string;\n webId: string;\n scopes: string[];\n issuedAt: Date;\n expiresAt: Date;\n jti: string;\n}\n\nexport type GatewayDeployment = 'cloud' | 'local';\n\nexport interface InvocationTokenSecret {\n kid: string;\n secret: string;\n}\n\nexport interface InvocationTokenInput {\n deployment: GatewayDeployment;\n audience: string;\n issuer: string;\n webId: string;\n scopes: string[];\n issuedAt: Date;\n expiresAt: Date;\n jti?: string;\n}\n\nexport interface InvocationTokenCodec {\n encode(input: InvocationTokenInput): string;\n decode(token: string): InvocationTokenClaims | undefined;\n}\n\nexport interface AesInvocationTokenCodecOptions {\n active: InvocationTokenSecret;\n previous?: InvocationTokenSecret[];\n}\n\nexport class AesInvocationTokenCodec implements InvocationTokenCodec {\n private readonly active: { kid: string; key: Buffer };\n private readonly ring = new Map<string, Buffer>();\n\n public constructor(options: AesInvocationTokenCodecOptions) {\n this.active = normalizeSecret(options.active);\n this.ring.set(this.active.kid, this.active.key);\n for (const previous of options.previous ?? []) {\n const normalized = normalizeSecret(previous);\n if (this.ring.has(normalized.kid)) {\n throw new Error(`Duplicate invocation token key id: ${normalized.kid}`);\n }\n this.ring.set(normalized.kid, normalized.key);\n }\n }\n\n public encode(input: InvocationTokenInput): string {\n const webId = requireCanonicalWebId(input.webId);\n const audience = requireCanonicalOrigin(input.audience, 'audience');\n const issuer = requireCanonicalOrigin(input.issuer, 'issuer');\n const scopes = requireScopes(input.scopes);\n const issuedAt = requireTimestamp(input.issuedAt, 'issuedAt');\n const expiresAt = requireTimestamp(input.expiresAt, 'expiresAt');\n if (expiresAt <= issuedAt || expiresAt - issuedAt > MAX_TTL_MS) {\n throw new Error(`Invocation token TTL must be between 1 and ${MAX_TTL_MS} milliseconds`);\n }\n const payload = {\n v: 1,\n kid: this.active.kid,\n deployment: input.deployment,\n aud: audience,\n iss: issuer,\n webId,\n scopes,\n iat: issuedAt,\n exp: expiresAt,\n jti: input.jti ?? randomBytes(18).toString('base64url'),\n };\n const nonce = randomBytes(NONCE_BYTES);\n const aad = Buffer.from(`${AAD_CONTEXT}.${this.active.kid}`);\n const cipher = createCipheriv('aes-256-gcm', this.active.key, nonce);\n cipher.setAAD(aad);\n const ciphertext = Buffer.concat([\n cipher.update(JSON.stringify(payload), 'utf8'),\n cipher.final(),\n ]);\n const tag = cipher.getAuthTag();\n return [\n PREFIX,\n this.active.kid,\n nonce.toString('base64url'),\n ciphertext.toString('base64url'),\n tag.toString('base64url'),\n ].join('.');\n }\n\n public decode(token: string): InvocationTokenClaims | undefined {\n if (token.length > MAX_TOKEN_LENGTH) {\n return undefined;\n }\n const parts = token.split('.');\n if (parts.length !== 5 || parts[0] !== PREFIX) {\n return undefined;\n }\n const kid = parts[1];\n const key = this.ring.get(kid);\n if (\n !key\n || !parts.slice(1).every((part) => /^[A-Za-z0-9_-]+$/u.test(part))\n ) {\n return undefined;\n }\n try {\n const nonce = decodeCanonicalBase64Url(parts[2]);\n const ciphertext = decodeCanonicalBase64Url(parts[3]);\n const tag = decodeCanonicalBase64Url(parts[4]);\n if (!nonce || !ciphertext || !tag) {\n return undefined;\n }\n if (\n nonce.length !== NONCE_BYTES\n || ciphertext.length === 0\n || ciphertext.length > MAX_CIPHERTEXT_BYTES\n || tag.length !== 16\n ) {\n return undefined;\n }\n const decipher = createDecipheriv('aes-256-gcm', key, nonce);\n decipher.setAAD(Buffer.from(`${AAD_CONTEXT}.${kid}`));\n decipher.setAuthTag(tag);\n const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);\n const parsed = JSON.parse(plaintext.toString('utf8')) as Record<string, unknown>;\n const keys = Object.keys(parsed).sort();\n if (\n keys.join(',') !== 'aud,deployment,exp,iat,iss,jti,kid,scopes,v,webId'\n ||\n parsed.v !== 1\n || parsed.kid !== kid\n || (parsed.deployment !== 'local' && parsed.deployment !== 'cloud')\n || typeof parsed.aud !== 'string'\n || typeof parsed.iss !== 'string'\n || typeof parsed.webId !== 'string'\n || !Array.isArray(parsed.scopes)\n || typeof parsed.iat !== 'number'\n || typeof parsed.exp !== 'number'\n || typeof parsed.jti !== 'string'\n || !/^[A-Za-z0-9_-]{16,128}$/u.test(parsed.jti)\n ) {\n return undefined;\n }\n const audience = requireCanonicalOrigin(parsed.aud, 'audience');\n const issuer = requireCanonicalOrigin(parsed.iss, 'issuer');\n const webId = requireCanonicalWebId(parsed.webId);\n const scopes = requireScopes(parsed.scopes);\n const issuedAt = requireEpoch(parsed.iat);\n const expiresAt = requireEpoch(parsed.exp);\n if (expiresAt <= issuedAt || expiresAt - issuedAt > MAX_TTL_MS) {\n return undefined;\n }\n return {\n version: 1,\n kid,\n deployment: parsed.deployment,\n audience,\n issuer,\n webId,\n scopes,\n issuedAt: new Date(issuedAt),\n expiresAt: new Date(expiresAt),\n jti: parsed.jti,\n };\n } catch {\n return undefined;\n }\n }\n}\n\nexport function requireCanonicalOrigin(value: string, name = 'origin'): string {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n throw new Error(`Invocation token ${name} must be a canonical HTTP(S) origin`);\n }\n if (\n (url.protocol !== 'https:' && url.protocol !== 'http:')\n || url.username\n || url.password\n || url.pathname !== '/'\n || url.search\n || url.hash\n || url.origin !== value\n ) {\n throw new Error(`Invocation token ${name} must be a canonical HTTP(S) origin`);\n }\n return url.origin;\n}\n\nfunction decodeCanonicalBase64Url(value: string): Buffer | undefined {\n const decoded = Buffer.from(value, 'base64url');\n return decoded.toString('base64url') === value ? decoded : undefined;\n}\n\nfunction normalizeSecret(input: InvocationTokenSecret): { kid: string; key: Buffer } {\n const kid = input.kid.trim();\n if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/u.test(kid)) {\n throw new Error('Invocation token key id is invalid');\n }\n if (!input.secret.trim()) {\n throw new Error('Invocation token secret is required');\n }\n return {\n kid,\n key: createHash('sha256')\n .update(`${AAD_CONTEXT}\\0`, 'utf8')\n .update(input.secret, 'utf8')\n .digest()\n .subarray(0, KEY_BYTES),\n };\n}\n\nexport function requireCanonicalWebId(value: string): string {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n throw new Error('Invocation token WebID must be a canonical HTTP(S) URL');\n }\n if (\n (url.protocol !== 'https:' && url.protocol !== 'http:')\n || url.username\n || url.password\n || url.href !== value\n ) {\n throw new Error('Invocation token WebID must be a canonical HTTP(S) URL');\n }\n return url.href;\n}\n\nfunction requireScopes(value: unknown[]): string[] {\n if (\n value.length === 0\n || value.length > MAX_SCOPES\n || value.some((scope) => typeof scope !== 'string' || !/^[a-z][a-z0-9-]*:[a-z][a-z0-9-]*$/u.test(scope))\n || new Set(value).size !== value.length\n ) {\n throw new Error('Invocation token scopes are invalid');\n }\n return [...value] as string[];\n}\n\nfunction requireTimestamp(value: Date, name: string): number {\n const timestamp = value.getTime();\n if (!Number.isSafeInteger(timestamp) || timestamp < 0) {\n throw new Error(`Invocation token ${name} is invalid`);\n }\n return timestamp;\n}\n\nfunction requireEpoch(value: number): number {\n if (!Number.isSafeInteger(value) || value < 0) {\n throw new Error('Invocation token timestamp is invalid');\n }\n return value;\n}\n"]}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { aiProviderResource, credentialResource } from '@undefineds.co/models';
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
import type { GatewayDeployment } from '../auth/GatewayApiKey';
|
|
2
|
+
import type { ProviderSecret } from '../credentials/CredentialVault';
|
|
3
|
+
import type { GatewayDeployment } from '../auth/InvocationTokenCodec';
|
|
5
4
|
import type { ProviderRegistry } from '../providers/ProviderRegistry';
|
|
6
5
|
import type { AuthContext } from '../../auth/AuthContext';
|
|
7
|
-
import type { InternalPodAccessTokenProvider } from '../
|
|
6
|
+
import type { InternalPodAccessTokenProvider } from '../pod/HostedPodDataAccess';
|
|
8
7
|
export type ConnectMode = 'browserAssistedApiKey' | 'deviceCodeOAuth' | 'connectUnsupported';
|
|
9
8
|
export type ConnectAttemptStatus = 'pending' | 'authorization_pending' | 'slow_down' | 'completed' | 'expired' | 'unsupported';
|
|
10
9
|
export interface ConnectBeginInput {
|
|
@@ -74,7 +73,8 @@ export interface ConnectCredentialRecord {
|
|
|
74
73
|
provider: string;
|
|
75
74
|
deployment: GatewayDeployment;
|
|
76
75
|
authMode: 'apiKey' | 'deviceCodeOAuth';
|
|
77
|
-
|
|
76
|
+
storageMode: 'plaintext-v1';
|
|
77
|
+
secretPayload: string;
|
|
78
78
|
status: 'active' | 'revoked';
|
|
79
79
|
accountLabel?: string;
|
|
80
80
|
expiresAt?: Date;
|
|
@@ -100,14 +100,6 @@ export interface PodCredentialRepository {
|
|
|
100
100
|
upsertConnectedCredential(record: ConnectCredentialRecord, context?: {
|
|
101
101
|
auth?: AuthContext;
|
|
102
102
|
}): Promise<ConnectCredentialRecord>;
|
|
103
|
-
rewrapCredential?(input: {
|
|
104
|
-
webId: string;
|
|
105
|
-
deployment: GatewayDeployment;
|
|
106
|
-
credentialId: string;
|
|
107
|
-
expectedVersion?: number;
|
|
108
|
-
encryptedSecret: EncryptedCredentialSecret;
|
|
109
|
-
auth?: AuthContext;
|
|
110
|
-
}): Promise<boolean>;
|
|
111
103
|
markReauthRequired(input: {
|
|
112
104
|
webId: string;
|
|
113
105
|
provider: string;
|
|
@@ -191,7 +183,8 @@ export declare class PodConnectedCredentialRepository implements PodCredentialRe
|
|
|
191
183
|
quota?: {
|
|
192
184
|
status: 'available' | 'unsupported' | 'exhausted' | 'error';
|
|
193
185
|
};
|
|
194
|
-
|
|
186
|
+
storageMode: 'plaintext-v1';
|
|
187
|
+
secretPayload: string;
|
|
195
188
|
version?: number;
|
|
196
189
|
runtimeCredential?: Record<string, unknown>;
|
|
197
190
|
metadata?: Record<string, unknown>;
|
|
@@ -199,14 +192,6 @@ export declare class PodConnectedCredentialRepository implements PodCredentialRe
|
|
|
199
192
|
upsertConnectedCredential(record: ConnectCredentialRecord, context?: {
|
|
200
193
|
auth?: AuthContext;
|
|
201
194
|
}): Promise<ConnectCredentialRecord>;
|
|
202
|
-
rewrapCredential(input: {
|
|
203
|
-
webId: string;
|
|
204
|
-
deployment: GatewayDeployment;
|
|
205
|
-
credentialId: string;
|
|
206
|
-
expectedVersion?: number;
|
|
207
|
-
encryptedSecret: EncryptedCredentialSecret;
|
|
208
|
-
auth?: AuthContext;
|
|
209
|
-
}): Promise<boolean>;
|
|
210
195
|
markReauthRequired(input: {
|
|
211
196
|
webId: string;
|
|
212
197
|
provider: string;
|
|
@@ -272,7 +257,6 @@ export interface BrowserAssistedApiKeyConnectAdapterOptions {
|
|
|
272
257
|
consoleUrl: string;
|
|
273
258
|
attempts: InMemoryConnectAttemptStore;
|
|
274
259
|
credentialRepository: PodCredentialRepository;
|
|
275
|
-
vault: CredentialVault;
|
|
276
260
|
deployment: GatewayDeployment;
|
|
277
261
|
now?: () => Date;
|
|
278
262
|
randomBytes?: (bytes: number) => Buffer;
|
|
@@ -283,7 +267,6 @@ export declare class BrowserAssistedApiKeyConnectAdapter implements ProviderConn
|
|
|
283
267
|
private readonly consoleUrl;
|
|
284
268
|
protected readonly attempts: InMemoryConnectAttemptStore;
|
|
285
269
|
protected readonly credentialRepository: PodCredentialRepository;
|
|
286
|
-
protected readonly vault: CredentialVault;
|
|
287
270
|
protected readonly deployment: GatewayDeployment;
|
|
288
271
|
protected readonly now: () => Date;
|
|
289
272
|
protected readonly randomBytes: (bytes: number) => Buffer;
|
|
@@ -327,7 +310,6 @@ export interface ProviderConnectServiceOptions {
|
|
|
327
310
|
registry: ProviderRegistry;
|
|
328
311
|
adapters: ProviderConnectAdapter[];
|
|
329
312
|
credentialRepository?: PodCredentialRepository;
|
|
330
|
-
vault?: CredentialVault;
|
|
331
313
|
}
|
|
332
314
|
export interface ProviderConnectionSummary {
|
|
333
315
|
provider: string;
|
|
@@ -347,7 +329,6 @@ export interface ProviderConnectionSummary {
|
|
|
347
329
|
export declare class ProviderConnectService {
|
|
348
330
|
private readonly registry;
|
|
349
331
|
private readonly credentialRepository?;
|
|
350
|
-
private readonly vault?;
|
|
351
332
|
private readonly adapters;
|
|
352
333
|
constructor(options: ProviderConnectServiceOptions);
|
|
353
334
|
begin(input: ConnectBeginInput): Promise<ConnectBeginResult>;
|
|
@@ -4,6 +4,7 @@ exports.ProviderConnectService = exports.DeepSeekConnectAdapter = exports.KimiDe
|
|
|
4
4
|
const node_crypto_1 = require("node:crypto");
|
|
5
5
|
const drizzle_solid_1 = require("@undefineds.co/drizzle-solid");
|
|
6
6
|
const models_1 = require("@undefineds.co/models");
|
|
7
|
+
const PlaintextCredentialPayload_1 = require("../credentials/PlaintextCredentialPayload");
|
|
7
8
|
const ProviderRegistry_1 = require("../providers/ProviderRegistry");
|
|
8
9
|
class PodConnectedCredentialRepository {
|
|
9
10
|
constructor(options = {}) {
|
|
@@ -18,7 +19,7 @@ class PodConnectedCredentialRepository {
|
|
|
18
19
|
const { db, credential } = await this.dbForOwner(input.webId, input.auth);
|
|
19
20
|
const id = models_1.aiRuntimeRepository.credentialId(input);
|
|
20
21
|
const row = await db.findById(credential, id);
|
|
21
|
-
const record = row ? recordFromCredentialRow(row) : undefined;
|
|
22
|
+
const record = row ? recordFromCredentialRow(row, input.webId) : undefined;
|
|
22
23
|
if (!record) {
|
|
23
24
|
return undefined;
|
|
24
25
|
}
|
|
@@ -42,7 +43,7 @@ class PodConnectedCredentialRepository {
|
|
|
42
43
|
}
|
|
43
44
|
}))).filter((row) => row !== null);
|
|
44
45
|
return rows
|
|
45
|
-
.map(recordFromCredentialRow)
|
|
46
|
+
.map((row) => recordFromCredentialRow(row, input.webId))
|
|
46
47
|
.filter((record) => record.webId === input.webId)
|
|
47
48
|
.filter((record) => record.deployment === input.deployment)
|
|
48
49
|
.filter((record) => record.status === 'active')
|
|
@@ -57,7 +58,8 @@ class PodConnectedCredentialRepository {
|
|
|
57
58
|
priority: priorityFromMetadata(record.metadata),
|
|
58
59
|
health: record.reauthRequired ? 'reauthRequired' : 'healthy',
|
|
59
60
|
quota: { status: 'available' },
|
|
60
|
-
|
|
61
|
+
storageMode: record.storageMode,
|
|
62
|
+
secretPayload: record.secretPayload,
|
|
61
63
|
version: record.version,
|
|
62
64
|
runtimeCredential: runtimeCredentialFromMetadata(record.metadata),
|
|
63
65
|
metadata: record.metadata,
|
|
@@ -77,36 +79,10 @@ class PodConnectedCredentialRepository {
|
|
|
77
79
|
});
|
|
78
80
|
if (existing) {
|
|
79
81
|
const updated = await db.updateById(credential, record.id, row);
|
|
80
|
-
return recordFromCredentialRow(updated ?? row);
|
|
82
|
+
return recordFromCredentialRow(updated ?? row, record.webId);
|
|
81
83
|
}
|
|
82
84
|
await db.insert(credential).values(row).execute();
|
|
83
|
-
return recordFromCredentialRow(row);
|
|
84
|
-
}
|
|
85
|
-
async rewrapCredential(input) {
|
|
86
|
-
const { db, credential } = await this.dbForOwner(input.webId, input.auth);
|
|
87
|
-
const existing = await db.findById(credential, input.credentialId);
|
|
88
|
-
if (!existing) {
|
|
89
|
-
return false;
|
|
90
|
-
}
|
|
91
|
-
const current = recordFromCredentialRow(existing);
|
|
92
|
-
if (current.webId !== input.webId || current.deployment !== input.deployment) {
|
|
93
|
-
return false;
|
|
94
|
-
}
|
|
95
|
-
const currentVersion = versionFromRow(existing);
|
|
96
|
-
if (input.expectedVersion === undefined || currentVersion !== input.expectedVersion) {
|
|
97
|
-
return false;
|
|
98
|
-
}
|
|
99
|
-
const updated = await db.update(credential)
|
|
100
|
-
.set({
|
|
101
|
-
encryptedSecret: JSON.stringify(input.encryptedSecret),
|
|
102
|
-
wrappedDataKey: input.encryptedSecret.wrappedDek,
|
|
103
|
-
encryptionAlgorithm: input.encryptedSecret.algorithm,
|
|
104
|
-
keyVersion: String(currentVersion + 1),
|
|
105
|
-
})
|
|
106
|
-
.where((0, drizzle_solid_1.and)((0, drizzle_solid_1.eq)(credential.id, input.credentialId), (0, drizzle_solid_1.eq)(credential.keyVersion, String(input.expectedVersion))))
|
|
107
|
-
.returning()
|
|
108
|
-
.execute();
|
|
109
|
-
return updated.length === 1;
|
|
85
|
+
return recordFromCredentialRow(row, record.webId);
|
|
110
86
|
}
|
|
111
87
|
async markReauthRequired(input) {
|
|
112
88
|
const { db, credential } = await this.dbForOwner(input.webId, input.auth);
|
|
@@ -124,7 +100,7 @@ class PodConnectedCredentialRepository {
|
|
|
124
100
|
status: 'active',
|
|
125
101
|
keyVersion: String(existingVersion + 1),
|
|
126
102
|
});
|
|
127
|
-
return updated ? recordFromCredentialRow(updated) : undefined;
|
|
103
|
+
return updated ? recordFromCredentialRow(updated, input.webId) : undefined;
|
|
128
104
|
}
|
|
129
105
|
async disconnect(input) {
|
|
130
106
|
const { db, credential } = await this.dbForOwner(input.webId, input.auth);
|
|
@@ -137,18 +113,18 @@ class PodConnectedCredentialRepository {
|
|
|
137
113
|
status: 'revoked',
|
|
138
114
|
keyVersion: String(versionFromRow(existing) + 1),
|
|
139
115
|
});
|
|
140
|
-
return updated ? recordFromCredentialRow(updated) : undefined;
|
|
116
|
+
return updated ? recordFromCredentialRow(updated, input.webId) : undefined;
|
|
141
117
|
}
|
|
142
118
|
async dbForOwner(owner, auth) {
|
|
143
|
-
const trustedFetch = await this.resolveTrustedFetch(owner);
|
|
119
|
+
const trustedFetch = await this.resolveTrustedFetch(owner, auth);
|
|
144
120
|
const credential = (0, drizzle_solid_1.alias)(this.credentialTemplate, 'credential');
|
|
145
121
|
const aiProvider = (0, drizzle_solid_1.alias)(this.aiProviderTemplate, 'aiProvider');
|
|
146
122
|
const db = await this.dbFactory({ owner, auth, fetch: trustedFetch, credential, aiProvider });
|
|
147
123
|
await db.init?.(credential, aiProvider);
|
|
148
124
|
return { db, credential };
|
|
149
125
|
}
|
|
150
|
-
async resolveTrustedFetch(owner) {
|
|
151
|
-
const trustedFetch = await this.internalPodAccess?.getTrustedFetch(owner);
|
|
126
|
+
async resolveTrustedFetch(owner, auth) {
|
|
127
|
+
const trustedFetch = await this.internalPodAccess?.getTrustedFetch(owner, auth);
|
|
152
128
|
if (!trustedFetch) {
|
|
153
129
|
throw new Error('AI Connection service identity is not configured');
|
|
154
130
|
}
|
|
@@ -261,7 +237,6 @@ class BrowserAssistedApiKeyConnectAdapter {
|
|
|
261
237
|
this.consoleUrl = options.consoleUrl;
|
|
262
238
|
this.attempts = options.attempts;
|
|
263
239
|
this.credentialRepository = options.credentialRepository;
|
|
264
|
-
this.vault = options.vault;
|
|
265
240
|
this.deployment = options.deployment;
|
|
266
241
|
this.now = options.now ?? (() => new Date());
|
|
267
242
|
this.randomBytes = options.randomBytes ?? node_crypto_1.randomBytes;
|
|
@@ -297,7 +272,7 @@ class BrowserAssistedApiKeyConnectAdapter {
|
|
|
297
272
|
deployment: input.deployment,
|
|
298
273
|
provider: this.provider,
|
|
299
274
|
});
|
|
300
|
-
const
|
|
275
|
+
const secretPayload = (0, PlaintextCredentialPayload_1.encodePlaintextCredential)({ type: 'apiKey', apiKey: input.apiKey });
|
|
301
276
|
const record = await this.credentialRepository.upsertConnectedCredential({
|
|
302
277
|
id: models_1.aiRuntimeRepository.credentialId({ deployment: input.deployment, provider: this.provider }),
|
|
303
278
|
credentialIri,
|
|
@@ -305,7 +280,8 @@ class BrowserAssistedApiKeyConnectAdapter {
|
|
|
305
280
|
provider: this.provider,
|
|
306
281
|
deployment: input.deployment,
|
|
307
282
|
authMode: 'apiKey',
|
|
308
|
-
|
|
283
|
+
storageMode: PlaintextCredentialPayload_1.PLAINTEXT_CREDENTIAL_STORAGE_MODE,
|
|
284
|
+
secretPayload,
|
|
309
285
|
status: 'active',
|
|
310
286
|
accountLabel: input.accountLabel,
|
|
311
287
|
expectedVersion: consumed.expectedCredentialVersion,
|
|
@@ -601,7 +577,6 @@ class KimiDeviceCodeConnectAdapter extends BrowserAssistedApiKeyConnectAdapter {
|
|
|
601
577
|
scope: stringFrom(body.scope),
|
|
602
578
|
idToken: stringFrom(body.id_token),
|
|
603
579
|
};
|
|
604
|
-
const encryptedSecret = await this.vault.seal(principal(input.webId), credentialIri, 'kimi', secret);
|
|
605
580
|
return this.credentialRepository.upsertConnectedCredential({
|
|
606
581
|
id: models_1.aiRuntimeRepository.credentialId({ deployment: input.deployment, provider: 'kimi' }),
|
|
607
582
|
credentialIri,
|
|
@@ -609,7 +584,8 @@ class KimiDeviceCodeConnectAdapter extends BrowserAssistedApiKeyConnectAdapter {
|
|
|
609
584
|
provider: 'kimi',
|
|
610
585
|
deployment: input.deployment,
|
|
611
586
|
authMode: 'deviceCodeOAuth',
|
|
612
|
-
|
|
587
|
+
storageMode: PlaintextCredentialPayload_1.PLAINTEXT_CREDENTIAL_STORAGE_MODE,
|
|
588
|
+
secretPayload: (0, PlaintextCredentialPayload_1.encodePlaintextCredential)(secret),
|
|
613
589
|
status: 'active',
|
|
614
590
|
expiresAt,
|
|
615
591
|
expectedVersion,
|
|
@@ -644,7 +620,6 @@ class ProviderConnectService {
|
|
|
644
620
|
this.adapters = new Map();
|
|
645
621
|
this.registry = options.registry;
|
|
646
622
|
this.credentialRepository = options.credentialRepository;
|
|
647
|
-
this.vault = options.vault;
|
|
648
623
|
for (const adapter of options.adapters) {
|
|
649
624
|
this.adapters.set(normalizeProvider(adapter.provider), adapter);
|
|
650
625
|
}
|
|
@@ -733,14 +708,14 @@ class ProviderConnectService {
|
|
|
733
708
|
if (!adapter.refresh) {
|
|
734
709
|
throw new Error('Provider does not support refresh');
|
|
735
710
|
}
|
|
736
|
-
if (!this.credentialRepository
|
|
737
|
-
throw new Error('
|
|
711
|
+
if (!this.credentialRepository) {
|
|
712
|
+
throw new Error('PodCredentialRepository is required for provider refresh');
|
|
738
713
|
}
|
|
739
714
|
const current = await this.credentialRepository.getActiveCredential(input);
|
|
740
715
|
if (!current) {
|
|
741
716
|
throw new Error('Active provider credential not found');
|
|
742
717
|
}
|
|
743
|
-
const secret =
|
|
718
|
+
const secret = (0, PlaintextCredentialPayload_1.decodePlaintextCredential)(current);
|
|
744
719
|
try {
|
|
745
720
|
return await adapter.refresh(input, current, secret);
|
|
746
721
|
}
|
|
@@ -794,9 +769,8 @@ function credentialRowFromRecord(record) {
|
|
|
794
769
|
service: 'ai',
|
|
795
770
|
authMode: record.authMode,
|
|
796
771
|
status: record.status,
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
encryptionAlgorithm: record.encryptedSecret.algorithm,
|
|
772
|
+
storageMode: record.storageMode,
|
|
773
|
+
secretPayload: record.secretPayload,
|
|
800
774
|
keyVersion: String(record.version ?? 1),
|
|
801
775
|
scopes: record.scopes ?? [],
|
|
802
776
|
expiresAt: record.expiresAt,
|
|
@@ -806,21 +780,33 @@ function credentialRowFromRecord(record) {
|
|
|
806
780
|
lastRefreshAt: new Date(),
|
|
807
781
|
};
|
|
808
782
|
}
|
|
809
|
-
function recordFromCredentialRow(row) {
|
|
810
|
-
const
|
|
783
|
+
function recordFromCredentialRow(row, owner) {
|
|
784
|
+
const storageMode = stringFrom(row.storageMode) === PlaintextCredentialPayload_1.PLAINTEXT_CREDENTIAL_STORAGE_MODE
|
|
785
|
+
? PlaintextCredentialPayload_1.PLAINTEXT_CREDENTIAL_STORAGE_MODE
|
|
786
|
+
: stringFrom(row.storageMode);
|
|
787
|
+
const secretPayload = typeof row.secretPayload === 'string' ? row.secretPayload : '';
|
|
788
|
+
(0, PlaintextCredentialPayload_1.decodePlaintextCredential)({
|
|
789
|
+
storageMode,
|
|
790
|
+
secretPayload,
|
|
791
|
+
encryptedSecret: row.encryptedSecret,
|
|
792
|
+
wrappedDataKey: row.wrappedDataKey,
|
|
793
|
+
encryptionAlgorithm: row.encryptionAlgorithm,
|
|
794
|
+
});
|
|
811
795
|
const id = stringFrom(row.id);
|
|
812
796
|
const provider = providerFromRelation(stringFrom(row.provider))
|
|
813
797
|
|| providerFromCredentialId(id);
|
|
814
798
|
const deployment = deploymentFromCredentialId(id);
|
|
815
|
-
const
|
|
799
|
+
const credentialIri = stringFrom(row.credentialIri)
|
|
800
|
+
|| models_1.aiRuntimeRepository.credentialIri(owner, { deployment, provider });
|
|
816
801
|
return {
|
|
817
802
|
id,
|
|
818
|
-
credentialIri
|
|
819
|
-
webId,
|
|
803
|
+
credentialIri,
|
|
804
|
+
webId: owner,
|
|
820
805
|
provider,
|
|
821
806
|
deployment,
|
|
822
807
|
authMode: stringFrom(row.authMode) === 'deviceCodeOAuth' ? 'deviceCodeOAuth' : 'apiKey',
|
|
823
|
-
|
|
808
|
+
storageMode: PlaintextCredentialPayload_1.PLAINTEXT_CREDENTIAL_STORAGE_MODE,
|
|
809
|
+
secretPayload,
|
|
824
810
|
status: stringFrom(row.status) === 'revoked' ? 'revoked' : 'active',
|
|
825
811
|
accountLabel: stringFrom(row.accountLabel) || stringFrom(row.label) || undefined,
|
|
826
812
|
expiresAt: dateFrom(row.expiresAt),
|
|
@@ -884,16 +870,6 @@ function runtimeCredentialFromMetadata(metadata) {
|
|
|
884
870
|
? value
|
|
885
871
|
: undefined;
|
|
886
872
|
}
|
|
887
|
-
function parseEncryptedSecret(value) {
|
|
888
|
-
if (typeof value !== 'string' || !value.trim()) {
|
|
889
|
-
throw new Error('Credential row is missing encrypted secret payload');
|
|
890
|
-
}
|
|
891
|
-
const parsed = JSON.parse(value);
|
|
892
|
-
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
893
|
-
throw new Error('Credential row encrypted secret payload is invalid');
|
|
894
|
-
}
|
|
895
|
-
return parsed;
|
|
896
|
-
}
|
|
897
873
|
function versionFromRow(row) {
|
|
898
874
|
const value = row.keyVersion;
|
|
899
875
|
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
@@ -943,9 +919,6 @@ function signatureMatches(actual, expected) {
|
|
|
943
919
|
function codeChallenge(verifier) {
|
|
944
920
|
return (0, node_crypto_1.createHash)('sha256').update(verifier).digest('base64url');
|
|
945
921
|
}
|
|
946
|
-
function principal(webId) {
|
|
947
|
-
return { webId };
|
|
948
|
-
}
|
|
949
922
|
function cloneAttempt(attempt) {
|
|
950
923
|
return {
|
|
951
924
|
...attempt,
|