@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
@@ -452,6 +452,46 @@ async function mintUserSignerToken(options) {
452
452
  return parseMintUserSignerTokenResponse(parsed);
453
453
  }
454
454
 
455
+ // src/signer/direct-signer.ts
456
+ var DIRECT_SIGNER_PATHS = {
457
+ signOrchestratorInfo: "sign-orchestrator-info",
458
+ generateLivePayment: "generate-live-payment",
459
+ discoverOrchestrators: "discover-orchestrators"
460
+ };
461
+ function signerEndpointUrl(signerBaseUrl, path) {
462
+ const base = stripTrailingSlashes(signerBaseUrl.trim());
463
+ if (!base) {
464
+ throw new PmtHouseError("signerBaseUrl is required", {
465
+ status: 400,
466
+ code: "invalid_signer_url"
467
+ });
468
+ }
469
+ const suffix = path.replace(/^\/+/, "");
470
+ return `${base}/${suffix}`;
471
+ }
472
+ function signerUrlFromExchangeResponse(response) {
473
+ const url = response.signerUrl?.trim();
474
+ return url || void 0;
475
+ }
476
+ function assertDirectSignerBaseUrl(signerBaseUrl) {
477
+ let parsed;
478
+ try {
479
+ parsed = new URL(signerBaseUrl.trim());
480
+ } catch {
481
+ throw new PmtHouseError("signer URL must be an absolute http(s) URL", {
482
+ status: 400,
483
+ code: "invalid_signer_url"
484
+ });
485
+ }
486
+ const pathname = stripTrailingSlashes(parsed.pathname);
487
+ if (pathname === "/api/signer" || pathname.startsWith("/api/signer/")) {
488
+ throw new PmtHouseError(
489
+ "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.",
490
+ { status: 400, code: "invalid_signer_url" }
491
+ );
492
+ }
493
+ }
494
+
455
495
  // src/signer/device-exchange.ts
456
496
  var TOKEN_EXCHANGE_GRANT = "urn:ietf:params:oauth:grant-type:token-exchange";
457
497
  var SUBJECT_ACCESS_TOKEN_TYPE = "urn:ietf:params:oauth:token-type:access_token";
