Commerce and Fulfillment Architecture
Status: Design specification only. No processor, credentials, checkout session, webhook, payment call, download endpoint, entitlement, or fulfillment process is active.
Ownership boundaries
Coal Road's future server-side system will own the product catalog, server-authoritative price, customer identity, quote decision, order number/state, product and license-version references, acceptance timestamp, and fulfillment state. A selected processor will handle regulated card or bank entry, authorization/processing, processor risk controls, and processor settlement. A redirect to a success page is never payment proof.
Provider-neutral interface
A future adapter contract will define create_checkout(order), get_payment_status(reference), handle_webhook(payload), refund(payment), and get_provider_reference(payment). Provider selection will be environment-driven (for example PAYMENT_PROVIDER=stripe) and credentials will be external secrets, never source constants. Stripe may fit a customized card flow; GoDaddy Payments may be evaluated for its payment links and ACH/card options; Plaid Transfer is a bank-transfer rail and account connectivity product, not a conventional card checkout. No provider is selected here.
State model
DRAFT → QUOTE_REQUIRED → AWAITING_LICENSE → AWAITING_PAYMENT → PAYMENT_PENDING → PAID → FULFILLMENT_READY → FULFILLED. Failure, refund, and cancellation use explicit PAYMENT_FAILED, REFUNDED, and CANCELLED states. Transitions are server-side, validated, idempotent, and audit recorded. PAID requires a provider-verified server state and the provider's signed event/status procedure.
Proposed records
- ProductCatalog: product/version, authoritative price, availability, release and checksum references.
- Order / OrderLine: immutable order identifier, customer, product/version, quantity, server-priced amount, currency, state, timestamps.
- QuoteRequest: scope inputs, gate reasons, review state, customer-provided brief, no automatic fixed total when the scope gate applies.
- CustomerContact: minimum contact fields and organization data needed for an order or quote.
- PaymentAttempt: provider name, opaque provider reference, idempotency key, amount/currency, normalized status, timestamps. Never store raw card, security-code, or online-banking credentials.
- LicenseAcceptance: order, product/version, exact license version, actor, timestamp, and a record of the offered document/version.
- DownloadEntitlement / FulfillmentState: issued only after verified payment, valid license acceptance, and existence of the exact release artifact.
API outline
Proposed first-party operations: POST /api/quote-requests (CSRF protected and idempotent), POST /api/orders (server reprices catalog selection), POST /api/orders/{id}/license-acceptance (exact published version only), POST /api/orders/{id}/checkout (provider adapter), GET /api/orders/{id} (authorized state), provider-specific signed POST /api/payment-events/{provider} (signature verification, replay window, idempotency), and authenticated GET /api/downloads/{entitlement} (short-lived authorized access, checksum and audit). These are design proposals, not implemented routes.
Security requirements
Use CSRF protection for browser mutations; webhook signature verification and replay protection; idempotency keys; duplicate-order controls; server-side catalog price authority; append-only payment/license/fulfillment audit; explicit allowed state transitions; access checks on customer and entitlement; rate limits and abuse monitoring. Never trust client-supplied prices, query-string success, or browser redirects. Do not fulfill until payment, license version/acceptance, and release-artifact checks all pass.
Current gate
The storefront is presentation-only. It collects no card/bank credentials and transmits no quote. Software artifacts and the production payment backend are not available through the public site.