Repository navigation
feat: adopt the pinned spec target and the shared base, and close the conformance gaps - #9
Conversation
…-of-stock case and the three coupons the conformance run expects. Re-running updates in place.
…p, and follow the OrderPlatformSchema rename.
…s open string no longer defines them, and only DI compilation caught the XML references.
…bit_AgenticCore, deleting the duplicated price converter.
…pping from claim outcome to this module's error envelope. A data patch copies rows still inside their TTL window; the old table stays declared because declarative schema runs before data patches.
…n map becomes two routes with different methods, and its any-shared-segment match is replaced by an anchored pattern.
…ethod writer and shipping option resolver. The fulfillment option total now carries the incl-tax amount, which is what the schema's fulfillment total means.
…n unfiltered backfill copies every existing link; ucp_checkout_meta.order_id stays declared and stops being read.
…26-01-23 in discovery, the merchant profile, both capabilities and every checkout response while building payloads from the released library's 2026-04-08 types, so agents negotiated against the wrong version. A test now fails if the constant and the installed library's target drift apart.
…module. The read is gated on the encryptor's envelope rather than decrypting speculatively: it returns binary garbage instead of failing on a value it never encrypted, so rows written before this change would have replayed corruption.
…rser had no caller at all, so the URL it extracts was parsed and thrown away, and ucp_checkout_meta.webhook_url — the column that exists for it — was never written. Also binds the platform schema, which nothing had ever built.
…0, Webhook-Id, Webhook-Timestamp and UCP-Agent, dispatched through the shared queue on its own cron. The event timestamp is when the order changed rather than when the attempt is made, since a retry is the same event. No credential is sent and delivery ships disabled: the protocol offers three authentication schemes and none has been agreed, and the body needs the Order representation that does not exist yet, so the enqueue site is deliberately unwired.
…get types total amounts as signed_amount and constrains discount and items_discount to exclusiveMaximum 0, where the 2026-01-23 snapshot the code was written against typed every amount minimum 0.
…026-04-08 defines the shape and forbids extra properties, so the old top-level status was a violation; the four hand-built messages it carried were also missing content and severity.
… order with quantity tracking, fulfillment expectations, the shipment event log and refund adjustments. An order is only disclosed when the shared link shows this protocol's checkout produced it, and the region rule now follows the store's configuration instead of demanding one everywhere.
…d keep every scrubbed id consistent so a fixture's cross-references still resolve. The echoed selection named an identifier the response had renamed to the quote address id, and the scrubber renumbered each id occurrence independently.
…d no body to carry. The agent's webhook URL was never resolved because the parser looked for a `name` field inside the capability registry, which is keyed by name; shipments and refunds are read through their repositories so an event does not report the order as it was before the document it is announcing.
… unbound spec types
…coupon discounts in totals
…se, and send queued webhooks on demand
…at was never checked
✅ Magebit Code Review — Review completeReviewed up to No issues met the confidence threshold to publish.
Findings checklist
Changed files (180).github/
Api/
Console/
Controller/
Cron/
Exception/
Model/
+130 more files… Reviewed by |
…s the storefront hides
|
All seven findings are addressed. One correction to the reasoning, and one severity I disagree with. Order enumeration — fixed. Orders are now addressed by their checkout session id, which is Webhook SSRF — fixed, the URL goes through Catalog lookup — capped at the existing Catalog search — paged in SQL. The total now comes from a Hidden products — the single-SKU path now applies the same status, visibility and store rules as Catalog tests — added, 12 tests covering the cap, an empty query, a missing id, and a Thumbnails — fixed, but I disagree with High. The loop is bounded by how many lines a real order Verification: Also added on this branch: a CI workflow running PHPStan and the unit tests against a real Magento |
| // The order is addressed by its checkout session, which nobody can guess. The store's own | ||
| // order number is only a label, because it runs in sequence and anyone could count up to it. | ||
| $response->setId($checkoutId); | ||
| $response->setLabel((string) $order->getIncrementId()); |
There was a problem hiding this comment.
[Medium] No test checks that an order is advertised by session id
maintainability · general profile · confidence 75%
The whole point of this follow-up is that agents must come back with the checkout session, not the sequential order number. setId($checkoutId) and setLabel(...) do that, but nothing asserts it.
OrderToOrderResponseTest only checks that pictures load once. QuoteToCheckoutResponse does the same mapping for the checkout confirmation and has no test at all. Putting the increment id back on id would still pass this change’s tests.
Assert that convert() sets id (and the confirmation’s id) to the session, and label to the increment id.
… products Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…er number Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
@magebit-automation review |
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nnot require Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…t a factory Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…break search Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Brings this module onto the pinned specification target and the shared base, and closes the
conformance gaps that surfaced along the way. Conformance is 61 of 65 against the official suite
with its own three defects patched, 39 of 65 against an unmodified checkout, which cannot
complete a purchase against any server.
Talking the protocol properly
UCP-Agentheader is read and an unsupported version is refused withunsupported_version. Checked inside idempotency handling rather than after it, because an agentthat cannot read this version's payloads cannot read a replayed one either.
Magento sentence. It now reports every blocker as a typed message with the JSONPath of the field:
a missing email, no delivery option chosen, a product that does not exist, a quantity the store
cannot supply. Validation answers 422 rather than 400, because the body parsed and the objection is
to what it says.
before the item is added. Magento only reports a refused quantity while collecting totals, by which
point nothing can say which item it was about.
dropped.
the extras now come back as
not_applied.PUT /orders/{id}accepts an adjustment request, records it and puts a note onthe order for staff. It does not refund anything, and it refuses an agent-declared shipment with
not_accepted: only the store can say a parcel was sent.delivery address when the cart carries only one.
Signed webhooks
Order events are delivered with RFC 9421 message signatures over the receiver's own authority and
path, not ours, so a relayed delivery does not still verify. Per-store ES256 keys are generated on
first use and published as JWKs with a key id in the discovery profile, with rotation and a grace
window. Retries reuse the event's identity and occurrence time; the first retry is almost immediate,
then the waits grow hard.
Taken from the shared base
Request validation and hydration, idempotency arbitration, the stock check, the buyer writer, the
total label, the scheduled dispatch and the JSON endpoint plumbing all moved to
Magebit_AgenticCoreand are consumed from there. Nothing about either protocol lives in thatmodule. Validation rules now come from the generated specification interfaces rather than being
restated here, which is what removed the hand-written checks.
Two latent bugs fell out of that comparison:
missing street was reported by nothing until the order failed with a message naming no field.
Notes for review
d/checkpasses: phpcs, phpstan and 340 unit tests.correctly refusing to let an agent mark an order shipped, one wants two coupons on one cart, and
one expects a card payment to be declined by a handler the store does not advertise. All four are
written up in
dev/tests/conformance/ucp/README.md.CONSTRAINTSconstant thegenerator now emits; see fix: carry the rules a list declares on its entries ucp-php-spec#11.
cut until the new tables are confirmed populated on a real install.