Skip to content

fix: accept a set of ACP API versions and ignore unknown fields - #11

Merged
KristofersOzolinsMagebit merged 2 commits into
developfrom
bugfix/phase-0-version-gate
Aug 11, 2026
Merged

fix: accept a set of ACP API versions and ignore unknown fields#11
KristofersOzolinsMagebit merged 2 commits into
developfrom
bugfix/phase-0-version-gate

Conversation

@KristofersOzolinsMagebit

Copy link
Copy Markdown
Member

Every conformant request was rejected before any handler ran.

1. The version gate

public const API_VERSION = '2025-10-01';
return $request->getHeader('API-Version') === self::API_VERSION;

Two faults. 2025-10-01 is not a released ACP version — the published ones are 2025-09-29,
2025-12-12, 2026-01-16, 2026-01-30 and 2026-04-17; the value traces to a hypothetical
example in upstream's CONTRIBUTING.md. And the strict comparison against a single value means
validateRequest() — the first gate in all six controllers — rejected every client regardless of
payload correctness.

Replaced with membership in a supported-version set, and the failure branch now distinguishes two
cases, both HTTP 400 per rfc.agentic_checkout.md:

Condition code
Header absent or empty missing_api_version
Header present, not in the set unsupported_api_version

Both carry type: invalid_request and a supported_versions array, which required a new optional
field on ErrorResponseInterface.

API_VERSION — the value returned in the response header — is deliberately set to 2025-09-29,
not the newest accepted version. Accepting a header is not the same as implementing that version,
and the module still emits 2025-09-29-shaped payloads. It should move once the payloads do.

This change only ever widens what is accepted, so no client that works today can break.

2. Unknown fields were rejected

The four request DTOs validated with Assert\Collection carrying 'allowExtraFields' => false
15 sites. Any field the module did not know was a validation failure.

ACP objects are additionalProperties: false upstream and gain optional fields between releases
(Item.suggested_price, Item.url, CheckoutSessionCompleteRequest.fulfillment_details are
landing now, and 2026-04-17 already added fields this module has never seen). Strict validation
turns a routine upstream rollout into an outage with no change on our side.

All 15 set to true. allowMissingFields is untouched — required-field enforcement is correct
and survives.

Verification

Request Result
API-Version: 2025-09-29 reaches controller
API-Version: 2026-04-17 reaches controller
API-Version: 1999-01-01 400 unsupported_api_version + supported_versions
no API-Version header 400 missing_api_version + supported_versions
body with unknown fields accepted, ignored
body missing items still 400 $.items
body with invalid buyer.email still 400 $.buyer.email

PHPStan level 9 error count unchanged (188 → 188); PHPCS clean on every file touched.

Note for anyone deploying this

symfony/validator is declared in this module's composer.json but is not pulled in when the
module is installed under app/code rather than via Composer. Without it every request 500s in
RequestValidationService with Class "Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader" not found,
whatever the API-Version header says.

Known, not addressed here

POST /checkout_sessions now reaches the controller and then 500s in
CartToFulfillmentAddress::execute(). CheckoutSessionService::assignCartDataToResponse() builds
a fulfillment address unconditionally, so an empty quote address passes null into
Address::setCity(string $city). fulfillment_address is optional in ACP and should be omitted
when unset. Separate fix.

The pinned 2025-10-01 is not a released version and the strict comparison
rejected every conformant client before any handler ran.
@KristofersOzolinsMagebit
KristofersOzolinsMagebit merged commit e68da9d into develop Aug 11, 2026
@KristofersOzolinsMagebit
KristofersOzolinsMagebit deleted the bugfix/phase-0-version-gate branch August 11, 2026 11:28
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