@astrasyncai/verification-gateway 5.18.1 → 5.20.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/CHANGELOG.md +232 -0
- package/README.md +217 -4
- package/dist/adapter-interface/interface.d.mts +2 -2
- package/dist/adapter-interface/interface.d.ts +2 -2
- package/dist/adapters/express.d.mts +9 -1
- package/dist/adapters/express.d.ts +9 -1
- package/dist/adapters/express.js +160 -52
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/express.mjs +160 -52
- package/dist/adapters/express.mjs.map +1 -1
- package/dist/adapters/http-pdlss.d.mts +7 -1
- package/dist/adapters/http-pdlss.d.ts +7 -1
- package/dist/adapters/http-pdlss.js +18 -2
- package/dist/adapters/http-pdlss.js.map +1 -1
- package/dist/adapters/http-pdlss.mjs +16 -1
- package/dist/adapters/http-pdlss.mjs.map +1 -1
- package/dist/adapters/kit-express.d.mts +93 -1
- package/dist/adapters/kit-express.d.ts +93 -1
- package/dist/adapters/kit-express.js +181 -2
- package/dist/adapters/kit-express.js.map +1 -1
- package/dist/adapters/kit-express.mjs +180 -2
- package/dist/adapters/kit-express.mjs.map +1 -1
- package/dist/adapters/mcp.d.mts +102 -9
- package/dist/adapters/mcp.d.ts +102 -9
- package/dist/adapters/mcp.js +242 -19
- package/dist/adapters/mcp.js.map +1 -1
- package/dist/adapters/mcp.mjs +240 -19
- package/dist/adapters/mcp.mjs.map +1 -1
- package/dist/adapters/nextjs.d.mts +1 -1
- package/dist/adapters/nextjs.d.ts +1 -1
- package/dist/adapters/nextjs.js +97 -14
- package/dist/adapters/nextjs.js.map +1 -1
- package/dist/adapters/nextjs.mjs +97 -14
- package/dist/adapters/nextjs.mjs.map +1 -1
- package/dist/adapters/sdk.d.mts +101 -2
- package/dist/adapters/sdk.d.ts +101 -2
- package/dist/adapters/sdk.js +199 -12
- package/dist/adapters/sdk.js.map +1 -1
- package/dist/adapters/sdk.mjs +199 -12
- package/dist/adapters/sdk.mjs.map +1 -1
- package/dist/agent/index.d.mts +1 -1
- package/dist/agent/index.d.ts +1 -1
- package/dist/agent/index.js +1 -1
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/index.mjs +1 -1
- package/dist/agent/index.mjs.map +1 -1
- package/dist/bin/astrasync-claude-hook.js +94 -16
- package/dist/bin/astrasync-codex-hook.js +94 -16
- package/dist/bin/astrasync-guard.js +94 -16
- package/dist/bin/astrasync.js +127 -16
- package/dist/browser/background.js +94 -16
- package/dist/browser/background.js.map +1 -1
- package/dist/browser/background.mjs +94 -16
- package/dist/browser/background.mjs.map +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +1 -1
- package/dist/cli/index.mjs.map +1 -1
- package/dist/codex/index.js +94 -16
- package/dist/codex/index.js.map +1 -1
- package/dist/codex/index.mjs +94 -16
- package/dist/codex/index.mjs.map +1 -1
- package/dist/cursor/extension.js +94 -16
- package/dist/cursor/extension.js.map +1 -1
- package/dist/cursor/extension.mjs +94 -16
- package/dist/cursor/extension.mjs.map +1 -1
- package/dist/edge-config.d.mts +1 -1
- package/dist/edge-config.d.ts +1 -1
- package/dist/edge-config.js +1 -1
- package/dist/edge-config.js.map +1 -1
- package/dist/edge-config.mjs +1 -1
- package/dist/edge-config.mjs.map +1 -1
- package/dist/edge-core/index.d.mts +1 -1
- package/dist/edge-core/index.d.ts +1 -1
- package/dist/edge-core/index.js +69 -12
- package/dist/edge-core/index.js.map +1 -1
- package/dist/edge-core/index.mjs +69 -12
- package/dist/edge-core/index.mjs.map +1 -1
- package/dist/gateway/gateway.d.mts +2 -2
- package/dist/gateway/gateway.d.ts +2 -2
- package/dist/gateway/gateway.js +94 -16
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/gateway.mjs +94 -16
- package/dist/gateway/gateway.mjs.map +1 -1
- package/dist/git-trigger/git-hooks.d.mts +1 -1
- package/dist/git-trigger/git-hooks.d.ts +1 -1
- package/dist/index.d.mts +706 -34
- package/dist/index.d.ts +706 -34
- package/dist/index.js +1391 -205
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1374 -195
- package/dist/index.mjs.map +1 -1
- package/dist/local-evaluator/evaluator.d.mts +2 -2
- package/dist/local-evaluator/evaluator.d.ts +2 -2
- package/dist/registration/index.d.mts +11 -2
- package/dist/registration/index.d.ts +11 -2
- package/dist/registration/index.js +1 -1
- package/dist/registration/index.js.map +1 -1
- package/dist/registration/index.mjs +1 -1
- package/dist/registration/index.mjs.map +1 -1
- package/dist/transport/index.d.mts +1 -1
- package/dist/transport/index.d.ts +1 -1
- package/dist/transport/index.js +3 -2
- package/dist/transport/index.js.map +1 -1
- package/dist/transport/index.mjs +3 -2
- package/dist/transport/index.mjs.map +1 -1
- package/dist/{types-BRz2U0Pn.d.ts → types-B_HLhZ9n.d.ts} +1 -1
- package/dist/{types-BfILnheI.d.mts → types-CU17R4Nr.d.mts} +11 -0
- package/dist/{types-BfILnheI.d.ts → types-CU17R4Nr.d.ts} +11 -0
- package/dist/{types-Cns4l8gX.d.mts → types-CxjqmPl-.d.mts} +115 -13
- package/dist/{types-Cns4l8gX.d.ts → types-CxjqmPl-.d.ts} +115 -13
- package/dist/{types-3ObBpsnf.d.mts → types-D37aSQ9c.d.mts} +106 -3
- package/dist/{types-CfBpm3w5.d.mts → types-Djpz-L0w.d.mts} +1 -1
- package/dist/{types-BoxZEYPS.d.ts → types-Dn8tXnei.d.ts} +106 -3
- package/dist/ui/index.d.mts +1 -1
- package/dist/ui/index.d.ts +1 -1
- package/dist/verify.d.mts +50 -4
- package/dist/verify.d.ts +50 -4
- package/dist/verify.js +93 -14
- package/dist/verify.js.map +1 -1
- package/dist/verify.mjs +91 -14
- package/dist/verify.mjs.map +1 -1
- package/dist/webhooks.d.mts +16 -3
- package/dist/webhooks.d.ts +16 -3
- package/dist/webhooks.js +24 -13
- package/dist/webhooks.js.map +1 -1
- package/dist/webhooks.mjs +24 -13
- package/dist/webhooks.mjs.map +1 -1
- package/package.json +1 -1
package/dist/adapters/sdk.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/version.ts
|
|
2
|
-
var SDK_VERSION = "5.
|
|
2
|
+
var SDK_VERSION = "5.20.0";
|
|
3
3
|
|
|
4
4
|
// src/http.ts
|
|
5
5
|
var SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;
|
|
@@ -177,7 +177,12 @@ function getCacheKey(request, counterpartyId) {
|
|
|
177
177
|
// its start_checkout quote was served the cached quote-leg grant (no
|
|
178
178
|
// settlementOutcome) and never reached the backend. Same F-A1-07 bug class.
|
|
179
179
|
request.commercePhase || "",
|
|
180
|
-
request.checkoutSessionId || ""
|
|
180
|
+
request.checkoutSessionId || "",
|
|
181
|
+
// 5.19.0: a route_config purpose claim is checked server-side against
|
|
182
|
+
// the stored rule for this method + path, so it changes the verdict.
|
|
183
|
+
request.purposeSource || "",
|
|
184
|
+
request.requestMethod || "",
|
|
185
|
+
request.requestPath || ""
|
|
181
186
|
].join("|");
|
|
182
187
|
}
|
|
183
188
|
function getCachedResult(request, counterpartyId) {
|
|
@@ -202,6 +207,7 @@ function cacheResult(request, result, configuredTtl, counterpartyId) {
|
|
|
202
207
|
}
|
|
203
208
|
function clearCache() {
|
|
204
209
|
verificationCache.clear();
|
|
210
|
+
inflightVerifies.clear();
|
|
205
211
|
}
|
|
206
212
|
function mcpGuidance(urls) {
|
|
207
213
|
if (!urls?.mcpEndpoint) return void 0;
|
|
@@ -338,6 +344,9 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
338
344
|
if (requestData.enableRuntimeChallenge)
|
|
339
345
|
body.enableRuntimeChallenge = requestData.enableRuntimeChallenge;
|
|
340
346
|
if (requestData.routePolicy) body.routePolicy = requestData.routePolicy;
|
|
347
|
+
if (config.actingProof?.connectorToken) {
|
|
348
|
+
body.actingProof = { connectorToken: config.actingProof.connectorToken };
|
|
349
|
+
}
|
|
341
350
|
if (requestData.approvalHeldByRoute) body.approvalHeldByRoute = true;
|
|
342
351
|
if (requestData.createSession) body.createSession = requestData.createSession;
|
|
343
352
|
if (requestData.durationRequired) body.durationRequired = requestData.durationRequired;
|
|
@@ -354,6 +363,11 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
354
363
|
if (requestData.buyerEmail) body.buyerEmail = requestData.buyerEmail;
|
|
355
364
|
if (requestData.commerceArtifacts) body.commerceArtifacts = requestData.commerceArtifacts;
|
|
356
365
|
if (requestData.attemptId) body.attemptId = requestData.attemptId;
|
|
366
|
+
if (requestData.purposeSource) body.purposeSource = requestData.purposeSource;
|
|
367
|
+
if (requestData.agentArtifacts) body.agentArtifacts = requestData.agentArtifacts;
|
|
368
|
+
if (requestData.metadata) body.metadata = requestData.metadata;
|
|
369
|
+
if (requestData.requestMethod) body.requestMethod = requestData.requestMethod;
|
|
370
|
+
if (requestData.requestPath) body.requestPath = requestData.requestPath;
|
|
357
371
|
if (requestData.considerationSet) body.considerationSet = requestData.considerationSet;
|
|
358
372
|
body.sdkVersion = SDK_VERSION;
|
|
359
373
|
if (requestData.callerMetadata || requestData.clientIp || requestData.userAgent) {
|
|
@@ -500,22 +514,43 @@ async function verify(config, request, options) {
|
|
|
500
514
|
"[VerificationGateway] minTrustScore / minTrustScoreForFull are deprecated in v2.3.0 and have no effect. Server is now the single source of truth for access decisions (verified ID + runtime challenge + PDLSS + trust score). To gate access to an endpoint, configure the endpoint's trust_score_requirement server-side."
|
|
501
515
|
);
|
|
502
516
|
}
|
|
503
|
-
const uncacheable = Boolean(request.commerceArtifacts);
|
|
517
|
+
const uncacheable = Boolean(request.commerceArtifacts) || Boolean(mergedConfig.actingProof);
|
|
504
518
|
if (mergedConfig.cacheTtl !== 0 && !options?.bypassCache && !uncacheable) {
|
|
505
519
|
const cached = getCachedResult(request, mergedConfig.counterpartyId);
|
|
506
520
|
if (cached) {
|
|
507
521
|
if (mergedConfig.debug) {
|
|
508
522
|
console.log("[VerificationGateway] Returning cached result");
|
|
509
523
|
}
|
|
510
|
-
|
|
511
|
-
if (request.attemptId) {
|
|
512
|
-
hit.attemptId = request.attemptId;
|
|
513
|
-
} else {
|
|
514
|
-
delete hit.attemptId;
|
|
515
|
-
}
|
|
516
|
-
return hit;
|
|
524
|
+
return sharedVerdict(cached, request);
|
|
517
525
|
}
|
|
518
526
|
}
|
|
527
|
+
if (mergedConfig.cacheTtl !== 0 && !options?.bypassCache && !uncacheable) {
|
|
528
|
+
const key = getCacheKey(request, mergedConfig.counterpartyId);
|
|
529
|
+
const pending = inflightVerifies.get(key);
|
|
530
|
+
if (pending) return sharedVerdict(await pending, request);
|
|
531
|
+
const flight = verifyViaApi(mergedConfig, request, urls, uncacheable);
|
|
532
|
+
inflightVerifies.set(key, flight);
|
|
533
|
+
try {
|
|
534
|
+
return await flight;
|
|
535
|
+
} finally {
|
|
536
|
+
inflightVerifies.delete(key);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
return verifyViaApi(mergedConfig, request, urls, uncacheable);
|
|
540
|
+
}
|
|
541
|
+
var inflightVerifies = /* @__PURE__ */ new Map();
|
|
542
|
+
var sharedVerdicts = /* @__PURE__ */ new WeakSet();
|
|
543
|
+
function sharedVerdict(source, request) {
|
|
544
|
+
const hit = { ...source };
|
|
545
|
+
if (request.attemptId) {
|
|
546
|
+
hit.attemptId = request.attemptId;
|
|
547
|
+
} else {
|
|
548
|
+
delete hit.attemptId;
|
|
549
|
+
}
|
|
550
|
+
sharedVerdicts.add(hit);
|
|
551
|
+
return hit;
|
|
552
|
+
}
|
|
553
|
+
async function verifyViaApi(mergedConfig, request, urls, uncacheable) {
|
|
519
554
|
const enrichedRequest = { ...request };
|
|
520
555
|
if (!enrichedRequest.counterpartyUrl && mergedConfig.counterpartyUrl) {
|
|
521
556
|
enrichedRequest.counterpartyUrl = mergedConfig.counterpartyUrl;
|
|
@@ -543,9 +578,18 @@ async function verify(config, request, options) {
|
|
|
543
578
|
if (!apiResponse.access?.allowed) {
|
|
544
579
|
const aggregatedFailures = apiResponse.access?.failures;
|
|
545
580
|
const idVerifiedFromBackend = apiResponse.verificationContext?.idVerified === true && !aggregatedFailures?.some((f) => REJECTED_IDENTITY_DIMENSIONS.has(f.dimension));
|
|
581
|
+
const denyAgent = idVerifiedFromBackend && apiResponse.agent ? {
|
|
582
|
+
astraId: apiResponse.agent.astraId,
|
|
583
|
+
name: apiResponse.agent.name,
|
|
584
|
+
trustScore: apiResponse.agent.trustScore,
|
|
585
|
+
trustLevel: getTrustLevel(apiResponse.agent.trustScore),
|
|
586
|
+
blockchainAnchored: apiResponse.agent.blockchainStatus === "anchored",
|
|
587
|
+
status: apiResponse.agent.agentStatus
|
|
588
|
+
} : void 0;
|
|
546
589
|
const result2 = {
|
|
547
590
|
identityVerified: idVerifiedFromBackend,
|
|
548
591
|
policyAllowed: false,
|
|
592
|
+
...denyAgent && { agent: denyAgent },
|
|
549
593
|
// 3.6.0: the server now emits top-level denialReasons on every deny
|
|
550
594
|
// path — prefer it verbatim; the failure-message reconstruction remains
|
|
551
595
|
// as the fallback for older backends.
|
|
@@ -585,7 +629,9 @@ async function verify(config, request, options) {
|
|
|
585
629
|
fulfilment: apiResponse.fulfilment,
|
|
586
630
|
mandates: apiResponse.mandates,
|
|
587
631
|
kyaToken: apiResponse.kyaToken,
|
|
588
|
-
aep: apiResponse.aep
|
|
632
|
+
aep: apiResponse.aep,
|
|
633
|
+
// 5.20.0 (round 29.1): non-fatal integration warnings (e.g. events_url_missing).
|
|
634
|
+
warnings: apiResponse.warnings
|
|
589
635
|
};
|
|
590
636
|
return result2;
|
|
591
637
|
}
|
|
@@ -653,7 +699,9 @@ async function verify(config, request, options) {
|
|
|
653
699
|
// 5.15.0: merchant-lane AP2 mandates + KYAPay identity token.
|
|
654
700
|
mandates: apiResponse.mandates,
|
|
655
701
|
kyaToken: apiResponse.kyaToken,
|
|
656
|
-
aep: apiResponse.aep
|
|
702
|
+
aep: apiResponse.aep,
|
|
703
|
+
// 5.20.0 (round 29.1): non-fatal integration warnings (e.g. events_url_missing).
|
|
704
|
+
warnings: apiResponse.warnings
|
|
657
705
|
};
|
|
658
706
|
if (result.recommendation === "deny") {
|
|
659
707
|
result.policyAllowed = false;
|
|
@@ -679,8 +727,18 @@ async function verify(config, request, options) {
|
|
|
679
727
|
cacheResult(request, result, mergedConfig.cacheTtl, mergedConfig.counterpartyId);
|
|
680
728
|
}
|
|
681
729
|
}
|
|
730
|
+
notifyVerificationListeners(request, result);
|
|
682
731
|
return result;
|
|
683
732
|
}
|
|
733
|
+
var verificationListeners = /* @__PURE__ */ new Set();
|
|
734
|
+
function notifyVerificationListeners(request, result) {
|
|
735
|
+
for (const listener of verificationListeners) {
|
|
736
|
+
try {
|
|
737
|
+
listener(result, request);
|
|
738
|
+
} catch {
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
}
|
|
684
742
|
async function quickVerify(config, credentials) {
|
|
685
743
|
const result = await verify(config, {
|
|
686
744
|
credentials,
|
|
@@ -716,6 +774,7 @@ var SettlementReportError = class extends AstraSyncError {
|
|
|
716
774
|
};
|
|
717
775
|
|
|
718
776
|
// src/adapters/sdk.ts
|
|
777
|
+
var warnedPhaselessValue = false;
|
|
719
778
|
var VerificationGatewayClient = class {
|
|
720
779
|
constructor(options) {
|
|
721
780
|
this.config = {
|
|
@@ -747,9 +806,16 @@ var VerificationGatewayClient = class {
|
|
|
747
806
|
apiKey: options.apiKey,
|
|
748
807
|
jwt: options.jwt
|
|
749
808
|
};
|
|
809
|
+
if (options.transactionValue && !options.commercePhase && !warnedPhaselessValue) {
|
|
810
|
+
warnedPhaselessValue = true;
|
|
811
|
+
console.warn(
|
|
812
|
+
"[astrasync] verify() with a transactionValue and no commercePhase is a purchase leg: it records a pending order and redeems a matching owner approval. Use quoteCheckout() for a price / limit check (commercePhase 'quote') and confirmCheckout() for the purchase. The default becomes 'quote' in 6.0."
|
|
813
|
+
);
|
|
814
|
+
}
|
|
750
815
|
return this.executeWithRetry(
|
|
751
816
|
() => verify(this.config, {
|
|
752
817
|
credentials,
|
|
818
|
+
...options.commercePhase && { commercePhase: options.commercePhase },
|
|
753
819
|
purpose: options.purpose,
|
|
754
820
|
action: options.action,
|
|
755
821
|
resourceType: options.resourceType,
|
|
@@ -765,6 +831,43 @@ var VerificationGatewayClient = class {
|
|
|
765
831
|
})
|
|
766
832
|
);
|
|
767
833
|
}
|
|
834
|
+
/**
|
|
835
|
+
* 5.19.0: the QUOTE leg of a checkout — a price / limit check before the
|
|
836
|
+
* purchase. Sends `commercePhase: 'quote'`: verify-access evaluates the
|
|
837
|
+
* agent's policy at this value and tells you whether a purchase would be
|
|
838
|
+
* granted, held for the owner's approval, or denied, but records no order,
|
|
839
|
+
* moves no money and never redeems an approval. Always reaches the backend
|
|
840
|
+
* (no verdict cache).
|
|
841
|
+
*
|
|
842
|
+
* Quotes count toward limit-probing detection: a run of rising quotes is
|
|
843
|
+
* how an agent (or a merchant) maps a spending limit. Quote what the buyer
|
|
844
|
+
* asked for, not a ladder of values.
|
|
845
|
+
*/
|
|
846
|
+
async quoteCheckout(options) {
|
|
847
|
+
const credentials = {
|
|
848
|
+
astraId: options.astraId,
|
|
849
|
+
apiKey: options.apiKey,
|
|
850
|
+
jwt: options.jwt
|
|
851
|
+
};
|
|
852
|
+
return this.executeWithRetry(
|
|
853
|
+
() => verify(
|
|
854
|
+
this.config,
|
|
855
|
+
{
|
|
856
|
+
credentials,
|
|
857
|
+
purpose: options.purpose ?? "shopping",
|
|
858
|
+
action: options.action ?? "shopping.purchase",
|
|
859
|
+
transactionValue: options.transactionValue,
|
|
860
|
+
currency: options.currency,
|
|
861
|
+
commercePhase: "quote",
|
|
862
|
+
...options.checkoutSessionId && { checkoutSessionId: options.checkoutSessionId },
|
|
863
|
+
...options.attemptId && { attemptId: options.attemptId },
|
|
864
|
+
counterpartyUrl: options.counterpartyUrl,
|
|
865
|
+
counterpartyType: options.counterpartyType
|
|
866
|
+
},
|
|
867
|
+
{ bypassCache: true }
|
|
868
|
+
)
|
|
869
|
+
);
|
|
870
|
+
}
|
|
768
871
|
/**
|
|
769
872
|
* 5.4.0 (astra-pay): confirm-leg of a checkout — the ONLY call that may fire
|
|
770
873
|
* first-party charge-at-redeem (server-side settlement on the owner's saved
|
|
@@ -803,6 +906,14 @@ var VerificationGatewayClient = class {
|
|
|
803
906
|
* is matched to — and only to — this confirm. A held cart's approval is
|
|
804
907
|
* bound to its checkout session and exact value; a confirm for any other
|
|
805
908
|
* cart is held for its own approval.
|
|
909
|
+
*
|
|
910
|
+
* 5.19.0 checkout kits: pass the kit's `agentArtifacts` (the inbound agent
|
|
911
|
+
* request — signed RFC 9421 headers with the public URL and raw-body
|
|
912
|
+
* digest, or `{ unsigned: true }`) and `metadata` (`{ kitSessionId,
|
|
913
|
+
* protocol }`) from the `verifyPurchase` context. The platform attributes
|
|
914
|
+
* the confirm to the agent from the artifacts, and stores the metadata on
|
|
915
|
+
* any approval this confirm creates so the approval event
|
|
916
|
+
* (`handleApprovalEvents`) can find the kit session.
|
|
806
917
|
*/
|
|
807
918
|
async confirmCheckout(options) {
|
|
808
919
|
const credentials = {
|
|
@@ -825,6 +936,8 @@ var VerificationGatewayClient = class {
|
|
|
825
936
|
...options.checkoutJwt && { checkoutJwt: options.checkoutJwt },
|
|
826
937
|
...options.attemptId && { attemptId: options.attemptId },
|
|
827
938
|
buyerEmail: options.buyerEmail,
|
|
939
|
+
...options.agentArtifacts && { agentArtifacts: options.agentArtifacts },
|
|
940
|
+
...options.metadata && { metadata: options.metadata },
|
|
828
941
|
counterpartyUrl: options.counterpartyUrl,
|
|
829
942
|
counterpartyType: options.counterpartyType
|
|
830
943
|
},
|
|
@@ -885,6 +998,80 @@ var VerificationGatewayClient = class {
|
|
|
885
998
|
}
|
|
886
999
|
return json.data;
|
|
887
1000
|
}
|
|
1001
|
+
/**
|
|
1002
|
+
* 5.20.0 (round 29.1): change an endpoint's OPERATIONAL URLs with this
|
|
1003
|
+
* client's API key — `PATCH /api/endpoints/:id`. Accepts the key of the
|
|
1004
|
+
* endpoint's owner, or a personal key of an individual with an active seat
|
|
1005
|
+
* in the owning organisation. Policy (rules, trust floor, challenge, edge
|
|
1006
|
+
* config) stays dashboard-only. `null` clears a field. The owner is alerted
|
|
1007
|
+
* when `eventsUrl` changes.
|
|
1008
|
+
*
|
|
1009
|
+
* @param endpointId the ASTRAE id (defaults to the client's `counterpartyId`)
|
|
1010
|
+
* @returns the endpoint as stored, plus `changed` (the fields that changed)
|
|
1011
|
+
* @throws AstraSyncError — 400 `UNKNOWN_FIELDS` / validation, 401/403, 404
|
|
1012
|
+
*/
|
|
1013
|
+
async updateEndpoint(endpointId, patch) {
|
|
1014
|
+
return this.endpointCall("PATCH", endpointId, "", patch);
|
|
1015
|
+
}
|
|
1016
|
+
/**
|
|
1017
|
+
* 5.20.0 (round 29.1): ask AstraSync to send ONE signed step-up event to the
|
|
1018
|
+
* endpoint's Events URL now — `POST /api/endpoints/:id/events/test`.
|
|
1019
|
+
* Delivered synchronously, outside the event outbox (random `eventId`, no
|
|
1020
|
+
* retries), signed with the endpoint's webhook secret like a real event.
|
|
1021
|
+
* Without `approvalId` the payload is synthetic (a kit acknowledges and
|
|
1022
|
+
* ignores it). With the id of a held kit approval at this endpoint the
|
|
1023
|
+
* payload is the real one, so your resume path runs: `approved` makes the
|
|
1024
|
+
* kit re-confirm (held again — nothing is charged); `denied` / `expired` /
|
|
1025
|
+
* `lapsed` release the session.
|
|
1026
|
+
*
|
|
1027
|
+
* Resolves even when your endpoint refused the event (`delivered: false`,
|
|
1028
|
+
* with `responseCode` / `error`).
|
|
1029
|
+
*/
|
|
1030
|
+
async sendTestEvent(endpointId, options) {
|
|
1031
|
+
return this.endpointCall("POST", endpointId, "/events/test", options);
|
|
1032
|
+
}
|
|
1033
|
+
async endpointCall(method, endpointId, suffix, body) {
|
|
1034
|
+
const id = endpointId ?? this.config.counterpartyId;
|
|
1035
|
+
if (!id) {
|
|
1036
|
+
throw new AstraSyncError(
|
|
1037
|
+
"An endpoint id (ASTRAE-\u2026) is required: pass it, or set counterpartyId on the client",
|
|
1038
|
+
400,
|
|
1039
|
+
"VALIDATION"
|
|
1040
|
+
);
|
|
1041
|
+
}
|
|
1042
|
+
if (!this.config.apiKey) {
|
|
1043
|
+
throw new AstraSyncError("This call needs the client apiKey", 401, "AUTH_REQUIRED");
|
|
1044
|
+
}
|
|
1045
|
+
const base = this.config.apiBaseUrl.replace(/\/+$/, "");
|
|
1046
|
+
const url = `${base}/endpoints/${encodeURIComponent(id)}${suffix}`;
|
|
1047
|
+
let res;
|
|
1048
|
+
try {
|
|
1049
|
+
res = await sdkFetch(url, {
|
|
1050
|
+
method,
|
|
1051
|
+
headers: {
|
|
1052
|
+
"Content-Type": "application/json",
|
|
1053
|
+
Authorization: `Bearer ${this.config.apiKey}`,
|
|
1054
|
+
"X-API-Key": this.config.apiKey
|
|
1055
|
+
},
|
|
1056
|
+
body: JSON.stringify(body),
|
|
1057
|
+
signal: AbortSignal.timeout(Math.max(this.timeout, 15e3))
|
|
1058
|
+
});
|
|
1059
|
+
} catch (err) {
|
|
1060
|
+
throw new AstraSyncError(
|
|
1061
|
+
`${method} ${suffix || "/endpoints/:id"} failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
1062
|
+
0,
|
|
1063
|
+
"network_error"
|
|
1064
|
+
);
|
|
1065
|
+
}
|
|
1066
|
+
const json = await res.json().catch(() => ({}));
|
|
1067
|
+
if (!res.ok || json.success === false || json.data === void 0) {
|
|
1068
|
+
const errObj = typeof json.error === "object" ? json.error : void 0;
|
|
1069
|
+
const code = json.code ?? errObj?.code ?? (typeof json.error === "string" ? json.error : "unknown_error");
|
|
1070
|
+
const message = json.message ?? errObj?.message ?? `HTTP ${res.status}`;
|
|
1071
|
+
throw new AstraSyncError(`${message} (${code})`, res.status, code);
|
|
1072
|
+
}
|
|
1073
|
+
return json.data;
|
|
1074
|
+
}
|
|
888
1075
|
/**
|
|
889
1076
|
* Quick verification — checks credentials and policy in one call.
|
|
890
1077
|
*
|