@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
@@ -46,62 +46,6 @@ function signerHandlerErrorResponse(error) {
46
46
  });
47
47
  }
48
48
 
49
- // src/signer/token-manager.ts
50
- function cacheKey(clientId, externalUserId) {
51
- return `${clientId}\0${externalUserId}`;
52
- }
53
- function createSignerTokenManager(options) {
54
- const ttlRefreshRatio = options.ttlRefreshRatio ?? 0.8;
55
- const cache = /* @__PURE__ */ new Map();
56
- const inflight = /* @__PURE__ */ new Map();
57
- function isUsable(entry, now, forceRefresh) {
58
- if (forceRefresh) return false;
59
- if (now >= entry.expiresAt) return false;
60
- if (now >= entry.refreshAt) return false;
61
- return true;
62
- }
63
- async function refresh(publicClientId, externalUserId) {
64
- const key = cacheKey(publicClientId, externalUserId);
65
- const existing = inflight.get(key);
66
- if (existing) {
67
- return existing;
68
- }
69
- const promise = options.mint(externalUserId).then((token) => {
70
- const normalized = {
71
- ...token,
72
- refreshAt: token.refreshAt || Date.now() + Math.floor((token.expiresAt - Date.now()) * ttlRefreshRatio)
73
- };
74
- cache.set(key, normalized);
75
- inflight.delete(key);
76
- return normalized;
77
- }).catch((error) => {
78
- inflight.delete(key);
79
- throw error;
80
- });
81
- inflight.set(key, promise);
82
- return promise;
83
- }
84
- return {
85
- peek(publicClientId, externalUserId) {
86
- return cache.get(cacheKey(publicClientId, externalUserId));
87
- },
88
- invalidate(publicClientId, externalUserId) {
89
- const key = cacheKey(publicClientId, externalUserId);
90
- cache.delete(key);
91
- inflight.delete(key);
92
- },
93
- async getToken(publicClientId, externalUserId, getOptions = {}) {
94
- const now = Date.now();
95
- const key = cacheKey(publicClientId, externalUserId);
96
- const cached = cache.get(key);
97
- if (cached && isUsable(cached, now, getOptions.forceRefresh === true)) {
98
- return cached;
99
- }
100
- return refresh(publicClientId, externalUserId);
101
- }
102
- };
103
- }
104
-
105
49
  // src/signer/forward.ts
