The new purchase flows bypass Office RnD's Grow Hub and write directly via API after Stripe confirms payment. That creates a seam where a successful payment might not produce the expected downstream record — and when it fails, it fails silently.
The pattern
Stripe payment ──► Worker ──► OfficeRnD (write) ──► MailerSend
(reliable) (may fail independently at any step)
Stripe is the system of record for money. Steps after it can each miss. Customer is still charged; the operational consequence varies by track.
Seam severities
Track 1 — Stripe ↔ OfficeRnD (member + membership)
| What failed | How you'd notice | Severity |
|---|---|---|
| Member creation | Worker log "member creation failed"; no OfficeRnD member for that Stripe email | High — no access |
| Membership assignment | Member exists but no plan; Stripe subscription active | High — can't use plan |
| MailerSend customer email | No email; MailerSend shows no record or failure | Low — non-blocking |
| MailerSend team notification | Team missed the new-member ping | Low — non-customer-facing |
Track 2 — Stripe ↔ Google Calendar (OfficeRnD not written)
| What failed | How you'd notice | Severity |
|---|---|---|
| Gate 2 conflict | Auto-refund in Stripe; no calendar event | Medium — rebook help |
| Calendar event creation | Single-day: auto-refund fires. Multi-day: Worker deletes partials + refunds | Medium |
| Multi-day cleanup failure | Partial events and no refund | High |
| Webhook not delivered | Stripe says succeeded; Worker has no record | High |
Track 3 — Stripe ↔ OfficeRnD (day pass)
| What failed | How you'd notice | Severity |
|---|---|---|
| Pass creation | Worker warning; kiosk rejects | High — paid, can't enter |
| Zero-validity pass | Pass visible but kiosk rejects | High — check intervalCount |
| Duplicate PaymentIntent (rapid double-click) | Two charges, one or two passes | Medium |
| MailerSend confirmation | No receipt, but pass is live | Low |
Monthly reconciliation (~15 min)
Run by the 15th of each month so discrepancies from the previous month are caught while context is fresh. Delegate to anyone with Stripe + OfficeRnD access.
Step-by-step
- Export Stripe. Dashboard → Payments → CSV for last month, successful only.
- Split by type using
description/ metadata: - Subscriptions → Track 1 - PaymentIntents withbooking_datesmetadata → Track 2 - PaymentIntents with day-pass metadata → Track 3 - Track 1 checks. Each new subscription: OfficeRnD member exists? Active membership matches Stripe plan? Initiation fee applied?
- Track 2 checks. Each booking PaymentIntent: Calendar event on every
booking_datesday? Refund? If refunded, event should not exist (or was cleaned up). - Track 3 checks (highest failure rate — audit closest). Each PaymentIntent: OfficeRnD member exists? Pass created with
validFrom/validTomatching purchase date? - Summary at the bottom of the sheet. - T1 checks: N / mismatches: M / repaired: M - T2 checks: N / mismatches: M / repaired: M - T3 checks: N / mismatches: M / repaired: M - Any systemic pattern (same miss twice+) → flag to Chris - File
Repair. Create the missing record manually (member, membership, calendar event, or pass per the relevant playbook). Email the customer with a brief apology + what you fixed.
Ad-hoc — when to also reconcile
- Customer complains about missing access (always 3-way check before assuming the flow worked)
- After a Worker deploy (smoke test with a real low-dollar purchase + refund)
- OfficeRnD or Stripe API deprecation / change notice
- New plan or product added
- Unusual pattern of complaints
Credentials inventory
Verify: [VERIFY — Chris to fill "Account Owner" before handover.]
| System | Holds | Account Owner | 2FA access | Notes |
|---|---|---|---|---|
| Stripe | Payments, subscriptions, refunds | Live mode | ||
| OfficeRnD | Members, memberships, day passes | Org: labour-temple |
||
| Cloudflare | Two Workers + domain/DNS | labour-temple-checkout, labour-temple-bookings |
||
| Webflow | Site + CMS | Site ID: 639b202ca505e87cee446ad0 |
||
| MailerSend | Templates + sender domain | Templates: z3m5jgr0y5xgdpyo, pr9084zxnvjlw63d |
||
| Google Workspace | Service account for bookings | JWT; no Domain-Wide Delegation | ||
| Domain registrar | labourtemple.com | Renewal: [VERIFY] | ||
| Slack / team email | admin@, membership@, chris@hundredacre.design | Recipients hardcoded in worker.js |
Credential rotation — what to update where
Expand — per-key rotation rules
- Stripe secret key → update
STRIPE_SECRET_KEYin both Workers; redeploy each. - OfficeRnD OAuth → update
OFFICERND_CLIENT_ID+OFFICERND_CLIENT_SECRETin checkout Worker; redeploy. - MailerSend API key → update
MAILERSEND_API_KEYin both Workers; redeploy. - Google service account → update
GOOGLE_SERVICE_ACCOUNT_EMAIL+GOOGLE_PRIVATE_KEYin bookings Worker; redeploy. - Stripe webhook secret → update
STRIPE_WEBHOOK_SECRETin bookings Worker; redeploy.
The Admin Reference as reconciliation tool
The offerings-comparison.html page is itself a reconciliation artifact — cross-checks Google Sheets source, Webflow CMS, Stripe config, and Worker plan config. Currently generated 2026-03-25. Regenerate quarterly or after any pricing/plan change.
Current inconsistencies to work through are listed in roadmap.md — moved there to keep this page operational.