@pymthouse/builder-sdk 0.4.4 → 0.4.6

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 (44) hide show
  1. package/README.md +120 -5
  2. package/dist/{client-C0HgAugK.d.cts → client-CEBVgCD7.d.cts} +28 -4
  3. package/dist/{client-zCskUJag.d.ts → client-D-p6v8ju.d.ts} +28 -4
  4. package/dist/device.d.cts +1 -1
  5. package/dist/device.d.ts +1 -1
  6. package/dist/env.cjs +64 -9
  7. package/dist/env.cjs.map +1 -1
  8. package/dist/env.d.cts +2 -2
  9. package/dist/env.d.ts +2 -2
  10. package/dist/env.js +64 -9
  11. package/dist/env.js.map +1 -1
  12. package/dist/{index-CAIAYJv7.d.cts → index-M0tsyotJ.d.cts} +1 -1
  13. package/dist/{index-BL1wpOki.d.ts → index-rC8smShg.d.ts} +1 -1
  14. package/dist/index.cjs +64 -9
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +4 -4
  17. package/dist/index.d.ts +4 -4
  18. package/dist/index.js +64 -9
  19. package/dist/index.js.map +1 -1
  20. package/dist/{proxy-KrA1vEmh.d.ts → proxy-CZLY0IfL.d.cts} +5 -2
  21. package/dist/{proxy-0wa8QZIU.d.cts → proxy-D36SpZ6k.d.ts} +5 -2
  22. package/dist/signer/gateway.cjs +542 -0
  23. package/dist/signer/gateway.cjs.map +1 -0
  24. package/dist/signer/gateway.d.cts +81 -0
  25. package/dist/signer/gateway.d.ts +81 -0
  26. package/dist/signer/gateway.js +538 -0
  27. package/dist/signer/gateway.js.map +1 -0
  28. package/dist/signer/server.cjs +225 -0
  29. package/dist/signer/server.cjs.map +1 -1
  30. package/dist/signer/server.d.cts +35 -4
  31. package/dist/signer/server.d.ts +35 -4
  32. package/dist/signer/server.js +219 -1
  33. package/dist/signer/server.js.map +1 -1
  34. package/dist/signer/webhook/adapters/oidc.d.cts +2 -2
  35. package/dist/signer/webhook/adapters/oidc.d.ts +2 -2
  36. package/dist/signer/webhook.d.cts +3 -3
  37. package/dist/signer/webhook.d.ts +3 -3
  38. package/dist/tokens.d.cts +1 -1
  39. package/dist/tokens.d.ts +1 -1
  40. package/dist/{types-BORaHW_x.d.cts → types-CcP67AZm.d.cts} +2 -0
  41. package/dist/{types-BORaHW_x.d.ts → types-CcP67AZm.d.ts} +2 -0
  42. package/dist/verify.d.cts +1 -1
  43. package/dist/verify.d.ts +1 -1
  44. package/package.json +6 -1
package/dist/env.d.cts CHANGED
@@ -1,6 +1,6 @@
1
- import { P as PmtHouseClient } from './client-C0HgAugK.cjs';
1
+ import { P as PmtHouseClient } from './client-CEBVgCD7.cjs';
2
2
  import './tokens.cjs';
3
- import './types-BORaHW_x.cjs';
3
+ import './types-CcP67AZm.cjs';
4
4
 
5
5
  /**
6
6
  * Site origin for the PymtHouse deployment (e.g. https://pymthouse.com), derived
package/dist/env.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { P as PmtHouseClient } from './client-zCskUJag.js';
1
+ import { P as PmtHouseClient } from './client-D-p6v8ju.js';
2
2
  import './tokens.js';
3
- import './types-BORaHW_x.js';
3
+ import './types-CcP67AZm.js';
4
4
 
5
5
  /**
6
6
  * Site origin for the PymtHouse deployment (e.g. https://pymthouse.com), derived
package/dist/env.js CHANGED
@@ -305,6 +305,32 @@ var init_mint_token = __esm({
305
305
  }
306
306
  });
307
307
 
308
+ // src/signer/direct-signer.ts
309
+ function assertDirectSignerBaseUrl(signerBaseUrl) {
310
+ let parsed;
311
+ try {
312
+ parsed = new URL(signerBaseUrl.trim());
313
+ } catch {
314
+ throw new PmtHouseError("signer URL must be an absolute http(s) URL", {
315
+ status: 400,
316
+ code: "invalid_signer_url"
317
+ });
318
+ }
319
+ const pathname = stripTrailingSlashes(parsed.pathname);
320
+ if (pathname === "/api/signer" || pathname.startsWith("/api/signer/")) {
321
+ throw new PmtHouseError(
322
+ "signer URL must be the remote signer DMZ base, not a dashboard /api/signer/* proxy path. Exchange at the platform facade, then call signer endpoints directly using signerUrl from the exchange response.",
323
+ { status: 400, code: "invalid_signer_url" }
324
+ );
325
+ }
326
+ }
327
+ var init_direct_signer = __esm({
328
+ "src/signer/direct-signer.ts"() {
329
+ init_string_utils();
330
+ init_errors();
331
+ }
332
+ });
333
+
308
334
  // src/signer/device-exchange.ts
309
335
  function extractSignerAccessTokenFromExchangeBody(body) {
310
336
  const tokenObj = body.token;
@@ -537,6 +563,9 @@ async function exchangeApiKeyForSigner(options) {
537
563
  const accessToken = extractSignerAccessTokenFromExchangeBody(parsed);
538
564
  const signerUrlRaw = parsed.signerUrl ?? parsed.signer_url;
539
565
  const signerUrl = typeof signerUrlRaw === "string" && signerUrlRaw.trim() ? signerUrlRaw.trim() : void 0;
566
+ if (signerUrl) {
567
+ assertDirectSignerBaseUrl(signerUrl);
568
+ }
540
569
  return normalizeDeviceExchangeResponse(
541
570
  {
542
571
  access_token: accessToken,
@@ -599,6 +628,7 @@ var init_api_key_exchange = __esm({
599
628
  init_fetch_json();
600
629
  init_handler_errors();
601
630
  init_device_exchange();
631
+ init_direct_signer();
602
632
  EXCHANGE_RESPONSE_ERROR2 = "invalid_exchange_response";
603
633
  }
604
634
  });
@@ -1095,8 +1125,14 @@ var PmtHouseClient = class {
1095
1125
  });
1096
1126
  }
1097
1127
  /**
1098
- * Exchange a dashboard API key for a signer session via a trusted facade (recommended)
1099
- * or directly when M2M credentials are available on this client.
1128
+ * Exchange a dashboard API key for a short-lived signer JWT via a trusted facade.
1129
+ *
1130
+ * `facadeUrl` is used only for `POST {facadeUrl}/api/pymthouse/keys/exchange`.
1131
+ * After exchange, call signer RPCs directly at `signerUrl` from the response
1132
+ * (e.g. `{signerUrl}/sign-orchestrator-info`), not via dashboard `/api/signer/*`.
1133
+ *
1134
+ * When M2M credentials are available on this client, omit `facadeUrl` to exchange
1135
+ * directly against the PymtHouse issuer.
1100
1136
  */