106
50
  function base64UrlPayloadToUtf8(payloadB64) {
107
51
  const normalized = payloadB64.replaceAll("-", "+").replaceAll("_", "/");
@@ -215,6 +159,70 @@ async function forwardDirectSignerRequest(options) {
215
159
  return fetchImpl(target, init);
216
160
  }
217
161
 
162
+ // src/signer/token-manager.ts
163
+ function cacheKey(clientId, externalUserId) {
164
+ return `${clientId}\0${externalUserId}`;
165
+ }
166
+ function createSignerTokenManager(options) {
167
+ const ttlRefreshRatio = options.ttlRefreshRatio ?? 0.8;
168
+ const cache = /* @__PURE__ */ new Map();
169
+ const inflight = /* @__PURE__ */ new Map();
170
+ function isUsable(entry, now, forceRefresh) {
171
+ if (forceRefresh) return false;
172
+ if (now >= entry.expiresAt) return false;
173
+ if (now >= entry.refreshAt) return false;
174
+ return true;
175
+ }
176
+ async function refresh(publicClientId, externalUserId) {
177
+ const key = cacheKey(publicClientId, externalUserId);
178
+ const existing = inflight.get(key);
179
+ if (existing) {
180
+ return existing;
181
+ }
182
+ const promise = options.mint(publicClientId, externalUserId).then((token) => {
183
+ const identity = identityFromJwtPayload(decodeJwtPayload(token.jwt));
184
+ if (identity.clientId !== publicClientId) {
185
+ throw new PmtHouseError("minted JWT client_id does not match public client id", {
186
+ status: 500,
187
+ code: "invalid_client_id",
188
+ details: { expected: publicClientId, actual: identity.clientId }
189
+ });
190
+ }
191
+ const normalized = {
192
+ ...token,
193
+ refreshAt: token.refreshAt || Date.now() + Math.floor((token.expiresAt - Date.now()) * ttlRefreshRatio)
194
+ };
195
+ cache.set(key, normalized);
196
+ inflight.delete(key);
197
+ return normalized;
198
+ }).catch((error) => {
199
+ inflight.delete(key);
200
+ throw error;
201
+ });
202
+ inflight.set(key, promise);
203
+ return promise;
204
+ }
205
+ return {
206
+ peek(publicClientId, externalUserId) {
207
+ return cache.get(cacheKey(publicClientId, externalUserId));
208
+ },
209
+ invalidate(publicClientId, externalUserId) {
210
+ const key = cacheKey(publicClientId, externalUserId);
211
+ cache.delete(key);
212
+ inflight.delete(key);
213
+ },
214
+ async getToken(publicClientId, externalUserId, getOptions = {}) {
215
+ const now = Date.now();
216
+ const key = cacheKey(publicClientId, externalUserId);
217
+ const cached = cache.get(key);
218
+ if (cached && isUsable(cached, now, getOptions.forceRefresh === true)) {
219
+ return cached;
220
+ }
221
+ return refresh(publicClientId, externalUserId);
222
+ }
223
+ };
224
+ }
225
+
218
226
  // src/string-utils.ts
219
227
  function stripTrailingSlashes(value) {
220
228
  let end = value.length;
@@ -1011,7 +1019,7 @@ async function forwardToSigner(options) {
1011
1019
  const headers = { "Content-Type": "application/json" };
1012
1020
  const explicitAuth = options.authorization?.trim();
1013
1021
  if (explicitAuth) {
1014
- headers.Authorization = explicitAuth.startsWith("Bearer ") ? explicitAuth : `Bearer ${explicitAuth}`;
1022
+ headers.Authorization = explicitAuth;
1015
1023
  } else {
1016
1024
  const attachJwt = options.forwardJwt ?? true;
1017
1025
  if (attachJwt) {
@@ -1155,15 +1163,30 @@ function toResponse(result) {
1155
1163
  });
1156
1164
  }
1157
1165
  function createDirectSignerProxyHandler(config) {
1158
- const tokenManager = createSignerTokenManager({
1159
- mint: (externalUserId) => mintUserSignerToken({
1160
- issuerUrl: config.pymthouseIssuerUrl,
1166
+ async function resolveM2MCredentials(publicClientId) {
1167
+ if (config.resolveM2MCredentials) {
1168
+ return config.resolveM2MCredentials(publicClientId);
1169
+ }
1170
+ return {
1161
1171
  m2mClientId: config.pymthouseM2MClientId,
1162
- m2mClientSecret: config.pymthouseM2MClientSecret,
1163
- externalUserId,
1164
- fetch: config.fetch,
1165
- allowInsecureHttp: config.allowInsecureHttp
1166
- })
1172
+ m2mClientSecret: config.pymthouseM2MClientSecret
1173
+ };
1174
+ }
1175
+ const tokenManager = createSignerTokenManager({
1176
+ // `publicClientId` selects the M2M credentials so the minted JWT's
1177
+ // `client_id` matches the cache partition key. The token manager rejects any
1178
+ // minted token whose `client_id` diverges from `publicClientId`.
1179
+ mint: async (publicClientId, externalUserId) => {
1180
+ const { m2mClientId, m2mClientSecret } = await resolveM2MCredentials(publicClientId);
1181
+ return mintUserSignerToken({
1182
+ issuerUrl: config.pymthouseIssuerUrl,
1183
+ m2mClientId,
1184
+ m2mClientSecret,
1185
+ externalUserId,
1186
+ fetch: config.fetch,
1187
+ allowInsecureHttp: config.allowInsecureHttp
1188
+ });
1189
+ }
1167
1190
  });
1168
1191
  async function runBeforeSign(token, externalUserId, request) {
1169
1192
  if (!config.beforeSign) {
@@ -1227,8 +1250,8 @@ function createDirectSignerProxyHandler(config) {
1227
1250
  return signerHandlerErrorResponse(error);
1228
1251
  }
1229
1252
  };
1230
- handler.getCachedUsage = (externalUserId) => tokenManager.peek(config.pymthouseClientId, externalUserId);
1231
- handler.invalidateToken = (externalUserId) => tokenManager.invalidate(config.pymthouseClientId, externalUserId);
1253
+ handler.getCachedUsage = (publicClientId, externalUserId) => tokenManager.peek(publicClientId, externalUserId);
1254
+ handler.invalidateToken = (publicClientId, externalUserId) => tokenManager.invalidate(publicClientId, externalUserId);
1232
1255
  return handler;
1233
1256
  }
1234
1257