From 877cb1a2eb39e9362cab78f07ec94cf4f305b929 Mon Sep 17 00:00:00 2001 From: vvillait88 Date: Thu, 27 Aug 2026 18:13:37 -0400 Subject: [PATCH] Document that PolicyBlock field names are not the wire format PolicyBlock uses camelCase and the API expects snake_case. This SDK already translates the five compliance fields correctly at the request boundary, so anyone using the SDK is unaffected, and nothing here changes behavior. The gap is that the type is exported, so a caller who hand-rolls the HTTP request takes the field names from it and sends camelCase. That used to be silently ignored by the API: the key matched no rule, no check ran, and the response came back allow, which is a compliance gate passing without evaluating anything. The API now rejects it with a 400 naming the correct spelling, so the failure is loud rather than silent, and this type should say so rather than continuing to suggest a shape the API refuses. Also records which fields actually cross the wire. enforcement, allowedShippingCountries and allowedShippingStates are merchant-side concerns this SDK acts on locally and never sends, which is not obvious from a type whose other members all do. --- src/identity/policy.ts | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/identity/policy.ts b/src/identity/policy.ts index 95e94d1..03e02a0 100644 --- a/src/identity/policy.ts +++ b/src/identity/policy.ts @@ -37,7 +37,27 @@ export type EnforcementMode = 'hard' | 'soft'; /** Per-order trust level captured at settle time. */ export type IdentityStatus = 'verified' | 'unverified' | 'anonymous' | 'denied'; -/** Compliance fields a merchant attaches per product / per tier. All optional. */ +/** + * Compliance fields a merchant attaches per product / per tier. All optional. + * + * THESE ARE SDK FIELD NAMES, NOT THE WIRE FORMAT. The AgentScore API expects + * snake_case, and this SDK translates the five compliance fields at the request + * boundary (`buildGateFromPolicy` in `../core.ts`). Sending these names to + * `POST /v1/assess` directly is rejected with a 400 `invalid_policy`. + * + * That rejection is deliberate and recent. The API previously ignored a key it + * did not recognise, which meant a camelCase policy matched no rule, ran no + * check, and came back `decision: "allow"`, a silent pass from a compliance + * gate. It now fails loudly instead, and the 400 names the correct spelling. + * + * So if you are hand-rolling the HTTP request rather than using this SDK, use + * the snake_case names: `require_kyc`, `require_sanctions_clear`, `min_age`, + * `blocked_jurisdictions`, `allowed_jurisdictions`. + * + * Note also that only those five cross the wire. `enforcement`, + * `allowedShippingCountries` and `allowedShippingStates` are merchant-side + * concerns this SDK acts on locally and never sends. + */ export interface PolicyBlock { enforcement?: EnforcementMode; requireKyc?: boolean;