@pymthouse/builder-sdk 0.3.1 → 0.4.1-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/README.md +54 -28
  2. package/dist/{client-BHfjDvIe.d.ts → client-CauCfGa7.d.ts} +1 -1
  3. package/dist/{client-CvhJEhjV.d.cts → client-D1Xz-xlx.d.cts} +1 -1
  4. package/dist/config.cjs +0 -21
  5. package/dist/config.cjs.map +1 -1
  6. package/dist/config.d.cts +1 -5
  7. package/dist/config.d.ts +1 -5
  8. package/dist/config.js +1 -20
  9. package/dist/config.js.map +1 -1
  10. package/dist/device-initiate.cjs.map +1 -1
  11. package/dist/device-initiate.js.map +1 -1
  12. package/dist/device.cjs.map +1 -1
  13. package/dist/device.d.cts +1 -1
  14. package/dist/device.d.ts +1 -1
  15. package/dist/device.js.map +1 -1
  16. package/dist/env.cjs +13 -4
  17. package/dist/env.cjs.map +1 -1
  18. package/dist/env.d.cts +2 -2
  19. package/dist/env.d.ts +2 -2
  20. package/dist/env.js +13 -4
  21. package/dist/env.js.map +1 -1
  22. package/dist/index-BTDKEorK.d.ts +64 -0
  23. package/dist/index-BixH4VIG.d.cts +64 -0
  24. package/dist/index.cjs +13 -4
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.d.cts +29 -5
  27. package/dist/index.d.ts +29 -5
  28. package/dist/index.js +13 -4
  29. package/dist/index.js.map +1 -1
  30. package/dist/{ingest-DoKJTWU9.d.ts → proxy-JrT6raU_.d.cts} +5 -42
  31. package/dist/{ingest-B3Yi8Tb1.d.cts → proxy-U32DFNuj.d.ts} +5 -42
  32. package/dist/signer/server.cjs +799 -895
  33. package/dist/signer/server.cjs.map +1 -1
  34. package/dist/signer/server.d.cts +9 -13
  35. package/dist/signer/server.d.ts +9 -13
  36. package/dist/signer/server.js +799 -893
  37. package/dist/signer/server.js.map +1 -1
  38. package/dist/signer/webhook/adapters/api-key.cjs +78 -0
  39. package/dist/signer/webhook/adapters/api-key.cjs.map +1 -0
  40. package/dist/signer/webhook/adapters/api-key.d.cts +18 -0
  41. package/dist/signer/webhook/adapters/api-key.d.ts +18 -0
  42. package/dist/signer/webhook/adapters/api-key.js +76 -0
  43. package/dist/signer/webhook/adapters/api-key.js.map +1 -0
  44. package/dist/signer/webhook/adapters/composite.cjs +60 -0
  45. package/dist/signer/webhook/adapters/composite.cjs.map +1 -0
  46. package/dist/signer/webhook/adapters/composite.d.cts +5 -0
  47. package/dist/signer/webhook/adapters/composite.d.ts +5 -0
  48. package/dist/signer/webhook/adapters/composite.js +58 -0
  49. package/dist/signer/webhook/adapters/composite.js.map +1 -0
  50. package/dist/signer/webhook/adapters/oauth1.cjs +18 -0
  51. package/dist/signer/webhook/adapters/oauth1.cjs.map +1 -0
  52. package/dist/signer/webhook/adapters/oauth1.d.cts +19 -0
  53. package/dist/signer/webhook/adapters/oauth1.d.ts +19 -0
  54. package/dist/signer/webhook/adapters/oauth1.js +16 -0
  55. package/dist/signer/webhook/adapters/oauth1.js.map +1 -0
  56. package/dist/signer/webhook/adapters/oidc.cjs +522 -0
  57. package/dist/signer/webhook/adapters/oidc.cjs.map +1 -0
  58. package/dist/signer/webhook/adapters/oidc.d.cts +4 -0
  59. package/dist/signer/webhook/adapters/oidc.d.ts +4 -0
  60. package/dist/signer/webhook/adapters/oidc.js +515 -0
  61. package/dist/signer/webhook/adapters/oidc.js.map +1 -0
  62. package/dist/signer/webhook/adapters/trusted-headers.cjs +103 -0
  63. package/dist/signer/webhook/adapters/trusted-headers.cjs.map +1 -0
  64. package/dist/signer/webhook/adapters/trusted-headers.d.cts +18 -0
  65. package/dist/signer/webhook/adapters/trusted-headers.d.ts +18 -0
  66. package/dist/signer/webhook/adapters/trusted-headers.js +99 -0
  67. package/dist/signer/webhook/adapters/trusted-headers.js.map +1 -0
  68. package/dist/signer/webhook.cjs +747 -0
  69. package/dist/signer/webhook.cjs.map +1 -0
  70. package/dist/signer/webhook.d.cts +26 -0
  71. package/dist/signer/webhook.d.ts +26 -0
  72. package/dist/signer/webhook.js +721 -0
  73. package/dist/signer/webhook.js.map +1 -0
  74. package/dist/tokens.d.cts +1 -1
  75. package/dist/tokens.d.ts +1 -1
  76. package/dist/{types-_R1AwEZp.d.cts → types-BORaHW_x.d.cts} +5 -5
  77. package/dist/{types-_R1AwEZp.d.ts → types-BORaHW_x.d.ts} +5 -5
  78. package/dist/verifier-B-WFDMz6.d.cts +48 -0
  79. package/dist/verifier-B-WFDMz6.d.ts +48 -0
  80. package/dist/verify.cjs.map +1 -1
  81. package/dist/verify.d.cts +1 -1
  82. package/dist/verify.d.ts +1 -1
  83. package/dist/verify.js.map +1 -1
  84. package/package.json +30 -30
  85. package/dist/gateway/client/index.cjs +0 -492
  86. package/dist/gateway/client/index.cjs.map +0 -1
  87. package/dist/gateway/client/index.d.cts +0 -63
  88. package/dist/gateway/client/index.d.ts +0 -63
  89. package/dist/gateway/client/index.js +0 -489
  90. package/dist/gateway/client/index.js.map +0 -1
  91. package/dist/gateway/index.cjs +0 -16
  92. package/dist/gateway/index.cjs.map +0 -1
  93. package/dist/gateway/index.d.cts +0 -52
  94. package/dist/gateway/index.d.ts +0 -52
  95. package/dist/gateway/index.js +0 -10
  96. package/dist/gateway/index.js.map +0 -1
  97. package/dist/gateway/server/index.cjs +0 -1248
  98. package/dist/gateway/server/index.cjs.map +0 -1
  99. package/dist/gateway/server/index.d.cts +0 -31
  100. package/dist/gateway/server/index.d.ts +0 -31
  101. package/dist/gateway/server/index.js +0 -1233
  102. package/dist/gateway/server/index.js.map +0 -1
  103. package/gateway/proto/lp_rpc.proto +0 -542
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/signer/webhook/types.ts","../../src/errors.ts","../../src/signer/webhook/identity.ts","../../src/signer/webhook/payload.ts","../../src/signer/webhook/authorize.ts","../../src/signer/webhook/bearer.ts","../../src/signer/webhook/adapters/api-key/verifier.ts","../../src/signer/webhook/adapters/composite/verifier.ts","../../src/string-utils.ts","../../src/discovery.ts","../../src/oauth-map.ts","../../src/verify.ts","../../src/signer/webhook/adapters/oidc/verifier.ts","../../src/signer/webhook/adapters/oauth1/verifier.ts","../../src/signer/webhook/adapters/trusted-headers/verifier.ts","../../src/signer/webhook/adapters/oidc/config.ts","../../src/signer/webhook/server.ts","../../src/signer/webhook/index.ts"],"names":["customFetch","allowInsecureRequests"],"mappings":"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","file":"webhook.js","sourcesContent":["/** Wire protocol between go-livepeer remote signer and identity webhook providers. */\n\nexport type UsageIdentity = {\n issuer: string;\n client_id: string;\n usage_subject: string;\n usage_subject_type: string;\n};\n\nexport function isValidUsageIdentity(identity: UsageIdentity): boolean {\n return Boolean(\n identity.issuer.trim() &&\n identity.client_id.trim() &&\n identity.usage_subject.trim() &&\n identity.usage_subject_type.trim(),\n );\n}\n\nexport type PaymentWebhookRequest = {\n /** Legacy; prefer Authorization in `headers` (go-livepeer PR #3897 wire format). */\n authorization?: string;\n headers?: Record<string, string[]>;\n state?: unknown;\n /** GPU tier forwarded by go-livepeer when available (e.g. `4090`, `h100`). */\n gpu?: string;\n};\n\nexport type PaymentWebhookResponse = {\n status?: number;\n reason?: string;\n expiry?: number;\n /** Opaque identity binding persisted by go-livepeer RemotePaymentState. */\n auth_id?: string;\n identity?: UsageIdentity;\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","import { PmtHouseError } from \"../../errors.js\";\nimport type { UsageIdentity } from \"./types.js\";\n\nexport type WebhookIdentityClaimMapping = {\n claimClientId: string;\n claimUsageSubject: string;\n usageSubjectType: string;\n};\n\nexport const DEFAULT_WEBHOOK_IDENTITY_CLAIMS: WebhookIdentityClaimMapping = {\n claimClientId: \"client_id\",\n claimUsageSubject: \"sub\",\n usageSubjectType: \"external_user_id\",\n};\n\nfunction readClaim(payload: Record<string, unknown>, key: string): string {\n const value = payload[key];\n if (typeof value === \"string\" && value.trim()) {\n return value.trim();\n }\n if (\n typeof value === \"number\" ||\n typeof value === \"boolean\" ||\n typeof value === \"bigint\"\n ) {\n return value.toString().trim();\n }\n return \"\";\n}\n\nexport function identityFromWebhookClaims(\n claims: Record<string, unknown>,\n mapping: Partial<WebhookIdentityClaimMapping> = {},\n): UsageIdentity {\n const claimClientId =\n mapping.claimClientId ?? DEFAULT_WEBHOOK_IDENTITY_CLAIMS.claimClientId;\n const claimUsageSubject =\n mapping.claimUsageSubject ?? DEFAULT_WEBHOOK_IDENTITY_CLAIMS.claimUsageSubject;\n const defaultUsageSubjectType =\n mapping.usageSubjectType ?? DEFAULT_WEBHOOK_IDENTITY_CLAIMS.usageSubjectType;\n\n let clientId = readClaim(claims, claimClientId);\n if (!clientId) {\n clientId = readClaim(claims, \"azp\");\n }\n\n const usageSubject = readClaim(claims, claimUsageSubject);\n let usageSubjectType = defaultUsageSubjectType;\n const claimUsageSubjectType = readClaim(claims, \"usage_subject_type\");\n if (claimUsageSubjectType) {\n usageSubjectType = claimUsageSubjectType;\n }\n\n const identity: UsageIdentity = {\n issuer: readClaim(claims, \"iss\"),\n client_id: clientId,\n usage_subject: usageSubject,\n usage_subject_type: usageSubjectType,\n };\n\n if (!identity.issuer || !identity.client_id || !identity.usage_subject) {\n throw new PmtHouseError(\"JWT missing required identity claims\", {\n status: 403,\n code: \"invalid_identity\",\n });\n }\n\n return identity;\n}\n\nexport function claimExpirySeconds(\n claims: Record<string, unknown>,\n fallbackTtlSeconds = 300,\n): number {\n const exp = claims.exp;\n if (typeof exp === \"number\" && Number.isFinite(exp)) {\n return Math.trunc(exp);\n }\n if (typeof exp === \"string\" && exp.trim()) {\n const parsed = Number(exp);\n if (Number.isFinite(parsed)) {\n return Math.trunc(parsed);\n }\n }\n return Math.trunc(Date.now() / 1000) + fallbackTtlSeconds;\n}\n","import type { PaymentWebhookRequest } from \"./types.js\";\n\nexport function headerValueFromWebhookPayload(\n headers: Record<string, string[]> | undefined,\n name: string,\n): string {\n if (!headers) {\n return \"\";\n }\n const target = name.toLowerCase();\n for (const [key, values] of Object.entries(headers)) {\n if (key.toLowerCase() !== target) {\n continue;\n }\n if (!Array.isArray(values)) {\n continue;\n }\n for (const value of values) {\n if (typeof value === \"string\" && value.trim()) {\n return value.trim();\n }\n }\n }\n return \"\";\n}\n\n/** End-user Authorization from go-livepeer webhook body (headers map or legacy field). */\nexport function authorizationFromWebhookPayload(\n payload: PaymentWebhookRequest,\n): string {\n const fromHeaders = headerValueFromWebhookPayload(\n payload.headers,\n \"Authorization\",\n );\n if (fromHeaders) {\n return fromHeaders;\n }\n return payload.authorization?.trim() ?? \"\";\n}\n","import { timingSafeEqual } from \"node:crypto\";\nimport { PmtHouseError } from \"../../errors.js\";\nimport { authorizationFromWebhookPayload } from \"./payload.js\";\nimport type { PaymentWebhookRequest, PaymentWebhookResponse } from \"./types.js\";\nimport type { EndUserAuthVerifier, VerifiedEndUserAuth } from \"./verifier.js\";\n\nexport type {\n EndUserAuthVerifier,\n EndUserAuthVerifyContext,\n VerifiedEndUserAuth,\n WebhookAdminRoute,\n} from \"./verifier.js\";\n\nexport type WebhookAuthorizeContext = {\n authorization: string;\n payload: PaymentWebhookRequest;\n request: Request;\n verified: VerifiedEndUserAuth;\n identity: VerifiedEndUserAuth[\"identity\"];\n};\n\nexport type RemoteSignerWebhookConfig = {\n webhookSecret: string;\n endUserAuth: EndUserAuthVerifier;\n afterVerify?: (context: WebhookAuthorizeContext) => Promise<void>;\n};\n\nfunction authIdFromIdentity(identity: VerifiedEndUserAuth[\"identity\"]): string {\n return `${identity.client_id}:${identity.usage_subject}`;\n}\n\nfunction timingSafeEqualStrings(a: string, b: string): boolean {\n const aBuffer = Buffer.from(a);\n const bBuffer = Buffer.from(b);\n if (aBuffer.length !== bBuffer.length) {\n return false;\n }\n return timingSafeEqual(aBuffer, bBuffer);\n}\n\nexport function authenticateWebhookCaller(request: Request, secret: string): boolean {\n if (!secret.trim()) {\n return false;\n }\n const trimmed = secret.trim();\n const auth = request.headers.get(\"authorization\")?.trim() ?? \"\";\n if (auth === `Bearer ${trimmed}`) {\n return true;\n }\n const apiKey = request.headers.get(\"x-api-key\")?.trim() ?? \"\";\n if (apiKey && timingSafeEqualStrings(apiKey, trimmed)) {\n return true;\n }\n const legacySecret = request.headers.get(\"x-webhook-secret\")?.trim() ?? \"\";\n if (legacySecret && timingSafeEqualStrings(legacySecret, trimmed)) {\n return true;\n }\n return false;\n}\n\nfunction paymentWebhookJson(\n httpStatus: number,\n body: PaymentWebhookResponse,\n): Response {\n return new Response(JSON.stringify(body), {\n status: httpStatus,\n headers: { \"Content-Type\": \"application/json\" },\n });\n}\n\nfunction rejectStatusFromError(err: unknown): { status: number; reason: string } {\n if (err instanceof PmtHouseError) {\n return {\n status: err.status >= 400 && err.status < 600 ? err.status : 403,\n reason: err.message,\n };\n }\n const reason = err instanceof Error ? err.message : \"authorization rejected\";\n return { status: 403, reason };\n}\n\nexport async function handleRemoteSignerAuthorize(\n request: Request,\n config: RemoteSignerWebhookConfig,\n): Promise<Response> {\n if (!authenticateWebhookCaller(request, config.webhookSecret)) {\n return paymentWebhookJson(401, {\n status: 401,\n reason: \"unauthorized webhook caller\",\n });\n }\n\n let payload: PaymentWebhookRequest;\n try {\n payload = (await request.json()) as PaymentWebhookRequest;\n } catch {\n return paymentWebhookJson(400, {\n status: 400,\n reason: \"invalid request json\",\n });\n }\n\n const authorization = authorizationFromWebhookPayload(payload) ?? \"\";\n\n try {\n const verified = await config.endUserAuth.verify({\n authorization,\n payload,\n request,\n });\n\n if (config.afterVerify) {\n await config.afterVerify({\n authorization,\n payload,\n request,\n verified,\n identity: verified.identity,\n });\n }\n\n return paymentWebhookJson(200, {\n status: 200,\n expiry: verified.expiry,\n auth_id: authIdFromIdentity(verified.identity),\n identity: verified.identity,\n });\n } catch (err) {\n const { status, reason } = rejectStatusFromError(err);\n return paymentWebhookJson(200, {\n status,\n reason,\n });\n }\n}\n\nexport function createRemoteSignerAuthorizeHandler(\n config: RemoteSignerWebhookConfig,\n): (request: Request) => Promise<Response> {\n return (request) => handleRemoteSignerAuthorize(request, config);\n}\n\nexport async function routeRemoteSignerWebhookRequest(\n request: Request,\n config: RemoteSignerWebhookConfig,\n): Promise<Response | null> {\n const url = new URL(request.url);\n if (request.method === \"POST\" && url.pathname === \"/authorize\") {\n return handleRemoteSignerAuthorize(request, config);\n }\n\n const adminRoutes = config.endUserAuth.adminRoutes ?? [];\n for (const route of adminRoutes) {\n if (request.method === route.method && url.pathname === route.pathname) {\n return route.handler(request);\n }\n }\n\n return null;\n}\n","export function bearerTokenFromAuthorization(authorization: string): string {\n const trimmed = authorization.trim();\n if (!trimmed) {\n throw new Error(\"missing authorization\");\n }\n const prefix = \"Bearer \";\n if (!trimmed.startsWith(prefix)) {\n throw new Error(\"authorization must be Bearer token\");\n }\n const token = trimmed.slice(prefix.length).trim();\n if (!token) {\n throw new Error(\"empty bearer token\");\n }\n return token;\n}\n","import { PmtHouseError } from \"../../../../errors.js\";\nimport { bearerTokenFromAuthorization } from \"../../bearer.js\";\nimport type { UsageIdentity } from \"../../types.js\";\nimport type { EndUserAuthVerifier } from \"../../verifier.js\";\n\nexport type ApiKeyResolveResult = {\n userId: string;\n clientId?: string;\n usageSubjectType?: string;\n};\n\nexport type ApiKeyEndUserVerifierConfig = {\n issuer: string;\n resolveApiKey: (apiKey: string) => Promise<ApiKeyResolveResult | null>;\n expiryTtlSeconds?: number;\n apiKeyPrefix?: string;\n defaultClientId?: string;\n defaultUsageSubjectType?: string;\n};\n\nexport function createApiKeyEndUserVerifier(\n config: ApiKeyEndUserVerifierConfig,\n): EndUserAuthVerifier {\n const prefix = config.apiKeyPrefix ?? \"sk_\";\n const defaultClientId = config.defaultClientId ?? \"daydream-scope\";\n const defaultUsageSubjectType =\n config.defaultUsageSubjectType ?? \"clerk_user_id\";\n const ttl = config.expiryTtlSeconds ?? 60;\n\n return {\n kind: \"custom\",\n verify: async ({ authorization }) => {\n const token = bearerTokenFromAuthorization(authorization);\n if (prefix && !token.startsWith(prefix)) {\n throw new PmtHouseError(\"invalid api key\", {\n status: 401,\n code: \"invalid_api_key\",\n });\n }\n\n const resolved = await config.resolveApiKey(token);\n if (!resolved?.userId) {\n throw new PmtHouseError(\"invalid api key\", {\n status: 401,\n code: \"invalid_api_key\",\n });\n }\n\n const identity: UsageIdentity = {\n issuer: config.issuer,\n client_id: resolved.clientId ?? defaultClientId,\n usage_subject: resolved.userId,\n usage_subject_type:\n resolved.usageSubjectType ?? defaultUsageSubjectType,\n };\n\n return {\n identity,\n expiry: Math.trunc(Date.now() / 1000) + ttl,\n raw: resolved,\n };\n },\n };\n}\n","import { PmtHouseError } from \"../../../../errors.js\";\nimport type { EndUserAuthVerifier } from \"../../verifier.js\";\n\nexport function createFirstMatchEndUserVerifier(\n verifiers: EndUserAuthVerifier[],\n): EndUserAuthVerifier {\n if (verifiers.length === 0) {\n throw new PmtHouseError(\"at least one verifier is required\", {\n status: 500,\n code: \"invalid_verifier_config\",\n });\n }\n\n return {\n kind: \"custom\",\n verify: async (context) => {\n let lastError: unknown;\n for (const verifier of verifiers) {\n try {\n return await verifier.verify(context);\n } catch (err) {\n lastError = err;\n }\n }\n\n if (lastError instanceof PmtHouseError) {\n throw lastError;\n }\n if (lastError instanceof Error) {\n throw new PmtHouseError(lastError.message, {\n status: 401,\n code: \"invalid_credentials\",\n });\n }\n throw new PmtHouseError(\"invalid credentials\", {\n status: 401,\n code: \"invalid_credentials\",\n });\n },\n adminRoutes: verifiers.flatMap((verifier) => verifier.adminRoutes ?? []),\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.codePointAt(end - 1) ?? 0) === 47) {\n end--;\n }\n return value.slice(0, end);\n}\n\nfunction endsWithIgnoreCase(value: string, suffix: string): boolean {\n if (suffix.length > value.length) {\n return false;\n }\n const start = value.length - suffix.length;\n for (let i = 0; i < suffix.length; i++) {\n const a = value.codePointAt(start + i) ?? 0;\n const b = suffix.codePointAt(i) ?? 0;\n if (a !== b && (a | 32) !== (b | 32)) {\n return false;\n }\n }\n return true;\n}\n\nfunction stripSuffixIgnoreCase(value: string, suffix: string): string {\n return endsWithIgnoreCase(value, suffix)\n ? value.slice(0, value.length - suffix.length)\n : value;\n}\n\n/** Issuer URL (`…/oidc`) → Builder API base (`…/api/v1`). Linear-time; no regex. */\nexport function stripOidcPathSuffix(issuerUrl: string): string {\n let base = stripTrailingSlashes(issuerUrl.trim());\n base = stripSuffixIgnoreCase(base, \"/oidc\");\n return stripTrailingSlashes(base);\n}\n\n/** Issuer URL (`…/api/v1/oidc`) → host origin for signer/API-key routes. Linear-time; no regex. */\nexport function stripIssuerOriginFromOidcUrl(issuerUrl: string): string {\n let base = stripTrailingSlashes(issuerUrl.trim());\n base = stripSuffixIgnoreCase(base, \"/api/v1/oidc\");\n base = stripSuffixIgnoreCase(base, \"/oidc\");\n return stripTrailingSlashes(base);\n}\n\n/** Parse and validate an http(s) facade origin (no path). */\nexport function parseHttpOrigin(raw: string | undefined, fallback: string): string {\n const trimmed = (raw ?? fallback).trim();\n let parsed: URL;\n try {\n parsed = new URL(trimmed);\n } catch {\n throw new TypeError(\"Origin must be a valid http(s) URL\");\n }\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n throw new TypeError(\"Origin must use http or https\");\n }\n return parsed.origin;\n}\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","import { loadAuthorizationServer } from \"../../../../discovery.js\";\nimport { verifyJwt } from \"../../../../verify.js\";\nimport type { FetchLike } from \"../../../../types.js\";\nimport { authenticateWebhookCaller } from \"../../authorize.js\";\nimport {\n claimExpirySeconds,\n DEFAULT_WEBHOOK_IDENTITY_CLAIMS,\n identityFromWebhookClaims,\n type WebhookIdentityClaimMapping,\n} from \"../../identity.js\";\nimport { bearerTokenFromAuthorization } from \"../../bearer.js\";\nimport type { EndUserAuthVerifier } from \"../../verifier.js\";\n\nexport type OidcEndUserAuthConfig = {\n jwtIssuer: string;\n jwtAudience: string;\n claimMapping?: Partial<WebhookIdentityClaimMapping>;\n allowInsecureHttp?: boolean;\n fetch?: FetchLike;\n requiredScopes?: string[];\n webhookSecret: string;\n};\n\nexport async function handleRemoteSignerRefreshJwks(\n request: Request,\n config: Pick<\n OidcEndUserAuthConfig,\n \"webhookSecret\" | \"jwtIssuer\" | \"fetch\" | \"allowInsecureHttp\"\n >,\n): Promise<Response> {\n if (!authenticateWebhookCaller(request, config.webhookSecret)) {\n return new Response(\"unauthorized\", { status: 401 });\n }\n\n try {\n await loadAuthorizationServer(config.jwtIssuer, config.fetch ?? fetch, {\n force: true,\n allowInsecureHttp: config.allowInsecureHttp,\n });\n return new Response(JSON.stringify({ status: \"ok\" }), {\n status: 200,\n headers: { \"Content-Type\": \"application/json\" },\n });\n } catch (err) {\n const message = err instanceof Error ? err.message : \"jwks refresh failed\";\n return new Response(message, { status: 500 });\n }\n}\n\nexport function createOidcEndUserVerifier(\n config: OidcEndUserAuthConfig,\n): EndUserAuthVerifier {\n const claimMapping = {\n ...DEFAULT_WEBHOOK_IDENTITY_CLAIMS,\n ...config.claimMapping,\n };\n\n return {\n kind: \"oidc\",\n verify: async ({ authorization }) => {\n const token = bearerTokenFromAuthorization(authorization);\n const audience = config.jwtAudience.trim();\n if (!audience) {\n throw new Error(\"jwt audience is required for webhook verification\");\n }\n\n const claims = await verifyJwt(token, {\n issuerUrl: config.jwtIssuer,\n audience,\n fetch: config.fetch,\n allowInsecureHttp: config.allowInsecureHttp,\n requiredScopes: config.requiredScopes,\n });\n\n const claimsRecord = claims as unknown as Record<string, unknown>;\n const identity = identityFromWebhookClaims(claimsRecord, claimMapping);\n\n return {\n identity,\n expiry: claimExpirySeconds(claimsRecord),\n raw: claimsRecord,\n };\n },\n adminRoutes: [\n {\n method: \"POST\",\n pathname: \"/admin/refresh-jwks\",\n handler: (request) => handleRemoteSignerRefreshJwks(request, config),\n },\n ],\n };\n}\n","import type { UsageIdentity } from \"../../types.js\";\nimport type { EndUserAuthVerifier } from \"../../verifier.js\";\n\nexport type OAuth1EndUserAuthConfig = {\n consumerKey: string;\n consumerSecret: string;\n /** Resolve oauth_token → UsageIdentity (platform-owned store). */\n resolveIdentity: (oauthToken: string) => Promise<UsageIdentity>;\n tokenSecretLookup?: (oauthToken: string) => Promise<string | undefined>;\n};\n\n/**\n * OAuth 1.0a end-user auth verifier (stub).\n *\n * A full implementation will parse `Authorization: OAuth …` from\n * `context.authorization`, validate the signature using `context.payload.headers`\n * and the request URL, then call `resolveIdentity`.\n */\nexport function createOAuth1EndUserVerifier(\n config: OAuth1EndUserAuthConfig,\n): EndUserAuthVerifier {\n return {\n kind: \"oauth1\",\n verify: async () => {\n if (!config.consumerKey.trim() || !config.consumerSecret.trim()) {\n throw new Error(\"OAuth 1.0 consumer credentials are required\");\n }\n throw new Error(\"OAuth 1.0 webhook verification is not implemented yet\");\n },\n };\n}\n","import { PmtHouseError } from \"../../../../errors.js\";\nimport { headerValueFromWebhookPayload } from \"../../payload.js\";\nimport type { EndUserAuthVerifier } from \"../../verifier.js\";\nimport type { UsageIdentity } from \"../../types.js\";\n\nexport const DEFAULT_DMZ_TRUSTED_HEADERS = {\n issuer: \"X-Livepeer-Usage-Issuer\",\n clientId: \"X-Livepeer-Client-ID\",\n usageSubject: \"X-Livepeer-Usage-Subject\",\n usageSubjectType: \"X-Livepeer-Usage-Subject-Type\",\n} as const;\n\nexport type TrustedHeadersEndUserAuthConfig = {\n expectedIssuer: string;\n headerNames?: Partial<typeof DEFAULT_DMZ_TRUSTED_HEADERS>;\n /** Auth cache TTL returned to go-livepeer when headers are trusted. */\n expiryTtlSeconds?: number;\n};\n\nfunction normalizeIssuer(value: string): string {\n let end = value.length;\n while (end > 0 && value[end - 1] === \"/\") {\n end -= 1;\n }\n return value.slice(0, end);\n}\n\nexport function identityFromTrustedHeaders(\n headers: Record<string, string[]> | undefined,\n config: TrustedHeadersEndUserAuthConfig,\n): UsageIdentity {\n const names = {\n ...DEFAULT_DMZ_TRUSTED_HEADERS,\n ...config.headerNames,\n };\n const issuer = headerValueFromWebhookPayload(headers, names.issuer);\n const clientId = headerValueFromWebhookPayload(headers, names.clientId);\n const usageSubject = headerValueFromWebhookPayload(headers, names.usageSubject);\n const usageSubjectType =\n headerValueFromWebhookPayload(headers, names.usageSubjectType) ||\n \"external_user_id\";\n\n if (!issuer || !clientId || !usageSubject) {\n throw new PmtHouseError(\"missing trusted usage identity headers\", {\n status: 403,\n code: \"invalid_identity\",\n });\n }\n\n if (\n normalizeIssuer(issuer) !== normalizeIssuer(config.expectedIssuer.trim())\n ) {\n throw new PmtHouseError(\"trusted usage issuer mismatch\", {\n status: 403,\n code: \"invalid_identity\",\n });\n }\n\n return {\n issuer,\n client_id: clientId,\n usage_subject: usageSubject,\n usage_subject_type: usageSubjectType,\n };\n}\n\nexport function createTrustedHeadersEndUserVerifier(\n config: TrustedHeadersEndUserAuthConfig,\n): EndUserAuthVerifier {\n const expiryTtlSeconds = config.expiryTtlSeconds ?? 300;\n\n return {\n kind: \"trusted_headers\",\n verify: async ({ payload }) => {\n const identity = identityFromTrustedHeaders(payload.headers, config);\n return {\n identity,\n expiry: Math.trunc(Date.now() / 1000) + expiryTtlSeconds,\n };\n },\n };\n}\n","import type {\n RemoteSignerWebhookConfig,\n WebhookAuthorizeContext,\n} from \"../../authorize.js\";\nimport { createFirstMatchEndUserVerifier } from \"../composite/verifier.js\";\nimport {\n createTrustedHeadersEndUserVerifier,\n type TrustedHeadersEndUserAuthConfig,\n} from \"../trusted-headers/verifier.js\";\nimport {\n createOidcEndUserVerifier,\n type OidcEndUserAuthConfig,\n} from \"./verifier.js\";\n\nfunction envTrim(env: NodeJS.ProcessEnv, key: string): string | undefined {\n const value = env[key]?.trim();\n return value || undefined;\n}\n\nexport type OidcRemoteSignerWebhookConfigInput = OidcEndUserAuthConfig & {\n afterVerify?: (context: WebhookAuthorizeContext) => Promise<void>;\n};\n\nexport type SignerDmzRemoteSignerWebhookConfigInput =\n OidcRemoteSignerWebhookConfigInput & {\n /** When true (default), accept Apache DMZ X-Livepeer-* identity headers. */\n dmzTrustedHeaders?: boolean;\n trustedHeaders?: Omit<TrustedHeadersEndUserAuthConfig, \"expectedIssuer\">;\n };\n\nexport function createOidcRemoteSignerWebhookConfig(\n input: OidcRemoteSignerWebhookConfigInput,\n): RemoteSignerWebhookConfig {\n const { afterVerify, ...oidcConfig } = input;\n return {\n webhookSecret: oidcConfig.webhookSecret,\n endUserAuth: createOidcEndUserVerifier(oidcConfig),\n afterVerify,\n };\n}\n\n/**\n * PymtHouse signer-dmz: Apache validates the end-user JWT (iss/aud = issuer), injects\n * X-Livepeer-* headers, and go-livepeer forwards those headers to this webhook per\n * go-livepeer remote-signer.md. Falls back to Bearer JWT verification when present.\n */\nexport function createSignerDmzRemoteSignerWebhookConfig(\n input: SignerDmzRemoteSignerWebhookConfigInput,\n): RemoteSignerWebhookConfig {\n const {\n afterVerify,\n dmzTrustedHeaders = true,\n trustedHeaders,\n ...oidcConfig\n } = input;\n const oidcVerifier = createOidcEndUserVerifier(oidcConfig);\n const endUserAuth =\n dmzTrustedHeaders === false\n ? oidcVerifier\n : createFirstMatchEndUserVerifier([\n createTrustedHeadersEndUserVerifier({\n expectedIssuer: oidcConfig.jwtIssuer,\n ...trustedHeaders,\n }),\n oidcVerifier,\n ]);\n\n return {\n webhookSecret: oidcConfig.webhookSecret,\n endUserAuth,\n afterVerify,\n };\n}\n\nexport function readOidcRemoteSignerWebhookConfigFromEnv(\n env: NodeJS.ProcessEnv = process.env,\n): RemoteSignerWebhookConfig {\n const webhookSecret = envTrim(env, \"WEBHOOK_SECRET\");\n const jwtIssuer = envTrim(env, \"JWT_ISSUER\");\n const jwtAudience = envTrim(env, \"JWT_AUDIENCE\") ?? jwtIssuer;\n\n if (!webhookSecret) {\n throw new Error(\"WEBHOOK_SECRET is required\");\n }\n if (!jwtIssuer) {\n throw new Error(\"JWT_ISSUER is required\");\n }\n if (!jwtAudience) {\n throw new Error(\"JWT_AUDIENCE is required\");\n }\n\n return createSignerDmzRemoteSignerWebhookConfig({\n webhookSecret,\n jwtIssuer,\n jwtAudience,\n claimMapping: {\n claimClientId: envTrim(env, \"CLAIM_CLIENT_ID\") ?? \"client_id\",\n claimUsageSubject: envTrim(env, \"CLAIM_USAGE_SUBJECT\") ?? \"sub\",\n usageSubjectType: envTrim(env, \"USAGE_SUBJECT_TYPE\") ?? \"external_user_id\",\n },\n allowInsecureHttp: envTrim(env, \"ALLOW_INSECURE_HTTP\") === \"1\",\n });\n}\n\n/** @deprecated Use readOidcRemoteSignerWebhookConfigFromEnv */\nexport const readRemoteSignerWebhookConfigFromEnv =\n readOidcRemoteSignerWebhookConfigFromEnv;\n","import { createServer, type Server } from \"node:http\";\nimport { readOidcRemoteSignerWebhookConfigFromEnv } from \"./adapters/oidc/config.js\";\nimport { routeRemoteSignerWebhookRequest, type RemoteSignerWebhookConfig } from \"./authorize.js\";\n\nexport type RemoteSignerWebhookServerOptions = {\n config?: RemoteSignerWebhookConfig;\n addr?: string;\n port?: number;\n};\n\nexport function startRemoteSignerWebhookServer(\n options: RemoteSignerWebhookServerOptions = {},\n): Server {\n const config = options.config ?? readOidcRemoteSignerWebhookConfigFromEnv();\n const port = options.port ?? Number(process.env.PORT ?? 8090);\n const addr = options.addr ?? process.env.ADDR ?? \"0.0.0.0\";\n\n const server = createServer(async (req, res) => {\n try {\n const host = req.headers.host ?? \"localhost\";\n const url = `http://${host}${req.url ?? \"/\"}`;\n const headers = new Headers();\n for (const [name, value] of Object.entries(req.headers)) {\n if (typeof value === \"string\") {\n headers.set(name, value);\n } else if (Array.isArray(value)) {\n for (const item of value) {\n headers.append(name, item);\n }\n }\n }\n\n const chunks: Buffer[] = [];\n for await (const chunk of req) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n const body = Buffer.concat(chunks);\n\n const request = new Request(url, {\n method: req.method,\n headers,\n body: req.method === \"GET\" || req.method === \"HEAD\" ? undefined : body,\n });\n\n const response =\n (await routeRemoteSignerWebhookRequest(request, config)) ??\n new Response(\"not found\", { status: 404 });\n\n res.statusCode = response.status;\n response.headers.forEach((value, name) => {\n res.setHeader(name, value);\n });\n const responseBody = Buffer.from(await response.arrayBuffer());\n res.end(responseBody);\n } catch (err) {\n const message = err instanceof Error ? err.message : \"internal error\";\n res.statusCode = 500;\n res.end(message);\n }\n });\n\n server.listen(port, addr, () => {\n console.log(\n `[builder-sdk] remote signer identity webhook listening on http://${addr}:${port}`,\n );\n console.log(\n `[builder-sdk] end-user auth strategy=${config.endUserAuth.kind}`,\n );\n });\n\n return server;\n}\n","export type {\n PaymentWebhookRequest,\n PaymentWebhookResponse,\n UsageIdentity,\n} from \"./types.js\";\nexport { isValidUsageIdentity } from \"./types.js\";\nexport {\n DEFAULT_WEBHOOK_IDENTITY_CLAIMS,\n claimExpirySeconds,\n identityFromWebhookClaims,\n type WebhookIdentityClaimMapping,\n} from \"./identity.js\";\nexport {\n authenticateWebhookCaller,\n createRemoteSignerAuthorizeHandler,\n handleRemoteSignerAuthorize,\n routeRemoteSignerWebhookRequest,\n type RemoteSignerWebhookConfig,\n type WebhookAuthorizeContext,\n} from \"./authorize.js\";\nexport type {\n EndUserAuthVerifier,\n EndUserAuthVerifyContext,\n VerifiedEndUserAuth,\n WebhookAdminRoute,\n} from \"./verifier.js\";\nexport { bearerTokenFromAuthorization } from \"./bearer.js\";\nexport {\n createApiKeyEndUserVerifier,\n type ApiKeyEndUserVerifierConfig,\n type ApiKeyResolveResult,\n} from \"./adapters/api-key/index.js\";\nexport { createFirstMatchEndUserVerifier } from \"./adapters/composite/index.js\";\nexport {\n createOidcEndUserVerifier,\n handleRemoteSignerRefreshJwks,\n type OidcEndUserAuthConfig,\n} from \"./adapters/oidc/verifier.js\";\nexport {\n createOAuth1EndUserVerifier,\n type OAuth1EndUserAuthConfig,\n} from \"./adapters/oauth1/index.js\";\nexport { authorizationFromWebhookPayload, headerValueFromWebhookPayload } from \"./payload.js\";\nexport {\n createOidcRemoteSignerWebhookConfig,\n createSignerDmzRemoteSignerWebhookConfig,\n readOidcRemoteSignerWebhookConfigFromEnv,\n readRemoteSignerWebhookConfigFromEnv,\n type OidcRemoteSignerWebhookConfigInput,\n type SignerDmzRemoteSignerWebhookConfigInput,\n} from \"./adapters/oidc/config.js\";\nexport {\n createTrustedHeadersEndUserVerifier,\n DEFAULT_DMZ_TRUSTED_HEADERS,\n identityFromTrustedHeaders,\n type TrustedHeadersEndUserAuthConfig,\n} from \"./adapters/trusted-headers/index.js\";\nexport {\n startRemoteSignerWebhookServer,\n type RemoteSignerWebhookServerOptions,\n} from \"./server.js\";\n\nimport type { OidcRemoteSignerWebhookConfigInput } from \"./adapters/oidc/config.js\";\nimport { handleRemoteSignerRefreshJwks as refreshJwks } from \"./adapters/oidc/verifier.js\";\n\n/** @deprecated Use handleRemoteSignerRefreshJwks with OidcEndUserAuthConfig */\nexport function createRemoteSignerRefreshJwksHandler(\n config: OidcRemoteSignerWebhookConfigInput,\n): (request: Request) => Promise<Response> {\n return (request) => refreshJwks(request, config);\n}\n"]}
package/dist/tokens.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { T as TokenExchangeResponse } from './types-_R1AwEZp.cjs';
1
+ import { T as TokenExchangeResponse } from './types-BORaHW_x.cjs';
2
2
 
