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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/{index-BixH4VIG.d.cts → index-D5wdxNYy.d.cts} +4 -2
  2. package/dist/{index-BTDKEorK.d.ts → index-DFJ6qcK0.d.ts} +4 -2
  3. package/dist/index.d.cts +1 -1
  4. package/dist/index.d.ts +1 -1
  5. package/dist/{proxy-JrT6raU_.d.cts → proxy-0wa8QZIU.d.cts} +16 -2
  6. package/dist/{proxy-U32DFNuj.d.ts → proxy-KrA1vEmh.d.ts} +16 -2
  7. package/dist/signer/server.cjs +90 -67
  8. package/dist/signer/server.cjs.map +1 -1
  9. package/dist/signer/server.d.cts +4 -4
  10. package/dist/signer/server.d.ts +4 -4
  11. package/dist/signer/server.js +90 -67
  12. package/dist/signer/server.js.map +1 -1
  13. package/dist/signer/webhook/adapters/api-key.cjs +15 -11
  14. package/dist/signer/webhook/adapters/api-key.cjs.map +1 -1
  15. package/dist/signer/webhook/adapters/api-key.d.cts +1 -1
  16. package/dist/signer/webhook/adapters/api-key.d.ts +1 -1
  17. package/dist/signer/webhook/adapters/api-key.js +15 -11
  18. package/dist/signer/webhook/adapters/api-key.js.map +1 -1
  19. package/dist/signer/webhook/adapters/composite.cjs +1 -1
  20. package/dist/signer/webhook/adapters/composite.cjs.map +1 -1
  21. package/dist/signer/webhook/adapters/composite.d.cts +1 -1
  22. package/dist/signer/webhook/adapters/composite.d.ts +1 -1
  23. package/dist/signer/webhook/adapters/composite.js +1 -1
  24. package/dist/signer/webhook/adapters/composite.js.map +1 -1
  25. package/dist/signer/webhook/adapters/oauth1.d.cts +1 -1
  26. package/dist/signer/webhook/adapters/oauth1.d.ts +1 -1
  27. package/dist/signer/webhook/adapters/oidc.cjs +39 -25
  28. package/dist/signer/webhook/adapters/oidc.cjs.map +1 -1
  29. package/dist/signer/webhook/adapters/oidc.d.cts +2 -2
  30. package/dist/signer/webhook/adapters/oidc.d.ts +2 -2
  31. package/dist/signer/webhook/adapters/oidc.js +39 -25
  32. package/dist/signer/webhook/adapters/oidc.js.map +1 -1
  33. package/dist/signer/webhook/adapters/trusted-headers.cjs +18 -11
  34. package/dist/signer/webhook/adapters/trusted-headers.cjs.map +1 -1
  35. package/dist/signer/webhook/adapters/trusted-headers.d.cts +1 -1
  36. package/dist/signer/webhook/adapters/trusted-headers.d.ts +1 -1
  37. package/dist/signer/webhook/adapters/trusted-headers.js +18 -11
  38. package/dist/signer/webhook/adapters/trusted-headers.js.map +1 -1
  39. package/dist/signer/webhook.cjs +90 -38
  40. package/dist/signer/webhook.cjs.map +1 -1
  41. package/dist/signer/webhook.d.cts +6 -4
  42. package/dist/signer/webhook.d.ts +6 -4
  43. package/dist/signer/webhook.js +90 -39
  44. package/dist/signer/webhook.js.map +1 -1
  45. package/dist/{verifier-B-WFDMz6.d.cts → verifier-Be9WAjFF.d.cts} +3 -2
  46. package/dist/{verifier-B-WFDMz6.d.ts → verifier-Be9WAjFF.d.ts} +3 -2
  47. package/package.json +2 -2
@@ -1,5 +1,5 @@
1
1
  import { F as FetchLike } from './types-BORaHW_x.cjs';
2
- import { U as UsageIdentity, P as PaymentWebhookRequest, V as VerifiedEndUserAuth, E as EndUserAuthVerifier } from './verifier-B-WFDMz6.cjs';
2
+ import { U as UsageIdentity, P as PaymentWebhookRequest, V as VerifiedEndUserAuth, E as EndUserAuthVerifier } from './verifier-Be9WAjFF.cjs';
3
3
  import { TrustedHeadersEndUserAuthConfig } from './signer/webhook/adapters/trusted-headers.cjs';
4
4
 
