Skip to content

Document that PolicyBlock field names are not the wire format - #117

Merged
vvillait88 merged 1 commit into
mainfrom
docs/policyblock-wire-shape
Aug 28, 2026
Merged

Document that PolicyBlock field names are not the wire format#117
vvillait88 merged 1 commit into
mainfrom
docs/policyblock-wire-shape

Conversation

@vvillait88

Copy link
Copy Markdown
Contributor

Summary

Documentation only. No behavior change.

PolicyBlock uses 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 a 400 invalid_policy naming 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, allowedShippingCountries and allowedShippingStates are 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

  • Bug fix (no breaking change)
  • New feature (no breaking change)
  • Breaking change (existing callers must update)
  • Docs, tests, or internal maintenance only

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) and bun run test all 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-783 maps 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 == null in src/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

  • Tests cover the new behavior, and the suite passes locally
    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.
  • Lint, format, and type checks pass
  • Docs and README examples updated if the public surface changed
  • No secrets, credentials, or personal data in the diff or the tests

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.
@vvillait88
vvillait88 merged commit ec5fa66 into main Aug 28, 2026
6 checks passed
@vvillait88
vvillait88 deleted the docs/policyblock-wire-shape branch August 28, 2026 00:24
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant