cp10 standalone checkout engine
14 of 17 REQs done — all engineering complete and e2e-proven; the rollout (REQ-573/574/575) was discarded by user decision on 2026-06-10. cp10 is a reference build: no production traffic, fully tested and locally servable. For understanding how the engine works, read the guided walkthrough — this page is the historical delivery record of the UR-196 batch.
What the deliverable looks like today
This is the cp10 engine served standalone from its own directory
(php -S + index.php, screenshot taken 2026-06-09). It returns HTTP 200 with the
JS bundle baked in — proof of the REQ-572 live-route delivery and the guarded PHP includes.
- Card payment block — Braintree hosted fields mount here once the engine boots on a real page. Behind this form sits the new explicit decline-code map (REQ-565/566) that replaced fragile substring matching, with every customer-facing error banner preserved verbatim.
- PayPal option — its popup lifecycle is broadcast via the hardened, origin-scoped
postMessagehelper (REQ-567). A declined PayPal payment now reliably shows the PayPal banner instead of generic card advice (REQ-582). - Address-suggestion block, visibly un-hidden — normally hidden by script. It shows here because standalone serving has no page-provided jQuery, which is exactly the documented load precondition: the host page must supply
window.jQuery≥ 3.5. Expected in this context, not a bug. - Subscribe button — on success the engine writes
window.newSubData/window.existingSubData, the contract the page's post-purchase hooks read.
All 17 cp10 REQs
| REQ | What it delivers, in plain words | Status | Commit |
|---|---|---|---|
| Built & committed (offline batch complete) | |||
| REQ-564 | Forked cp9's engine into its own directory and severed every path that escaped it — own build, own dependencies, vendored gateway constants. Zero shared code with cp8/cp9, by design. | Done | ec3ff728 |
| REQ-565 | Investigated real gateway decline responses (real Braintree sandbox) and specified the explicit decline-code map. | Done | 75494047 |
| REQ-566 | Replaced the brittle "does the error text contain the word Declined?" matching with that explicit map (src/decline-codes.js) — every banner customers see reproduced exactly, proven by golden-master tests. | Done | a4be4605 |
| REQ-567 | Hardened the engine's outbound messaging: all postMessage calls now locked to this site's origin instead of "anyone" ('*'), through one shared helper. | Done | 146178ee |
| REQ-568 | Made the engine's analytics version label (checkoutEngineVersion) immutable and suffix-free, so reporting can never silently drift mid-session. | Done | 58c7f5e1 |
| REQ-569 | Unit tests on all extracted modules — 128 tests green as of this batch, including the load-bearing 3D-Secure safety predicate. | Done | 0af08f2c |
| REQ-571 | Wrote the engine's contract down: the prime doc (area index) covering how a page loads the engine, what it must provide, and what comes back. | Done | a1d0a4c8 |
| REQ-572 | Live-route delivery (?page=checkout-eet-engine-cp10) verified working with defensive "bundle missing" logging — the scaffold already carried it; confirmed live, no code change. | Done | cabb4f10 |
| REQ-581 | Renamed leftover cp9-named internals to cp10 (globals, data-attributes, log labels) — behavior-neutral, all tests still green. | Done | c749d26e |
| The gate — passed | |||
| REQ-570 | Playwright e2e of the full page↔engine handshake, 4/4 green: the page's real loader injects cp10 (the cp9 engine URL network-swapped — REQ-573's repoint in test form); card happy path with real Braintree-sandbox tokenization; generic + PayPal decline banners verbatim, including the engine's real PayPal popup flow — the PayPal-400 fix proven end to end. Run with npm run test:e2e from the engine dir. | Done | 6b46d2a6 |
| Rollout tail — discarded 2026-06-10 (user decision: no deployment) | |||
| REQ-573 | A/B-gate the cp9 page so a configurable % of traffic loads cp10, with instant rollback to the cp9 engine. This is the proving step — the first real customers. | Discarded | — |
| REQ-574 | Add cp10's adopting page to Feroot PCI script monitoring. | Discarded | — |
| REQ-575 | General availability: publish cp10 as one self-contained cached file (cached/…cp10.html?v=YYYYMMDD), which permanently removes the "deploy dropped dist/" failure mode. Rollback = previous version or cp9. | Discarded | — |
| Hardening follow-ups discovered during the build — all shipped after clarify | |||
| REQ-582 | Fixed the long-standing PayPal-400 banner bug: the decline mapper now receives the attempt's payment-method type, so every PayPal-path failure shows the PayPal banner instead of generic card advice. Built from the captured response shapes; live-capture confirmation is a pre-rollout checklist item for the A/B window. | Done | 10e92bdd |
| REQ-583 | Null-guarded the analytics message listener — a third-party message with null data is now ignored instead of throwing. One guard hardens both analytics buffers. | Done | 77c600e5 |
| REQ-584 | Origin allowlist on the page-side loader's message listener — the receive-side mirror of REQ-567's send-side hardening. (Shared loader, serves cp8/cp9 too.) | Done | 175d9fa5 |
| REQ-585 | PayPal payer fields are now omitted from fraud-screening (Forter) params when absent — no more literal "undefined" strings sent to the backend. | Done | a682bb39 |
How cp10 integrates — and where the isolation line is
The engine is not an iframe. The host page fetches the engine's HTML and injects it into its own document, so page and engine share one window. The robustness comes from where the boundary is drawn: nothing inside the engine directory reaches outside it, and nothing in cp8/cp9 can touch it.
Rollout path (everything reversible at every step)
flowchart LR
A["Today: built, unit-tested,
e2e-proven — 14 REQs done"] --> B{"Your sign-off
first real customers"}
B -->|go| C["REQ-573 A/B gate
small % of cp9-page traffic
+ PayPal live-capture check"]
C --> D["REQ-574 Feroot
PCI monitoring"]
C -->|proving succeeds| E["REQ-575 GA: cached
self-contained .html?v="]
C -.instant rollback.-> R["cp9 engine URL"]
E -.rollback.-> R
Limitations — what this does not give you yet
- No customer has touched cp10. Until REQ-573 flips the A/B gate, zero production traffic flows to it. Verification so far is unit-level (135 tests) plus a live HTTP serve check — not a real purchase.
- The e2e proof ran against mocked declines, not live ones. The card path tokenizes against the real Braintree sandbox, but the decline cases use the captured backend response shapes — the local Go service holds no merchant credentials and implements neither the card nor PayPal legs. Real decline bodies get confirmed during the A/B window (the live-capture checklist item below).
- The PayPal-400 fix is built from captured response shapes, not live captures. The four hardening follow-ups (REQ-582–585) are all fixed and test-pinned, but REQ-582's decline-signal design rests on the source-derived backend shapes from the REQ-565 investigation. The pre-rollout checklist item: an operator live-captures real PayPal decline bodies during the A/B window and confirms PayPal-path declines report the PayPal banner in
Subscription Erroranalytics. - The engine cannot run alone by design. It needs a host page providing jQuery ≥ 3.5 and the platform's serve-time PHP mounts. That couples cp10 to the page — never to the cp8/cp9 engines — and is documented as a load precondition, not hidden.
- Until the cached GA artifact ships (REQ-575), a deploy filter that drops
dist/bundle.jskills the engine. A precise console error surfaces it, but the real cure is the self-contained cached file. - Gateway-ID rotation is now an N-place edit. Vendoring the gateway constants is the accepted price of isolation (the keys are browser-public, so no new secret exposure).
How to get to a well-integrated, robust launch
The architecture work is done; what remains is sequencing. The recommended order:
- Give the go for REQ-573 and open the A/B gate at a small percentage — the only remaining decision is yours; every dependency is met. Watch declines, PayPal completion, and analytics labels (
cp10 3DS, version field). During this window, run the REQ-582 pre-rollout check: live-capture real PayPal decline bodies and confirm they report the PayPal banner. Rollback is one config change back to the cp9 URL. - REQ-574: add the page to Feroot monitoring during the proving window.
- REQ-575: publish the cached versioned artifact and cut over. From then on, rollback is a previous
?v=— and thedist/deploy trap is gone for good.
prime-checkout-eet-engine-cp10.md so the next page integrates from a written spec instead of
copying by osmosis.
Verify it yourself
# Isolation gate — must print nothing grep -rn "\.\./\.\./\.\./shared\|\.\./\.\./shared\|shared/common" \ web/checkout-eet/p/static/checkout-eet-engine-cp10/src/ # cp8/cp9 engines untouched — must print nothing git -C web/checkout-eet diff --stat -- \ p/static/checkout-eet-digital-inline-form p/static/checkout-eet-digital-inline-form-cp9 # Independent build + unit suite (135 tests) cd web/checkout-eet/p/static/checkout-eet-engine-cp10 npm run build && npm run test:unit # The load-contract e2e (4 tests; auto-starts PHP on :8100, needs network) npm run test:e2e # Serve the engine standalone (what the screenshot shows) php -S localhost:8123 # then open http://localhost:8123/index.php # Trace any REQ to its commit git show ec3ff728 # REQ-564 scaffold; see the table for the other twelve SHAs
AI-generated report (2026-06-09, updated 2026-06-10 after REQ-582–585 and the REQ-570 e2e
shipped). REQ statuses, commit SHAs, and the screenshot were verified against the repo and live local runs;
test counts (135 unit / 4 e2e) were re-run at the REQ-570 completion and will drift as work continues. Source
assets: ai-reports/2026-06-09_2338_UR-196-cp10-engine-status/screenshots/.