Task flow · Office Hours seat

Office Hours seat

A visitor buys a payable tier or joins a free waitlist for Office Hours sessions.

Status Implemented Last reviewed 2026-08-06 All task flows →

Flow

flowchart TD
      A["Visitor opens /ressources/office-hours/"] --> B["Browse tiers and sessions"]
      B --> C["Open tier / session detail"]
      C --> D{"Product type?"}
      D -- "office_hours" --> E{"Payable price?"}
      E -- Yes --> F["Render checkout form"]
      F --> G["POST /paiement/produit/<slug>"]
      G --> H["Same flow as product purchase"]
      E -- No --> I["Render waitlist form"]
      I --> J["POST registration"]
      J --> K["Store WebinarInterest + assign cohort"]
      D -- "cohort_access" --> L["Render lead form"]
      L --> M["POST cohort application"]
      M --> N["Store lead; no payment"]
            

Payment states and transitions

StateSet byNext
PENDINGView creates the row→ PROCESSING (checkout started)
PROCESSINGView after Stripe session created→ PAID (webhook) or FAILED (provider error)
PAIDWebhook only→ settled; entitlements granted
CANCELLEDBuyer action on Stripe→ terminal; row stays open
FAILEDProvider outage or invalid signature→ terminal; owner may retry
EXPIREDTime or terms window→ terminal; owner must reissue

Security and integrity rules

RuleEnforcement
Amount authorityServer reads ProductPrice.amount_eur; browser input is never charged.
Terms freezeterms_version is stamped at payment creation.
Settlement authorityOnly the signed Stripe webhook writes PAID.
No card data on serverStripe hosts the checkout page.
ThrottlingMax 10 pending payments per email per hour.

Validation and recovery

ConditionSystem response
Product has no payable priceThe checkout form is not rendered; waitlist form appears instead.
Email is throttledError message; redirect back to Office Hours page. No row is created.
Webhook signature is invalid400; nothing is written. Stripe retries.
Payment is already settledRedirect to the return page; no second charge is created.

Entitlement and delivery

When the webhook records a settled payment, grant_entitlements() creates the corresponding Entitlement row. The buyer receives a Stripe receipt by email and a personal delivery link.