Document that PolicyBlock field names are not the wire format - #117
Merged
Conversation
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.
8 tasks
vvillait88
added a commit
that referenced
this pull request
Aug 28, 2026
…val (#119) ## Summary Version bump for the fail-closed change merged in #118, plus the `PolicyBlock` documentation from #117. Minor rather than patch, because runtime behavior changes for merchants. A response the gate cannot read as an approval is now refused where it was previously allowed: a missing or null decision, an unrecognised decision value, and an `allow` whose `policy_result` did not pass on a request that sent a policy. ## Type of change - [ ] Bug fix (no breaking change) - [ ] New feature (no breaking change) - [ ] Breaking change (existing callers must update) - [x] Docs, tests, or internal maintenance only The version bump itself is maintenance; the behavior it releases landed in #118 and is classified there. ## Public API No exported type, signature or wire-format changes. Behavior changes for three response shapes that should not occur against a current API, all of which now deny where they previously allowed. Nothing to migrate: a merchant seeing any of them in production has a real problem the gate was hiding, and `failOpen` still applies to the unreadable-response case, which is the only one of the three that is an availability question rather than a compliance one. ## Test plan `bun run lint`, `bun run typecheck` (including the examples project) and `bun run test` all clean on the bumped tree: 119 files, 1824 tests passing, 4 skipped. The behavior itself is verified in #118, including drills that reintroduce each guard's removal and confirm the tests fail. ## Checklist - [x] Tests cover the new behavior, and the suite passes locally - [x] Lint, format, and type checks pass - [x] Docs and README examples updated if the public surface changed - [x] No secrets, credentials, or personal data in the diff or the tests
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Documentation only. No behavior change.
PolicyBlockuses camelCase and the AgentScore API expects snake_case. This SDK already translates the five compliance fields correctly at the request boundary (buildGateFromPolicy,src/core.ts:779-783), so anyone using the SDK is unaffected and always has been.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. The API used to ignore a key it did not recognise, which meant such a policy matched no rule, ran no check, and returned
decision: "allow": a compliance gate passing without evaluating anything. The API now rejects it with a400 invalid_policynaming the correct spelling, so the failure is loud instead of silent.That leaves this type as the last place still suggesting a shape the API refuses, which is what this fixes. It also records which fields actually cross the wire:
enforcement,allowedShippingCountriesandallowedShippingStatesare merchant-side concerns the SDK acts on locally and never sends, which is not obvious from a type whose other members all do.Worked with Varun, going through the Q3 2026 penetration test findings.
Type of change
Public API
None. No exported type, signature, wire format or response shape changes.
PolicyBlock's members are untouched; only its doc comment is added to.Deliberately NOT renamed: aligning the field names to snake_case would be a breaking change to a published package, and the SDK's translation is already correct, so the camelCase names are a genuine convenience rather than a defect. If we ever want them aligned it belongs in a major.
Test plan
Nothing here is executable, so the suite is a regression check rather than evidence for the change itself:
bun run lint,bun run typecheck(including the examples project) andbun run testall clean, 119 files and 1817 tests passing with 4 skipped.The claims in the doc comment were checked against the source rather than assumed.
src/core.ts:779-783maps exactly the five compliance fields to snake_case, and the three merchant-side fields (enforcement,allowedShippingCountries,allowedShippingStates) appear nowhere in the outbound request.Two things deliberately left out. The commerce-side half of the same finding is not here: the report separately flags
const allow = decision === 'allow' || decision == nullinsrc/core.ts, which treats a missing decision as allow, and that is a behavior change with its own tests and release. The finding stays open until it lands. And the 14 pre-existing em-dashes in this file are left alone, since our convention is that a gate judges the lines a change publishes and sweeping the prose would balloon a documentation diff.Checklist
Not ticked deliberately: this is a doc comment, so there is no behavior to
cover. The suite passes and is included above as a regression check.