@@ -609,6 +649,9 @@ async function exchangeDeviceTokenForSigner(options) {
609
649
  const accessToken = extractSignerAccessTokenFromExchangeBody(parsed);
610
650
  const signerUrlRaw = parsed.signerUrl ?? parsed.signer_url;
611
651
  const signerUrl = typeof signerUrlRaw === "string" && signerUrlRaw.trim() ? signerUrlRaw.trim() : void 0;
652
+ if (signerUrl) {
653
+ assertDirectSignerBaseUrl(signerUrl);
654
+ }
612
655
  return normalizeDeviceExchangeResponse(
613
656
  {
614
657
  access_token: accessToken,
@@ -788,6 +831,9 @@ async function exchangeApiKeyForSigner(options) {
788
831
  const accessToken = extractSignerAccessTokenFromExchangeBody(parsed);
789
832
  const signerUrlRaw = parsed.signerUrl ?? parsed.signer_url;
790
833
  const signerUrl = typeof signerUrlRaw === "string" && signerUrlRaw.trim() ? signerUrlRaw.trim() : void 0;
834
+ if (signerUrl) {
835
+ assertDirectSignerBaseUrl(signerUrl);
836
+ }
791
837
  return normalizeDeviceExchangeResponse(
792
838
  {
793
839
  access_token: accessToken,
@@ -843,6 +889,178 @@ function createApiKeyExchangeHandler(config) {
843
889
  };
844
890
  }
845
891
 
892
+ // src/signer/gateway-token.ts
893
+ function requireString(value, label) {
894
+ if (typeof value !== "string") {
895
+ throw new PmtHouseError(`${label} must be a string`, {
896
+ status: 400,
897
+ code: "invalid_gateway_token"
898
+ });
899
+ }
900
+ return value.trim();
901
+ }
902
+ function optionalString(value, label) {
903
+ if (value === void 0 || value === null) {
904
+ return void 0;
905
+ }
906
+ return requireString(value, label) || void 0;
907
+ }
908
+ function encodeBase64Json(value) {
909
+ const json = JSON.stringify(value);
910
+ if (typeof Buffer === "undefined") {
911
+ const binary = Array.from(
912
+ new TextEncoder().encode(json),
913
+ (c) => String.fromCodePoint(c)
914
+ ).join("");
915
+ return btoa(binary);
916
+ }
917
+ return Buffer.from(json, "utf8").toString("base64");
918
+ }
919
+ function decodeBase64Json(token) {
920
+ const trimmed = requireString(token, "gateway token");
921
+ let json;
922
+ try {
923
+ if (typeof Buffer === "undefined") {
924
+ json = new TextDecoder().decode(
925
+ Uint8Array.from(atob(trimmed), (c) => c.codePointAt(0) ?? 0)
926
+ );
927
+ } else {
928
+ json = Buffer.from(trimmed, "base64").toString("utf8");
929
+ }
930
+ } catch {
931
+ throw new PmtHouseError("Invalid gateway token: expected base64-encoded JSON", {
932
+ status: 400,
933
+ code: "invalid_gateway_token"
934
+ });
935
+ }
936
+ try {
937
+ return JSON.parse(json);
938
+ } catch {
939
+ throw new PmtHouseError("Invalid gateway token: expected UTF-8 JSON payload", {
940
+ status: 400,
941
+ code: "invalid_gateway_token"
942
+ });
943
+ }
944
+ }
945
+ function normalizeStringMap(map) {
946
+ if (!map) {
947
+ return void 0;
948
+ }
949
+ const entries = Object.entries(map).filter(
950
+ ([key, value]) => key.trim() && typeof value === "string"
951
+ );
952
+ return entries.length > 0 ? Object.fromEntries(entries) : void 0;
953
+ }
954
+ function buildGatewayToken(input) {
955
+ if (input === null || typeof input !== "object") {
956
+ throw new PmtHouseError("buildGatewayToken requires an input object", {
957
+ status: 400,
958
+ code: "invalid_gateway_token"
959
+ });
960
+ }
961
+ const signer = requireString(input.signer, "signer URL");
962
+ if (!signer) {
963
+ throw new PmtHouseError("buildGatewayToken requires a non-empty signer URL", {
964
+ status: 400,
965
+ code: "invalid_gateway_token"
966
+ });
967
+ }
968
+ const signerHeaders = { ...input.signerHeaders };
969
+ const bundle = { signer };
970
+ const discovery = optionalString(input.discovery, "discovery URL");
971
+ if (discovery) {
972
+ bundle.discovery = discovery;
973
+ }
974
+ const rawOrchestrators = input.orchestrators ?? [];
975
+ if (!Array.isArray(rawOrchestrators)) {
976
+ throw new PmtHouseError("orchestrators must be an array of strings", {
977
+ status: 400,
978
+ code: "invalid_gateway_token"
979
+ });
980
+ }
981
+ const orchestrators = rawOrchestrators.map((entry) => requireString(entry, "orchestrator entry")).filter((entry) => entry.length > 0);
982
+ if (orchestrators.length > 0) {
983
+ bundle.orchestrators = orchestrators;
984
+ }
985
+ if (input.auth?.kind === "signerJwt") {
986
+ const accessToken = requireString(input.auth.accessToken, "signerJwt accessToken");
987
+ if (!accessToken) {
988
+ throw new PmtHouseError("signerJwt auth requires a non-empty accessToken", {
989
+ status: 400,
990
+ code: "invalid_gateway_token"
991
+ });
992
+ }
993
+ signerHeaders.Authorization = `Bearer ${accessToken}`;
994
+ } else if (input.auth?.kind === "pmthApiKey") {
995
+ const apiKey = requireString(input.auth.apiKey, "pmthApiKey apiKey");
996
+ if (!apiKey) {
997
+ throw new PmtHouseError("pmthApiKey auth requires a non-empty apiKey", {
998
+ status: 400,
999
+ code: "invalid_gateway_token"
1000
+ });
1001
+ }
1002
+ bundle.api_key = apiKey;
1003
+ const billing = optionalString(input.auth.billing, "pmthApiKey billing URL");
1004
+ if (billing) {
1005
+ bundle.billing = billing;
1006
+ }
1007
+ }
1008
+ const normalizedSignerHeaders = normalizeStringMap(signerHeaders);
1009
+ if (normalizedSignerHeaders) {
1010
+ bundle.signer_headers = normalizedSignerHeaders;
1011
+ }
1012
+ const normalizedDiscoveryHeaders = normalizeStringMap(input.discoveryHeaders);
1013
+ if (normalizedDiscoveryHeaders) {
1014
+ bundle.discovery_headers = normalizedDiscoveryHeaders;
1015
+ }
1016
+ return encodeBase64Json(bundle);
1017
+ }
1018
+ function decodeGatewayToken(token) {
1019
+ const payload = decodeBase64Json(token);
1020
+ if (payload === null || typeof payload !== "object" || Array.isArray(payload)) {
1021
+ throw new PmtHouseError("Invalid gateway token: payload must be a JSON object", {
1022
+ status: 400,
1023
+ code: "invalid_gateway_token"
1024
+ });
1025
+ }
1026
+ return payload;
1027
+ }
1028
+ async function mintGatewayToken(options) {
1029
+ let accessToken;
1030
+ if (options.source === "m2m") {
1031
+ const minted = await mintUserSignerToken({
1032
+ issuerUrl: options.issuerUrl,
1033
+ m2mClientId: options.m2mClientId,
1034
+ m2mClientSecret: options.m2mClientSecret,
1035
+ externalUserId: options.externalUserId,
1036
+ fetch: options.fetch,
1037
+ allowInsecureHttp: options.allowInsecureHttp
1038
+ });
1039
+ accessToken = minted.jwt;
1040
+ } else {
1041
+ const minted = await mintSignerSessionFromApiKey({
1042
+ issuerUrl: options.issuerUrl,
1043
+ publicClientId: options.publicClientId,
1044
+ m2mClientId: options.m2mClientId,
1045
+ m2mClientSecret: options.m2mClientSecret,
1046
+ apiKey: options.apiKey,
1047
+ scope: options.scope,
1048
+ audience: options.audience,
1049
+ fetch: options.fetch,
1050
+ allowInsecureHttp: options.allowInsecureHttp
1051
+ });
1052
+ accessToken = minted.access_token;
1053
+ }
1054
+ return buildGatewayToken({
1055
+ signer: options.signer,
1056
+ discovery: options.discovery,
1057
+ orchestrators: options.orchestrators,
1058
+ signerHeaders: options.signerHeaders,
1059
+ discoveryHeaders: options.discoveryHeaders,
1060
+ auth: { kind: "signerJwt", accessToken }
1061
+ });
1062
+ }
1063
+
846
1064
  // src/signer/proxy.ts
847
1065
  var HTTP_DMZ_TOKEN_MAX_ENTRIES = 100;
848
1066
  var HTTP_DMZ_TOKEN_TTL_MS = 3.5 * 60 * 1e3;
@@ -1251,12 +1469,16 @@ function createDirectSignerProxyHandler(config) {
1251
1469
  return handler;
1252
1470
  }
1253
1471
 
1472
+ exports.DIRECT_SIGNER_PATHS = DIRECT_SIGNER_PATHS;
1254
1473
  exports.LIVEPEER_REMOTE_SIGNER_AUDIENCE = LIVEPEER_REMOTE_SIGNER_AUDIENCE;
1255
1474
  exports.SIGN_MINT_USER_TOKEN_SCOPE = SIGN_MINT_USER_TOKEN_SCOPE;
1475
+ exports.assertDirectSignerBaseUrl = assertDirectSignerBaseUrl;
1476
+ exports.buildGatewayToken = buildGatewayToken;
1256
1477
  exports.createApiKeyExchangeHandler = createApiKeyExchangeHandler;
1257
1478
  exports.createDeviceExchangeHandler = createDeviceExchangeHandler;
1258
1479
  exports.createDirectSignerProxyHandler = createDirectSignerProxyHandler;
1259
1480
  exports.createSignerTokenManager = createSignerTokenManager;
1481
+ exports.decodeGatewayToken = decodeGatewayToken;
1260
1482
  exports.decodeJwtPayload = decodeJwtPayload;
1261
1483
  exports.exchangeApiKeyForSigner = exchangeApiKeyForSigner;
1262
1484
  exports.exchangeDeviceTokenForSigner = exchangeDeviceTokenForSigner;
@@ -1266,6 +1488,7 @@ exports.forwardToSigner = forwardToSigner;
1266
1488
  exports.getCachedDmzBearerToken = getCachedDmzBearerToken;
1267
1489
  exports.identityFromJwtPayload = identityFromJwtPayload;
1268
1490
  exports.livepeerIdentityHeaders = livepeerIdentityHeaders;
1491
+ exports.mintGatewayToken = mintGatewayToken;
1269
1492
  exports.mintSignerSessionFromApiKey = mintSignerSessionFromApiKey;
1270
1493
  exports.mintSignerTokenFromDeviceToken = mintSignerTokenFromDeviceToken;
1271
1494
  exports.mintUserAccessTokenFromApiKey = mintUserAccessTokenFromApiKey;
@@ -1281,7 +1504,9 @@ exports.pickConflictingStringAliases = pickConflictingStringAliases;
1281
1504
  exports.probeSignerHttpReachability = probeSignerHttpReachability;
1282
1505
  exports.readSignerUpstreamBody = readSignerUpstreamBody;
1283
1506
  exports.resolveSignerBaseUrl = resolveSignerBaseUrl;
1507
+ exports.signerEndpointUrl = signerEndpointUrl;
1284
1508
  exports.signerJwtAudience = signerJwtAudience;
1509
+ exports.signerUrlFromExchangeResponse = signerUrlFromExchangeResponse;
1285
1510
  exports.stripSignerUsageFromResponse = stripSignerUsageFromResponse;
1286
1511
  //# sourceMappingURL=server.cjs.map
1287
1512
  //# sourceMappingURL=server.cjs.map