1101
1137
  async exchangeApiKeyForSignerSession(input) {
1102
1138
  if (input.facadeUrl?.trim()) {
@@ -1113,7 +1149,8 @@ var PmtHouseClient = class {
1113
1149
  token_type: exchanged.token_type,
1114
1150
  expires_in: exchanged.expires_in,
1115
1151
  scope: exchanged.scope,
1116
- issued_token_type: "urn:ietf:params:oauth:token-type:access_token"
1152
+ issued_token_type: "urn:ietf:params:oauth:token-type:access_token",
1153
+ signerUrl: exchanged.signerUrl
1117
1154
  };
1118
1155
  }
1119
1156
  const userToken = await this.exchangeApiKeyForUserAccessToken({
@@ -1187,8 +1224,13 @@ var PmtHouseClient = class {
1187
1224
  params.set("subject_token", input.userJwt);
1188
1225
  params.set("subject_token_type", SUBJECT_ACCESS_TOKEN_TYPE2);
1189
1226
  params.set("requested_token_type", REQUESTED_ACCESS_TOKEN_TYPE);
1190
- const resourceCandidate = typeof input.resource === "string" && input.resource.trim() !== "" ? input.resource.trim() : this.issuerUrl;
1191
- params.set("resource", stripTrailingSlashes(resourceCandidate));
1227
+ if (typeof input.scope === "string" && input.scope.trim() !== "") {
1228
+ params.set("scope", input.scope.trim());
1229
+ }
1230
+ if (!input.omitResource) {
1231
+ const resourceCandidate = typeof input.resource === "string" && input.resource.trim() !== "" ? input.resource.trim() : this.issuerUrl;
1232
+ params.set("resource", stripTrailingSlashes(resourceCandidate));
1233
+ }
1192
1234
  try {
1193
1235
  const response = await genericTokenEndpointRequest(
1194
1236
  as,
@@ -1474,18 +1516,31 @@ var PmtHouseClient = class {
1474
1516
  };
1475
1517
  }
1476
1518
  /**
1477
- * Upsert an external user, mint a short-lived JWT, and exchange for an opaque signer session.
1519
+ * Upsert an external user, mint a short-lived JWT, and exchange it for a
1520
+ * long-lived opaque (`pmth_*`) signer session.
1521
+ *
1522
+ * Performs the *documented* remote-signer-session exchange (see
1523
+ * `builder-api.md` → "Remote signer session exchange"): the RFC 8693 token
1524
+ * exchange is sent with `scope=sign:job` and **no `resource` indicator**,
1525
+ * which selects the PymtHouse gateway/opaque path. A prior implementation set
1526
+ * `resource = issuer`, which routed to the signer-JWT path and returned a JWT
1527
+ * that {@link parseSignerSessionExchange} then rejected as non-opaque.
1478
1528
  */
1479
1529
  async mintSignerSessionForExternalUser(input) {
1530
+ const scope = input.scope ?? SIGN_JOB_SCOPE;
1480
1531
  await this.upsertAppUser({
1481
1532
  externalUserId: input.externalUserId,
1482
1533
  email: input.email,
1483
1534
  status: "active"
1484
1535
  });
1485
- const exchange = await this.mintUserSignerSessionToken({
1536
+ const userToken = await this.mintUserAccessToken({
1486
1537
  externalUserId: input.externalUserId,
1487
- scope: input.scope ?? SIGN_JOB_SCOPE,
1488
- resource: this.issuerUrl
1538
+ scope
1539
+ });
1540
+ const exchange = await this.exchangeForSignerSession({
1541
+ userJwt: userToken.access_token,
1542
+ omitResource: true,
1543
+ scope
1489
1544
  });
1490
1545
  return parseSignerSessionExchange(exchange);
1491
1546
  }