Feedback from the origin app (the production two-location wet cleaner customPOS was generalized from). We just finished a pre-launch hardening pass there: every payment mechanism was consolidated into single tested units, adversarially reviewed by multi-agent workflows, and regression-tested (196-assertion money harness gating every deploy). These are the card-handling lessons that were each learned from a REAL production incident — the payments module should bake every one of them into its core so no operator ever re-learns them. The owner also wants this module packaged so it can be shared standalone with operators who only want the card piece — see "Packaging" at the bottom.
Charge-path invariants (each of these bit us live)
- One saved-card charge primitive. Tokenized charges MUST send the card expiry normalized to MMYY digits (
String(exp).replace(/\D/g,'') — accept "03/28" and "0328"). In the origin app this rule was hand-copied at 7 call sites and the "non-numeric expiry" decline had to be fixed FIVE separate times before consolidation. The primitive should also own: per-location merchant-account resolution (card's store → customer's home store → station), and clearing an "unverified" flag on any approved charge.
- One card-present (reader) scaffold owning the whole lifecycle: double-tap debounce; the STATION's terminal (the reader in front of the customer — never the customer's home location's terminal; books still attribute by order/location separately); a cancel contract that cancels the PHYSICAL terminal (Esc/nav teardown included); and the stale-result rule below.
- Late-approval alarm — captured money must never vanish silently. If a terminal approval races past the cashier's Cancel, the charge exists at the processor with nothing recorded. Never silently drop it: log auth+ref in ONE searchable format and show a loud tell-a-manager alarm. The origin app had this alarmed at one screen and silently dropped at three others until the audit caught it.
- Refund reachability. Store the processor reference on EVERY card payment row and mirror it into the canonical txn field (never overwriting a check number). The origin app had card payments whose "refunds" were recorded in the books but never sent to the card because the ref was stored under a different field per path. Refunds: original tender only, amount computed from the ticket (never typed — anti-theft), owner/approval-gated.
- The "3DS-style" issuer fallback. Some issuers refuse ALL $0 account verifications on typed-in cards. Ladder: $0 verify → $1 auth+void fallback → save-unverified with a visible ⚠ flag where the first real charge becomes the test (decline of that first charge lands in a collections queue, not a void).
- Debounce at every interactive entry point — but NOT inside the charge primitive. A batch path (monthly auto-billing charging many customers sequentially) will false-decline its second customer if the debounce lives inside the primitive. Learned by near-miss.
- Card fee / surcharge discipline. Surcharge is caller policy; fee rows use an exact method label excluded from paid-total math; recompute due+fee at CLICK time (a background sync can change the balance between render and tap — a stale render-time fee once nearly charged a fee against a $0 due), and always show a confirm step before charging a saved card.
- Every decline is LOGGED before it is shown. Three origin-app screens presented declines with no audit entry — a dying card or fraud probing on one customer was invisible. A disputed "you charged me / no we didn't" needs the trail.
PCI / trust posture (matches the module's existing blueprint — keep it loud)
- The browser never touches a PAN: hosted iframe/tokenizer only; gateway credentials live only on the operator's own server; the downloaded file contains no secrets. This posture is exactly what makes the module shareable — operators can adopt the card piece without inheriting PCI scope.
Packaging request (the owner's ask)
Publish the payments piece as a standalone, operator-shareable module page on the site: the processor-agnostic interface + certified reference adapter + THIS hardening checklist as its test plan. Many shops don't want a new POS — they want card handling that is actually right. A page that says "here is the card module, here are the eight production-learned invariants it enforces, here is the harness that proves them" is the sharpest wedge the project has.
Source: origin-app consolidation pass, 2026-07 (adversarial multi-agent review; findings regression-tested). No proprietary data included.
Feedback from the origin app (the production two-location wet cleaner customPOS was generalized from). We just finished a pre-launch hardening pass there: every payment mechanism was consolidated into single tested units, adversarially reviewed by multi-agent workflows, and regression-tested (196-assertion money harness gating every deploy). These are the card-handling lessons that were each learned from a REAL production incident — the payments module should bake every one of them into its core so no operator ever re-learns them. The owner also wants this module packaged so it can be shared standalone with operators who only want the card piece — see "Packaging" at the bottom.
Charge-path invariants (each of these bit us live)
String(exp).replace(/\D/g,'')— accept "03/28" and "0328"). In the origin app this rule was hand-copied at 7 call sites and the "non-numeric expiry" decline had to be fixed FIVE separate times before consolidation. The primitive should also own: per-location merchant-account resolution (card's store → customer's home store → station), and clearing an "unverified" flag on any approved charge.PCI / trust posture (matches the module's existing blueprint — keep it loud)
Packaging request (the owner's ask)
Publish the payments piece as a standalone, operator-shareable module page on the site: the processor-agnostic interface + certified reference adapter + THIS hardening checklist as its test plan. Many shops don't want a new POS — they want card handling that is actually right. A page that says "here is the card module, here are the eight production-learned invariants it enforces, here is the harness that proves them" is the sharpest wedge the project has.
Source: origin-app consolidation pass, 2026-07 (adversarial multi-agent review; findings regression-tested). No proprietary data included.