79
A1 touchpoints
126
A2 touchpoints
196
A3 event types
areas data external Twirp RPC PGQ trigger HTTP call direct DB direct DB direct DB webhooks A1: Account Mgmt 79 touchpoints A2: Sub Commerce 126 touchpoints A3: Auto Billing 196 event types Shared State 5 tables Stripe external
Three areas, five data stores, and Stripe — all connections shown. Every area reaches inward to shared mutable state.
A1 Account Mgmt Twirp RPC A2 Sub Commerce PGQ trigger A3 Auto Billing HTTP call A1 (cycle)

A directed cycle. Each area depends on the next through a different integration mechanism — Twirp RPC, PGQ triggers, and HTTP callbacks. All three reach inward to the same shared mutable state. The coupling is in the data, not the code paths.

FromToMechanismData / EffectSeam Type
A1 Account MgmtA2 Sub CommerceTwirp RPCPM type determines collection path — card vs. invoice vs. ACH routingInter-area
A2 Sub CommerceA3 Auto BillingPGQ triggerSubscription changes trigger billing recalculation and invoice generationInter-area
A3 Auto BillingA1 Account MgmtHTTP callDunning escalation flags trigger ban/unban — bad_debt status propagationInter-area
The Blind Surface · 79 touchpoints

Customers and support see billing state without understanding it. 23 Dashboard endpoints, 38 iAPI Gateway endpoints, 18 NinjaPanel endpoints. Billing history showed "Paid / Paid" for resolved bad debt. No observability.

changes_calculator · 126 touchpoints

Every subscription mutation flows through a unified 4-stage pipeline. The system committed state before payment — then attempted to roll everything back on failure. The rollback path was incomplete.

Event Compression · 196 event types

196 Stripe event types compress through a single surface before fanning out to 5 subsystems. 27 webhook handlers, five stores — but no handler reads all five.