@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.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { T as TrustLevel, S as SDKOptions,
|
|
1
|
+
import { T as TrustLevel, S as SDKOptions, e as VerificationResult, d as VerificationRequest, A as AgentArtifacts, C as CheckoutMetadata } from '../types-CxjqmPl-.mjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* AstraSync Universal Verification Gateway — Trust Level helpers.
|
|
@@ -68,6 +68,37 @@ declare class VerificationGatewayClient {
|
|
|
68
68
|
subAgentDepth?: number;
|
|
69
69
|
counterpartyUrl?: string;
|
|
70
70
|
counterpartyType?: string;
|
|
71
|
+
/**
|
|
72
|
+
* 5.19.0: `'quote'` marks a price / limit check (peek only: no order, no
|
|
73
|
+
* approval redeemed) — prefer `quoteCheckout()`. Omitted with a
|
|
74
|
+
* `transactionValue`, the call is a PURCHASE leg (see the warning below).
|
|
75
|
+
*/
|
|
76
|
+
commercePhase?: 'quote';
|
|
77
|
+
}): Promise<VerificationResult>;
|
|
78
|
+
/**
|
|
79
|
+
* 5.19.0: the QUOTE leg of a checkout — a price / limit check before the
|
|
80
|
+
* purchase. Sends `commercePhase: 'quote'`: verify-access evaluates the
|
|
81
|
+
* agent's policy at this value and tells you whether a purchase would be
|
|
82
|
+
* granted, held for the owner's approval, or denied, but records no order,
|
|
83
|
+
* moves no money and never redeems an approval. Always reaches the backend
|
|
84
|
+
* (no verdict cache).
|
|
85
|
+
*
|
|
86
|
+
* Quotes count toward limit-probing detection: a run of rising quotes is
|
|
87
|
+
* how an agent (or a merchant) maps a spending limit. Quote what the buyer
|
|
88
|
+
* asked for, not a ladder of values.
|
|
89
|
+
*/
|
|
90
|
+
quoteCheckout(options: {
|
|
91
|
+
astraId?: string;
|
|
92
|
+
apiKey?: string;
|
|
93
|
+
jwt?: string;
|
|
94
|
+
purpose?: string;
|
|
95
|
+
action?: string;
|
|
96
|
+
transactionValue?: number;
|
|
97
|
+
currency?: string;
|
|
98
|
+
checkoutSessionId?: string;
|
|
99
|
+
attemptId?: string;
|
|
100
|
+
counterpartyUrl?: string;
|
|
101
|
+
counterpartyType?: string;
|
|
71
102
|
}): Promise<VerificationResult>;
|
|
72
103
|
/**
|
|
73
104
|
* 5.4.0 (astra-pay): confirm-leg of a checkout — the ONLY call that may fire
|
|
@@ -107,6 +138,14 @@ declare class VerificationGatewayClient {
|
|
|
107
138
|
* is matched to — and only to — this confirm. A held cart's approval is
|
|
108
139
|
* bound to its checkout session and exact value; a confirm for any other
|
|
109
140
|
* cart is held for its own approval.
|
|
141
|
+
*
|
|
142
|
+
* 5.19.0 checkout kits: pass the kit's `agentArtifacts` (the inbound agent
|
|
143
|
+
* request — signed RFC 9421 headers with the public URL and raw-body
|
|
144
|
+
* digest, or `{ unsigned: true }`) and `metadata` (`{ kitSessionId,
|
|
145
|
+
* protocol }`) from the `verifyPurchase` context. The platform attributes
|
|
146
|
+
* the confirm to the agent from the artifacts, and stores the metadata on
|
|
147
|
+
* any approval this confirm creates so the approval event
|
|
148
|
+
* (`handleApprovalEvents`) can find the kit session.
|
|
110
149
|
*/
|
|
111
150
|
confirmCheckout(options: {
|
|
112
151
|
astraId?: string;
|
|
@@ -125,6 +164,10 @@ declare class VerificationGatewayClient {
|
|
|
125
164
|
/** 5.6.0: alternate receipt/delivery email (transit-only) — omit to let
|
|
126
165
|
* the platform default `fulfilment.email` to the buyer's account email. */
|
|
127
166
|
buyerEmail?: string;
|
|
167
|
+
/** 5.19.0: the inbound agent request behind this confirm (from the kit's verifyPurchase ctx). */
|
|
168
|
+
agentArtifacts?: AgentArtifacts;
|
|
169
|
+
/** 5.19.0: `{ kitSessionId, protocol }` (from the kit's verifyPurchase ctx). */
|
|
170
|
+
metadata?: CheckoutMetadata;
|
|
128
171
|
counterpartyUrl?: string;
|
|
129
172
|
counterpartyType?: string;
|
|
130
173
|
}): Promise<VerificationResult>;
|
|
@@ -156,6 +199,40 @@ declare class VerificationGatewayClient {
|
|
|
156
199
|
status: string;
|
|
157
200
|
alreadySettled?: boolean;
|
|
158
201
|
}>;
|
|
202
|
+
/**
|
|
203
|
+
* 5.20.0 (round 29.1): change an endpoint's OPERATIONAL URLs with this
|
|
204
|
+
* client's API key — `PATCH /api/endpoints/:id`. Accepts the key of the
|
|
205
|
+
* endpoint's owner, or a personal key of an individual with an active seat
|
|
206
|
+
* in the owning organisation. Policy (rules, trust floor, challenge, edge
|
|
207
|
+
* config) stays dashboard-only. `null` clears a field. The owner is alerted
|
|
208
|
+
* when `eventsUrl` changes.
|
|
209
|
+
*
|
|
210
|
+
* @param endpointId the ASTRAE id (defaults to the client's `counterpartyId`)
|
|
211
|
+
* @returns the endpoint as stored, plus `changed` (the fields that changed)
|
|
212
|
+
* @throws AstraSyncError — 400 `UNKNOWN_FIELDS` / validation, 401/403, 404
|
|
213
|
+
*/
|
|
214
|
+
updateEndpoint(endpointId: string | undefined, patch: EndpointOperationalPatch): Promise<Record<string, unknown> & {
|
|
215
|
+
changed: Array<keyof EndpointOperationalPatch>;
|
|
216
|
+
}>;
|
|
217
|
+
/**
|
|
218
|
+
* 5.20.0 (round 29.1): ask AstraSync to send ONE signed step-up event to the
|
|
219
|
+
* endpoint's Events URL now — `POST /api/endpoints/:id/events/test`.
|
|
220
|
+
* Delivered synchronously, outside the event outbox (random `eventId`, no
|
|
221
|
+
* retries), signed with the endpoint's webhook secret like a real event.
|
|
222
|
+
* Without `approvalId` the payload is synthetic (a kit acknowledges and
|
|
223
|
+
* ignores it). With the id of a held kit approval at this endpoint the
|
|
224
|
+
* payload is the real one, so your resume path runs: `approved` makes the
|
|
225
|
+
* kit re-confirm (held again — nothing is charged); `denied` / `expired` /
|
|
226
|
+
* `lapsed` release the session.
|
|
227
|
+
*
|
|
228
|
+
* Resolves even when your endpoint refused the event (`delivered: false`,
|
|
229
|
+
* with `responseCode` / `error`).
|
|
230
|
+
*/
|
|
231
|
+
sendTestEvent(endpointId: string | undefined, options: {
|
|
232
|
+
type: TestEventType;
|
|
233
|
+
approvalId?: string;
|
|
234
|
+
}): Promise<TestEventResult>;
|
|
235
|
+
private endpointCall;
|
|
159
236
|
/**
|
|
160
237
|
* Quick verification — checks credentials and policy in one call.
|
|
161
238
|
*
|
|
@@ -195,6 +272,28 @@ declare class VerificationGatewayClient {
|
|
|
195
272
|
*/
|
|
196
273
|
private executeWithRetry;
|
|
197
274
|
}
|
|
275
|
+
/** 5.20.0: the operational fields `updateEndpoint` may change (`null` clears). */
|
|
276
|
+
interface EndpointOperationalPatch {
|
|
277
|
+
eventsUrl?: string | null;
|
|
278
|
+
healthCheckUrl?: string | null;
|
|
279
|
+
skillUrl?: string | null;
|
|
280
|
+
catalogUrl?: string | null;
|
|
281
|
+
checkoutUrl?: string | null;
|
|
282
|
+
}
|
|
283
|
+
/** 5.20.0: the step-up event types `sendTestEvent` can send. */
|
|
284
|
+
type TestEventType = 'step_up.approved' | 'step_up.denied' | 'step_up.expired' | 'step_up.lapsed';
|
|
285
|
+
/** 5.20.0: what `sendTestEvent` reports. */
|
|
286
|
+
interface TestEventResult {
|
|
287
|
+
delivered: boolean;
|
|
288
|
+
/** delivered | failed (bad answer / unreachable) | not_configured (no Events URL or secret). */
|
|
289
|
+
status: 'delivered' | 'failed' | 'not_configured';
|
|
290
|
+
/** Your endpoint's HTTP status, or null when nothing answered. */
|
|
291
|
+
responseCode: number | null;
|
|
292
|
+
error: string | null;
|
|
293
|
+
eventId: string;
|
|
294
|
+
type: TestEventType;
|
|
295
|
+
approvalId: string | null;
|
|
296
|
+
}
|
|
198
297
|
/**
|
|
199
298
|
* Create a new SDK client
|
|
200
299
|
*/
|
|
@@ -210,4 +309,4 @@ declare function verifyOnce(options: SDKOptions & {
|
|
|
210
309
|
action?: string;
|
|
211
310
|
}): Promise<VerificationResult>;
|
|
212
311
|
|
|
213
|
-
export { VerificationGatewayClient, createClient, getTrustLevel, verifyOnce };
|
|
312
|
+
export { type EndpointOperationalPatch, type TestEventResult, type TestEventType, VerificationGatewayClient, createClient, getTrustLevel, verifyOnce };
|
package/dist/adapters/sdk.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { T as TrustLevel, S as SDKOptions,
|
|
1
|
+
import { T as TrustLevel, S as SDKOptions, e as VerificationResult, d as VerificationRequest, A as AgentArtifacts, C as CheckoutMetadata } from '../types-CxjqmPl-.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* AstraSync Universal Verification Gateway — Trust Level helpers.
|
|
@@ -68,6 +68,37 @@ declare class VerificationGatewayClient {
|
|
|
68
68
|
subAgentDepth?: number;
|
|
69
69
|
counterpartyUrl?: string;
|
|
70
70
|
counterpartyType?: string;
|
|
71
|
+
/**
|
|
72
|
+
* 5.19.0: `'quote'` marks a price / limit check (peek only: no order, no
|
|
73
|
+
* approval redeemed) — prefer `quoteCheckout()`. Omitted with a
|
|
74
|
+
* `transactionValue`, the call is a PURCHASE leg (see the warning below).
|
|
75
|
+
*/
|
|
76
|
+
commercePhase?: 'quote';
|
|
77
|
+
}): Promise<VerificationResult>;
|
|
78
|
+
/**
|
|
79
|
+
* 5.19.0: the QUOTE leg of a checkout — a price / limit check before the
|
|
80
|
+
* purchase. Sends `commercePhase: 'quote'`: verify-access evaluates the
|
|
81
|
+
* agent's policy at this value and tells you whether a purchase would be
|
|
82
|
+
* granted, held for the owner's approval, or denied, but records no order,
|
|
83
|
+
* moves no money and never redeems an approval. Always reaches the backend
|
|
84
|
+
* (no verdict cache).
|
|
85
|
+
*
|
|
86
|
+
* Quotes count toward limit-probing detection: a run of rising quotes is
|
|
87
|
+
* how an agent (or a merchant) maps a spending limit. Quote what the buyer
|
|
88
|
+
* asked for, not a ladder of values.
|
|
89
|
+
*/
|
|
90
|
+
quoteCheckout(options: {
|
|
91
|
+
astraId?: string;
|
|
92
|
+
apiKey?: string;
|
|
93
|
+
jwt?: string;
|
|
94
|
+
purpose?: string;
|
|
95
|
+
action?: string;
|
|
96
|
+
transactionValue?: number;
|
|
97
|
+
currency?: string;
|
|
98
|
+
checkoutSessionId?: string;
|
|
99
|
+
attemptId?: string;
|
|
100
|
+
counterpartyUrl?: string;
|
|
101
|
+
counterpartyType?: string;
|
|
71
102
|
}): Promise<VerificationResult>;
|
|
72
103
|
/**
|
|
73
104
|
* 5.4.0 (astra-pay): confirm-leg of a checkout — the ONLY call that may fire
|
|
@@ -107,6 +138,14 @@ declare class VerificationGatewayClient {
|
|
|
107
138
|
* is matched to — and only to — this confirm. A held cart's approval is
|
|
108
139
|
* bound to its checkout session and exact value; a confirm for any other
|
|
109
140
|
* cart is held for its own approval.
|
|
141
|
+
*
|
|
142
|
+
* 5.19.0 checkout kits: pass the kit's `agentArtifacts` (the inbound agent
|
|
143
|
+
* request — signed RFC 9421 headers with the public URL and raw-body
|
|
144
|
+
* digest, or `{ unsigned: true }`) and `metadata` (`{ kitSessionId,
|
|
145
|
+
* protocol }`) from the `verifyPurchase` context. The platform attributes
|
|
146
|
+
* the confirm to the agent from the artifacts, and stores the metadata on
|
|
147
|
+
* any approval this confirm creates so the approval event
|
|
148
|
+
* (`handleApprovalEvents`) can find the kit session.
|
|
110
149
|
*/
|
|
111
150
|
confirmCheckout(options: {
|
|
112
151
|
astraId?: string;
|
|
@@ -125,6 +164,10 @@ declare class VerificationGatewayClient {
|
|
|
125
164
|
/** 5.6.0: alternate receipt/delivery email (transit-only) — omit to let
|
|
126
165
|
* the platform default `fulfilment.email` to the buyer's account email. */
|
|
127
166
|
buyerEmail?: string;
|
|
167
|
+
/** 5.19.0: the inbound agent request behind this confirm (from the kit's verifyPurchase ctx). */
|
|
168
|
+
agentArtifacts?: AgentArtifacts;
|
|
169
|
+
/** 5.19.0: `{ kitSessionId, protocol }` (from the kit's verifyPurchase ctx). */
|
|
170
|
+
metadata?: CheckoutMetadata;
|
|
128
171
|
counterpartyUrl?: string;
|
|
129
172
|
counterpartyType?: string;
|
|
130
173
|
}): Promise<VerificationResult>;
|
|
@@ -156,6 +199,40 @@ declare class VerificationGatewayClient {
|
|
|
156
199
|
status: string;
|
|
157
200
|
alreadySettled?: boolean;
|
|
158
201
|
}>;
|
|
202
|
+
/**
|
|
203
|
+
* 5.20.0 (round 29.1): change an endpoint's OPERATIONAL URLs with this
|
|
204
|
+
* client's API key — `PATCH /api/endpoints/:id`. Accepts the key of the
|
|
205
|
+
* endpoint's owner, or a personal key of an individual with an active seat
|
|
206
|
+
* in the owning organisation. Policy (rules, trust floor, challenge, edge
|
|
207
|
+
* config) stays dashboard-only. `null` clears a field. The owner is alerted
|
|
208
|
+
* when `eventsUrl` changes.
|
|
209
|
+
*
|
|
210
|
+
* @param endpointId the ASTRAE id (defaults to the client's `counterpartyId`)
|
|
211
|
+
* @returns the endpoint as stored, plus `changed` (the fields that changed)
|
|
212
|
+
* @throws AstraSyncError — 400 `UNKNOWN_FIELDS` / validation, 401/403, 404
|
|
213
|
+
*/
|
|
214
|
+
updateEndpoint(endpointId: string | undefined, patch: EndpointOperationalPatch): Promise<Record<string, unknown> & {
|
|
215
|
+
changed: Array<keyof EndpointOperationalPatch>;
|
|
216
|
+
}>;
|
|
217
|
+
/**
|
|
218
|
+
* 5.20.0 (round 29.1): ask AstraSync to send ONE signed step-up event to the
|
|
219
|
+
* endpoint's Events URL now — `POST /api/endpoints/:id/events/test`.
|
|
220
|
+
* Delivered synchronously, outside the event outbox (random `eventId`, no
|
|
221
|
+
* retries), signed with the endpoint's webhook secret like a real event.
|
|
222
|
+
* Without `approvalId` the payload is synthetic (a kit acknowledges and
|
|
223
|
+
* ignores it). With the id of a held kit approval at this endpoint the
|
|
224
|
+
* payload is the real one, so your resume path runs: `approved` makes the
|
|
225
|
+
* kit re-confirm (held again — nothing is charged); `denied` / `expired` /
|
|
226
|
+
* `lapsed` release the session.
|
|
227
|
+
*
|
|
228
|
+
* Resolves even when your endpoint refused the event (`delivered: false`,
|
|
229
|
+
* with `responseCode` / `error`).
|
|
230
|
+
*/
|
|
231
|
+
sendTestEvent(endpointId: string | undefined, options: {
|
|
232
|
+
type: TestEventType;
|
|
233
|
+
approvalId?: string;
|
|
234
|
+
}): Promise<TestEventResult>;
|
|
235
|
+
private endpointCall;
|
|
159
236
|
/**
|
|
160
237
|
* Quick verification — checks credentials and policy in one call.
|
|
161
238
|
*
|
|
@@ -195,6 +272,28 @@ declare class VerificationGatewayClient {
|
|
|
195
272
|
*/
|
|
196
273
|
private executeWithRetry;
|
|
197
274
|
}
|
|
275
|
+
/** 5.20.0: the operational fields `updateEndpoint` may change (`null` clears). */
|
|
276
|
+
interface EndpointOperationalPatch {
|
|
277
|
+
eventsUrl?: string | null;
|
|
278
|
+
healthCheckUrl?: string | null;
|
|
279
|
+
skillUrl?: string | null;
|
|
280
|
+
catalogUrl?: string | null;
|
|
281
|
+
checkoutUrl?: string | null;
|
|
282
|
+
}
|
|
283
|
+
/** 5.20.0: the step-up event types `sendTestEvent` can send. */
|
|
284
|
+
type TestEventType = 'step_up.approved' | 'step_up.denied' | 'step_up.expired' | 'step_up.lapsed';
|
|
285
|
+
/** 5.20.0: what `sendTestEvent` reports. */
|
|
286
|
+
interface TestEventResult {
|
|
287
|
+
delivered: boolean;
|
|
288
|
+
/** delivered | failed (bad answer / unreachable) | not_configured (no Events URL or secret). */
|
|
289
|
+
status: 'delivered' | 'failed' | 'not_configured';
|
|
290
|
+
/** Your endpoint's HTTP status, or null when nothing answered. */
|
|
291
|
+
responseCode: number | null;
|
|
292
|
+
error: string | null;
|
|
293
|
+
eventId: string;
|
|
294
|
+
type: TestEventType;
|
|
295
|
+
approvalId: string | null;
|
|
296
|
+
}
|
|
198
297
|
/**
|
|
199
298
|
* Create a new SDK client
|
|
200
299
|
*/
|
|
@@ -210,4 +309,4 @@ declare function verifyOnce(options: SDKOptions & {
|
|
|
210
309
|
action?: string;
|
|
211
310
|
}): Promise<VerificationResult>;
|
|
212
311
|
|
|
213
|
-
export { VerificationGatewayClient, createClient, getTrustLevel, verifyOnce };
|
|
312
|
+
export { type EndpointOperationalPatch, type TestEventResult, type TestEventType, VerificationGatewayClient, createClient, getTrustLevel, verifyOnce };
|
package/dist/adapters/sdk.js
CHANGED
|
@@ -28,7 +28,7 @@ __export(sdk_exports, {
|
|
|
28
28
|
module.exports = __toCommonJS(sdk_exports);
|
|
29
29
|
|
|
30
30
|
// src/version.ts
|
|
31
|
-
var SDK_VERSION = "5.
|
|
31
|
+
var SDK_VERSION = "5.20.0";
|
|
32
32
|
|
|
33
33
|
// src/http.ts
|
|
34
34
|
var SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;
|
|
@@ -206,7 +206,12 @@ function getCacheKey(request, counterpartyId) {
|
|
|
206
206
|
// its start_checkout quote was served the cached quote-leg grant (no
|
|
207
207
|
// settlementOutcome) and never reached the backend. Same F-A1-07 bug class.
|
|
208
208
|
request.commercePhase || "",
|
|
209
|
-
request.checkoutSessionId || ""
|
|
209
|
+
request.checkoutSessionId || "",
|
|
210
|
+
// 5.19.0: a route_config purpose claim is checked server-side against
|
|
211
|
+
// the stored rule for this method + path, so it changes the verdict.
|
|
212
|
+
request.purposeSource || "",
|
|
213
|
+
request.requestMethod || "",
|
|
214
|
+
request.requestPath || ""
|
|
210
215
|
].join("|");
|
|
211
216
|
}
|
|
212
217
|
function getCachedResult(request, counterpartyId) {
|
|
@@ -231,6 +236,7 @@ function cacheResult(request, result, configuredTtl, counterpartyId) {
|
|
|
231
236
|
}
|
|
232
237
|
function clearCache() {
|
|
233
238
|
verificationCache.clear();
|
|
239
|
+
inflightVerifies.clear();
|
|
234
240
|
}
|
|
235
241
|
function mcpGuidance(urls) {
|
|
236
242
|
if (!urls?.mcpEndpoint) return void 0;
|
|
@@ -367,6 +373,9 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
367
373
|
if (requestData.enableRuntimeChallenge)
|
|
368
374
|
body.enableRuntimeChallenge = requestData.enableRuntimeChallenge;
|
|
369
375
|
if (requestData.routePolicy) body.routePolicy = requestData.routePolicy;
|
|
376
|
+
if (config.actingProof?.connectorToken) {
|
|
377
|
+
body.actingProof = { connectorToken: config.actingProof.connectorToken };
|
|
378
|
+
}
|
|
370
379
|
if (requestData.approvalHeldByRoute) body.approvalHeldByRoute = true;
|
|
371
380
|
if (requestData.createSession) body.createSession = requestData.createSession;
|
|
372
381
|
if (requestData.durationRequired) body.durationRequired = requestData.durationRequired;
|
|
@@ -383,6 +392,11 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
383
392
|
if (requestData.buyerEmail) body.buyerEmail = requestData.buyerEmail;
|
|
384
393
|
if (requestData.commerceArtifacts) body.commerceArtifacts = requestData.commerceArtifacts;
|
|
385
394
|
if (requestData.attemptId) body.attemptId = requestData.attemptId;
|
|
395
|
+
if (requestData.purposeSource) body.purposeSource = requestData.purposeSource;
|
|
396
|
+
if (requestData.agentArtifacts) body.agentArtifacts = requestData.agentArtifacts;
|
|
397
|
+
if (requestData.metadata) body.metadata = requestData.metadata;
|
|
398
|
+
if (requestData.requestMethod) body.requestMethod = requestData.requestMethod;
|
|
399
|
+
if (requestData.requestPath) body.requestPath = requestData.requestPath;
|
|
386
400
|
if (requestData.considerationSet) body.considerationSet = requestData.considerationSet;
|
|
387
401
|
body.sdkVersion = SDK_VERSION;
|
|
388
402
|
if (requestData.callerMetadata || requestData.clientIp || requestData.userAgent) {
|
|
@@ -529,22 +543,43 @@ async function verify(config, request, options) {
|
|
|
529
543
|
"[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."
|
|
530
544
|
);
|
|
531
545
|
}
|
|
532
|
-
const uncacheable = Boolean(request.commerceArtifacts);
|
|
546
|
+
const uncacheable = Boolean(request.commerceArtifacts) || Boolean(mergedConfig.actingProof);
|
|
533
547
|
if (mergedConfig.cacheTtl !== 0 && !options?.bypassCache && !uncacheable) {
|
|
534
548
|
const cached = getCachedResult(request, mergedConfig.counterpartyId);
|
|
535
549
|
if (cached) {
|
|
536
550
|
if (mergedConfig.debug) {
|
|
537
551
|
console.log("[VerificationGateway] Returning cached result");
|
|
538
552
|
}
|
|
539
|
-
|
|
540
|
-
if (request.attemptId) {
|
|
541
|
-
hit.attemptId = request.attemptId;
|
|
542
|
-
} else {
|
|
543
|
-
delete hit.attemptId;
|
|
544
|
-
}
|
|
545
|
-
return hit;
|
|
553
|
+
return sharedVerdict(cached, request);
|
|
546
554
|
}
|
|
547
555
|
}
|
|
556
|
+
if (mergedConfig.cacheTtl !== 0 && !options?.bypassCache && !uncacheable) {
|
|
557
|
+
const key = getCacheKey(request, mergedConfig.counterpartyId);
|
|
558
|
+
const pending = inflightVerifies.get(key);
|
|
559
|
+
if (pending) return sharedVerdict(await pending, request);
|
|
560
|
+
const flight = verifyViaApi(mergedConfig, request, urls, uncacheable);
|
|
561
|
+
inflightVerifies.set(key, flight);
|
|
562
|
+
try {
|
|
563
|
+
return await flight;
|
|
564
|
+
} finally {
|
|
565
|
+
inflightVerifies.delete(key);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
return verifyViaApi(mergedConfig, request, urls, uncacheable);
|
|
569
|
+
}
|
|
570
|
+
var inflightVerifies = /* @__PURE__ */ new Map();
|
|
571
|
+
var sharedVerdicts = /* @__PURE__ */ new WeakSet();
|
|
572
|
+
function sharedVerdict(source, request) {
|
|
573
|
+
const hit = { ...source };
|
|
574
|
+
if (request.attemptId) {
|
|
575
|
+
hit.attemptId = request.attemptId;
|
|
576
|
+
} else {
|
|
577
|
+
delete hit.attemptId;
|
|
578
|
+
}
|
|
579
|
+
sharedVerdicts.add(hit);
|
|
580
|
+
return hit;
|
|
581
|
+
}
|
|
582
|
+
async function verifyViaApi(mergedConfig, request, urls, uncacheable) {
|
|
548
583
|
const enrichedRequest = { ...request };
|
|
549
584
|
if (!enrichedRequest.counterpartyUrl && mergedConfig.counterpartyUrl) {
|
|
550
585
|
enrichedRequest.counterpartyUrl = mergedConfig.counterpartyUrl;
|
|
@@ -572,9 +607,18 @@ async function verify(config, request, options) {
|
|
|
572
607
|
if (!apiResponse.access?.allowed) {
|
|
573
608
|
const aggregatedFailures = apiResponse.access?.failures;
|
|
574
609
|
const idVerifiedFromBackend = apiResponse.verificationContext?.idVerified === true && !aggregatedFailures?.some((f) => REJECTED_IDENTITY_DIMENSIONS.has(f.dimension));
|
|
610
|
+
const denyAgent = idVerifiedFromBackend && apiResponse.agent ? {
|
|
611
|
+
astraId: apiResponse.agent.astraId,
|
|
612
|
+
name: apiResponse.agent.name,
|
|
613
|
+
trustScore: apiResponse.agent.trustScore,
|
|
614
|
+
trustLevel: getTrustLevel(apiResponse.agent.trustScore),
|
|
615
|
+
blockchainAnchored: apiResponse.agent.blockchainStatus === "anchored",
|
|
616
|
+
status: apiResponse.agent.agentStatus
|
|
617
|
+
} : void 0;
|
|
575
618
|
const result2 = {
|
|
576
619
|
identityVerified: idVerifiedFromBackend,
|
|
577
620
|
policyAllowed: false,
|
|
621
|
+
...denyAgent && { agent: denyAgent },
|
|
578
622
|
// 3.6.0: the server now emits top-level denialReasons on every deny
|
|
579
623
|
// path — prefer it verbatim; the failure-message reconstruction remains
|
|
580
624
|
// as the fallback for older backends.
|
|
@@ -614,7 +658,9 @@ async function verify(config, request, options) {
|
|
|
614
658
|
fulfilment: apiResponse.fulfilment,
|
|
615
659
|
mandates: apiResponse.mandates,
|
|
616
660
|
kyaToken: apiResponse.kyaToken,
|
|
617
|
-
aep: apiResponse.aep
|
|
661
|
+
aep: apiResponse.aep,
|
|
662
|
+
// 5.20.0 (round 29.1): non-fatal integration warnings (e.g. events_url_missing).
|
|
663
|
+
warnings: apiResponse.warnings
|
|
618
664
|
};
|
|
619
665
|
return result2;
|
|
620
666
|
}
|
|
@@ -682,7 +728,9 @@ async function verify(config, request, options) {
|
|
|
682
728
|
// 5.15.0: merchant-lane AP2 mandates + KYAPay identity token.
|
|
683
729
|
mandates: apiResponse.mandates,
|
|
684
730
|
kyaToken: apiResponse.kyaToken,
|
|
685
|
-
aep: apiResponse.aep
|
|
731
|
+
aep: apiResponse.aep,
|
|
732
|
+
// 5.20.0 (round 29.1): non-fatal integration warnings (e.g. events_url_missing).
|
|
733
|
+
warnings: apiResponse.warnings
|
|
686
734
|
};
|
|
687
735
|
if (result.recommendation === "deny") {
|
|
688
736
|
result.policyAllowed = false;
|
|
@@ -708,8 +756,18 @@ async function verify(config, request, options) {
|
|
|
708
756
|
cacheResult(request, result, mergedConfig.cacheTtl, mergedConfig.counterpartyId);
|
|
709
757
|
}
|
|
710
758
|
}
|
|
759
|
+
notifyVerificationListeners(request, result);
|
|
711
760
|
return result;
|
|
712
761
|
}
|
|
762
|
+
var verificationListeners = /* @__PURE__ */ new Set();
|
|
763
|
+
function notifyVerificationListeners(request, result) {
|
|
764
|
+
for (const listener of verificationListeners) {
|
|
765
|
+
try {
|
|
766
|
+
listener(result, request);
|
|
767
|
+
} catch {
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
}
|
|
713
771
|
async function quickVerify(config, credentials) {
|
|
714
772
|
const result = await verify(config, {
|
|
715
773
|
credentials,
|
|
@@ -745,6 +803,7 @@ var SettlementReportError = class extends AstraSyncError {
|
|
|
745
803
|
};
|
|
746
804
|
|
|
747
805
|
// src/adapters/sdk.ts
|
|
806
|
+
var warnedPhaselessValue = false;
|
|
748
807
|
var VerificationGatewayClient = class {
|
|
749
808
|
constructor(options) {
|
|
750
809
|
this.config = {
|
|
@@ -776,9 +835,16 @@ var VerificationGatewayClient = class {
|
|
|
776
835
|
apiKey: options.apiKey,
|
|
777
836
|
jwt: options.jwt
|
|
778
837
|
};
|
|
838
|
+
if (options.transactionValue && !options.commercePhase && !warnedPhaselessValue) {
|
|
839
|
+
warnedPhaselessValue = true;
|
|
840
|
+
console.warn(
|
|
841
|
+
"[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."
|
|
842
|
+
);
|
|
843
|
+
}
|
|
779
844
|
return this.executeWithRetry(
|
|
780
845
|
() => verify(this.config, {
|
|
781
846
|
credentials,
|
|
847
|
+
...options.commercePhase && { commercePhase: options.commercePhase },
|
|
782
848
|
purpose: options.purpose,
|
|
783
849
|
action: options.action,
|
|
784
850
|
resourceType: options.resourceType,
|
|
@@ -794,6 +860,43 @@ var VerificationGatewayClient = class {
|
|
|
794
860
|
})
|
|
795
861
|
);
|
|
796
862
|
}
|
|
863
|
+
/**
|
|
864
|
+
* 5.19.0: the QUOTE leg of a checkout — a price / limit check before the
|
|
865
|
+
* purchase. Sends `commercePhase: 'quote'`: verify-access evaluates the
|
|
866
|
+
* agent's policy at this value and tells you whether a purchase would be
|
|
867
|
+
* granted, held for the owner's approval, or denied, but records no order,
|
|
868
|
+
* moves no money and never redeems an approval. Always reaches the backend
|
|
869
|
+
* (no verdict cache).
|
|
870
|
+
*
|
|
871
|
+
* Quotes count toward limit-probing detection: a run of rising quotes is
|
|
872
|
+
* how an agent (or a merchant) maps a spending limit. Quote what the buyer
|
|
873
|
+
* asked for, not a ladder of values.
|
|
874
|
+
*/
|
|
875
|
+
async quoteCheckout(options) {
|
|
876
|
+
const credentials = {
|
|
877
|
+
astraId: options.astraId,
|
|
878
|
+
apiKey: options.apiKey,
|
|
879
|
+
jwt: options.jwt
|
|
880
|
+
};
|
|
881
|
+
return this.executeWithRetry(
|
|
882
|
+
() => verify(
|
|
883
|
+
this.config,
|
|
884
|
+
{
|
|
885
|
+
credentials,
|
|
886
|
+
purpose: options.purpose ?? "shopping",
|
|
887
|
+
action: options.action ?? "shopping.purchase",
|
|
888
|
+
transactionValue: options.transactionValue,
|
|
889
|
+
currency: options.currency,
|
|
890
|
+
commercePhase: "quote",
|
|
891
|
+
...options.checkoutSessionId && { checkoutSessionId: options.checkoutSessionId },
|
|
892
|
+
...options.attemptId && { attemptId: options.attemptId },
|
|
893
|
+
counterpartyUrl: options.counterpartyUrl,
|
|
894
|
+
counterpartyType: options.counterpartyType
|
|
895
|
+
},
|
|
896
|
+
{ bypassCache: true }
|
|
897
|
+
)
|
|
898
|
+
);
|
|
899
|
+
}
|
|
797
900
|
/**
|
|
798
901
|
* 5.4.0 (astra-pay): confirm-leg of a checkout — the ONLY call that may fire
|
|
799
902
|
* first-party charge-at-redeem (server-side settlement on the owner's saved
|
|
@@ -832,6 +935,14 @@ var VerificationGatewayClient = class {
|
|
|
832
935
|
* is matched to — and only to — this confirm. A held cart's approval is
|
|
833
936
|
* bound to its checkout session and exact value; a confirm for any other
|
|
834
937
|
* cart is held for its own approval.
|
|
938
|
+
*
|
|
939
|
+
* 5.19.0 checkout kits: pass the kit's `agentArtifacts` (the inbound agent
|
|
940
|
+
* request — signed RFC 9421 headers with the public URL and raw-body
|
|
941
|
+
* digest, or `{ unsigned: true }`) and `metadata` (`{ kitSessionId,
|
|
942
|
+
* protocol }`) from the `verifyPurchase` context. The platform attributes
|
|
943
|
+
* the confirm to the agent from the artifacts, and stores the metadata on
|
|
944
|
+
* any approval this confirm creates so the approval event
|
|
945
|
+
* (`handleApprovalEvents`) can find the kit session.
|
|
835
946
|
*/
|
|
836
947
|
async confirmCheckout(options) {
|
|
837
948
|
const credentials = {
|
|
@@ -854,6 +965,8 @@ var VerificationGatewayClient = class {
|
|
|
854
965
|
...options.checkoutJwt && { checkoutJwt: options.checkoutJwt },
|
|
855
966
|
...options.attemptId && { attemptId: options.attemptId },
|
|
856
967
|
buyerEmail: options.buyerEmail,
|
|
968
|
+
...options.agentArtifacts && { agentArtifacts: options.agentArtifacts },
|
|
969
|
+
...options.metadata && { metadata: options.metadata },
|
|
857
970
|
counterpartyUrl: options.counterpartyUrl,
|
|
858
971
|
counterpartyType: options.counterpartyType
|
|
859
972
|
},
|
|
@@ -914,6 +1027,80 @@ var VerificationGatewayClient = class {
|
|
|
914
1027
|
}
|
|
915
1028
|
return json.data;
|
|
916
1029
|
}
|
|
1030
|
+
/**
|
|
1031
|
+
* 5.20.0 (round 29.1): change an endpoint's OPERATIONAL URLs with this
|
|
1032
|
+
* client's API key — `PATCH /api/endpoints/:id`. Accepts the key of the
|
|
1033
|
+
* endpoint's owner, or a personal key of an individual with an active seat
|
|
1034
|
+
* in the owning organisation. Policy (rules, trust floor, challenge, edge
|
|
1035
|
+
* config) stays dashboard-only. `null` clears a field. The owner is alerted
|
|
1036
|
+
* when `eventsUrl` changes.
|
|
1037
|
+
*
|
|
1038
|
+
* @param endpointId the ASTRAE id (defaults to the client's `counterpartyId`)
|
|
1039
|
+
* @returns the endpoint as stored, plus `changed` (the fields that changed)
|
|
1040
|
+
* @throws AstraSyncError — 400 `UNKNOWN_FIELDS` / validation, 401/403, 404
|
|
1041
|
+
*/
|
|
1042
|
+
async updateEndpoint(endpointId, patch) {
|
|
1043
|
+
return this.endpointCall("PATCH", endpointId, "", patch);
|
|
1044
|
+
}
|
|
1045
|
+
/**
|
|
1046
|
+
* 5.20.0 (round 29.1): ask AstraSync to send ONE signed step-up event to the
|
|
1047
|
+
* endpoint's Events URL now — `POST /api/endpoints/:id/events/test`.
|
|
1048
|
+
* Delivered synchronously, outside the event outbox (random `eventId`, no
|
|
1049
|
+
* retries), signed with the endpoint's webhook secret like a real event.
|
|
1050
|
+
* Without `approvalId` the payload is synthetic (a kit acknowledges and
|
|
1051
|
+
* ignores it). With the id of a held kit approval at this endpoint the
|
|
1052
|
+
* payload is the real one, so your resume path runs: `approved` makes the
|
|
1053
|
+
* kit re-confirm (held again — nothing is charged); `denied` / `expired` /
|
|
1054
|
+
* `lapsed` release the session.
|
|
1055
|
+
*
|
|
1056
|
+
* Resolves even when your endpoint refused the event (`delivered: false`,
|
|
1057
|
+
* with `responseCode` / `error`).
|
|
1058
|
+
*/
|
|
1059
|
+
async sendTestEvent(endpointId, options) {
|
|
1060
|
+
return this.endpointCall("POST", endpointId, "/events/test", options);
|
|
1061
|
+
}
|
|
1062
|
+
async endpointCall(method, endpointId, suffix, body) {
|
|
1063
|
+
const id = endpointId ?? this.config.counterpartyId;
|
|
1064
|
+
if (!id) {
|
|
1065
|
+
throw new AstraSyncError(
|
|
1066
|
+
"An endpoint id (ASTRAE-\u2026) is required: pass it, or set counterpartyId on the client",
|
|
1067
|
+
400,
|
|
1068
|
+
"VALIDATION"
|
|
1069
|
+
);
|
|
1070
|
+
}
|
|
1071
|
+
if (!this.config.apiKey) {
|
|
1072
|
+
throw new AstraSyncError("This call needs the client apiKey", 401, "AUTH_REQUIRED");
|
|
1073
|
+
}
|
|
1074
|
+
const base = this.config.apiBaseUrl.replace(/\/+$/, "");
|
|
1075
|
+
const url = `${base}/endpoints/${encodeURIComponent(id)}${suffix}`;
|
|
1076
|
+
let res;
|
|
1077
|
+
try {
|
|
1078
|
+
res = await sdkFetch(url, {
|
|
1079
|
+
method,
|
|
1080
|
+
headers: {
|
|
1081
|
+
"Content-Type": "application/json",
|
|
1082
|
+
Authorization: `Bearer ${this.config.apiKey}`,
|
|
1083
|
+
"X-API-Key": this.config.apiKey
|
|
1084
|
+
},
|
|
1085
|
+
body: JSON.stringify(body),
|
|
1086
|
+
signal: AbortSignal.timeout(Math.max(this.timeout, 15e3))
|
|
1087
|
+
});
|
|
1088
|
+
} catch (err) {
|
|
1089
|
+
throw new AstraSyncError(
|
|
1090
|
+
`${method} ${suffix || "/endpoints/:id"} failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
1091
|
+
0,
|
|
1092
|
+
"network_error"
|
|
1093
|
+
);
|
|
1094
|
+
}
|
|
1095
|
+
const json = await res.json().catch(() => ({}));
|
|
1096
|
+
if (!res.ok || json.success === false || json.data === void 0) {
|
|
1097
|
+
const errObj = typeof json.error === "object" ? json.error : void 0;
|
|
1098
|
+
const code = json.code ?? errObj?.code ?? (typeof json.error === "string" ? json.error : "unknown_error");
|
|
1099
|
+
const message = json.message ?? errObj?.message ?? `HTTP ${res.status}`;
|
|
1100
|
+
throw new AstraSyncError(`${message} (${code})`, res.status, code);
|
|
1101
|
+
}
|
|
1102
|
+
return json.data;
|
|
1103
|
+
}
|
|
917
1104
|
/**
|
|
918
1105
|
* Quick verification — checks credentials and policy in one call.
|
|
919
1106
|
*
|