spaps-sdk 1.12.0 → 1.13.0

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.
package/dist/index.mjs CHANGED
@@ -519,6 +519,148 @@ var X402PaymentRequiredSDKError = class extends Error {
519
519
  this.response = response;
520
520
  }
521
521
  };
522
+ var SPAPSSDKError = class extends Error {
523
+ code;
524
+ status;
525
+ statusCode;
526
+ details;
527
+ requestId;
528
+ request_id;
529
+ diagnostics;
530
+ remediations;
531
+ constructor(options) {
532
+ super(options.message);
533
+ this.name = "SPAPSSDKError";
534
+ this.code = options.code;
535
+ this.status = options.status;
536
+ this.statusCode = options.status;
537
+ this.details = options.details;
538
+ this.requestId = options.requestId;
539
+ this.request_id = options.requestId;
540
+ this.diagnostics = options.diagnostics || [];
541
+ this.remediations = options.remediations || [];
542
+ }
543
+ };
544
+ function isObjectRecord(value) {
545
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
546
+ }
547
+ function toOptionalString(value) {
548
+ return typeof value === "string" && value.length > 0 ? value : void 0;
549
+ }
550
+ function toOptionalNumber(value) {
551
+ if (typeof value === "number" && Number.isFinite(value)) return value;
552
+ if (typeof value === "string" && value.trim()) {
553
+ const parsed = Number(value);
554
+ if (Number.isFinite(parsed)) return parsed;
555
+ }
556
+ return void 0;
557
+ }
558
+ function extractResponseHeader(headers, name) {
559
+ if (!headers || typeof headers !== "object") return void 0;
560
+ const getter = headers.get;
561
+ if (typeof getter === "function") {
562
+ return toOptionalString(getter.call(headers, name));
563
+ }
564
+ const normalized = name.toLowerCase();
565
+ for (const [key, value] of Object.entries(headers)) {
566
+ if (key.toLowerCase() === normalized) {
567
+ return Array.isArray(value) ? toOptionalString(value[0]) : toOptionalString(value);
568
+ }
569
+ }
570
+ return void 0;
571
+ }
572
+ function extractRequestId(payload, fallback) {
573
+ if (!isObjectRecord(payload)) return fallback;
574
+ const metadata = isObjectRecord(payload.metadata) ? payload.metadata : {};
575
+ return toOptionalString(payload.request_id) || toOptionalString(metadata.request_id) || fallback;
576
+ }
577
+ function normalizeDiagnostics(payload, fallbackCode, fallbackMessage, status) {
578
+ const raw = isObjectRecord(payload) ? payload.diagnostics : void 0;
579
+ const diagnostics = [];
580
+ if (Array.isArray(raw)) {
581
+ for (const item of raw) {
582
+ if (!isObjectRecord(item)) continue;
583
+ const code = toOptionalString(item.code) || fallbackCode || "request_failed";
584
+ const message = toOptionalString(item.message) || fallbackMessage;
585
+ diagnostics.push({
586
+ code,
587
+ message,
588
+ status: toOptionalNumber(item.status) ?? status ?? null,
589
+ ...item.details !== void 0 ? { details: item.details } : {}
590
+ });
591
+ }
592
+ }
593
+ if (diagnostics.length > 0) {
594
+ return diagnostics;
595
+ }
596
+ if (fallbackCode || status !== void 0) {
597
+ return [
598
+ {
599
+ code: fallbackCode || `http_${status}`,
600
+ message: fallbackMessage,
601
+ status: status ?? null
602
+ }
603
+ ];
604
+ }
605
+ return [];
606
+ }
607
+ function normalizeRemediations(payload) {
608
+ const raw = isObjectRecord(payload) ? payload.remediations : void 0;
609
+ if (!Array.isArray(raw)) return [];
610
+ const remediations = [];
611
+ for (const item of raw) {
612
+ if (!isObjectRecord(item)) continue;
613
+ const kind = toOptionalString(item.kind);
614
+ if (!kind) continue;
615
+ remediations.push({
616
+ kind,
617
+ ...item.label === null || typeof item.label === "string" ? { label: item.label } : {},
618
+ ...item.method === null || typeof item.method === "string" ? { method: item.method } : {},
619
+ ...item.path === null || typeof item.path === "string" ? { path: item.path } : {},
620
+ ...item.cli === null || typeof item.cli === "string" ? { cli: item.cli } : {},
621
+ ...Array.isArray(item.requires) ? { requires: item.requires.filter((value) => typeof value === "string") } : {},
622
+ ...item.details !== void 0 ? { details: item.details } : {},
623
+ ...item.command_template === null || typeof item.command_template === "string" ? { command_template: item.command_template } : {},
624
+ ...item.safe_to_execute === null || typeof item.safe_to_execute === "boolean" ? { safe_to_execute: item.safe_to_execute } : {},
625
+ ...item.operator_gate_required === null || typeof item.operator_gate_required === "boolean" ? { operator_gate_required: item.operator_gate_required } : {}
626
+ });
627
+ }
628
+ return remediations;
629
+ }
630
+ function buildSPAPSSDKError(payload, fallback, status, requestId) {
631
+ const record = isObjectRecord(payload) ? payload : {};
632
+ const error = isObjectRecord(record.error) ? record.error : {};
633
+ const code = toOptionalString(error.code);
634
+ const message = toOptionalString(error.message) || fallback || "SPAPS request failed";
635
+ return new SPAPSSDKError({
636
+ message,
637
+ code,
638
+ status,
639
+ details: error.details,
640
+ requestId: extractRequestId(record, requestId),
641
+ diagnostics: normalizeDiagnostics(record, code, message, status),
642
+ remediations: normalizeRemediations(record)
643
+ });
644
+ }
645
+ function buildSPAPSSDKErrorFromAxios(error) {
646
+ const status = error.response?.status;
647
+ const requestId = extractResponseHeader(error.response?.headers, "x-request-id");
648
+ if (error.response) {
649
+ return buildSPAPSSDKError(
650
+ error.response.data,
651
+ error.message || "SPAPS request failed",
652
+ status,
653
+ requestId
654
+ );
655
+ }
656
+ return new SPAPSSDKError({
657
+ message: error.message || "SPAPS request failed",
658
+ code: error.code,
659
+ status,
660
+ requestId,
661
+ diagnostics: normalizeDiagnostics(void 0, error.code, error.message, status)
662
+ });
663
+ }
522
664
  var SPAPSClient = class _SPAPSClient {
523
665
  client;
524
666
  apiKey;
@@ -530,10 +672,19 @@ var SPAPSClient = class _SPAPSClient {
530
672
  if (!response) {
531
673
  throw new Error(fallback);
532
674
  }
533
- const payload = this.isAxiosResponse(response) ? response.data : this.isResponseLikeWithData(response) ? response.data : response;
675
+ const axiosResponse = this.isAxiosResponse(response) ? response : void 0;
676
+ if (axiosResponse?.status === 204) {
677
+ return void 0;
678
+ }
679
+ const payload = axiosResponse ? axiosResponse.data : this.isResponseLikeWithData(response) ? response.data : response;
534
680
  if (this.isApiResponse(payload)) {
535
681
  if (payload.success === false) {
536
- throw new Error(payload.error?.message || fallback);
682
+ throw buildSPAPSSDKError(
683
+ payload,
684
+ fallback,
685
+ axiosResponse?.status,
686
+ extractResponseHeader(axiosResponse?.headers, "x-request-id")
687
+ );
537
688
  }
538
689
  if (payload.data !== void 0) {
539
690
  return payload.data;
@@ -560,6 +711,19 @@ var SPAPSClient = class _SPAPSClient {
560
711
  }
561
712
  return userId;
562
713
  }
714
+ requireAccessToken(message = "Authentication required. Please authenticate first.") {
715
+ if (!this.accessToken) {
716
+ throw new Error(message);
717
+ }
718
+ return this.accessToken;
719
+ }
720
+ authConfig(message) {
721
+ return {
722
+ headers: {
723
+ Authorization: `Bearer ${this.requireAccessToken(message)}`
724
+ }
725
+ };
726
+ }
563
727
  isAxiosResponse(value) {
564
728
  if (!value || typeof value !== "object") {
565
729
  return false;
@@ -579,6 +743,41 @@ var SPAPSClient = class _SPAPSClient {
579
743
  const record = value;
580
744
  return "success" in record && typeof record.success === "boolean";
581
745
  }
746
+ static isMfaRequiredAuthResponse(value) {
747
+ return Boolean(value && typeof value === "object" && value.mfa_required === true);
748
+ }
749
+ normalizeAuthPayload(payload) {
750
+ if (_SPAPSClient.isMfaRequiredAuthResponse(payload)) {
751
+ return payload;
752
+ }
753
+ if (payload?.tokens && payload?.user) {
754
+ return {
755
+ access_token: payload.tokens.access_token,
756
+ refresh_token: payload.tokens.refresh_token,
757
+ expires_in: payload.tokens.expires_in,
758
+ token_type: payload.token_type || "Bearer",
759
+ user: payload.user
760
+ };
761
+ }
762
+ return payload;
763
+ }
764
+ storeAuthTokens(result) {
765
+ if (_SPAPSClient.isMfaRequiredAuthResponse(result)) {
766
+ return;
767
+ }
768
+ if (result.access_token) {
769
+ this.accessToken = result.access_token;
770
+ }
771
+ if (result.refresh_token) {
772
+ this.refreshToken = result.refresh_token;
773
+ }
774
+ }
775
+ unwrapAuthMethodResponse(response, fallback) {
776
+ const payload = this.unwrapApiResponse(response, fallback);
777
+ const result = this.normalizeAuthPayload(payload);
778
+ this.storeAuthTokens(result);
779
+ return result;
780
+ }
582
781
  static isSdkManagedHeader(name) {
583
782
  const normalized = name.toLowerCase();
584
783
  return normalized === "authorization" || normalized === "x-api-key";
@@ -1008,6 +1207,203 @@ var SPAPSClient = class _SPAPSClient {
1008
1207
  return this.unwrapApiResponse(res, "Failed to get app link");
1009
1208
  }
1010
1209
  };
1210
+ /**
1211
+ * Application email whitelist helpers.
1212
+ *
1213
+ * `check` is API-key scoped. Mutations and admin reads require an
1214
+ * authenticated admin JWT plus the configured API key.
1215
+ */
1216
+ whitelist = {
1217
+ check: async (email) => {
1218
+ const q = new URLSearchParams({ email });
1219
+ const res = await this.client.get(`/api/v1/whitelist/check?${q.toString()}`);
1220
+ return this.unwrapApiResponse(res, "Failed to check whitelist");
1221
+ },
1222
+ add: async (payload) => {
1223
+ const res = await this.client.post(
1224
+ "/api/v1/whitelist",
1225
+ payload,
1226
+ this.authConfig("Access token is required for whitelist admin operations")
1227
+ );
1228
+ return this.unwrapApiResponse(res, "Failed to add whitelist entry");
1229
+ },
1230
+ bulkAdd: async (payload) => {
1231
+ const res = await this.client.post(
1232
+ "/api/v1/whitelist/bulk",
1233
+ payload,
1234
+ this.authConfig("Access token is required for whitelist admin operations")
1235
+ );
1236
+ return this.unwrapApiResponse(res, "Failed to bulk add whitelist entries");
1237
+ },
1238
+ list: async (params = {}) => {
1239
+ const q = new URLSearchParams();
1240
+ if (params.limit !== void 0) q.set("limit", String(params.limit));
1241
+ if (params.offset !== void 0) q.set("offset", String(params.offset));
1242
+ if (params.tier) q.set("tier", params.tier);
1243
+ const qs = q.toString();
1244
+ const res = await this.client.get(
1245
+ `/api/v1/whitelist${qs ? `?${qs}` : ""}`,
1246
+ this.authConfig("Access token is required for whitelist admin operations")
1247
+ );
1248
+ return this.unwrapApiResponse(res, "Failed to list whitelist entries");
1249
+ },
1250
+ update: async (email, payload) => {
1251
+ const res = await this.client.put(
1252
+ `/api/v1/whitelist/${encodeURIComponent(email)}`,
1253
+ payload,
1254
+ this.authConfig("Access token is required for whitelist admin operations")
1255
+ );
1256
+ return this.unwrapApiResponse(res, "Failed to update whitelist entry");
1257
+ },
1258
+ stats: async () => {
1259
+ const res = await this.client.get(
1260
+ "/api/v1/whitelist/stats",
1261
+ this.authConfig("Access token is required for whitelist admin operations")
1262
+ );
1263
+ return this.unwrapApiResponse(res, "Failed to get whitelist stats");
1264
+ },
1265
+ clear: async () => {
1266
+ const res = await this.client.delete(
1267
+ "/api/v1/whitelist/all",
1268
+ this.authConfig("Access token is required for whitelist admin operations")
1269
+ );
1270
+ return this.unwrapApiResponse(res, "Failed to clear whitelist");
1271
+ },
1272
+ remove: async (email) => {
1273
+ const res = await this.client.delete(
1274
+ `/api/v1/whitelist/${encodeURIComponent(email)}`,
1275
+ this.authConfig("Access token is required for whitelist admin operations")
1276
+ );
1277
+ return this.unwrapApiResponse(res, "Failed to remove whitelist entry");
1278
+ }
1279
+ };
1280
+ /**
1281
+ * User lookup and app membership administration helpers.
1282
+ */
1283
+ users = {
1284
+ getEmailsBatch: async (userIds) => {
1285
+ const res = await this.client.post("/api/users/emails", { user_ids: userIds });
1286
+ return this.unwrapApiResponse(res, "Failed to get user emails");
1287
+ },
1288
+ getUsersBatch: async (userIds) => {
1289
+ const res = await this.client.post("/api/users/batch", { user_ids: userIds });
1290
+ return this.unwrapApiResponse(res, "Failed to get users");
1291
+ },
1292
+ memberships: {
1293
+ list: async (params = {}) => {
1294
+ const q = new URLSearchParams();
1295
+ if (params.status) q.set("status", params.status);
1296
+ if (params.limit !== void 0) q.set("limit", String(params.limit));
1297
+ if (params.offset !== void 0) q.set("offset", String(params.offset));
1298
+ if (params.cursor) q.set("cursor", params.cursor);
1299
+ const qs = q.toString();
1300
+ const res = await this.client.get(
1301
+ `/api/users/memberships${qs ? `?${qs}` : ""}`,
1302
+ this.authConfig("Access token is required for membership admin operations")
1303
+ );
1304
+ return this.unwrapApiResponse(res, "Failed to list memberships");
1305
+ },
1306
+ add: async (payload) => {
1307
+ if (!payload.user_id && !payload.email) {
1308
+ throw new Error("Either user_id or email is required");
1309
+ }
1310
+ const res = await this.client.post(
1311
+ "/api/users/memberships",
1312
+ payload,
1313
+ this.authConfig("Access token is required for membership admin operations")
1314
+ );
1315
+ return this.unwrapApiResponse(res, "Failed to add membership");
1316
+ },
1317
+ remove: async (userId) => {
1318
+ const res = await this.client.delete(
1319
+ `/api/users/memberships/${encodeURIComponent(userId)}`,
1320
+ this.authConfig("Access token is required for membership admin operations")
1321
+ );
1322
+ return this.unwrapApiResponse(res, "Failed to remove membership");
1323
+ },
1324
+ deleteAccount: async (userId, params = {}) => {
1325
+ const config = {
1326
+ ...this.authConfig("Access token is required for user account deletion"),
1327
+ params
1328
+ };
1329
+ const res = await this.client.delete(
1330
+ `/api/users/${encodeURIComponent(userId)}`,
1331
+ config
1332
+ );
1333
+ return this.unwrapApiResponse(
1334
+ res,
1335
+ "Failed to delete user account"
1336
+ );
1337
+ }
1338
+ }
1339
+ };
1340
+ /**
1341
+ * Trusted-service support telemetry helpers.
1342
+ *
1343
+ * These endpoints require a secret API key. Case lifecycle patching also
1344
+ * requires a super-admin JWT.
1345
+ */
1346
+ supportTelemetry = {
1347
+ ingestEvent: async (payload) => {
1348
+ const res = await this.client.post("/api/v1/support-telemetry/events", payload);
1349
+ return this.unwrapApiResponse(
1350
+ res,
1351
+ "Failed to ingest support telemetry event"
1352
+ );
1353
+ },
1354
+ listCases: async (params = {}) => {
1355
+ const q = new URLSearchParams();
1356
+ if (params.application_id) q.set("application_id", params.application_id);
1357
+ if (params.status) q.set("status", params.status);
1358
+ if (params.priority) q.set("priority", params.priority);
1359
+ if (params.severity_gte) q.set("severity_gte", params.severity_gte);
1360
+ if (params.assigned_to_user_id) q.set("assigned_to_user_id", params.assigned_to_user_id);
1361
+ if (params.limit !== void 0) q.set("limit", String(params.limit));
1362
+ if (params.offset !== void 0) q.set("offset", String(params.offset));
1363
+ const qs = q.toString();
1364
+ const res = await this.client.get(`/api/v1/support-telemetry/cases${qs ? `?${qs}` : ""}`);
1365
+ return this.unwrapApiResponse(
1366
+ res,
1367
+ "Failed to list support telemetry cases"
1368
+ );
1369
+ },
1370
+ getCase: async (caseId, params = {}) => {
1371
+ const q = new URLSearchParams();
1372
+ if (params.event_limit !== void 0) q.set("event_limit", String(params.event_limit));
1373
+ if (params.event_offset !== void 0) q.set("event_offset", String(params.event_offset));
1374
+ const qs = q.toString();
1375
+ const res = await this.client.get(
1376
+ `/api/v1/support-telemetry/cases/${encodeURIComponent(caseId)}${qs ? `?${qs}` : ""}`
1377
+ );
1378
+ return this.unwrapApiResponse(
1379
+ res,
1380
+ "Failed to get support telemetry case"
1381
+ );
1382
+ },
1383
+ patchCase: async (caseId, payload) => {
1384
+ const res = await this.client.patch(
1385
+ `/api/v1/support-telemetry/cases/${encodeURIComponent(caseId)}`,
1386
+ payload,
1387
+ this.authConfig("Access token is required for support telemetry case updates")
1388
+ );
1389
+ return this.unwrapApiResponse(
1390
+ res,
1391
+ "Failed to patch support telemetry case"
1392
+ );
1393
+ },
1394
+ getCaseByExternalRef: async (externalCaseRef, params = {}) => {
1395
+ const q = new URLSearchParams();
1396
+ if (params.application_id) q.set("application_id", params.application_id);
1397
+ const qs = q.toString();
1398
+ const res = await this.client.get(
1399
+ `/api/v1/support-telemetry/cases/by-external/${encodeURIComponent(externalCaseRef)}${qs ? `?${qs}` : ""}`
1400
+ );
1401
+ return this.unwrapApiResponse(
1402
+ res,
1403
+ "Failed to get support telemetry case by external ref"
1404
+ );
1405
+ }
1406
+ };
1011
1407
  /**
1012
1408
  * Marketing events and experiment results.
1013
1409
  *
@@ -1126,7 +1522,7 @@ var SPAPSClient = class _SPAPSClient {
1126
1522
  this.refreshToken = void 0;
1127
1523
  }
1128
1524
  }
1129
- return Promise.reject(error);
1525
+ return Promise.reject(buildSPAPSSDKErrorFromAxios(error));
1130
1526
  }
1131
1527
  );
1132
1528
  }
@@ -1141,6 +1537,9 @@ var SPAPSClient = class _SPAPSClient {
1141
1537
  const res = await this.client.request(config);
1142
1538
  return { success: true, data: res.data };
1143
1539
  } catch (err) {
1540
+ if (err instanceof SPAPSSDKError) {
1541
+ return Promise.reject(err);
1542
+ }
1144
1543
  const message = err?.response?.data?.error?.message || err?.message || "Request failed";
1145
1544
  return Promise.reject(new Error(message));
1146
1545
  }
@@ -1200,8 +1599,20 @@ var SPAPSClient = class _SPAPSClient {
1200
1599
  async getUser() {
1201
1600
  return this.client.get("/api/auth/user");
1202
1601
  }
1602
+ async getSessionContext() {
1603
+ const res = await this.client.get("/api/auth/session-context", this.authConfig());
1604
+ return this.unwrapApiResponse(res, "Failed to get session context");
1605
+ }
1203
1606
  // -------- Facade namespaces (compat with previous SDK shape) --------
1204
1607
  auth = {
1608
+ getMethods: async () => {
1609
+ const res = await this.client.get("/api/auth/methods");
1610
+ return this.unwrapApiResponse(res, "Auth method discovery failed");
1611
+ },
1612
+ getSessionContext: async () => {
1613
+ const res = await this.client.get("/api/auth/session-context", this.authConfig());
1614
+ return this.unwrapApiResponse(res, "Failed to get session context");
1615
+ },
1205
1616
  /**
1206
1617
  * Verify magic link token without mutating token state.
1207
1618
  * Returns a simple success object from the API.
@@ -1214,12 +1625,7 @@ var SPAPSClient = class _SPAPSClient {
1214
1625
  },
1215
1626
  signInWithWallet: async (req) => {
1216
1627
  const res = await this.client.post("/api/auth/wallet-sign-in", req);
1217
- const body = res.data;
1218
- if (body?.success === false) throw new Error(body?.error?.message || "Wallet sign-in failed");
1219
- const data = body?.data ?? body;
1220
- this.accessToken = data.access_token;
1221
- this.refreshToken = data.refresh_token;
1222
- return data;
1628
+ return this.unwrapAuthMethodResponse(res, "Wallet sign-in failed");
1223
1629
  },
1224
1630
  authenticateWallet: async (walletAddress, signFn, chainType, username) => {
1225
1631
  const nonce = await this.auth.getNonce(walletAddress);
@@ -1228,12 +1634,11 @@ var SPAPSClient = class _SPAPSClient {
1228
1634
  },
1229
1635
  signInWithPassword: async (payload) => {
1230
1636
  const res = await this.client.post("/api/auth/login", payload);
1231
- const body = res.data;
1232
- if (body?.success === false) throw new Error(body?.error?.message || "Login failed");
1233
- const data = body?.data ?? body;
1234
- this.accessToken = data.access_token;
1235
- this.refreshToken = data.refresh_token;
1236
- return data;
1637
+ return this.unwrapAuthMethodResponse(res, "Login failed");
1638
+ },
1639
+ login: async (payload) => {
1640
+ const res = await this.client.post("/api/auth/login", payload);
1641
+ return this.unwrapAuthMethodResponse(res, "Login failed");
1237
1642
  },
1238
1643
  requestMagicLink: async (payload) => {
1239
1644
  await this.client.post("/api/auth/magic-link", payload);
@@ -1255,6 +1660,20 @@ var SPAPSClient = class _SPAPSClient {
1255
1660
  if (body?.success === false) throw new Error(body?.error?.message || "Set password failed");
1256
1661
  return { message: body?.message || "Password updated successfully" };
1257
1662
  },
1663
+ deleteCurrentAccount: async (payload) => {
1664
+ const config = {
1665
+ ...this.authConfig("Access token is required to delete the current account"),
1666
+ data: payload
1667
+ };
1668
+ const res = await this.client.delete("/api/auth/me", config);
1669
+ const result = this.unwrapApiResponse(
1670
+ res,
1671
+ "Failed to delete current account"
1672
+ );
1673
+ this.accessToken = void 0;
1674
+ this.refreshToken = void 0;
1675
+ return result;
1676
+ },
1258
1677
  register: async (payload) => {
1259
1678
  const res = await this.client.post("/api/auth/register", payload);
1260
1679
  const body = res.data;
@@ -1271,18 +1690,71 @@ var SPAPSClient = class _SPAPSClient {
1271
1690
  verifyMagicLink: async (payload) => {
1272
1691
  const res = await this.client.post("/api/auth/verify-magic-link", {
1273
1692
  token: payload.token,
1274
- type: payload.type || "magiclink"
1693
+ type: payload.type || "magiclink",
1694
+ ...payload.state ? { state: payload.state } : {}
1275
1695
  });
1276
- const body = res.data;
1277
- if (body?.success === false) throw new Error(body?.error?.message || "Magic link verification failed");
1278
- const data = {
1279
- access_token: body.tokens?.access_token || body.access_token,
1280
- refresh_token: body.tokens?.refresh_token || body.refresh_token,
1281
- user: body.user
1282
- };
1283
- this.accessToken = data.access_token;
1284
- this.refreshToken = data.refresh_token;
1285
- return data;
1696
+ return this.unwrapAuthMethodResponse(res, "Magic link verification failed");
1697
+ },
1698
+ oidc: {
1699
+ getNonce: async () => {
1700
+ const res = await this.client.post("/api/auth/oidc/nonce");
1701
+ return this.unwrapApiResponse(res, "OIDC nonce request failed");
1702
+ },
1703
+ signIn: async (payload) => {
1704
+ const res = await this.client.post("/api/auth/oidc/sign-in", payload);
1705
+ return this.unwrapAuthMethodResponse(res, "OIDC sign-in failed");
1706
+ }
1707
+ },
1708
+ webauthn: {
1709
+ registerOptions: async () => {
1710
+ const res = await this.client.post("/api/auth/webauthn/register/options");
1711
+ return this.unwrapApiResponse(res, "WebAuthn registration options failed");
1712
+ },
1713
+ registerVerify: async (payload) => {
1714
+ const res = await this.client.post("/api/auth/webauthn/register/verify", payload);
1715
+ return this.unwrapApiResponse(
1716
+ res,
1717
+ "WebAuthn registration verification failed"
1718
+ );
1719
+ },
1720
+ assertionOptions: async (payload) => {
1721
+ const res = await this.client.post("/api/auth/webauthn/assertion/options", payload ?? {});
1722
+ return this.unwrapApiResponse(res, "WebAuthn assertion options failed");
1723
+ },
1724
+ assertionVerify: async (payload) => {
1725
+ const res = await this.client.post("/api/auth/webauthn/assertion/verify", payload);
1726
+ return this.unwrapAuthMethodResponse(res, "WebAuthn assertion verification failed");
1727
+ }
1728
+ },
1729
+ mfa: {
1730
+ totp: {
1731
+ enroll: async () => {
1732
+ const res = await this.client.post("/api/auth/mfa/totp/enroll");
1733
+ return this.unwrapApiResponse(res, "MFA TOTP enrollment failed");
1734
+ },
1735
+ activate: async (payload) => {
1736
+ const res = await this.client.post("/api/auth/mfa/totp/activate", payload);
1737
+ return this.unwrapApiResponse(res, "MFA TOTP activation failed");
1738
+ },
1739
+ disable: async (payload) => {
1740
+ const res = await this.client.post("/api/auth/mfa/totp/disable", payload);
1741
+ return this.unwrapApiResponse(res, "MFA TOTP disable failed");
1742
+ }
1743
+ },
1744
+ verify: async (payload) => {
1745
+ const res = await this.client.post("/api/auth/mfa/verify", payload);
1746
+ return this.unwrapAuthMethodResponse(res, "MFA verification failed");
1747
+ }
1748
+ },
1749
+ sms: {
1750
+ request: async (payload) => {
1751
+ const res = await this.client.post("/api/auth/sms/request", payload);
1752
+ return this.unwrapApiResponse(res, "SMS OTP request failed");
1753
+ },
1754
+ verify: async (payload) => {
1755
+ const res = await this.client.post("/api/auth/sms/verify", payload);
1756
+ return this.unwrapAuthMethodResponse(res, "SMS OTP verification failed");
1757
+ }
1286
1758
  },
1287
1759
  solana: {
1288
1760
  linkWallet: async (payload) => {
@@ -1914,6 +2386,92 @@ var SPAPSClient = class _SPAPSClient {
1914
2386
  return this.unwrapApiResponse(res, "Failed to list usage history");
1915
2387
  }
1916
2388
  };
2389
+ /**
2390
+ * Agent-oriented access decisions and action preparation.
2391
+ *
2392
+ * `check` intentionally resolves for denied decisions; inspect
2393
+ * `allowed`, `outcome`, and `next_actions` to decide what to do next.
2394
+ */
2395
+ access = {
2396
+ check: async (payload) => {
2397
+ const res = await this.client.post("/api/access/decide", payload);
2398
+ return this.unwrapApiResponse(res, "Failed to check access");
2399
+ },
2400
+ decide: async (payload) => {
2401
+ const res = await this.client.post("/api/access/decide", payload);
2402
+ return this.unwrapApiResponse(res, "Failed to decide access");
2403
+ },
2404
+ prepareAction: async (payload) => {
2405
+ const res = await this.client.post("/api/actions/prepare", payload);
2406
+ return this.unwrapApiResponse(res, "Failed to prepare action");
2407
+ },
2408
+ getDecision: async (decisionTraceId) => {
2409
+ const res = await this.client.get(`/api/access/decisions/${encodeURIComponent(decisionTraceId)}`);
2410
+ return this.unwrapApiResponse(res, "Failed to get access decision");
2411
+ },
2412
+ explain: async (decisionTraceId) => {
2413
+ const res = await this.client.get(`/api/graph/explain/${encodeURIComponent(decisionTraceId)}`);
2414
+ return this.unwrapApiResponse(res, "Failed to explain access decision");
2415
+ }
2416
+ };
2417
+ /**
2418
+ * Capability graph inspection helpers. These require a secret key.
2419
+ */
2420
+ graph = {
2421
+ listNodes: async (query = {}) => {
2422
+ const params = new URLSearchParams();
2423
+ if (query.node_type) params.set("node_type", query.node_type);
2424
+ if (query.status) params.set("status", query.status);
2425
+ if (query.q) params.set("q", query.q);
2426
+ if (query.cursor) params.set("cursor", query.cursor);
2427
+ if (query.limit !== void 0) params.set("limit", String(query.limit));
2428
+ if (query.application_id) params.set("application_id", query.application_id);
2429
+ const suffix = params.toString() ? `?${params.toString()}` : "";
2430
+ const res = await this.client.get(`/api/graph/nodes${suffix}`);
2431
+ return this.unwrapApiResponse(res, "Failed to list capability graph nodes");
2432
+ },
2433
+ getPaths: async (query) => {
2434
+ const params = new URLSearchParams();
2435
+ params.set("from_node_key", query.from_node_key);
2436
+ params.set("to_node_key", query.to_node_key);
2437
+ if (query.max_depth !== void 0) params.set("max_depth", String(query.max_depth));
2438
+ if (query.limit !== void 0) params.set("limit", String(query.limit));
2439
+ if (query.include_stale !== void 0) params.set("include_stale", String(query.include_stale));
2440
+ if (query.application_id) params.set("application_id", query.application_id);
2441
+ const res = await this.client.get(`/api/graph/paths?${params.toString()}`);
2442
+ return this.unwrapApiResponse(res, "Failed to get capability graph paths");
2443
+ },
2444
+ getImpact: async (query) => {
2445
+ const params = new URLSearchParams();
2446
+ params.set("node_key", query.node_key);
2447
+ if (query.max_depth !== void 0) params.set("max_depth", String(query.max_depth));
2448
+ if (query.limit !== void 0) params.set("limit", String(query.limit));
2449
+ if (query.include_stale !== void 0) params.set("include_stale", String(query.include_stale));
2450
+ if (query.application_id) params.set("application_id", query.application_id);
2451
+ const res = await this.client.get(`/api/graph/impact?${params.toString()}`);
2452
+ return this.unwrapApiResponse(res, "Failed to get capability graph impact");
2453
+ },
2454
+ explain: async (decisionTraceId) => {
2455
+ return this.access.explain(decisionTraceId);
2456
+ },
2457
+ refresh: async (correlationId, applicationId) => {
2458
+ const params = new URLSearchParams();
2459
+ if (correlationId) params.set("correlation_id", correlationId);
2460
+ if (applicationId) params.set("application_id", applicationId);
2461
+ const suffix = params.toString() ? `?${params.toString()}` : "";
2462
+ const res = await this.client.post(`/api/graph/refresh${suffix}`);
2463
+ return this.unwrapApiResponse(res, "Failed to refresh capability graph");
2464
+ }
2465
+ };
2466
+ /**
2467
+ * Machine-readable capability graph contract for agents and SDK adapters.
2468
+ */
2469
+ contract = {
2470
+ get: async () => {
2471
+ const res = await this.client.get("/api/contract");
2472
+ return this.unwrapApiResponse(res, "Failed to get capability graph contract");
2473
+ }
2474
+ };
1917
2475
  // Stripe Methods
1918
2476
  async createCheckoutSession(priceId, successUrl, cancelUrl) {
1919
2477
  return this.client.post("/api/stripe/checkout-sessions", {
@@ -2050,11 +2608,12 @@ var SPAPSClient = class _SPAPSClient {
2050
2608
  if (!this.accessToken) {
2051
2609
  throw new Error("Authentication required. Please authenticate first.");
2052
2610
  }
2053
- return this.client.delete(`/api/stripe/products/${productId}`, {
2611
+ const res = await this.client.delete(`/api/stripe/products/${productId}`, {
2054
2612
  headers: {
2055
2613
  "Authorization": `Bearer ${this.accessToken}`
2056
2614
  }
2057
2615
  });
2616
+ return this.unwrapApiResponse(res, "Failed to archive product");
2058
2617
  }
2059
2618
  /**
2060
2619
  * Create a new price for a product (Admin required)
@@ -2366,8 +2925,7 @@ function isErrorEnvelope(value) {
2366
2925
  function unwrapEnvelope(value, fallbackMessage) {
2367
2926
  if (!isEnvelope(value)) return value;
2368
2927
  if (value.success === false) {
2369
- const message = isErrorEnvelope(value) ? value.error.message : void 0;
2370
- throw new Error(message || fallbackMessage || "SPAPS request failed");
2928
+ throw buildSPAPSSDKError(value, fallbackMessage || "SPAPS request failed");
2371
2929
  }
2372
2930
  return value.data;
2373
2931
  }
@@ -2414,6 +2972,7 @@ export {
2414
2972
  RoleHierarchy,
2415
2973
  SPAPSClient as SPAPS,
2416
2974
  SPAPSClient,
2975
+ SPAPSSDKError,
2417
2976
  TokenManager,
2418
2977
  WalletUtils,
2419
2978
  WebSocketAuthHelper,