@pymthouse/builder-sdk 0.0.8

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/usage.ts","../src/encoding.ts","../src/errors.ts","../src/string-utils.ts","../src/discovery.ts","../src/oauth-map.ts","../src/client.ts","../src/env.ts"],"names":["customFetch","allowInsecureRequests"],"mappings":"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","file":"index.js","sourcesContent":["import type {\n UsageApiResponse,\n UsageByPipelineModelRow,\n UsageByUserRow,\n UsageForExternalUser,\n} from \"./types.js\";\n\n/**\n * Sum all `byUser` buckets whose `externalUserId` matches the provider user.\n *\n * PymtHouse may emit multiple rows for the same external user during transitions\n * (e.g. legacy internal ids vs external id on `usage_records.user_id`).\n */\nexport function aggregateUsageByExternalUserId(\n byUser: UsageByUserRow[] | undefined,\n externalUserId: string,\n): UsageForExternalUser {\n const rows = byUser?.filter((row) => row.externalUserId === externalUserId) ?? [];\n if (rows.length === 0) {\n return {\n externalUserId,\n requestCount: 0,\n feeWei: \"0\",\n };\n }\n\n let feeWei = 0n;\n let requestCount = 0;\n for (const row of rows) {\n feeWei += BigInt(row.feeWei);\n requestCount += row.requestCount;\n }\n\n return {\n externalUserId,\n requestCount,\n feeWei: feeWei.toString(),\n };\n}\n\n/**\n * Convenience over {@link aggregateUsageByExternalUserId} using a full Usage API response.\n */\nexport function summarizeUsageForExternalUser(\n usage: UsageApiResponse,\n externalUserId: string,\n): UsageForExternalUser {\n return aggregateUsageByExternalUserId(usage.byUser, externalUserId);\n}\n\n/**\n * Returns `byPipelineModel` rows from a Usage API response, sorted by `pipeline` then `modelId`.\n * Use with `getUsage({ groupBy: \"pipeline_model\", ... })`.\n */\nexport function listUsageByPipelineModel(usage: UsageApiResponse): UsageByPipelineModelRow[] {\n const rows = usage.byPipelineModel ?? [];\n return [...rows].sort((a, b) => {\n const p = a.pipeline.localeCompare(b.pipeline);\n if (p !== 0) return p;\n return a.modelId.localeCompare(b.modelId);\n });\n}\n","/**\n * Base64url-safe Basic auth encoding for `client_id:client_secret` (UTF-8).\n * Works in Node, Edge, and Workers without assuming `Buffer`.\n */\nexport function encodeClientSecretBasic(clientId: string, clientSecret: string): string {\n const raw = `${clientId}:${clientSecret}`;\n const b64 =\n typeof Buffer !== \"undefined\"\n ? Buffer.from(raw, \"utf8\").toString(\"base64\")\n : btoa(Array.from(new TextEncoder().encode(raw), (c) => String.fromCharCode(c)).join(\"\"));\n return `Basic ${b64}`;\n}\n","export class PmtHouseError extends Error {\n readonly status: number;\n readonly code: string;\n readonly details?: unknown;\n\n constructor(\n message: string,\n {\n status = 500,\n code = \"pymthouse_error\",\n details,\n }: {\n status?: number;\n code?: string;\n details?: unknown;\n } = {},\n ) {\n super(message);\n this.name = \"PmtHouseError\";\n this.status = status;\n this.code = code;\n this.details = details;\n }\n}\n\nexport function toPmtHouseError(\n error: unknown,\n fallbackMessage: string,\n): PmtHouseError {\n if (error instanceof PmtHouseError) {\n return error;\n }\n\n if (error instanceof Error) {\n return new PmtHouseError(error.message || fallbackMessage, {\n code: \"unexpected_error\",\n status: 500,\n });\n }\n\n return new PmtHouseError(fallbackMessage, {\n code: \"unexpected_error\",\n status: 500,\n });\n}\n","/** Removes trailing `/` without regex (linear time). */\nexport function stripTrailingSlashes(value: string): string {\n let end = value.length;\n while (end > 0 && value.charCodeAt(end - 1) === 47) {\n end--;\n }\n return value.slice(0, end);\n}\n","import {\n allowInsecureRequests,\n customFetch,\n discoveryRequest,\n processDiscoveryResponse,\n type AuthorizationServer,\n} from \"oauth4webapi\";\nimport { PmtHouseError } from \"./errors.js\";\nimport { stripTrailingSlashes } from \"./string-utils.js\";\nimport type { FetchLike, OidcDiscoveryDocument } from \"./types.js\";\n\nexport function authorizationServerToOidcDocument(as: AuthorizationServer): OidcDiscoveryDocument {\n const tokenEndpoint = as.token_endpoint;\n const jwksUri = as.jwks_uri;\n if (!tokenEndpoint || !jwksUri) {\n throw new PmtHouseError(\"OIDC discovery document is missing token_endpoint or jwks_uri\", {\n status: 500,\n code: \"oidc_discovery_invalid\",\n });\n }\n return {\n issuer: as.issuer,\n authorization_endpoint: as.authorization_endpoint ?? \"\",\n token_endpoint: tokenEndpoint,\n jwks_uri: jwksUri,\n userinfo_endpoint: as.userinfo_endpoint,\n device_authorization_endpoint: as.device_authorization_endpoint,\n };\n}\n\nconst CACHE_TTL_MS = 5 * 60 * 1000;\n\ntype CacheEntry = {\n as: AuthorizationServer;\n fetchedAt: number;\n};\n\nconst discoveryCache = new Map<string, CacheEntry>();\n\nfunction normalizedIssuerKey(issuerUrl: string): string {\n return stripTrailingSlashes(issuerUrl);\n}\n\nexport interface LoadAuthorizationServerOptions {\n force?: boolean;\n allowInsecureHttp?: boolean;\n}\n\n/**\n * Loads OIDC discovery metadata via oauth4webapi (RFC 8414 / OIDC Discovery), with a 5-minute cache.\n */\nexport async function loadAuthorizationServer(\n issuerUrl: string,\n fetchImpl: FetchLike,\n options: LoadAuthorizationServerOptions = {},\n): Promise<AuthorizationServer> {\n const key = normalizedIssuerKey(issuerUrl);\n const now = Date.now();\n const cached = discoveryCache.get(key);\n\n if (!options.force && cached && now - cached.fetchedAt < CACHE_TTL_MS) {\n return cached.as;\n }\n\n const issuerIdentifier = new URL(key);\n const discoveryOpts: Parameters<typeof discoveryRequest>[1] = {\n algorithm: \"oidc\",\n [customFetch]: fetchImpl,\n };\n if (options.allowInsecureHttp) {\n discoveryOpts[allowInsecureRequests] = true;\n }\n\n let response: Response;\n try {\n response = await discoveryRequest(issuerIdentifier, discoveryOpts);\n } catch (e) {\n throw mapDiscoveryNetworkError(e);\n }\n\n let as: AuthorizationServer;\n try {\n as = await processDiscoveryResponse(issuerIdentifier, response);\n } catch (e) {\n throw mapOAuthDiscoveryError(e);\n }\n\n discoveryCache.set(key, { as, fetchedAt: now });\n return as;\n}\n\nexport async function fetchDiscoveryDocument(\n issuerUrl: string,\n fetchImpl: FetchLike,\n options: LoadAuthorizationServerOptions = {},\n): Promise<OidcDiscoveryDocument> {\n const as = await loadAuthorizationServer(issuerUrl, fetchImpl, options);\n return authorizationServerToOidcDocument(as);\n}\n\nexport function clearDiscoveryCache(issuerUrl?: string): void {\n if (!issuerUrl) {\n discoveryCache.clear();\n return;\n }\n discoveryCache.delete(normalizedIssuerKey(issuerUrl));\n}\n\nfunction mapOAuthDiscoveryError(error: unknown): PmtHouseError {\n if (error instanceof PmtHouseError) {\n return error;\n }\n if (error instanceof Error) {\n return new PmtHouseError(error.message, {\n status: 500,\n code: \"oidc_discovery_invalid\",\n details: { cause: error.cause },\n });\n }\n return new PmtHouseError(\"OIDC discovery failed\", {\n status: 500,\n code: \"oidc_discovery_invalid\",\n });\n}\n\nfunction mapDiscoveryNetworkError(error: unknown): PmtHouseError {\n if (error instanceof PmtHouseError) {\n return error;\n }\n if (error instanceof Error) {\n return new PmtHouseError(`Failed to load OIDC discovery: ${error.message}`, {\n status: 502,\n code: \"oidc_discovery_failed\",\n });\n }\n return new PmtHouseError(\"Failed to load OIDC discovery\", {\n status: 502,\n code: \"oidc_discovery_failed\",\n });\n}\n","import { type Client, OperationProcessingError, ResponseBodyError } from \"oauth4webapi\";\nimport { PmtHouseError } from \"./errors.js\";\nimport type { ClientCredentialsTokenResponse, TokenExchangeResponse } from \"./types.js\";\n\nconst ACCEPTED_ISSUED_TOKEN_TYPES = new Set([\n \"urn:ietf:params:oauth:token-type:access_token\",\n \"urn:pmth:token-type:remote-signer-session\",\n]);\n\nexport function mapOAuthError(error: unknown): PmtHouseError {\n if (error instanceof PmtHouseError) {\n return error;\n }\n\n if (error instanceof ResponseBodyError) {\n const cause = error.cause as Record<string, unknown>;\n const description =\n typeof error.error_description === \"string\"\n ? error.error_description\n : error.message;\n const details: Record<string, unknown> = { ...cause };\n if (typeof cause.error_uri === \"string\") {\n details.error_uri = cause.error_uri;\n }\n return new PmtHouseError(description, {\n status: error.status,\n code: error.error,\n details,\n });\n }\n\n if (error instanceof OperationProcessingError) {\n return new PmtHouseError(error.message, {\n status: 502,\n code: error.code ?? \"oauth_processing_error\",\n details: { cause: error.cause },\n });\n }\n\n if (error instanceof Error) {\n return new PmtHouseError(error.message, {\n status: 500,\n code: \"unexpected_error\",\n });\n }\n\n return new PmtHouseError(\"Unexpected error\", {\n status: 500,\n code: \"unexpected_error\",\n });\n}\n\nexport function tokenEndpointResponseToExchange(\n tr: import(\"oauth4webapi\").TokenEndpointResponse,\n): TokenExchangeResponse {\n const issued = tr.issued_token_type;\n if (typeof issued !== \"string\" || !ACCEPTED_ISSUED_TOKEN_TYPES.has(issued)) {\n throw new PmtHouseError(\"Token exchange returned an unexpected issued_token_type\", {\n status: 502,\n code: \"invalid_token_response\",\n details: { issued_token_type: issued },\n });\n }\n\n const tt = tr.token_type;\n if (typeof tt !== \"string\" || tt.toLowerCase() !== \"bearer\") {\n throw new PmtHouseError(\"Token endpoint returned a non-Bearer token_type\", {\n status: 502,\n code: \"invalid_token_response\",\n details: { token_type: tt },\n });\n }\n\n const expiresIn = tr.expires_in;\n if (typeof expiresIn !== \"number\") {\n throw new PmtHouseError(\"Token response missing expires_in\", {\n status: 502,\n code: \"invalid_token_response\",\n });\n }\n\n const scope = typeof tr.scope === \"string\" ? tr.scope : \"\";\n\n return {\n access_token: tr.access_token,\n token_type: \"Bearer\",\n expires_in: expiresIn,\n scope,\n issued_token_type: issued,\n };\n}\n\nexport function tokenEndpointResponseToClientCredentials(\n tr: import(\"oauth4webapi\").TokenEndpointResponse,\n): ClientCredentialsTokenResponse {\n const tt = tr.token_type;\n if (typeof tt !== \"string\" || tt.toLowerCase() !== \"bearer\") {\n throw new PmtHouseError(\"Token endpoint returned a non-Bearer token_type\", {\n status: 502,\n code: \"invalid_token_response\",\n details: { token_type: tt },\n });\n }\n\n return {\n access_token: tr.access_token,\n token_type: \"Bearer\",\n expires_in: tr.expires_in,\n scope: typeof tr.scope === \"string\" ? tr.scope : undefined,\n };\n}\n\nexport function m2mClient(clientId: string): Client {\n return { client_id: clientId };\n}\n","import {\n allowInsecureRequests,\n clientCredentialsGrantRequest,\n customFetch,\n genericTokenEndpointRequest,\n processClientCredentialsResponse,\n processGenericTokenEndpointResponse,\n type ClientAuth,\n type ClientCredentialsGrantRequestOptions,\n type TokenEndpointRequestOptions,\n} from \"oauth4webapi\";\nimport { encodeClientSecretBasic } from \"./encoding.js\";\nimport { loadAuthorizationServer, authorizationServerToOidcDocument } from \"./discovery.js\";\nimport { PmtHouseError } from \"./errors.js\";\nimport { stripTrailingSlashes } from \"./string-utils.js\";\nimport {\n mapOAuthError,\n m2mClient,\n tokenEndpointResponseToClientCredentials,\n tokenEndpointResponseToExchange,\n} from \"./oauth-map.js\";\nimport type {\n AppUserRecord,\n ClientCredentialsTokenResponse,\n DeviceApprovalInput,\n FetchLike,\n GetDiscoveryOptions,\n MintUserSignerSessionTokenInput,\n MintUserAccessTokenInput,\n MintUserAccessTokenResponse,\n OidcDiscoveryDocument,\n ParsedDeviceApprovalRedirect,\n PmtHouseClientOptions,\n TokenExchangeResponse,\n UpsertAppUserInput,\n UsageApiResponse,\n UsageQueryInput,\n} from \"./types.js\";\n\nconst TOKEN_EXCHANGE_GRANT = \"urn:ietf:params:oauth:grant-type:token-exchange\";\nconst SUBJECT_ACCESS_TOKEN_TYPE = \"urn:ietf:params:oauth:token-type:access_token\";\nconst REQUESTED_ACCESS_TOKEN_TYPE = \"urn:ietf:params:oauth:token-type:access_token\";\n\nconst DEVICE_RESOURCE_PREFIX = \"urn:pmth:device_code:\";\n\n/**\n * Normalize RFC 8628 user codes for comparison and resource URIs (uppercase, strip separators).\n */\nexport function normalizeUserCode(value: string): string {\n return value\n .replace(/[a-z]/g, (char) => char.toUpperCase())\n .replace(/\\W/g, \"\");\n}\n\n/**\n * RFC 8707 resource indicator for NaaP Option B device approval (`urn:pmth:device_code:<normalized>`).\n */\nexport function buildDeviceCodeResource(userCode: string): string {\n return `${DEVICE_RESOURCE_PREFIX}${normalizeUserCode(userCode)}`;\n}\n\nexport class PmtHouseClient {\n private readonly issuerUrl: string;\n private readonly publicClientId: string;\n private readonly m2mClientId: string;\n private readonly m2mClientSecret: string;\n private readonly fetchImpl: FetchLike;\n private readonly logger?: PmtHouseClientOptions[\"logger\"];\n private readonly allowInsecureHttp: boolean;\n\n constructor(options: PmtHouseClientOptions) {\n this.issuerUrl = stripTrailingSlashes(options.issuerUrl);\n this.publicClientId = options.publicClientId;\n this.m2mClientId = options.m2mClientId;\n this.m2mClientSecret = options.m2mClientSecret;\n this.fetchImpl = options.fetch ?? fetch;\n this.logger = options.logger;\n this.allowInsecureHttp = options.allowInsecureHttp ?? false;\n }\n\n async getDiscovery(options: GetDiscoveryOptions = {}): Promise<OidcDiscoveryDocument> {\n const as = await loadAuthorizationServer(this.issuerUrl, this.fetchImpl, {\n force: options.force,\n allowInsecureHttp: this.allowInsecureHttp,\n });\n return authorizationServerToOidcDocument(as);\n }\n\n verifyIssuer(iss: string): boolean {\n const candidate = stripTrailingSlashes(iss.trim());\n return candidate === this.issuerUrl;\n }\n\n parseDeviceApprovalRedirect(\n searchParams: URLSearchParams,\n ): ParsedDeviceApprovalRedirect {\n const issuer = searchParams.get(\"iss\")?.trim() ?? \"\";\n const targetLinkUri = searchParams.get(\"target_link_uri\")?.trim() ?? \"\";\n\n if (!issuer || !targetLinkUri) {\n throw new PmtHouseError(\"Missing iss or target_link_uri\", {\n status: 400,\n code: \"invalid_request\",\n });\n }\n\n if (!this.verifyIssuer(issuer)) {\n throw new PmtHouseError(\"Issuer mismatch for initiate login\", {\n status: 400,\n code: \"invalid_issuer\",\n });\n }\n\n let targetUrl: URL;\n try {\n targetUrl = new URL(targetLinkUri);\n } catch {\n throw new PmtHouseError(\"target_link_uri is not a valid URL\", {\n status: 400,\n code: \"invalid_target\",\n });\n }\n\n const issuerOrigin = new URL(this.issuerUrl).origin;\n if (targetUrl.origin !== issuerOrigin || targetUrl.pathname !== \"/oidc/device\") {\n throw new PmtHouseError(\n \"target_link_uri does not point to the issuer device path\",\n {\n status: 400,\n code: \"invalid_target\",\n },\n );\n }\n\n const userCode = normalizeUserCode(targetUrl.searchParams.get(\"user_code\") ?? \"\");\n const clientId = targetUrl.searchParams.get(\"client_id\")?.trim() ?? \"\";\n\n if (!userCode || !clientId) {\n throw new PmtHouseError(\"target_link_uri is missing user_code or client_id\", {\n status: 400,\n code: \"invalid_target\",\n });\n }\n\n return {\n issuer,\n targetLinkUri,\n userCode,\n clientId,\n };\n }\n\n async listAppUsers(): Promise<{ users: AppUserRecord[] }> {\n const url = `${this.getAppsBaseUrl()}/users`;\n return this.requestJson<{ users: AppUserRecord[] }>(url, {\n method: \"GET\",\n headers: this.builderHeaders(),\n cache: \"no-store\",\n });\n }\n\n async upsertAppUser(input: UpsertAppUserInput): Promise<AppUserRecord> {\n const payload: Record<string, unknown> = {\n externalUserId: input.externalUserId,\n };\n if (input.email) payload.email = input.email;\n if (input.status) payload.status = input.status;\n\n const url = `${this.getAppsBaseUrl()}/users`;\n return this.requestJson<AppUserRecord>(url, {\n method: \"POST\",\n headers: this.builderHeaders(),\n body: JSON.stringify(payload),\n cache: \"no-store\",\n });\n }\n\n async deleteAppUser(params: { externalUserId: string }): Promise<{ success: boolean }> {\n const url = new URL(`${this.getAppsBaseUrl()}/users`);\n url.searchParams.set(\"externalUserId\", params.externalUserId);\n return this.requestJson<{ success: boolean }>(url.toString(), {\n method: \"DELETE\",\n headers: this.builderHeaders(),\n cache: \"no-store\",\n });\n }\n\n async mintUserAccessToken(\n input: MintUserAccessTokenInput,\n ): Promise<MintUserAccessTokenResponse> {\n const url = `${this.getAppsBaseUrl()}/users/${encodeURIComponent(input.externalUserId)}/token`;\n const body = input.scope ? { scope: input.scope } : {};\n\n return this.requestJson<MintUserAccessTokenResponse>(url, {\n method: \"POST\",\n headers: this.builderHeaders(),\n body: JSON.stringify(body),\n cache: \"no-store\",\n });\n }\n\n async completeDeviceApproval(\n input: DeviceApprovalInput,\n ): Promise<TokenExchangeResponse> {\n const as = await loadAuthorizationServer(this.issuerUrl, this.fetchImpl, {\n allowInsecureHttp: this.allowInsecureHttp,\n });\n const client = m2mClient(this.m2mClientId);\n const clientAuth = this.m2mClientAuth();\n const params = new URLSearchParams();\n params.set(\"subject_token\", input.userJwt);\n params.set(\"subject_token_type\", SUBJECT_ACCESS_TOKEN_TYPE);\n params.set(\"resource\", buildDeviceCodeResource(input.userCode));\n\n try {\n const response = await genericTokenEndpointRequest(\n as,\n client,\n clientAuth,\n TOKEN_EXCHANGE_GRANT,\n params,\n this.tokenEndpointFetchOptions(),\n );\n const tr = await processGenericTokenEndpointResponse(\n as,\n client,\n response,\n );\n return tokenEndpointResponseToExchange(tr);\n } catch (e) {\n throw mapOAuthError(e);\n }\n }\n\n async issueMachineAccessToken(\n scope = \"sign:job\",\n ): Promise<ClientCredentialsTokenResponse> {\n const as = await loadAuthorizationServer(this.issuerUrl, this.fetchImpl, {\n allowInsecureHttp: this.allowInsecureHttp,\n });\n const client = m2mClient(this.m2mClientId);\n const clientAuth = this.m2mClientAuth();\n const params = new URLSearchParams();\n params.set(\"scope\", scope);\n\n try {\n const response = await clientCredentialsGrantRequest(\n as,\n client,\n clientAuth,\n params,\n this.tokenEndpointFetchOptions(),\n );\n const tr = await processClientCredentialsResponse(\n as,\n client,\n response,\n );\n return tokenEndpointResponseToClientCredentials(tr);\n } catch (e) {\n throw mapOAuthError(e);\n }\n }\n\n async exchangeForSignerSession(input: {\n userJwt: string;\n resource?: string;\n }): Promise<TokenExchangeResponse> {\n const as = await loadAuthorizationServer(this.issuerUrl, this.fetchImpl, {\n allowInsecureHttp: this.allowInsecureHttp,\n });\n const client = m2mClient(this.m2mClientId);\n const clientAuth = this.m2mClientAuth();\n const params = new URLSearchParams();\n params.set(\"subject_token\", input.userJwt);\n params.set(\"subject_token_type\", SUBJECT_ACCESS_TOKEN_TYPE);\n params.set(\"requested_token_type\", REQUESTED_ACCESS_TOKEN_TYPE);\n const resourceCandidate =\n typeof input.resource === \"string\" && input.resource.trim() !== \"\"\n ? input.resource.trim()\n : this.issuerUrl;\n params.set(\"resource\", stripTrailingSlashes(resourceCandidate));\n\n try {\n const response = await genericTokenEndpointRequest(\n as,\n client,\n clientAuth,\n TOKEN_EXCHANGE_GRANT,\n params,\n this.tokenEndpointFetchOptions(),\n );\n const tr = await processGenericTokenEndpointResponse(\n as,\n client,\n response,\n );\n return tokenEndpointResponseToExchange(tr);\n } catch (e) {\n throw mapOAuthError(e);\n }\n }\n\n /**\n * Mint a short-lived per-user JWT with the Builder API, then exchange it for\n * a long-lived opaque signer session token at the PymtHouse OIDC token endpoint.\n */\n async mintUserSignerSessionToken(\n input: MintUserSignerSessionTokenInput,\n ): Promise<TokenExchangeResponse> {\n const userToken = await this.mintUserAccessToken({\n externalUserId: input.externalUserId,\n scope: input.scope ?? \"sign:job\",\n });\n\n return this.exchangeForSignerSession({\n userJwt: userToken.access_token,\n resource: input.resource,\n });\n }\n\n async createSignerSessionToken(params: {\n userJwt?: string;\n }): Promise<TokenExchangeResponse> {\n if (params.userJwt) {\n try {\n return await this.exchangeForSignerSession({ userJwt: params.userJwt });\n } catch (error) {\n const err = this.asError(error);\n this.logger?.warn?.(\"User JWT exchange failed, falling back to machine exchange\", {\n code: err.code,\n status: err.status,\n });\n }\n }\n\n const machineToken = await this.issueMachineAccessToken(\"sign:job\");\n if (!machineToken.access_token) {\n throw new PmtHouseError(\"Client credentials flow did not return access_token\", {\n status: 502,\n code: \"invalid_token_response\",\n });\n }\n\n return this.exchangeForSignerSession({ userJwt: machineToken.access_token });\n }\n\n async getUsage(input: UsageQueryInput = {}): Promise<UsageApiResponse> {\n const url = new URL(`${this.getAppsBaseUrl()}/usage`);\n if (input.startDate) url.searchParams.set(\"startDate\", input.startDate);\n if (input.endDate) url.searchParams.set(\"endDate\", input.endDate);\n if (input.groupBy) url.searchParams.set(\"groupBy\", input.groupBy);\n if (input.userId) url.searchParams.set(\"userId\", input.userId);\n if (input.gatewayRequestId) url.searchParams.set(\"gatewayRequestId\", input.gatewayRequestId);\n\n return this.requestJson<UsageApiResponse>(url.toString(), {\n method: \"GET\",\n headers: this.builderHeaders(),\n cache: \"no-store\",\n });\n }\n\n private tokenEndpointFetchOptions():\n | ClientCredentialsGrantRequestOptions\n | TokenEndpointRequestOptions {\n const o: ClientCredentialsGrantRequestOptions = {\n [customFetch]: this.fetchImpl,\n };\n if (this.allowInsecureHttp) {\n o[allowInsecureRequests] = true;\n }\n return o;\n }\n\n private getAppsBaseUrl(): string {\n return `${this.getIssuerOrigin()}/api/v1/apps/${encodeURIComponent(this.publicClientId)}`;\n }\n\n private getIssuerOrigin(): string {\n return new URL(this.issuerUrl).origin;\n }\n\n private builderHeaders(): HeadersInit {\n return {\n Authorization: encodeClientSecretBasic(this.m2mClientId, this.m2mClientSecret),\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n };\n }\n\n private m2mClientAuth(): ClientAuth {\n return (_as, _client, _body, headers) => {\n headers.set(\"Authorization\", encodeClientSecretBasic(this.m2mClientId, this.m2mClientSecret));\n };\n }\n\n private async requestJson<T>(url: string, init: RequestInit): Promise<T> {\n this.logger?.debug?.(\"PmtHouse request\", {\n method: init.method ?? \"GET\",\n url,\n });\n\n const response = await this.fetchImpl(url, init);\n const raw = await response.text();\n const ct = response.headers.get(\"content-type\") ?? \"\";\n const looksJson = ct.includes(\"application/json\") || ct.includes(\"json\");\n const parsed = raw && looksJson ? this.safeParseJson(raw) : raw ? null : null;\n\n if (!response.ok) {\n const details = (parsed ?? {}) as Record<string, unknown>;\n const description =\n typeof details.error_description === \"string\"\n ? details.error_description\n : typeof details.error === \"string\"\n ? details.error\n : `Request failed (${response.status})`;\n\n throw new PmtHouseError(description, {\n status: response.status,\n code:\n typeof details.error === \"string\"\n ? details.error\n : \"pymthouse_http_error\",\n details,\n });\n }\n\n if (!looksJson || parsed === null) {\n throw new PmtHouseError(\"Expected JSON response from Builder or Usage API\", {\n status: 502,\n code: \"invalid_response\",\n details: { contentType: ct, preview: raw.slice(0, 200) },\n });\n }\n\n if (!parsed) {\n return {} as T;\n }\n\n return parsed as T;\n }\n\n private safeParseJson(value: string): unknown {\n try {\n return JSON.parse(value);\n } catch {\n return null;\n }\n }\n\n private asError(error: unknown): PmtHouseError {\n if (error instanceof PmtHouseError) {\n return error;\n }\n\n if (error instanceof Error) {\n return new PmtHouseError(error.message, {\n code: \"unexpected_error\",\n status: 500,\n });\n }\n\n return new PmtHouseError(\"Unexpected error\", {\n code: \"unexpected_error\",\n status: 500,\n });\n }\n}\n","import { PmtHouseClient } from \"./client.js\";\nimport { PmtHouseError } from \"./errors.js\";\nimport { stripTrailingSlashes } from \"./string-utils.js\";\n\n/**\n * Fail fast if this module is bundled for the browser. M2M secrets must never\n * ship to clients; Next.js users can also re-export behind `import \"server-only\"`\n * for build-time enforcement (see README).\n */\nfunction assertEnvModuleServerOnly(): void {\n if (\n typeof globalThis !== \"undefined\" &&\n typeof (globalThis as { window?: unknown }).window !== \"undefined\"\n ) {\n throw new Error(\n \"@pymthouse/builder-sdk/env is server-only: do not import createPmtHouseClientFromEnv or getPymthouseBaseUrl in client-side code. Use a Route Handler, Server Action, or other server/runtime; keep M2M credentials out of the browser bundle.\",\n );\n }\n}\n\nassertEnvModuleServerOnly();\n\nlet cachedClient: PmtHouseClient | null = null;\n\nfunction requiredEnv(name: string): string {\n const value = process.env[name];\n if (value && value.trim()) {\n return value.trim();\n }\n\n throw new PmtHouseError(`Missing required environment variable: ${name}`, {\n status: 500,\n code: \"missing_env\",\n });\n}\n\n/**\n * Site origin for the PymtHouse deployment (e.g. https://pymthouse.com), derived\n * from `PYMTHOUSE_ISSUER_URL`.\n */\nexport function getPymthouseBaseUrl(): string {\n const issuerUrl = requiredEnv(\"PYMTHOUSE_ISSUER_URL\");\n return new URL(stripTrailingSlashes(issuerUrl)).origin;\n}\n\n/**\n * Singleton `PmtHouseClient` from `PYMTHOUSE_*` environment variables (server-side).\n */\nexport function createPmtHouseClientFromEnv(): PmtHouseClient {\n if (cachedClient) {\n return cachedClient;\n }\n\n const issuerUrl = requiredEnv(\"PYMTHOUSE_ISSUER_URL\");\n\n cachedClient = new PmtHouseClient({\n issuerUrl,\n publicClientId: requiredEnv(\"PYMTHOUSE_PUBLIC_CLIENT_ID\"),\n m2mClientId: requiredEnv(\"PYMTHOUSE_M2M_CLIENT_ID\"),\n m2mClientSecret: requiredEnv(\"PYMTHOUSE_M2M_CLIENT_SECRET\"),\n allowInsecureHttp: issuerUrl.startsWith(\"http:\"),\n logger: {\n debug: (message, details) => {\n if (process.env.NODE_ENV !== \"production\") {\n console.debug(`[pymthouse] ${message}`, details ?? {});\n }\n },\n warn: (message, details) => {\n console.warn(`[pymthouse] ${message}`, details ?? {});\n },\n },\n });\n\n return cachedClient;\n}\n"]}
@@ -0,0 +1,136 @@
1
+ type FetchLike = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
2
+ interface OidcDiscoveryDocument {
3
+ issuer: string;
4
+ authorization_endpoint: string;
5
+ token_endpoint: string;
6
+ jwks_uri: string;
7
+ userinfo_endpoint?: string;
8
+ device_authorization_endpoint?: string;
9
+ }
10
+ interface GetDiscoveryOptions {
11
+ /**
12
+ * Bypass the in-memory discovery cache and fetch fresh metadata.
13
+ */
14
+ force?: boolean;
15
+ }
16
+ interface PmtHouseClientOptions {
17
+ issuerUrl: string;
18
+ publicClientId: string;
19
+ m2mClientId: string;
20
+ m2mClientSecret: string;
21
+ fetch?: FetchLike;
22
+ /**
23
+ * Allow HTTP issuer URLs (e.g. local dev). Passed to oauth4webapi as `allowInsecureRequests`.
24
+ */
25
+ allowInsecureHttp?: boolean;
26
+ logger?: {
27
+ debug?: (message: string, details?: Record<string, unknown>) => void;
28
+ warn?: (message: string, details?: Record<string, unknown>) => void;
29
+ };
30
+ }
31
+ interface UpsertAppUserInput {
32
+ externalUserId: string;
33
+ email?: string;
34
+ status?: "active" | "inactive";
35
+ }
36
+ interface AppUserRecord {
37
+ id: string;
38
+ clientId: string;
39
+ externalUserId: string;
40
+ email: string | null;
41
+ status: string;
42
+ role: string;
43
+ createdAt: string;
44
+ }
45
+ interface MintUserAccessTokenInput {
46
+ externalUserId: string;
47
+ scope?: string;
48
+ }
49
+ interface MintUserSignerSessionTokenInput extends MintUserAccessTokenInput {
50
+ /**
51
+ * Optional RFC 8707 resource indicator for the signer-session exchange.
52
+ * Defaults to the configured PymtHouse issuer URL.
53
+ */
54
+ resource?: string;
55
+ }
56
+ interface MintUserAccessTokenResponse {
57
+ access_token: string;
58
+ refresh_token: string;
59
+ token_type: "Bearer";
60
+ expires_in: number;
61
+ scope: string;
62
+ subject_type: "app_user";
63
+ correlation_id?: string;
64
+ }
65
+ interface DeviceApprovalInput {
66
+ userJwt: string;
67
+ userCode: string;
68
+ }
69
+ interface TokenExchangeResponse {
70
+ access_token: string;
71
+ token_type: "Bearer";
72
+ expires_in: number;
73
+ scope: string;
74
+ issued_token_type: string;
75
+ }
76
+ interface UsageQueryInput {
77
+ startDate?: string;
78
+ endDate?: string;
79
+ groupBy?: "none" | "user" | "pipeline_model";
80
+ userId?: string;
81
+ gatewayRequestId?: string;
82
+ }
83
+ interface UsageTotals {
84
+ requestCount: number;
85
+ totalFeeWei: string;
86
+ }
87
+ interface UsageByUserRow {
88
+ endUserId: string;
89
+ externalUserId: string | null;
90
+ requestCount: number;
91
+ feeWei: string;
92
+ userType?: "system_managed" | "oidc_authorized" | "unknown";
93
+ identifier?: string;
94
+ }
95
+ /** One bucket from Usage API `groupBy=pipeline_model` (validated pipeline + model). */
96
+ interface UsageByPipelineModelRow {
97
+ pipeline: string;
98
+ modelId: string;
99
+ requestCount: number;
100
+ networkFeeWei: string;
101
+ networkFeeEth?: string;
102
+ networkFeeUsdMicros: string;
103
+ ownerChargeUsdMicros: string;
104
+ endUserBillableUsdMicros: string;
105
+ }
106
+ interface UsageApiResponse {
107
+ clientId: string;
108
+ period: {
109
+ start: string | null;
110
+ end: string | null;
111
+ };
112
+ totals: UsageTotals;
113
+ byUser?: UsageByUserRow[];
114
+ byPipelineModel?: UsageByPipelineModelRow[];
115
+ }
116
+ /** Aggregated request count and fee for one provider `externalUserId` across duplicate `byUser` buckets. */
117
+ interface UsageForExternalUser {
118
+ externalUserId: string;
119
+ requestCount: number;
120
+ feeWei: string;
121
+ }
122
+ interface ClientCredentialsTokenResponse {
123
+ access_token: string;
124
+ token_type: "Bearer";
125
+ expires_in?: number;
126
+ scope?: string;
127
+ [key: string]: unknown;
128
+ }
129
+ interface ParsedDeviceApprovalRedirect {
130
+ issuer: string;
131
+ targetLinkUri: string;
132
+ userCode: string;
133
+ clientId: string;
134
+ }
135
+
136
+ export type { AppUserRecord as A, ClientCredentialsTokenResponse as C, DeviceApprovalInput as D, FetchLike as F, GetDiscoveryOptions as G, MintUserAccessTokenInput as M, OidcDiscoveryDocument as O, ParsedDeviceApprovalRedirect as P, TokenExchangeResponse as T, UsageByUserRow as U, UsageForExternalUser as a, UsageApiResponse as b, UsageByPipelineModelRow as c, MintUserAccessTokenResponse as d, MintUserSignerSessionTokenInput as e, PmtHouseClientOptions as f, UpsertAppUserInput as g, UsageQueryInput as h, UsageTotals as i };
@@ -0,0 +1,136 @@
1
+ type FetchLike = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
2
+ interface OidcDiscoveryDocument {
3
+ issuer: string;
4
+ authorization_endpoint: string;
5
+ token_endpoint: string;
6
+ jwks_uri: string;
7
+ userinfo_endpoint?: string;
8
+ device_authorization_endpoint?: string;
9
+ }
10
+ interface GetDiscoveryOptions {
11
+ /**
12
+ * Bypass the in-memory discovery cache and fetch fresh metadata.
13
+ */
14
+ force?: boolean;
15
+ }
16
+ interface PmtHouseClientOptions {
17
+ issuerUrl: string;
18
+ publicClientId: string;
19
+ m2mClientId: string;
20
+ m2mClientSecret: string;
21
+ fetch?: FetchLike;
22
+ /**
23
+ * Allow HTTP issuer URLs (e.g. local dev). Passed to oauth4webapi as `allowInsecureRequests`.
24
+ */
25
+ allowInsecureHttp?: boolean;
26
+ logger?: {
27
+ debug?: (message: string, details?: Record<string, unknown>) => void;
28
+ warn?: (message: string, details?: Record<string, unknown>) => void;
29
+ };
30
+ }
31
+ interface UpsertAppUserInput {
32
+ externalUserId: string;
33
+ email?: string;
34
+ status?: "active" | "inactive";
35
+ }
36
+ interface AppUserRecord {
37
+ id: string;
38
+ clientId: string;
39
+ externalUserId: string;
40
+ email: string | null;
41
+ status: string;
42
+ role: string;
43
+ createdAt: string;
44
+ }
45
+ interface MintUserAccessTokenInput {
46
+ externalUserId: string;
47
+ scope?: string;
48
+ }
49
+ interface MintUserSignerSessionTokenInput extends MintUserAccessTokenInput {
50
+ /**
51
+ * Optional RFC 8707 resource indicator for the signer-session exchange.
52
+ * Defaults to the configured PymtHouse issuer URL.
53
+ */
54
+ resource?: string;
55
+ }
56
+ interface MintUserAccessTokenResponse {
57
+ access_token: string;
58
+ refresh_token: string;
59
+ token_type: "Bearer";
60
+ expires_in: number;
61
+ scope: string;
62
+ subject_type: "app_user";
63
+ correlation_id?: string;
64
+ }
65
+ interface DeviceApprovalInput {
66
+ userJwt: string;
67
+ userCode: string;
68
+ }
69
+ interface TokenExchangeResponse {
70
+ access_token: string;
71
+ token_type: "Bearer";
72
+ expires_in: number;
73
+ scope: string;
74
+ issued_token_type: string;
75
+ }
76
+ interface UsageQueryInput {
77
+ startDate?: string;
78
+ endDate?: string;
79
+ groupBy?: "none" | "user" | "pipeline_model";
80
+ userId?: string;
81
+ gatewayRequestId?: string;
82
+ }
83
+ interface UsageTotals {
84
+ requestCount: number;
85
+ totalFeeWei: string;
86
+ }
87
+ interface UsageByUserRow {
88
+ endUserId: string;
89
+ externalUserId: string | null;
90
+ requestCount: number;
91
+ feeWei: string;
92
+ userType?: "system_managed" | "oidc_authorized" | "unknown";
93
+ identifier?: string;
94
+ }
95
+ /** One bucket from Usage API `groupBy=pipeline_model` (validated pipeline + model). */
96
+ interface UsageByPipelineModelRow {
97
+ pipeline: string;
98
+ modelId: string;
99
+ requestCount: number;
100
+ networkFeeWei: string;
101
+ networkFeeEth?: string;
102
+ networkFeeUsdMicros: string;
103
+ ownerChargeUsdMicros: string;
104
+ endUserBillableUsdMicros: string;
105
+ }
106
+ interface UsageApiResponse {
107
+ clientId: string;
108
+ period: {
109
+ start: string | null;
110
+ end: string | null;
111
+ };
112
+ totals: UsageTotals;
113
+ byUser?: UsageByUserRow[];
114
+ byPipelineModel?: UsageByPipelineModelRow[];
115
+ }
116
+ /** Aggregated request count and fee for one provider `externalUserId` across duplicate `byUser` buckets. */
117
+ interface UsageForExternalUser {
118
+ externalUserId: string;
119
+ requestCount: number;
120
+ feeWei: string;
121
+ }
122
+ interface ClientCredentialsTokenResponse {
123
+ access_token: string;
124
+ token_type: "Bearer";
125
+ expires_in?: number;
126
+ scope?: string;
127
+ [key: string]: unknown;
128
+ }
129
+ interface ParsedDeviceApprovalRedirect {
130
+ issuer: string;
131
+ targetLinkUri: string;
132
+ userCode: string;
133
+ clientId: string;
134
+ }
135
+
136
+ export type { AppUserRecord as A, ClientCredentialsTokenResponse as C, DeviceApprovalInput as D, FetchLike as F, GetDiscoveryOptions as G, MintUserAccessTokenInput as M, OidcDiscoveryDocument as O, ParsedDeviceApprovalRedirect as P, TokenExchangeResponse as T, UsageByUserRow as U, UsageForExternalUser as a, UsageApiResponse as b, UsageByPipelineModelRow as c, MintUserAccessTokenResponse as d, MintUserSignerSessionTokenInput as e, PmtHouseClientOptions as f, UpsertAppUserInput as g, UsageQueryInput as h, UsageTotals as i };
@@ -0,0 +1,181 @@
1
+ 'use strict';
2
+
3
+ var oauth4webapi = require('oauth4webapi');
4
+
5
+ // src/verify.ts
6
+
7
+ // src/errors.ts
8
+ var PmtHouseError = class extends Error {
9
+ status;
10
+ code;
11
+ details;
12
+ constructor(message, {
13
+ status = 500,
14
+ code = "pymthouse_error",
15
+ details
16
+ } = {}) {
17
+ super(message);
18
+ this.name = "PmtHouseError";
19
+ this.status = status;
20
+ this.code = code;
21
+ this.details = details;
22
+ }
23
+ };
24
+
25
+ // src/string-utils.ts
26
+ function stripTrailingSlashes(value) {
27
+ let end = value.length;
28
+ while (end > 0 && value.charCodeAt(end - 1) === 47) {
29
+ end--;
30
+ }
31
+ return value.slice(0, end);
32
+ }
33
+
34
+ // src/discovery.ts
35
+ var CACHE_TTL_MS = 5 * 60 * 1e3;
36
+ var discoveryCache = /* @__PURE__ */ new Map();
37
+ function normalizedIssuerKey(issuerUrl) {
38
+ return stripTrailingSlashes(issuerUrl);
39
+ }
40
+ async function loadAuthorizationServer(issuerUrl, fetchImpl, options = {}) {
41
+ const key = normalizedIssuerKey(issuerUrl);
42
+ const now = Date.now();
43
+ const cached = discoveryCache.get(key);
44
+ if (!options.force && cached && now - cached.fetchedAt < CACHE_TTL_MS) {
45
+ return cached.as;
46
+ }
47
+ const issuerIdentifier = new URL(key);
48
+ const discoveryOpts = {
49
+ algorithm: "oidc",
50
+ [oauth4webapi.customFetch]: fetchImpl
51
+ };
52
+ if (options.allowInsecureHttp) {
53
+ discoveryOpts[oauth4webapi.allowInsecureRequests] = true;
54
+ }
55
+ let response;
56
+ try {
57
+ response = await oauth4webapi.discoveryRequest(issuerIdentifier, discoveryOpts);
58
+ } catch (e) {
59
+ throw mapDiscoveryNetworkError(e);
60
+ }
61
+ let as;
62
+ try {
63
+ as = await oauth4webapi.processDiscoveryResponse(issuerIdentifier, response);
64
+ } catch (e) {
65
+ throw mapOAuthDiscoveryError(e);
66
+ }
67
+ discoveryCache.set(key, { as, fetchedAt: now });
68
+ return as;
69
+ }
70
+ function mapOAuthDiscoveryError(error) {
71
+ if (error instanceof PmtHouseError) {
72
+ return error;
73
+ }
74
+ if (error instanceof Error) {
75
+ return new PmtHouseError(error.message, {
76
+ status: 500,
77
+ code: "oidc_discovery_invalid",
78
+ details: { cause: error.cause }
79
+ });
80
+ }
81
+ return new PmtHouseError("OIDC discovery failed", {
82
+ status: 500,
83
+ code: "oidc_discovery_invalid"
84
+ });
85
+ }
86
+ function mapDiscoveryNetworkError(error) {
87
+ if (error instanceof PmtHouseError) {
88
+ return error;
89
+ }
90
+ if (error instanceof Error) {
91
+ return new PmtHouseError(`Failed to load OIDC discovery: ${error.message}`, {
92
+ status: 502,
93
+ code: "oidc_discovery_failed"
94
+ });
95
+ }
96
+ return new PmtHouseError("Failed to load OIDC discovery", {
97
+ status: 502,
98
+ code: "oidc_discovery_failed"
99
+ });
100
+ }
101
+ function mapOAuthError(error) {
102
+ if (error instanceof PmtHouseError) {
103
+ return error;
104
+ }
105
+ if (error instanceof oauth4webapi.ResponseBodyError) {
106
+ const cause = error.cause;
107
+ const description = typeof error.error_description === "string" ? error.error_description : error.message;
108
+ const details = { ...cause };
109
+ if (typeof cause.error_uri === "string") {
110
+ details.error_uri = cause.error_uri;
111
+ }
112
+ return new PmtHouseError(description, {
113
+ status: error.status,
114
+ code: error.error,
115
+ details
116
+ });
117
+ }
118
+ if (error instanceof oauth4webapi.OperationProcessingError) {
119
+ return new PmtHouseError(error.message, {
120
+ status: 502,
121
+ code: error.code ?? "oauth_processing_error",
122
+ details: { cause: error.cause }
123
+ });
124
+ }
125
+ if (error instanceof Error) {
126
+ return new PmtHouseError(error.message, {
127
+ status: 500,
128
+ code: "unexpected_error"
129
+ });
130
+ }
131
+ return new PmtHouseError("Unexpected error", {
132
+ status: 500,
133
+ code: "unexpected_error"
134
+ });
135
+ }
136
+
137
+ // src/verify.ts
138
+ async function verifyJwt(token, options) {
139
+ const fetchImpl = options.fetch ?? fetch;
140
+ const as = await loadAuthorizationServer(options.issuerUrl, fetchImpl, {
141
+ allowInsecureHttp: options.allowInsecureHttp
142
+ });
143
+ const request = new Request("https://resource.invalid/", {
144
+ headers: {
145
+ Authorization: `Bearer ${token}`
146
+ }
147
+ });
148
+ const httpOpts = {
149
+ [oauth4webapi.customFetch]: fetchImpl
150
+ };
151
+ if (options.allowInsecureHttp) {
152
+ httpOpts[oauth4webapi.allowInsecureRequests] = true;
153
+ }
154
+ try {
155
+ const claims = await oauth4webapi.validateJwtAccessToken(
156
+ as,
157
+ request,
158
+ options.audience,
159
+ httpOpts
160
+ );
161
+ if (options.requiredScopes?.length) {
162
+ const scopeStr = typeof claims.scope === "string" ? claims.scope : "";
163
+ const have = new Set(scopeStr.split(/\s+/).filter(Boolean));
164
+ for (const s of options.requiredScopes) {
165
+ if (!have.has(s)) {
166
+ throw new PmtHouseError(`Missing required scope: ${s}`, {
167
+ status: 403,
168
+ code: "insufficient_scope"
169
+ });
170
+ }
171
+ }
172
+ }
173
+ return claims;
174
+ } catch (e) {
175
+ throw mapOAuthError(e);
176
+ }
177
+ }
178
+
179
+ exports.verifyJwt = verifyJwt;
180
+ //# sourceMappingURL=verify.cjs.map
181
+ //# sourceMappingURL=verify.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts","../src/string-utils.ts","../src/discovery.ts","../src/oauth-map.ts","../src/verify.ts"],"names":["customFetch","allowInsecureRequests","discoveryRequest","processDiscoveryResponse","ResponseBodyError","OperationProcessingError","validateJwtAccessToken"],"mappings":"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","file":"verify.cjs","sourcesContent":["export class PmtHouseError extends Error {\n readonly status: number;\n readonly code: string;\n readonly details?: unknown;\n\n constructor(\n message: string,\n {\n status = 500,\n code = \"pymthouse_error\",\n details,\n }: {\n status?: number;\n code?: string;\n details?: unknown;\n } = {},\n ) {\n super(message);\n this.name = \"PmtHouseError\";\n this.status = status;\n this.code = code;\n this.details = details;\n }\n}\n\nexport function toPmtHouseError(\n error: unknown,\n fallbackMessage: string,\n): PmtHouseError {\n if (error instanceof PmtHouseError) {\n return error;\n }\n\n if (error instanceof Error) {\n return new PmtHouseError(error.message || fallbackMessage, {\n code: \"unexpected_error\",\n status: 500,\n });\n }\n\n return new PmtHouseError(fallbackMessage, {\n code: \"unexpected_error\",\n status: 500,\n });\n}\n","/** Removes trailing `/` without regex (linear time). */\nexport function stripTrailingSlashes(value: string): string {\n let end = value.length;\n while (end > 0 && value.charCodeAt(end - 1) === 47) {\n end--;\n }\n return value.slice(0, end);\n}\n","import {\n allowInsecureRequests,\n customFetch,\n discoveryRequest,\n processDiscoveryResponse,\n type AuthorizationServer,\n} from \"oauth4webapi\";\nimport { PmtHouseError } from \"./errors.js\";\nimport { stripTrailingSlashes } from \"./string-utils.js\";\nimport type { FetchLike, OidcDiscoveryDocument } from \"./types.js\";\n\nexport function authorizationServerToOidcDocument(as: AuthorizationServer): OidcDiscoveryDocument {\n const tokenEndpoint = as.token_endpoint;\n const jwksUri = as.jwks_uri;\n if (!tokenEndpoint || !jwksUri) {\n throw new PmtHouseError(\"OIDC discovery document is missing token_endpoint or jwks_uri\", {\n status: 500,\n code: \"oidc_discovery_invalid\",\n });\n }\n return {\n issuer: as.issuer,\n authorization_endpoint: as.authorization_endpoint ?? \"\",\n token_endpoint: tokenEndpoint,\n jwks_uri: jwksUri,\n userinfo_endpoint: as.userinfo_endpoint,\n device_authorization_endpoint: as.device_authorization_endpoint,\n };\n}\n\nconst CACHE_TTL_MS = 5 * 60 * 1000;\n\ntype CacheEntry = {\n as: AuthorizationServer;\n fetchedAt: number;\n};\n\nconst discoveryCache = new Map<string, CacheEntry>();\n\nfunction normalizedIssuerKey(issuerUrl: string): string {\n return stripTrailingSlashes(issuerUrl);\n}\n\nexport interface LoadAuthorizationServerOptions {\n force?: boolean;\n allowInsecureHttp?: boolean;\n}\n\n/**\n * Loads OIDC discovery metadata via oauth4webapi (RFC 8414 / OIDC Discovery), with a 5-minute cache.\n */\nexport async function loadAuthorizationServer(\n issuerUrl: string,\n fetchImpl: FetchLike,\n options: LoadAuthorizationServerOptions = {},\n): Promise<AuthorizationServer> {\n const key = normalizedIssuerKey(issuerUrl);\n const now = Date.now();\n const cached = discoveryCache.get(key);\n\n if (!options.force && cached && now - cached.fetchedAt < CACHE_TTL_MS) {\n return cached.as;\n }\n\n const issuerIdentifier = new URL(key);\n const discoveryOpts: Parameters<typeof discoveryRequest>[1] = {\n algorithm: \"oidc\",\n [customFetch]: fetchImpl,\n };\n if (options.allowInsecureHttp) {\n discoveryOpts[allowInsecureRequests] = true;\n }\n\n let response: Response;\n try {\n response = await discoveryRequest(issuerIdentifier, discoveryOpts);\n } catch (e) {\n throw mapDiscoveryNetworkError(e);\n }\n\n let as: AuthorizationServer;\n try {\n as = await processDiscoveryResponse(issuerIdentifier, response);\n } catch (e) {\n throw mapOAuthDiscoveryError(e);\n }\n\n discoveryCache.set(key, { as, fetchedAt: now });\n return as;\n}\n\nexport async function fetchDiscoveryDocument(\n issuerUrl: string,\n fetchImpl: FetchLike,\n options: LoadAuthorizationServerOptions = {},\n): Promise<OidcDiscoveryDocument> {\n const as = await loadAuthorizationServer(issuerUrl, fetchImpl, options);\n return authorizationServerToOidcDocument(as);\n}\n\nexport function clearDiscoveryCache(issuerUrl?: string): void {\n if (!issuerUrl) {\n discoveryCache.clear();\n return;\n }\n discoveryCache.delete(normalizedIssuerKey(issuerUrl));\n}\n\nfunction mapOAuthDiscoveryError(error: unknown): PmtHouseError {\n if (error instanceof PmtHouseError) {\n return error;\n }\n if (error instanceof Error) {\n return new PmtHouseError(error.message, {\n status: 500,\n code: \"oidc_discovery_invalid\",\n details: { cause: error.cause },\n });\n }\n return new PmtHouseError(\"OIDC discovery failed\", {\n status: 500,\n code: \"oidc_discovery_invalid\",\n });\n}\n\nfunction mapDiscoveryNetworkError(error: unknown): PmtHouseError {\n if (error instanceof PmtHouseError) {\n return error;\n }\n if (error instanceof Error) {\n return new PmtHouseError(`Failed to load OIDC discovery: ${error.message}`, {\n status: 502,\n code: \"oidc_discovery_failed\",\n });\n }\n return new PmtHouseError(\"Failed to load OIDC discovery\", {\n status: 502,\n code: \"oidc_discovery_failed\",\n });\n}\n","import { type Client, OperationProcessingError, ResponseBodyError } from \"oauth4webapi\";\nimport { PmtHouseError } from \"./errors.js\";\nimport type { ClientCredentialsTokenResponse, TokenExchangeResponse } from \"./types.js\";\n\nconst ACCEPTED_ISSUED_TOKEN_TYPES = new Set([\n \"urn:ietf:params:oauth:token-type:access_token\",\n \"urn:pmth:token-type:remote-signer-session\",\n]);\n\nexport function mapOAuthError(error: unknown): PmtHouseError {\n if (error instanceof PmtHouseError) {\n return error;\n }\n\n if (error instanceof ResponseBodyError) {\n const cause = error.cause as Record<string, unknown>;\n const description =\n typeof error.error_description === \"string\"\n ? error.error_description\n : error.message;\n const details: Record<string, unknown> = { ...cause };\n if (typeof cause.error_uri === \"string\") {\n details.error_uri = cause.error_uri;\n }\n return new PmtHouseError(description, {\n status: error.status,\n code: error.error,\n details,\n });\n }\n\n if (error instanceof OperationProcessingError) {\n return new PmtHouseError(error.message, {\n status: 502,\n code: error.code ?? \"oauth_processing_error\",\n details: { cause: error.cause },\n });\n }\n\n if (error instanceof Error) {\n return new PmtHouseError(error.message, {\n status: 500,\n code: \"unexpected_error\",\n });\n }\n\n return new PmtHouseError(\"Unexpected error\", {\n status: 500,\n code: \"unexpected_error\",\n });\n}\n\nexport function tokenEndpointResponseToExchange(\n tr: import(\"oauth4webapi\").TokenEndpointResponse,\n): TokenExchangeResponse {\n const issued = tr.issued_token_type;\n if (typeof issued !== \"string\" || !ACCEPTED_ISSUED_TOKEN_TYPES.has(issued)) {\n throw new PmtHouseError(\"Token exchange returned an unexpected issued_token_type\", {\n status: 502,\n code: \"invalid_token_response\",\n details: { issued_token_type: issued },\n });\n }\n\n const tt = tr.token_type;\n if (typeof tt !== \"string\" || tt.toLowerCase() !== \"bearer\") {\n throw new PmtHouseError(\"Token endpoint returned a non-Bearer token_type\", {\n status: 502,\n code: \"invalid_token_response\",\n details: { token_type: tt },\n });\n }\n\n const expiresIn = tr.expires_in;\n if (typeof expiresIn !== \"number\") {\n throw new PmtHouseError(\"Token response missing expires_in\", {\n status: 502,\n code: \"invalid_token_response\",\n });\n }\n\n const scope = typeof tr.scope === \"string\" ? tr.scope : \"\";\n\n return {\n access_token: tr.access_token,\n token_type: \"Bearer\",\n expires_in: expiresIn,\n scope,\n issued_token_type: issued,\n };\n}\n\nexport function tokenEndpointResponseToClientCredentials(\n tr: import(\"oauth4webapi\").TokenEndpointResponse,\n): ClientCredentialsTokenResponse {\n const tt = tr.token_type;\n if (typeof tt !== \"string\" || tt.toLowerCase() !== \"bearer\") {\n throw new PmtHouseError(\"Token endpoint returned a non-Bearer token_type\", {\n status: 502,\n code: \"invalid_token_response\",\n details: { token_type: tt },\n });\n }\n\n return {\n access_token: tr.access_token,\n token_type: \"Bearer\",\n expires_in: tr.expires_in,\n scope: typeof tr.scope === \"string\" ? tr.scope : undefined,\n };\n}\n\nexport function m2mClient(clientId: string): Client {\n return { client_id: clientId };\n}\n","import {\n allowInsecureRequests,\n customFetch,\n validateJwtAccessToken,\n type JWTAccessTokenClaims,\n} from \"oauth4webapi\";\nimport { loadAuthorizationServer } from \"./discovery.js\";\nimport { PmtHouseError } from \"./errors.js\";\nimport { mapOAuthError } from \"./oauth-map.js\";\nimport type { FetchLike } from \"./types.js\";\n\nexport interface VerifyJwtOptions {\n issuerUrl: string;\n /** Expected JWT `aud` (resource identifier). */\n audience: string;\n fetch?: FetchLike;\n allowInsecureHttp?: boolean;\n /** If set, every scope here must appear in the token's `scope` claim (space-separated). */\n requiredScopes?: string[];\n}\n\n/**\n * RFC 9068 / RFC 6750: validate a JWT access token using issuer JWKS via oauth4webapi.\n */\nexport async function verifyJwt(\n token: string,\n options: VerifyJwtOptions,\n): Promise<JWTAccessTokenClaims> {\n const fetchImpl = options.fetch ?? fetch;\n const as = await loadAuthorizationServer(options.issuerUrl, fetchImpl, {\n allowInsecureHttp: options.allowInsecureHttp,\n });\n\n const request = new Request(\"https://resource.invalid/\", {\n headers: {\n Authorization: `Bearer ${token}`,\n },\n });\n\n const httpOpts: Record<symbol, unknown> = {\n [customFetch]: fetchImpl,\n };\n if (options.allowInsecureHttp) {\n httpOpts[allowInsecureRequests] = true;\n }\n\n try {\n const claims = await validateJwtAccessToken(\n as,\n request,\n options.audience,\n httpOpts as import(\"oauth4webapi\").ValidateJWTAccessTokenOptions,\n );\n\n if (options.requiredScopes?.length) {\n const scopeStr = typeof claims.scope === \"string\" ? claims.scope : \"\";\n const have = new Set(scopeStr.split(/\\s+/).filter(Boolean));\n for (const s of options.requiredScopes) {\n if (!have.has(s)) {\n throw new PmtHouseError(`Missing required scope: ${s}`, {\n status: 403,\n code: \"insufficient_scope\",\n });\n }\n }\n }\n\n return claims;\n } catch (e) {\n throw mapOAuthError(e);\n }\n}\n"]}
@@ -0,0 +1,18 @@
1
+ import { JWTAccessTokenClaims } from 'oauth4webapi';
2
+ import { F as FetchLike } from './types-W9PJAspR.cjs';
3
+
4
+ interface VerifyJwtOptions {
5
+ issuerUrl: string;
6
+ /** Expected JWT `aud` (resource identifier). */
7
+ audience: string;
8
+ fetch?: FetchLike;
9
+ allowInsecureHttp?: boolean;
10
+ /** If set, every scope here must appear in the token's `scope` claim (space-separated). */
11
+ requiredScopes?: string[];
12
+ }
13
+ /**
14
+ * RFC 9068 / RFC 6750: validate a JWT access token using issuer JWKS via oauth4webapi.
15
+ */
16
+ declare function verifyJwt(token: string, options: VerifyJwtOptions): Promise<JWTAccessTokenClaims>;
17
+
18
+ export { type VerifyJwtOptions, verifyJwt };
@@ -0,0 +1,18 @@
1
+ import { JWTAccessTokenClaims } from 'oauth4webapi';
2
+ import { F as FetchLike } from './types-W9PJAspR.js';
3
+
4
+ interface VerifyJwtOptions {
5
+ issuerUrl: string;
6
+ /** Expected JWT `aud` (resource identifier). */
7
+ audience: string;
8
+ fetch?: FetchLike;
9
+ allowInsecureHttp?: boolean;
10
+ /** If set, every scope here must appear in the token's `scope` claim (space-separated). */
11
+ requiredScopes?: string[];
12
+ }
13
+ /**
14
+ * RFC 9068 / RFC 6750: validate a JWT access token using issuer JWKS via oauth4webapi.
15
+ */
16
+ declare function verifyJwt(token: string, options: VerifyJwtOptions): Promise<JWTAccessTokenClaims>;
17
+
18
+ export { type VerifyJwtOptions, verifyJwt };