3
3
  /**
4
4
  * Matches PymtHouse `gateway-token-exchange.ts` opaque signer session TTL (~90 days).
package/dist/tokens.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { T as TokenExchangeResponse } from './types-_R1AwEZp.js';
1
+ import { T as TokenExchangeResponse } from './types-BORaHW_x.js';
2
2
 
3
3
  /**
4
4
  * Matches PymtHouse `gateway-token-exchange.ts` opaque signer session TTL (~90 days).
@@ -211,20 +211,20 @@ interface SignerRoutingConfig {
211
211
  remoteDmzUrl: string | null;
212
212
  jwksUri: string;
213
213
  identityMode: string;
214
- meteringMode: "hosted_ingest" | "platform_ingest";
214
+ meteringMode: "platform_ingest";
215
215
  }
216
216
  interface SignerRoutingResponse {
217
217
  clientId: string;
218
218
  routing: SignerRoutingConfig;
219
219
  patterns: {
220
- hostedFacade: {
220
+ directDmz: {
221
221
  description: string;
222
222
  signerApiUrl: string;
223
+ webhookUrl: string;
223
224
  };
224
- platformDirectDmz: {
225
+ deprecatedHostedFacade: {
225
226
  description: string;
226
- remoteDmzUrl: string | null;
227
- ingestUrl: string;
227
+ signerApiUrl: string | null;
228
228
  };
229
229
  };
230
230
  }
@@ -211,20 +211,20 @@ interface SignerRoutingConfig {
211
211
  remoteDmzUrl: string | null;
212
212
  jwksUri: string;
213
213
  identityMode: string;
214
- meteringMode: "hosted_ingest" | "platform_ingest";
214
+ meteringMode: "platform_ingest";
215
215
  }
216
216
  interface SignerRoutingResponse {
217
217
  clientId: string;
218
218
  routing: SignerRoutingConfig;
219
219
  patterns: {
220
- hostedFacade: {
220
+ directDmz: {
221
221
  description: string;
222
222
  signerApiUrl: string;
223
+ webhookUrl: string;
223
224
  };
224
- platformDirectDmz: {
225
+ deprecatedHostedFacade: {
225
226
  description: string;
226
- remoteDmzUrl: string | null;
227
- ingestUrl: string;
227
+ signerApiUrl: string | null;
228
228
  };
229
229
  };
230
230
  }
@@ -0,0 +1,48 @@
1
+ /** Wire protocol between go-livepeer remote signer and identity webhook providers. */
2
+ type UsageIdentity = {
3
+ issuer: string;
4
+ client_id: string;
5
+ usage_subject: string;
6
+ usage_subject_type: string;
7
+ };
8
+ declare function isValidUsageIdentity(identity: UsageIdentity): boolean;
9
+ type PaymentWebhookRequest = {
10
+ /** Legacy; prefer Authorization in `headers` (go-livepeer PR #3897 wire format). */
11
+ authorization?: string;
12
+ headers?: Record<string, string[]>;
13
+ state?: unknown;
14
+ /** GPU tier forwarded by go-livepeer when available (e.g. `4090`, `h100`). */
15
+ gpu?: string;
16
+ };
17
+ type PaymentWebhookResponse = {
18
+ status?: number;
19
+ reason?: string;
20
+ expiry?: number;
21
+ /** Opaque identity binding persisted by go-livepeer RemotePaymentState. */
22
+ auth_id?: string;
23
+ identity?: UsageIdentity;
24
+ };
25
+
26
+ type EndUserAuthVerifyContext = {
27
+ authorization: string;
28
+ payload: PaymentWebhookRequest;
29
+ request: Request;
30
+ };
31
+ type VerifiedEndUserAuth = {
32
+ identity: UsageIdentity;
33
+ expiry: number;
34
+ /** Provider artifact: JWT claims for OIDC, oauth params for OAuth 1.0, etc. */
35
+ raw?: unknown;
36
+ };
37
+ type WebhookAdminRoute = {
38
+ method: "POST";
39
+ pathname: string;
40
+ handler: (request: Request) => Promise<Response>;
41
+ };
42
+ type EndUserAuthVerifier = {
43
+ kind: "oidc" | "oauth1" | "trusted_headers" | "custom";
44
+ verify: (context: EndUserAuthVerifyContext) => Promise<VerifiedEndUserAuth>;
45
+ adminRoutes?: WebhookAdminRoute[];
46
+ };
47
+
48
+ export { type EndUserAuthVerifier as E, type PaymentWebhookRequest as P, type UsageIdentity as U, type VerifiedEndUserAuth as V, type WebhookAdminRoute as W, type EndUserAuthVerifyContext as a, type PaymentWebhookResponse as b, isValidUsageIdentity as i };
@@ -0,0 +1,48 @@
1
+ /** Wire protocol between go-livepeer remote signer and identity webhook providers. */
2
+ type UsageIdentity = {
3
+ issuer: string;
4
+ client_id: string;
5
+ usage_subject: string;
6
+ usage_subject_type: string;
7
+ };
8
+ declare function isValidUsageIdentity(identity: UsageIdentity): boolean;
9
+ type PaymentWebhookRequest = {
10
+ /** Legacy; prefer Authorization in `headers` (go-livepeer PR #3897 wire format). */
11
+ authorization?: string;
12
+ headers?: Record<string, string[]>;
13
+ state?: unknown;
14
+ /** GPU tier forwarded by go-livepeer when available (e.g. `4090`, `h100`). */
15
+ gpu?: string;
16
+ };
17
+ type PaymentWebhookResponse = {
18
+ status?: number;
19
+ reason?: string;
20
+ expiry?: number;
21
+ /** Opaque identity binding persisted by go-livepeer RemotePaymentState. */
22
+ auth_id?: string;
23
+ identity?: UsageIdentity;
24
+ };
25
+
26
+ type EndUserAuthVerifyContext = {
27
+ authorization: string;
28
+ payload: PaymentWebhookRequest;
29
+ request: Request;
30
+ };
31
+ type VerifiedEndUserAuth = {
32
+ identity: UsageIdentity;
33
+ expiry: number;
34
+ /** Provider artifact: JWT claims for OIDC, oauth params for OAuth 1.0, etc. */
35
+ raw?: unknown;
36
+ };
37
+ type WebhookAdminRoute = {
38
+ method: "POST";
39
+ pathname: string;
40
+ handler: (request: Request) => Promise<Response>;
41
+ };
42
+ type EndUserAuthVerifier = {
43
+ kind: "oidc" | "oauth1" | "trusted_headers" | "custom";
44
+ verify: (context: EndUserAuthVerifyContext) => Promise<VerifiedEndUserAuth>;
45
+ adminRoutes?: WebhookAdminRoute[];
46
+ };
47
+
48
+ export { type EndUserAuthVerifier as E, type PaymentWebhookRequest as P, type UsageIdentity as U, type VerifiedEndUserAuth as V, type WebhookAdminRoute as W, type EndUserAuthVerifyContext as a, type PaymentWebhookResponse as b, isValidUsageIdentity as i };
@@ -1 +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.codePointAt(end - 1) ?? 0) === 47) {\n end--;\n }\n return value.slice(0, end);\n}\n\nfunction endsWithIgnoreCase(value: string, suffix: string): boolean {\n if (suffix.length > value.length) {\n return false;\n }\n const start = value.length - suffix.length;\n for (let i = 0; i < suffix.length; i++) {\n const a = value.codePointAt(start + i) ?? 0;\n const b = suffix.codePointAt(i) ?? 0;\n if (a !== b && (a | 32) !== (b | 32)) {\n return false;\n }\n }\n return true;\n}\n\nfunction stripSuffixIgnoreCase(value: string, suffix: string): string {\n return endsWithIgnoreCase(value, suffix)\n ? value.slice(0, value.length - suffix.length)\n : value;\n}\n\n/** Issuer URL (`…/oidc`) → Builder API base (`…/api/v1`). Linear-time; no regex. */\nexport function stripOidcPathSuffix(issuerUrl: string): string {\n let base = stripTrailingSlashes(issuerUrl.trim());\n base = stripSuffixIgnoreCase(base, \"/oidc\");\n return stripTrailingSlashes(base);\n}\n\n/** Issuer URL (`…/api/v1/oidc`) → host origin for signer/API-key routes. Linear-time; no regex. */\nexport function stripIssuerOriginFromOidcUrl(issuerUrl: string): string {\n let base = stripTrailingSlashes(issuerUrl.trim());\n base = stripSuffixIgnoreCase(base, \"/api/v1/oidc\");\n base = stripSuffixIgnoreCase(base, \"/oidc\");\n return stripTrailingSlashes(base);\n}\n\n/** Validate gateway session ids before embedding in request URLs. */\nexport function isSafePathSegment(value: unknown): value is string {\n if (typeof value !== \"string\" || value.length === 0 || value.length > 128) {\n return false;\n }\n for (let i = 0; i < value.length; i++) {\n const c = value.codePointAt(i) ?? 0;\n const ok =\n (c >= 48 && c <= 57) ||\n (c >= 65 && c <= 90) ||\n (c >= 97 && c <= 122) ||\n c === 95 ||\n c === 45;\n if (!ok) {\n return false;\n }\n }\n return true;\n}\n\n/** Parse and validate an http(s) facade origin (no path). */\nexport function parseHttpOrigin(raw: string | undefined, fallback: string): string {\n const trimmed = (raw ?? fallback).trim();\n let parsed: URL;\n try {\n parsed = new URL(trimmed);\n } catch {\n throw new TypeError(\"Origin must be a valid http(s) URL\");\n }\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n throw new TypeError(\"Origin must use http or https\");\n }\n return parsed.origin;\n}\n\n/** Build a validated DELETE URL for `/api/gateway/sessions/:id`. */\nexport function buildGatewaySessionDeleteUrl(origin: string, sessionId: string): URL {\n if (!isSafePathSegment(sessionId)) {\n throw new TypeError(\"Invalid gateway session id\");\n }\n return new URL(`/api/gateway/sessions/${encodeURIComponent(sessionId)}`, origin);\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"]}
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.codePointAt(end - 1) ?? 0) === 47) {\n end--;\n }\n return value.slice(0, end);\n}\n\nfunction endsWithIgnoreCase(value: string, suffix: string): boolean {\n if (suffix.length > value.length) {\n return false;\n }\n const start = value.length - suffix.length;\n for (let i = 0; i < suffix.length; i++) {\n const a = value.codePointAt(start + i) ?? 0;\n const b = suffix.codePointAt(i) ?? 0;\n if (a !== b && (a | 32) !== (b | 32)) {\n return false;\n }\n }\n return true;\n}\n\nfunction stripSuffixIgnoreCase(value: string, suffix: string): string {\n return endsWithIgnoreCase(value, suffix)\n ? value.slice(0, value.length - suffix.length)\n : value;\n}\n\n/** Issuer URL (`…/oidc`) → Builder API base (`…/api/v1`). Linear-time; no regex. */\nexport function stripOidcPathSuffix(issuerUrl: string): string {\n let base = stripTrailingSlashes(issuerUrl.trim());\n base = stripSuffixIgnoreCase(base, \"/oidc\");\n return stripTrailingSlashes(base);\n}\n\n/** Issuer URL (`…/api/v1/oidc`) → host origin for signer/API-key routes. Linear-time; no regex. */\nexport function stripIssuerOriginFromOidcUrl(issuerUrl: string): string {\n let base = stripTrailingSlashes(issuerUrl.trim());\n base = stripSuffixIgnoreCase(base, \"/api/v1/oidc\");\n base = stripSuffixIgnoreCase(base, \"/oidc\");\n return stripTrailingSlashes(base);\n}\n\n/** Parse and validate an http(s) facade origin (no path). */\nexport function parseHttpOrigin(raw: string | undefined, fallback: string): string {\n const trimmed = (raw ?? fallback).trim();\n let parsed: URL;\n try {\n parsed = new URL(trimmed);\n } catch {\n throw new TypeError(\"Origin must be a valid http(s) URL\");\n }\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n throw new TypeError(\"Origin must use http or https\");\n }\n return parsed.origin;\n}\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"]}
package/dist/verify.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { JWTAccessTokenClaims } from 'oauth4webapi';
2
- import { F as FetchLike } from './types-_R1AwEZp.cjs';
2
+ import { F as FetchLike } from './types-BORaHW_x.cjs';
3
3
 