5
5
  type WebhookIdentityClaimMapping = {
@@ -28,6 +28,8 @@ declare function handleRemoteSignerAuthorize(request: Request, config: RemoteSig
28
28
  declare function createRemoteSignerAuthorizeHandler(config: RemoteSignerWebhookConfig): (request: Request) => Promise<Response>;
29
29
  declare function routeRemoteSignerWebhookRequest(request: Request, config: RemoteSignerWebhookConfig): Promise<Response | null>;
30
30
 
31
+ /** Returns the token after `Bearer `, or null when the header is missing or not Bearer. */
32
+ declare function optionalBearerToken(authorization: string): string | null;
31
33
  declare function bearerTokenFromAuthorization(authorization: string): string;
32
34
 
33
35
  type OidcEndUserAuthConfig = {
@@ -61,4 +63,4 @@ declare function readOidcRemoteSignerWebhookConfigFromEnv(env?: NodeJS.ProcessEn
61
63
  /** @deprecated Use readOidcRemoteSignerWebhookConfigFromEnv */
62
64
  declare const readRemoteSignerWebhookConfigFromEnv: typeof readOidcRemoteSignerWebhookConfigFromEnv;
63
65
 
64
- export { DEFAULT_WEBHOOK_IDENTITY_CLAIMS as D, type OidcRemoteSignerWebhookConfigInput as O, type RemoteSignerWebhookConfig as R, type SignerDmzRemoteSignerWebhookConfigInput as S, type WebhookAuthorizeContext as W, type OidcEndUserAuthConfig as a, type WebhookIdentityClaimMapping as b, authenticateWebhookCaller as c, bearerTokenFromAuthorization as d, claimExpirySeconds as e, createOidcEndUserVerifier as f, createOidcRemoteSignerWebhookConfig as g, createRemoteSignerAuthorizeHandler as h, createSignerDmzRemoteSignerWebhookConfig as i, handleRemoteSignerAuthorize as j, handleRemoteSignerRefreshJwks as k, identityFromWebhookClaims as l, readRemoteSignerWebhookConfigFromEnv as m, routeRemoteSignerWebhookRequest as n, readOidcRemoteSignerWebhookConfigFromEnv as r };
66
+ export { DEFAULT_WEBHOOK_IDENTITY_CLAIMS as D, type OidcRemoteSignerWebhookConfigInput as O, type RemoteSignerWebhookConfig as R, type SignerDmzRemoteSignerWebhookConfigInput as S, type WebhookAuthorizeContext as W, type OidcEndUserAuthConfig as a, type WebhookIdentityClaimMapping as b, authenticateWebhookCaller as c, bearerTokenFromAuthorization as d, claimExpirySeconds as e, createOidcEndUserVerifier as f, createOidcRemoteSignerWebhookConfig as g, createRemoteSignerAuthorizeHandler as h, createSignerDmzRemoteSignerWebhookConfig as i, handleRemoteSignerAuthorize as j, handleRemoteSignerRefreshJwks as k, identityFromWebhookClaims as l, readRemoteSignerWebhookConfigFromEnv as m, routeRemoteSignerWebhookRequest as n, optionalBearerToken as o, readOidcRemoteSignerWebhookConfigFromEnv as r };
@@ -1,5 +1,5 @@
1
1
  import { F as FetchLike } from './types-BORaHW_x.js';
2
- import { U as UsageIdentity, P as PaymentWebhookRequest, V as VerifiedEndUserAuth, E as EndUserAuthVerifier } from './verifier-B-WFDMz6.js';
2
+ import { U as UsageIdentity, P as PaymentWebhookRequest, V as VerifiedEndUserAuth, E as EndUserAuthVerifier } from './verifier-Be9WAjFF.js';
3
3
  import { TrustedHeadersEndUserAuthConfig } from './signer/webhook/adapters/trusted-headers.js';
4
4
 
5
5
  type WebhookIdentityClaimMapping = {
@@ -28,6 +28,8 @@ declare function handleRemoteSignerAuthorize(request: Request, config: RemoteSig
28
28
  declare function createRemoteSignerAuthorizeHandler(config: RemoteSignerWebhookConfig): (request: Request) => Promise<Response>;
29
29
  declare function routeRemoteSignerWebhookRequest(request: Request, config: RemoteSignerWebhookConfig): Promise<Response | null>;
30
30
 
31
+ /** Returns the token after `Bearer `, or null when the header is missing or not Bearer. */
32
+ declare function optionalBearerToken(authorization: string): string | null;
31
33
  declare function bearerTokenFromAuthorization(authorization: string): string;
32
34
 
33
35
  type OidcEndUserAuthConfig = {
@@ -61,4 +63,4 @@ declare function readOidcRemoteSignerWebhookConfigFromEnv(env?: NodeJS.ProcessEn
61
63
  /** @deprecated Use readOidcRemoteSignerWebhookConfigFromEnv */
62
64
  declare const readRemoteSignerWebhookConfigFromEnv: typeof readOidcRemoteSignerWebhookConfigFromEnv;
63
65
 
64
- export { DEFAULT_WEBHOOK_IDENTITY_CLAIMS as D, type OidcRemoteSignerWebhookConfigInput as O, type RemoteSignerWebhookConfig as R, type SignerDmzRemoteSignerWebhookConfigInput as S, type WebhookAuthorizeContext as W, type OidcEndUserAuthConfig as a, type WebhookIdentityClaimMapping as b, authenticateWebhookCaller as c, bearerTokenFromAuthorization as d, claimExpirySeconds as e, createOidcEndUserVerifier as f, createOidcRemoteSignerWebhookConfig as g, createRemoteSignerAuthorizeHandler as h, createSignerDmzRemoteSignerWebhookConfig as i, handleRemoteSignerAuthorize as j, handleRemoteSignerRefreshJwks as k, identityFromWebhookClaims as l, readRemoteSignerWebhookConfigFromEnv as m, routeRemoteSignerWebhookRequest as n, readOidcRemoteSignerWebhookConfigFromEnv as r };
66
+ export { DEFAULT_WEBHOOK_IDENTITY_CLAIMS as D, type OidcRemoteSignerWebhookConfigInput as O, type RemoteSignerWebhookConfig as R, type SignerDmzRemoteSignerWebhookConfigInput as S, type WebhookAuthorizeContext as W, type OidcEndUserAuthConfig as a, type WebhookIdentityClaimMapping as b, authenticateWebhookCaller as c, bearerTokenFromAuthorization as d, claimExpirySeconds as e, createOidcEndUserVerifier as f, createOidcRemoteSignerWebhookConfig as g, createRemoteSignerAuthorizeHandler as h, createSignerDmzRemoteSignerWebhookConfig as i, handleRemoteSignerAuthorize as j, handleRemoteSignerRefreshJwks as k, identityFromWebhookClaims as l, readRemoteSignerWebhookConfigFromEnv as m, routeRemoteSignerWebhookRequest as n, optionalBearerToken as o, readOidcRemoteSignerWebhookConfigFromEnv as r };
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { NETWORK_USD_PER_MICRO, applyRetailRateToNetworkMicros, defaultRetailRateUsd, markupPercentToRetailRateUsd, parseMarkupPercentInput, parseRetailRateUsd, retailRateUsdPerMillion, retailRateUsdToMarkupPercent } from './plan-pricing.cjs';
2
2
  import { S as SignedTicketIngestInput, F as FetchLike, f as SignedTicketIngestResult, r as UsageByUserRow, s as UsageForExternalUser, e as UsageApiResponse, n as MeScopeUsagePayload, t as UsageByPipelineModelRow, u as UsageByPipelineModelFiatRow, O as OidcDiscoveryDocument, v as AppManifestResponse } from './types-BORaHW_x.cjs';
3
3
  export { w as AllowancePolicy, x as AppManifestCapability, A as AppUserRecord, q as ApproveDeviceLoginInput, B as BillingProduct, y as BillingSyncState, z as BillingSyncStatus, E as CapabilityPriceRule, C as ClientCredentialsTokenResponse, D as DeviceApprovalInput, o as GetAppManifestResult, G as GetDiscoveryOptions, l as GrantSource, L as ListBillingProductsResult, p as MintSignerSessionForExternalUserInput, M as MintUserAccessTokenInput, b as MintUserAccessTokenResponse, c as MintUserSignerSessionTokenInput, a as ParsedDeviceApprovalRedirect, h as PlanSyncResult, P as PmtHouseClientOptions, H as SignerRoutingConfig, g as SignerRoutingResponse, T as TokenExchangeResponse, U as UpsertAppUserInput, i as UsageBalanceResponse, I as UsageDailyPipelineRow, d as UsageQueryInput, J as UsageTotals, k as UserAllowanceGrantInput, j as UserAllowancesResponse, K as UserCreditGrantInput, N as UserCreditsResponse, m as UserSubscriptionResponse } from './types-BORaHW_x.cjs';
4
- import { S as SignerUsageSnapshot } from './proxy-JrT6raU_.cjs';
4
+ import { S as SignerUsageSnapshot } from './proxy-0wa8QZIU.cjs';
5
5
  export { P as PmtHouseClient, b as buildDeviceCodeResource, n as normalizeUserCode } from './client-D1Xz-xlx.cjs';
6
6
  export { PYMTHOUSE_NOT_CONFIGURED_MESSAGE, getBuilderApiV1BaseFromIssuerUrl, getPymthouseIssuerOrigin, getPymthouseIssuerUrlFromEnv, getPymthousePublicClientIdFromEnv, isPymthouseConfigured, readPymthouseEnv } from './config.cjs';
7
7
  import { AuthorizationServer } from 'oauth4webapi';
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { NETWORK_USD_PER_MICRO, applyRetailRateToNetworkMicros, defaultRetailRateUsd, markupPercentToRetailRateUsd, parseMarkupPercentInput, parseRetailRateUsd, retailRateUsdPerMillion, retailRateUsdToMarkupPercent } from './plan-pricing.js';
2
2
  import { S as SignedTicketIngestInput, F as FetchLike, f as SignedTicketIngestResult, r as UsageByUserRow, s as UsageForExternalUser, e as UsageApiResponse, n as MeScopeUsagePayload, t as UsageByPipelineModelRow, u as UsageByPipelineModelFiatRow, O as OidcDiscoveryDocument, v as AppManifestResponse } from './types-BORaHW_x.js';
3
3
  export { w as AllowancePolicy, x as AppManifestCapability, A as AppUserRecord, q as ApproveDeviceLoginInput, B as BillingProduct, y as BillingSyncState, z as BillingSyncStatus, E as CapabilityPriceRule, C as ClientCredentialsTokenResponse, D as DeviceApprovalInput, o as GetAppManifestResult, G as GetDiscoveryOptions, l as GrantSource, L as ListBillingProductsResult, p as MintSignerSessionForExternalUserInput, M as MintUserAccessTokenInput, b as MintUserAccessTokenResponse, c as MintUserSignerSessionTokenInput, a as ParsedDeviceApprovalRedirect, h as PlanSyncResult, P as PmtHouseClientOptions, H as SignerRoutingConfig, g as SignerRoutingResponse, T as TokenExchangeResponse, U as UpsertAppUserInput, i as UsageBalanceResponse, I as UsageDailyPipelineRow, d as UsageQueryInput, J as UsageTotals, k as UserAllowanceGrantInput, j as UserAllowancesResponse, K as UserCreditGrantInput, N as UserCreditsResponse, m as UserSubscriptionResponse } from './types-BORaHW_x.js';
4
- import { S as SignerUsageSnapshot } from './proxy-U32DFNuj.js';
4
+ import { S as SignerUsageSnapshot } from './proxy-KrA1vEmh.js';
5
5
  export { P as PmtHouseClient, b as buildDeviceCodeResource, n as normalizeUserCode } from './client-CauCfGa7.js';
6
6
  export { PYMTHOUSE_NOT_CONFIGURED_MESSAGE, getBuilderApiV1BaseFromIssuerUrl, getPymthouseIssuerOrigin, getPymthouseIssuerUrlFromEnv, getPymthousePublicClientIdFromEnv, isPymthouseConfigured, readPymthouseEnv } from './config.js';
7
7
  import { AuthorizationServer } from 'oauth4webapi';
@@ -1,6 +1,10 @@
1
1
  import { F as FetchLike } from './types-BORaHW_x.cjs';
2
2
 
3
3
  type SignerDmzGate = "http" | "cli";
4
+ interface M2MClientCredentials {
5
+ m2mClientId: string;
6
+ m2mClientSecret: string;
7
+ }
4
8
  interface DirectSignerProxyConfig {
5
9
  pymthouseIssuerUrl: string;
6
10
  /** Public Builder app client id (`app_…`); used for cache keys and JWT `client_id`. */
@@ -10,6 +14,16 @@ interface DirectSignerProxyConfig {
10
14
  remoteSignerUrl: string | URL;
11
15
  fetch?: FetchLike;
12
16
  allowInsecureHttp?: boolean;
17
+ /**
18
+ * Multi-tenant: resolve the M2M credentials used to mint signer JWTs for a
19
+ * given `publicClientId`. The PymtHouse issuer binds the minted JWT's
20
+ * `client_id` to the developer app linked to these M2M credentials, so each
21
+ * tenant's `publicClientId` (from {@link DirectSignerProxyConfig.resolvePublicClientId})
22
+ * must map to the M2M credentials whose app uses it. The token manager
23
+ * validates that the minted `client_id` matches the requested `publicClientId`.
24
+ * Defaults to `pymthouseM2MClientId` / `pymthouseM2MClientSecret`.
25
+ */
26
+ resolveM2MCredentials?: (publicClientId: string) => M2MClientCredentials | Promise<M2MClientCredentials>;
13
27
  /**
14
28
  * When set, incoming request paths matching this prefix are rewritten to the remote signer base.
15
29
  * Example: `/api/signer/proxy` → remote `/generate-live-payment` when the suffix is empty.
@@ -53,7 +67,7 @@ interface MintUserSignerTokenResponse {
53
67
  lifetimeGrantedUsdMicros: string;
54
68
  }
55
69
  interface SignerTokenManagerOptions {
56
- mint: (externalUserId: string) => Promise<CachedSignerToken>;
70
+ mint: (publicClientId: string, externalUserId: string) => Promise<CachedSignerToken>;
57
71
  /** Fraction of TTL after which a proactive refresh runs. Defaults to `0.8`. */
58
72
  ttlRefreshRatio?: number;
59
73
  fetch?: FetchLike;
@@ -231,4 +245,4 @@ declare function probeSignerHttpReachability(options: ProbeSignerHttpReachabilit
231
245
  ethAddress?: string;
232
246
  }>;
233
247
 
234
- export { type ApiKeyExchangeHandlerConfig as A, resolveSignerBaseUrl as B, type CachedSignerToken as C, type DeviceExchangeHandlerConfig as D, type ExchangeDeviceTokenForSignerOptions as E, type ForwardDirectSignerRequestOptions as F, stripSignerUsageFromResponse as G, type MintUserSignerTokenOptions as M, type ProbeSignerHttpReachabilityOptions as P, type SignerUsageSnapshot as S, type SignerTokenManagerOptions as a, type SignerJwtIdentity as b, type DeviceExchangeHandlerConfigRemote as c, type DeviceExchangeResponse as d, type MintSignerTokenFromDeviceTokenOptions as e, type DeviceExchangeMintResult as f, type DeviceExchangeRequestBody as g, type ExchangeApiKeyForSignerOptions as h, type ApiKeyExchangeMintResult as i, type ApiKeyExchangeRequestBody as j, type DirectSignerProxyConfig as k, type DeviceExchangeMintContext as l, type DirectSignerBeforeSignContext as m, type DirectSignerBeforeSignResult as n, type ForwardToSignerOptions as o, type ForwardToSignerResult as p, type MintUserSignerTokenResponse as q, type SignerDmzGate as r, forwardToSigner as s, getCachedDmzBearerToken as t, normalizeSignerBaseUrl as u, parseSignerUsageSnapshot as v, pickConflictingNumberAliases as w, pickConflictingStringAliases as x, probeSignerHttpReachability as y, readSignerUpstreamBody as z };
248
+ export { type ApiKeyExchangeHandlerConfig as A, readSignerUpstreamBody as B, type CachedSignerToken as C, type DeviceExchangeHandlerConfig as D, type ExchangeDeviceTokenForSignerOptions as E, type ForwardDirectSignerRequestOptions as F, resolveSignerBaseUrl as G, stripSignerUsageFromResponse as H, type MintUserSignerTokenOptions as M, type ProbeSignerHttpReachabilityOptions as P, type SignerUsageSnapshot as S, type SignerTokenManagerOptions as a, type SignerJwtIdentity as b, type DeviceExchangeHandlerConfigRemote as c, type DeviceExchangeResponse as d, type MintSignerTokenFromDeviceTokenOptions as e, type DeviceExchangeMintResult as f, type DeviceExchangeRequestBody as g, type ExchangeApiKeyForSignerOptions as h, type ApiKeyExchangeMintResult as i, type ApiKeyExchangeRequestBody as j, type DirectSignerProxyConfig as k, type DeviceExchangeMintContext as l, type DirectSignerBeforeSignContext as m, type DirectSignerBeforeSignResult as n, type ForwardToSignerOptions as o, type ForwardToSignerResult as p, type M2MClientCredentials as q, type MintUserSignerTokenResponse as r, type SignerDmzGate as s, forwardToSigner as t, getCachedDmzBearerToken as u, normalizeSignerBaseUrl as v, parseSignerUsageSnapshot as w, pickConflictingNumberAliases as x, pickConflictingStringAliases as y, probeSignerHttpReachability as z };
@@ -1,6 +1,10 @@
1
1
  import { F as FetchLike } from './types-BORaHW_x.js';
2
2
 
3
3
  type SignerDmzGate = "http" | "cli";
4
+ interface M2MClientCredentials {
5
+ m2mClientId: string;
6
+ m2mClientSecret: string;
7
+ }
4
8
  interface DirectSignerProxyConfig {
5
9
  pymthouseIssuerUrl: string;
6
10
  /** Public Builder app client id (`app_…`); used for cache keys and JWT `client_id`. */
@@ -10,6 +14,16 @@ interface DirectSignerProxyConfig {
10
14
  remoteSignerUrl: string | URL;
11
15
  fetch?: FetchLike;
12
16
  allowInsecureHttp?: boolean;
17
+ /**
18
+ * Multi-tenant: resolve the M2M credentials used to mint signer JWTs for a
19
+ * given `publicClientId`. The PymtHouse issuer binds the minted JWT's
20
+ * `client_id` to the developer app linked to these M2M credentials, so each
21
+ * tenant's `publicClientId` (from {@link DirectSignerProxyConfig.resolvePublicClientId})
22
+ * must map to the M2M credentials whose app uses it. The token manager
23
+ * validates that the minted `client_id` matches the requested `publicClientId`.
24
+ * Defaults to `pymthouseM2MClientId` / `pymthouseM2MClientSecret`.
25
+ */
26
+ resolveM2MCredentials?: (publicClientId: string) => M2MClientCredentials | Promise<M2MClientCredentials>;
13
27
  /**
14
28
  * When set, incoming request paths matching this prefix are rewritten to the remote signer base.
15
29
  * Example: `/api/signer/proxy` → remote `/generate-live-payment` when the suffix is empty.
@@ -53,7 +67,7 @@ interface MintUserSignerTokenResponse {
53
67
  lifetimeGrantedUsdMicros: string;
54
68
  }
55
69
  interface SignerTokenManagerOptions {
56
- mint: (externalUserId: string) => Promise<CachedSignerToken>;
70
+ mint: (publicClientId: string, externalUserId: string) => Promise<CachedSignerToken>;
57
71
  /** Fraction of TTL after which a proactive refresh runs. Defaults to `0.8`. */
58
72
  ttlRefreshRatio?: number;
59
73
  fetch?: FetchLike;
@@ -231,4 +245,4 @@ declare function probeSignerHttpReachability(options: ProbeSignerHttpReachabilit
231
245
  ethAddress?: string;
232
246
  }>;
233
247
 
234
- export { type ApiKeyExchangeHandlerConfig as A, resolveSignerBaseUrl as B, type CachedSignerToken as C, type DeviceExchangeHandlerConfig as D, type ExchangeDeviceTokenForSignerOptions as E, type ForwardDirectSignerRequestOptions as F, stripSignerUsageFromResponse as G, type MintUserSignerTokenOptions as M, type ProbeSignerHttpReachabilityOptions as P, type SignerUsageSnapshot as S, type SignerTokenManagerOptions as a, type SignerJwtIdentity as b, type DeviceExchangeHandlerConfigRemote as c, type DeviceExchangeResponse as d, type MintSignerTokenFromDeviceTokenOptions as e, type DeviceExchangeMintResult as f, type DeviceExchangeRequestBody as g, type ExchangeApiKeyForSignerOptions as h, type ApiKeyExchangeMintResult as i, type ApiKeyExchangeRequestBody as j, type DirectSignerProxyConfig as k, type DeviceExchangeMintContext as l, type DirectSignerBeforeSignContext as m, type DirectSignerBeforeSignResult as n, type ForwardToSignerOptions as o, type ForwardToSignerResult as p, type MintUserSignerTokenResponse as q, type SignerDmzGate as r, forwardToSigner as s, getCachedDmzBearerToken as t, normalizeSignerBaseUrl as u, parseSignerUsageSnapshot as v, pickConflictingNumberAliases as w, pickConflictingStringAliases as x, probeSignerHttpReachability as y, readSignerUpstreamBody as z };
248
+ export { type ApiKeyExchangeHandlerConfig as A, readSignerUpstreamBody as B, type CachedSignerToken as C, type DeviceExchangeHandlerConfig as D, type ExchangeDeviceTokenForSignerOptions as E, type ForwardDirectSignerRequestOptions as F, resolveSignerBaseUrl as G, stripSignerUsageFromResponse as H, type MintUserSignerTokenOptions as M, type ProbeSignerHttpReachabilityOptions as P, type SignerUsageSnapshot as S, type SignerTokenManagerOptions as a, type SignerJwtIdentity as b, type DeviceExchangeHandlerConfigRemote as c, type DeviceExchangeResponse as d, type MintSignerTokenFromDeviceTokenOptions as e, type DeviceExchangeMintResult as f, type DeviceExchangeRequestBody as g, type ExchangeApiKeyForSignerOptions as h, type ApiKeyExchangeMintResult as i, type ApiKeyExchangeRequestBody as j, type DirectSignerProxyConfig as k, type DeviceExchangeMintContext as l, type DirectSignerBeforeSignContext as m, type DirectSignerBeforeSignResult as n, type ForwardToSignerOptions as o, type ForwardToSignerResult as p, type M2MClientCredentials as q, type MintUserSignerTokenResponse as r, type SignerDmzGate as s, forwardToSigner as t, getCachedDmzBearerToken as u, normalizeSignerBaseUrl as v, parseSignerUsageSnapshot as w, pickConflictingNumberAliases as x, pickConflictingStringAliases as y, probeSignerHttpReachability as z };
@@ -48,62 +48,6 @@ function signerHandlerErrorResponse(error) {
48
48
  });
49
49
  }
50
50
 
51
- // src/signer/token-manager.ts
52
- function cacheKey(clientId, externalUserId) {
53
- return `${clientId}\0${externalUserId}`;
54
- }
55
- function createSignerTokenManager(options) {
56
- const ttlRefreshRatio = options.ttlRefreshRatio ?? 0.8;
57
- const cache = /* @__PURE__ */ new Map();
58
- const inflight = /* @__PURE__ */ new Map();
59
- function isUsable(entry, now, forceRefresh) {
60
- if (forceRefresh) return false;
61
- if (now >= entry.expiresAt) return false;
62
- if (now >= entry.refreshAt) return false;
63
- return true;
64
- }
65
- async function refresh(publicClientId, externalUserId) {
66
- const key = cacheKey(publicClientId, externalUserId);
67
- const existing = inflight.get(key);
68
- if (existing) {
69
- return existing;
70
- }
71
- const promise = options.mint(externalUserId).then((token) => {
72
- const normalized = {
73
- ...token,
74
- refreshAt: token.refreshAt || Date.now() + Math.floor((token.expiresAt - Date.now()) * ttlRefreshRatio)
75
- };
76
- cache.set(key, normalized);
77
- inflight.delete(key);
78
- return normalized;
79
- }).catch((error) => {
80
- inflight.delete(key);
81
- throw error;
82
- });
83
- inflight.set(key, promise);
84
- return promise;
85
- }
86
- return {
87
- peek(publicClientId, externalUserId) {
88
- return cache.get(cacheKey(publicClientId, externalUserId));
89
- },
90
- invalidate(publicClientId, externalUserId) {
91
- const key = cacheKey(publicClientId, externalUserId);
92
- cache.delete(key);
93
- inflight.delete(key);
94
- },
95
- async getToken(publicClientId, externalUserId, getOptions = {}) {
96
- const now = Date.now();
97
- const key = cacheKey(publicClientId, externalUserId);
98
- const cached = cache.get(key);
99
- if (cached && isUsable(cached, now, getOptions.forceRefresh === true)) {
100
- return cached;
101
- }
102
- return refresh(publicClientId, externalUserId);
103
- }
104
- };
105
- }
106
-
107
51
  // src/signer/forward.ts
108
52
  function base64UrlPayloadToUtf8(payloadB64) {
109
53
  const normalized = payloadB64.replaceAll("-", "+").replaceAll("_", "/");
@@ -217,6 +161,70 @@ async function forwardDirectSignerRequest(options) {
217
161
  return fetchImpl(target, init);
218
162
  }
219
163
 
164
+ // src/signer/token-manager.ts
165
+ function cacheKey(clientId, externalUserId) {
166
+ return `${clientId}\0${externalUserId}`;
167
+ }
168
+ function createSignerTokenManager(options) {
169
+ const ttlRefreshRatio = options.ttlRefreshRatio ?? 0.8;
170
+ const cache = /* @__PURE__ */ new Map();
171
+ const inflight = /* @__PURE__ */ new Map();
172
+ function isUsable(entry, now, forceRefresh) {
173
+ if (forceRefresh) return false;
174
+ if (now >= entry.expiresAt) return false;
175
+ if (now >= entry.refreshAt) return false;
176
+ return true;
177
+ }
178
+ async function refresh(publicClientId, externalUserId) {
179
+ const key = cacheKey(publicClientId, externalUserId);
180
+ const existing = inflight.get(key);
181
+ if (existing) {
182
+ return existing;
183
+ }
184
+ const promise = options.mint(publicClientId, externalUserId).then((token) => {
185
+ const identity = identityFromJwtPayload(decodeJwtPayload(token.jwt));
186
+ if (identity.clientId !== publicClientId) {
187
+ throw new PmtHouseError("minted JWT client_id does not match public client id", {
188
+ status: 500,
189
+ code: "invalid_client_id",
190
+ details: { expected: publicClientId, actual: identity.clientId }
191
+ });
192
+ }
193
+ const normalized = {
194
+ ...token,
195
+ refreshAt: token.refreshAt || Date.now() + Math.floor((token.expiresAt - Date.now()) * ttlRefreshRatio)
196
+ };
197
+ cache.set(key, normalized);
198
+ inflight.delete(key);
199
+ return normalized;
200
+ }).catch((error) => {
201
+ inflight.delete(key);
202
+ throw error;
203
+ });
204
+ inflight.set(key, promise);
205
+ return promise;
206
+ }
207
+ return {
208
+ peek(publicClientId, externalUserId) {
209
+ return cache.get(cacheKey(publicClientId, externalUserId));
210
+ },
211
+ invalidate(publicClientId, externalUserId) {
212
+ const key = cacheKey(publicClientId, externalUserId);
213
+ cache.delete(key);
214
+ inflight.delete(key);
215
+ },
216
+ async getToken(publicClientId, externalUserId, getOptions = {}) {
217
+ const now = Date.now();
218
+ const key = cacheKey(publicClientId, externalUserId);
219
+ const cached = cache.get(key);
220
+ if (cached && isUsable(cached, now, getOptions.forceRefresh === true)) {
221
+ return cached;
222
+ }
223
+ return refresh(publicClientId, externalUserId);
224
+ }
225
+ };
226
+ }
227
+
220
228
  // src/string-utils.ts
221
229
  function stripTrailingSlashes(value) {
222
230
  let end = value.length;
@@ -1013,7 +1021,7 @@ async function forwardToSigner(options) {
1013
1021
  const headers = { "Content-Type": "application/json" };
1014
1022
  const explicitAuth = options.authorization?.trim();
1015
1023
  if (explicitAuth) {
1016
- headers.Authorization = explicitAuth.startsWith("Bearer ") ? explicitAuth : `Bearer ${explicitAuth}`;
1024
+ headers.Authorization = explicitAuth;
1017
1025
  } else {
1018
1026
  const attachJwt = options.forwardJwt ?? true;
1019
1027
  if (attachJwt) {
@@ -1157,15 +1165,30 @@ function toResponse(result) {
1157
1165
  });
1158
1166
  }
1159
1167
  function createDirectSignerProxyHandler(config) {
1160
- const tokenManager = createSignerTokenManager({
1161
- mint: (externalUserId) => mintUserSignerToken({
1162
- issuerUrl: config.pymthouseIssuerUrl,
1168
+ async function resolveM2MCredentials(publicClientId) {
1169
+ if (config.resolveM2MCredentials) {
1170
+ return config.resolveM2MCredentials(publicClientId);
1171
+ }
1172
+ return {
1163
1173
  m2mClientId: config.pymthouseM2MClientId,
1164
- m2mClientSecret: config.pymthouseM2MClientSecret,
1165
- externalUserId,
1166
- fetch: config.fetch,
1167
- allowInsecureHttp: config.allowInsecureHttp
1168
- })
1174
+ m2mClientSecret: config.pymthouseM2MClientSecret
1175
+ };
1176
+ }
1177
+ const tokenManager = createSignerTokenManager({
1178
+ // `publicClientId` selects the M2M credentials so the minted JWT's
1179
+ // `client_id` matches the cache partition key. The token manager rejects any
1180
+ // minted token whose `client_id` diverges from `publicClientId`.
1181
+ mint: async (publicClientId, externalUserId) => {
1182
+ const { m2mClientId, m2mClientSecret } = await resolveM2MCredentials(publicClientId);
1183
+ return mintUserSignerToken({
1184
+ issuerUrl: config.pymthouseIssuerUrl,
1185
+ m2mClientId,
1186
+ m2mClientSecret,
1187
+ externalUserId,
1188
+ fetch: config.fetch,
1189
+ allowInsecureHttp: config.allowInsecureHttp
1190
+ });
1191
+ }
1169
1192
  });
1170
1193
  async function runBeforeSign(token, externalUserId, request) {
1171
1194
  if (!config.beforeSign) {
@@ -1229,8 +1252,8 @@ function createDirectSignerProxyHandler(config) {
1229
1252
  return signerHandlerErrorResponse(error);
1230
1253
  }
1231
1254
  };
1232
- handler.getCachedUsage = (externalUserId) => tokenManager.peek(config.pymthouseClientId, externalUserId);
1233
- handler.invalidateToken = (externalUserId) => tokenManager.invalidate(config.pymthouseClientId, externalUserId);
1255
+ handler.getCachedUsage = (publicClientId, externalUserId) => tokenManager.peek(publicClientId, externalUserId);
1256
+ handler.invalidateToken = (publicClientId, externalUserId) => tokenManager.invalidate(publicClientId, externalUserId);
1234
1257
  return handler;
1235
1258
  }
1236
1259