@astrasyncai/verification-gateway 3.11.1 → 3.12.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/adapter-interface/interface.d.mts +2 -2
- package/dist/adapter-interface/interface.d.ts +2 -2
- package/dist/adapters/express.d.mts +2 -2
- package/dist/adapters/express.d.ts +2 -2
- package/dist/adapters/express.js +22 -3
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/express.mjs +22 -3
- package/dist/adapters/express.mjs.map +1 -1
- package/dist/adapters/mcp.d.mts +1 -1
- package/dist/adapters/mcp.d.ts +1 -1
- package/dist/adapters/mcp.js +22 -3
- package/dist/adapters/mcp.js.map +1 -1
- package/dist/adapters/mcp.mjs +22 -3
- package/dist/adapters/mcp.mjs.map +1 -1
- package/dist/adapters/nextjs.d.mts +2 -2
- package/dist/adapters/nextjs.d.ts +2 -2
- package/dist/adapters/nextjs.js +22 -3
- package/dist/adapters/nextjs.js.map +1 -1
- package/dist/adapters/nextjs.mjs +22 -3
- package/dist/adapters/nextjs.mjs.map +1 -1
- package/dist/adapters/sdk.d.mts +2 -2
- package/dist/adapters/sdk.d.ts +2 -2
- package/dist/adapters/sdk.js +22 -3
- package/dist/adapters/sdk.js.map +1 -1
- package/dist/adapters/sdk.mjs +22 -3
- package/dist/adapters/sdk.mjs.map +1 -1
- package/dist/agent/index.d.mts +2 -2
- package/dist/agent/index.d.ts +2 -2
- package/dist/bin/astrasync-claude-hook.js +22 -3
- package/dist/bin/astrasync-codex-hook.js +22 -3
- package/dist/bin/astrasync-guard.js +22 -3
- package/dist/bin/astrasync.js +23 -3
- package/dist/browser/background.js +22 -3
- package/dist/browser/background.js.map +1 -1
- package/dist/browser/background.mjs +22 -3
- package/dist/browser/background.mjs.map +1 -1
- package/dist/browser/browser-adapter.d.mts +2 -2
- package/dist/browser/browser-adapter.d.ts +2 -2
- package/dist/claude-code/claude-code-adapter.d.mts +2 -2
- package/dist/claude-code/claude-code-adapter.d.ts +2 -2
- package/dist/cli/index.d.mts +2 -2
- package/dist/cli/index.d.ts +2 -2
- package/dist/codex/index.d.mts +2 -2
- package/dist/codex/index.d.ts +2 -2
- package/dist/codex/index.js +22 -3
- package/dist/codex/index.js.map +1 -1
- package/dist/codex/index.mjs +22 -3
- package/dist/codex/index.mjs.map +1 -1
- package/dist/cursor/cursor-adapter.d.mts +2 -2
- package/dist/cursor/cursor-adapter.d.ts +2 -2
- package/dist/cursor/extension.d.mts +2 -2
- package/dist/cursor/extension.d.ts +2 -2
- package/dist/cursor/extension.js +22 -3
- package/dist/cursor/extension.js.map +1 -1
- package/dist/cursor/extension.mjs +22 -3
- 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/{express-DCXa1oqj.d.mts → express-B39o89gf.d.mts} +1 -1
- package/dist/{express-ClNtDhhc.d.ts → express-BuxKNO_q.d.ts} +1 -1
- package/dist/gateway/gateway.d.mts +2 -2
- package/dist/gateway/gateway.d.ts +2 -2
- package/dist/gateway/gateway.js +22 -3
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/gateway.mjs +22 -3
- package/dist/gateway/gateway.mjs.map +1 -1
- package/dist/git-trigger/git-hooks.d.mts +2 -2
- package/dist/git-trigger/git-hooks.d.ts +2 -2
- package/dist/{index-CfHurO1P.d.ts → index-BG62SXso.d.ts} +1 -1
- package/dist/{index-D2ztkumS.d.ts → index-CLHdqs2M.d.ts} +1 -1
- package/dist/{index-Dr_XiN65.d.mts → index-CqydB4ks.d.mts} +1 -1
- package/dist/{index-BrNKDmiR.d.mts → index-DME3w3lf.d.mts} +1 -1
- package/dist/index.d.mts +9 -9
- package/dist/index.d.ts +9 -9
- package/dist/index.js +42 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +41 -3
- 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/{nextjs-DcQIk6Zj.d.mts → nextjs-D74W7wt-.d.mts} +1 -1
- package/dist/{nextjs-CEBVBsdi.d.ts → nextjs-Ddlw_J1J.d.ts} +1 -1
- package/dist/{sdk-CZkbSOeO.d.mts → sdk-Bn6bj7kt.d.mts} +1 -1
- package/dist/{sdk-H0JCLW2y.d.ts → sdk-CT7gdkfR.d.ts} +1 -1
- package/dist/transport/index.d.mts +2 -2
- package/dist/transport/index.d.ts +2 -2
- package/dist/{types-sy3tq8lp.d.mts → types-BntuzEEn.d.mts} +103 -1
- package/dist/{types-DhFPiZ3t.d.ts → types-DHu7m9HI.d.ts} +1 -1
- package/dist/{types-cQVCMeNV.d.mts → types-Djw4GLtz.d.mts} +1 -1
- package/dist/{types-9tns4wyl.d.ts → types-SDu4Llbe.d.ts} +103 -1
- package/dist/ui/index.d.mts +1 -1
- package/dist/ui/index.d.ts +1 -1
- package/dist/verify.d.mts +13 -2
- package/dist/verify.d.ts +13 -2
- package/dist/verify.js +42 -3
- package/dist/verify.js.map +1 -1
- package/dist/verify.mjs +41 -3
- package/dist/verify.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -4609,7 +4609,7 @@ function getTrustLevel(score) {
|
|
|
4609
4609
|
}
|
|
4610
4610
|
|
|
4611
4611
|
// src/version.ts
|
|
4612
|
-
var SDK_VERSION = "3.
|
|
4612
|
+
var SDK_VERSION = "3.12.0";
|
|
4613
4613
|
|
|
4614
4614
|
// src/well-known.ts
|
|
4615
4615
|
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
@@ -4776,6 +4776,7 @@ function createGuidanceResponse(_config, reason, options = {}) {
|
|
|
4776
4776
|
}
|
|
4777
4777
|
] : void 0,
|
|
4778
4778
|
correlationId: options.correlationId,
|
|
4779
|
+
attemptId: options.attemptId,
|
|
4779
4780
|
verifiedAt: /* @__PURE__ */ new Date()
|
|
4780
4781
|
};
|
|
4781
4782
|
}
|
|
@@ -4805,6 +4806,8 @@ async function callVerifyAccessAPI(config, request2) {
|
|
|
4805
4806
|
body.runtimeChallengeOptions = requestData.runtimeChallengeOptions;
|
|
4806
4807
|
if (requestData.invocationProtocol) body.invocationProtocol = requestData.invocationProtocol;
|
|
4807
4808
|
if (requestData.commerceArtifacts) body.commerceArtifacts = requestData.commerceArtifacts;
|
|
4809
|
+
if (requestData.attemptId) body.attemptId = requestData.attemptId;
|
|
4810
|
+
if (requestData.considerationSet) body.considerationSet = requestData.considerationSet;
|
|
4808
4811
|
body.sdkVersion = SDK_VERSION;
|
|
4809
4812
|
if (requestData.callerMetadata || requestData.clientIp || requestData.userAgent) {
|
|
4810
4813
|
const meta = {
|
|
@@ -4832,6 +4835,9 @@ async function callVerifyAccessAPI(config, request2) {
|
|
|
4832
4835
|
if (response.status === 410) {
|
|
4833
4836
|
return {
|
|
4834
4837
|
success: true,
|
|
4838
|
+
// 3.12.0 (Trust Record): keep the server-echoed attempt handle even on
|
|
4839
|
+
// the synthesised 410 deny shape (echoed on every branch).
|
|
4840
|
+
attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0,
|
|
4835
4841
|
access: {
|
|
4836
4842
|
allowed: false,
|
|
4837
4843
|
accessLevel: "none",
|
|
@@ -4850,7 +4856,8 @@ async function callVerifyAccessAPI(config, request2) {
|
|
|
4850
4856
|
return {
|
|
4851
4857
|
success: false,
|
|
4852
4858
|
error: data.message || data.error || `API returned ${response.status}`,
|
|
4853
|
-
correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0
|
|
4859
|
+
correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0,
|
|
4860
|
+
attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0
|
|
4854
4861
|
};
|
|
4855
4862
|
}
|
|
4856
4863
|
return data;
|
|
@@ -4884,7 +4891,13 @@ async function verify(config, request2, options) {
|
|
|
4884
4891
|
if (mergedConfig.debug) {
|
|
4885
4892
|
console.log("[VerificationGateway] Returning cached result");
|
|
4886
4893
|
}
|
|
4887
|
-
|
|
4894
|
+
const hit = { ...cached };
|
|
4895
|
+
if (request2.attemptId) {
|
|
4896
|
+
hit.attemptId = request2.attemptId;
|
|
4897
|
+
} else {
|
|
4898
|
+
delete hit.attemptId;
|
|
4899
|
+
}
|
|
4900
|
+
return hit;
|
|
4888
4901
|
}
|
|
4889
4902
|
}
|
|
4890
4903
|
const enrichedRequest = { ...request2 };
|
|
@@ -4904,6 +4917,7 @@ async function verify(config, request2, options) {
|
|
|
4904
4917
|
return createGuidanceResponse(mergedConfig, apiResponse.error, {
|
|
4905
4918
|
source: "api_error",
|
|
4906
4919
|
correlationId: apiResponse.correlationId,
|
|
4920
|
+
attemptId: apiResponse.attemptId,
|
|
4907
4921
|
urls
|
|
4908
4922
|
});
|
|
4909
4923
|
}
|
|
@@ -4939,6 +4953,9 @@ async function verify(config, request2, options) {
|
|
|
4939
4953
|
// Anonymous traffic has no session → correlationId is the per-attempt
|
|
4940
4954
|
// linking key (the sessionId-equivalent for anonymous callers).
|
|
4941
4955
|
correlationId: apiResponse.correlationId,
|
|
4956
|
+
// 3.12.0 (Trust Record): server echoes the attempt-chain handle on
|
|
4957
|
+
// every branch — denials included (the funnel outlives one deny).
|
|
4958
|
+
attemptId: apiResponse.attemptId,
|
|
4942
4959
|
recommendation: apiResponse.recommendation,
|
|
4943
4960
|
recommendationReasons: apiResponse.recommendationReasons,
|
|
4944
4961
|
stepUpApproval: apiResponse.stepUpApproval,
|
|
@@ -4990,6 +5007,8 @@ async function verify(config, request2, options) {
|
|
|
4990
5007
|
// v2.3.10 (defect #34, round-4): anonymous responses surface correlationId
|
|
4991
5008
|
// (no session row exists for unverified callers).
|
|
4992
5009
|
correlationId: apiResponse.correlationId,
|
|
5010
|
+
// 3.12.0 (Trust Record): server-echoed attempt-chain handle.
|
|
5011
|
+
attemptId: apiResponse.attemptId,
|
|
4993
5012
|
runtimeChallenge: apiResponse.runtimeChallenge,
|
|
4994
5013
|
tokenGuidance: apiResponse.tokenGuidance,
|
|
4995
5014
|
recommendation: apiResponse.recommendation,
|
package/dist/bin/astrasync.js
CHANGED
|
@@ -5000,7 +5000,7 @@ var SDK_VERSION;
|
|
|
5000
5000
|
var init_version = __esm({
|
|
5001
5001
|
"src/version.ts"() {
|
|
5002
5002
|
"use strict";
|
|
5003
|
-
SDK_VERSION = "3.
|
|
5003
|
+
SDK_VERSION = "3.12.0";
|
|
5004
5004
|
}
|
|
5005
5005
|
});
|
|
5006
5006
|
|
|
@@ -5157,6 +5157,7 @@ function createGuidanceResponse(_config, reason, options = {}) {
|
|
|
5157
5157
|
}
|
|
5158
5158
|
] : void 0,
|
|
5159
5159
|
correlationId: options.correlationId,
|
|
5160
|
+
attemptId: options.attemptId,
|
|
5160
5161
|
verifiedAt: /* @__PURE__ */ new Date()
|
|
5161
5162
|
};
|
|
5162
5163
|
}
|
|
@@ -5186,6 +5187,8 @@ async function callVerifyAccessAPI(config, request2) {
|
|
|
5186
5187
|
body.runtimeChallengeOptions = requestData.runtimeChallengeOptions;
|
|
5187
5188
|
if (requestData.invocationProtocol) body.invocationProtocol = requestData.invocationProtocol;
|
|
5188
5189
|
if (requestData.commerceArtifacts) body.commerceArtifacts = requestData.commerceArtifacts;
|
|
5190
|
+
if (requestData.attemptId) body.attemptId = requestData.attemptId;
|
|
5191
|
+
if (requestData.considerationSet) body.considerationSet = requestData.considerationSet;
|
|
5189
5192
|
body.sdkVersion = SDK_VERSION;
|
|
5190
5193
|
if (requestData.callerMetadata || requestData.clientIp || requestData.userAgent) {
|
|
5191
5194
|
const meta = {
|
|
@@ -5213,6 +5216,9 @@ async function callVerifyAccessAPI(config, request2) {
|
|
|
5213
5216
|
if (response.status === 410) {
|
|
5214
5217
|
return {
|
|
5215
5218
|
success: true,
|
|
5219
|
+
// 3.12.0 (Trust Record): keep the server-echoed attempt handle even on
|
|
5220
|
+
// the synthesised 410 deny shape (echoed on every branch).
|
|
5221
|
+
attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0,
|
|
5216
5222
|
access: {
|
|
5217
5223
|
allowed: false,
|
|
5218
5224
|
accessLevel: "none",
|
|
@@ -5231,7 +5237,8 @@ async function callVerifyAccessAPI(config, request2) {
|
|
|
5231
5237
|
return {
|
|
5232
5238
|
success: false,
|
|
5233
5239
|
error: data.message || data.error || `API returned ${response.status}`,
|
|
5234
|
-
correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0
|
|
5240
|
+
correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0,
|
|
5241
|
+
attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0
|
|
5235
5242
|
};
|
|
5236
5243
|
}
|
|
5237
5244
|
return data;
|
|
@@ -5265,7 +5272,13 @@ async function verify(config, request2, options) {
|
|
|
5265
5272
|
if (mergedConfig.debug) {
|
|
5266
5273
|
console.log("[VerificationGateway] Returning cached result");
|
|
5267
5274
|
}
|
|
5268
|
-
|
|
5275
|
+
const hit = { ...cached };
|
|
5276
|
+
if (request2.attemptId) {
|
|
5277
|
+
hit.attemptId = request2.attemptId;
|
|
5278
|
+
} else {
|
|
5279
|
+
delete hit.attemptId;
|
|
5280
|
+
}
|
|
5281
|
+
return hit;
|
|
5269
5282
|
}
|
|
5270
5283
|
}
|
|
5271
5284
|
const enrichedRequest = { ...request2 };
|
|
@@ -5285,6 +5298,7 @@ async function verify(config, request2, options) {
|
|
|
5285
5298
|
return createGuidanceResponse(mergedConfig, apiResponse.error, {
|
|
5286
5299
|
source: "api_error",
|
|
5287
5300
|
correlationId: apiResponse.correlationId,
|
|
5301
|
+
attemptId: apiResponse.attemptId,
|
|
5288
5302
|
urls
|
|
5289
5303
|
});
|
|
5290
5304
|
}
|
|
@@ -5320,6 +5334,9 @@ async function verify(config, request2, options) {
|
|
|
5320
5334
|
// Anonymous traffic has no session → correlationId is the per-attempt
|
|
5321
5335
|
// linking key (the sessionId-equivalent for anonymous callers).
|
|
5322
5336
|
correlationId: apiResponse.correlationId,
|
|
5337
|
+
// 3.12.0 (Trust Record): server echoes the attempt-chain handle on
|
|
5338
|
+
// every branch — denials included (the funnel outlives one deny).
|
|
5339
|
+
attemptId: apiResponse.attemptId,
|
|
5323
5340
|
recommendation: apiResponse.recommendation,
|
|
5324
5341
|
recommendationReasons: apiResponse.recommendationReasons,
|
|
5325
5342
|
stepUpApproval: apiResponse.stepUpApproval,
|
|
@@ -5371,6 +5388,8 @@ async function verify(config, request2, options) {
|
|
|
5371
5388
|
// v2.3.10 (defect #34, round-4): anonymous responses surface correlationId
|
|
5372
5389
|
// (no session row exists for unverified callers).
|
|
5373
5390
|
correlationId: apiResponse.correlationId,
|
|
5391
|
+
// 3.12.0 (Trust Record): server-echoed attempt-chain handle.
|
|
5392
|
+
attemptId: apiResponse.attemptId,
|
|
5374
5393
|
runtimeChallenge: apiResponse.runtimeChallenge,
|
|
5375
5394
|
tokenGuidance: apiResponse.tokenGuidance,
|
|
5376
5395
|
recommendation: apiResponse.recommendation,
|
|
@@ -5949,6 +5968,7 @@ var init_src = __esm({
|
|
|
5949
5968
|
init_edge_config();
|
|
5950
5969
|
init_platform_signatures();
|
|
5951
5970
|
init_verify();
|
|
5971
|
+
init_verify();
|
|
5952
5972
|
init_metadata_capture();
|
|
5953
5973
|
init_version();
|
|
5954
5974
|
}
|
|
@@ -3938,7 +3938,7 @@ function getTrustLevel(score) {
|
|
|
3938
3938
|
}
|
|
3939
3939
|
|
|
3940
3940
|
// src/version.ts
|
|
3941
|
-
var SDK_VERSION = "3.
|
|
3941
|
+
var SDK_VERSION = "3.12.0";
|
|
3942
3942
|
|
|
3943
3943
|
// src/well-known.ts
|
|
3944
3944
|
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
@@ -4105,6 +4105,7 @@ function createGuidanceResponse(_config, reason, options = {}) {
|
|
|
4105
4105
|
}
|
|
4106
4106
|
] : void 0,
|
|
4107
4107
|
correlationId: options.correlationId,
|
|
4108
|
+
attemptId: options.attemptId,
|
|
4108
4109
|
verifiedAt: /* @__PURE__ */ new Date()
|
|
4109
4110
|
};
|
|
4110
4111
|
}
|
|
@@ -4134,6 +4135,8 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
4134
4135
|
body.runtimeChallengeOptions = requestData.runtimeChallengeOptions;
|
|
4135
4136
|
if (requestData.invocationProtocol) body.invocationProtocol = requestData.invocationProtocol;
|
|
4136
4137
|
if (requestData.commerceArtifacts) body.commerceArtifacts = requestData.commerceArtifacts;
|
|
4138
|
+
if (requestData.attemptId) body.attemptId = requestData.attemptId;
|
|
4139
|
+
if (requestData.considerationSet) body.considerationSet = requestData.considerationSet;
|
|
4137
4140
|
body.sdkVersion = SDK_VERSION;
|
|
4138
4141
|
if (requestData.callerMetadata || requestData.clientIp || requestData.userAgent) {
|
|
4139
4142
|
const meta = {
|
|
@@ -4161,6 +4164,9 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
4161
4164
|
if (response.status === 410) {
|
|
4162
4165
|
return {
|
|
4163
4166
|
success: true,
|
|
4167
|
+
// 3.12.0 (Trust Record): keep the server-echoed attempt handle even on
|
|
4168
|
+
// the synthesised 410 deny shape (echoed on every branch).
|
|
4169
|
+
attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0,
|
|
4164
4170
|
access: {
|
|
4165
4171
|
allowed: false,
|
|
4166
4172
|
accessLevel: "none",
|
|
@@ -4179,7 +4185,8 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
4179
4185
|
return {
|
|
4180
4186
|
success: false,
|
|
4181
4187
|
error: data.message || data.error || `API returned ${response.status}`,
|
|
4182
|
-
correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0
|
|
4188
|
+
correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0,
|
|
4189
|
+
attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0
|
|
4183
4190
|
};
|
|
4184
4191
|
}
|
|
4185
4192
|
return data;
|
|
@@ -4213,7 +4220,13 @@ async function verify(config, request, options) {
|
|
|
4213
4220
|
if (mergedConfig.debug) {
|
|
4214
4221
|
console.log("[VerificationGateway] Returning cached result");
|
|
4215
4222
|
}
|
|
4216
|
-
|
|
4223
|
+
const hit = { ...cached };
|
|
4224
|
+
if (request.attemptId) {
|
|
4225
|
+
hit.attemptId = request.attemptId;
|
|
4226
|
+
} else {
|
|
4227
|
+
delete hit.attemptId;
|
|
4228
|
+
}
|
|
4229
|
+
return hit;
|
|
4217
4230
|
}
|
|
4218
4231
|
}
|
|
4219
4232
|
const enrichedRequest = { ...request };
|
|
@@ -4233,6 +4246,7 @@ async function verify(config, request, options) {
|
|
|
4233
4246
|
return createGuidanceResponse(mergedConfig, apiResponse.error, {
|
|
4234
4247
|
source: "api_error",
|
|
4235
4248
|
correlationId: apiResponse.correlationId,
|
|
4249
|
+
attemptId: apiResponse.attemptId,
|
|
4236
4250
|
urls
|
|
4237
4251
|
});
|
|
4238
4252
|
}
|
|
@@ -4268,6 +4282,9 @@ async function verify(config, request, options) {
|
|
|
4268
4282
|
// Anonymous traffic has no session → correlationId is the per-attempt
|
|
4269
4283
|
// linking key (the sessionId-equivalent for anonymous callers).
|
|
4270
4284
|
correlationId: apiResponse.correlationId,
|
|
4285
|
+
// 3.12.0 (Trust Record): server echoes the attempt-chain handle on
|
|
4286
|
+
// every branch — denials included (the funnel outlives one deny).
|
|
4287
|
+
attemptId: apiResponse.attemptId,
|
|
4271
4288
|
recommendation: apiResponse.recommendation,
|
|
4272
4289
|
recommendationReasons: apiResponse.recommendationReasons,
|
|
4273
4290
|
stepUpApproval: apiResponse.stepUpApproval,
|
|
@@ -4319,6 +4336,8 @@ async function verify(config, request, options) {
|
|
|
4319
4336
|
// v2.3.10 (defect #34, round-4): anonymous responses surface correlationId
|
|
4320
4337
|
// (no session row exists for unverified callers).
|
|
4321
4338
|
correlationId: apiResponse.correlationId,
|
|
4339
|
+
// 3.12.0 (Trust Record): server-echoed attempt-chain handle.
|
|
4340
|
+
attemptId: apiResponse.attemptId,
|
|
4322
4341
|
runtimeChallenge: apiResponse.runtimeChallenge,
|
|
4323
4342
|
tokenGuidance: apiResponse.tokenGuidance,
|
|
4324
4343
|
recommendation: apiResponse.recommendation,
|