4
4
  interface VerifyJwtOptions {
5
5
  issuerUrl: string;
package/dist/verify.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { JWTAccessTokenClaims } from 'oauth4webapi';
2
- import { F as FetchLike } from './types-_R1AwEZp.js';
2
+ import { F as FetchLike } from './types-BORaHW_x.js';
3
3
 
4
4
  interface VerifyJwtOptions {
5
5
  issuerUrl: string;
@@ -1 +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"],"mappings":"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","file":"verify.js","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.codePointAt(end - 1) ?? 0) === 47) {\n end--;\n }\n return value.slice(0, end);\n}\n\nfunction endsWithIgnoreCase(value: string, suffix: string): boolean {\n if (suffix.length > value.length) {\n return false;\n }\n const start = value.length - suffix.length;\n for (let i = 0; i < suffix.length; i++) {\n const a = value.codePointAt(start + i) ?? 0;\n const b = suffix.codePointAt(i) ?? 0;\n if (a !== b && (a | 32) !== (b | 32)) {\n return false;\n }\n }\n return true;\n}\n\nfunction stripSuffixIgnoreCase(value: string, suffix: string): string {\n return endsWithIgnoreCase(value, suffix)\n ? value.slice(0, value.length - suffix.length)\n : value;\n}\n\n/** Issuer URL (`…/oidc`) → Builder API base (`…/api/v1`). Linear-time; no regex. */\nexport function stripOidcPathSuffix(issuerUrl: string): string {\n let base = stripTrailingSlashes(issuerUrl.trim());\n base = stripSuffixIgnoreCase(base, \"/oidc\");\n return stripTrailingSlashes(base);\n}\n\n/** Issuer URL (`…/api/v1/oidc`) → host origin for signer/API-key routes. Linear-time; no regex. */\nexport function stripIssuerOriginFromOidcUrl(issuerUrl: string): string {\n let base = stripTrailingSlashes(issuerUrl.trim());\n base = stripSuffixIgnoreCase(base, \"/api/v1/oidc\");\n base = stripSuffixIgnoreCase(base, \"/oidc\");\n return stripTrailingSlashes(base);\n}\n\n/** Validate gateway session ids before embedding in request URLs. */\nexport function isSafePathSegment(value: unknown): value is string {\n if (typeof value !== \"string\" || value.length === 0 || value.length > 128) {\n return false;\n }\n for (let i = 0; i < value.length; i++) {\n const c = value.codePointAt(i) ?? 0;\n const ok =\n (c >= 48 && c <= 57) ||\n (c >= 65 && c <= 90) ||\n (c >= 97 && c <= 122) ||\n c === 95 ||\n c === 45;\n if (!ok) {\n return false;\n }\n }\n return true;\n}\n\n/** Parse and validate an http(s) facade origin (no path). */\nexport function parseHttpOrigin(raw: string | undefined, fallback: string): string {\n const trimmed = (raw ?? fallback).trim();\n let parsed: URL;\n try {\n parsed = new URL(trimmed);\n } catch {\n throw new TypeError(\"Origin must be a valid http(s) URL\");\n }\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n throw new TypeError(\"Origin must use http or https\");\n }\n return parsed.origin;\n}\n\n/** Build a validated DELETE URL for `/api/gateway/sessions/:id`. */\nexport function buildGatewaySessionDeleteUrl(origin: string, sessionId: string): URL {\n if (!isSafePathSegment(sessionId)) {\n throw new TypeError(\"Invalid gateway session id\");\n }\n return new URL(`/api/gateway/sessions/${encodeURIComponent(sessionId)}`, origin);\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"]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/string-utils.ts","../src/discovery.ts","../src/oauth-map.ts","../src/verify.ts"],"names":["customFetch","allowInsecureRequests"],"mappings":"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","file":"verify.js","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.codePointAt(end - 1) ?? 0) === 47) {\n end--;\n }\n return value.slice(0, end);\n}\n\nfunction endsWithIgnoreCase(value: string, suffix: string): boolean {\n if (suffix.length > value.length) {\n return false;\n }\n const start = value.length - suffix.length;\n for (let i = 0; i < suffix.length; i++) {\n const a = value.codePointAt(start + i) ?? 0;\n const b = suffix.codePointAt(i) ?? 0;\n if (a !== b && (a | 32) !== (b | 32)) {\n return false;\n }\n }\n return true;\n}\n\nfunction stripSuffixIgnoreCase(value: string, suffix: string): string {\n return endsWithIgnoreCase(value, suffix)\n ? value.slice(0, value.length - suffix.length)\n : value;\n}\n\n/** Issuer URL (`…/oidc`) → Builder API base (`…/api/v1`). Linear-time; no regex. */\nexport function stripOidcPathSuffix(issuerUrl: string): string {\n let base = stripTrailingSlashes(issuerUrl.trim());\n base = stripSuffixIgnoreCase(base, \"/oidc\");\n return stripTrailingSlashes(base);\n}\n\n/** Issuer URL (`…/api/v1/oidc`) → host origin for signer/API-key routes. Linear-time; no regex. */\nexport function stripIssuerOriginFromOidcUrl(issuerUrl: string): string {\n let base = stripTrailingSlashes(issuerUrl.trim());\n base = stripSuffixIgnoreCase(base, \"/api/v1/oidc\");\n base = stripSuffixIgnoreCase(base, \"/oidc\");\n return stripTrailingSlashes(base);\n}\n\n/** Parse and validate an http(s) facade origin (no path). */\nexport function parseHttpOrigin(raw: string | undefined, fallback: string): string {\n const trimmed = (raw ?? fallback).trim();\n let parsed: URL;\n try {\n parsed = new URL(trimmed);\n } catch {\n throw new TypeError(\"Origin must be a valid http(s) URL\");\n }\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n throw new TypeError(\"Origin must use http or https\");\n }\n return parsed.origin;\n}\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"]}