Skip to content

Partner-onboarding-gated work (#200 → #191 / #226)

A cluster of pre-launch work is deliberately parked on a single business/product milestone — onboarding ≥2 real partners — not on engineering availability. This note captures the dependency chain so it isn't buried in Riff #200's comments.

TL;DR: Until ≥2 partners are each (a) a row in partner_stripe_accounts (Stripe Connect) and (b) linked from their Strapi partner entry to a partner-service UUID, the FALLBACK_PARTNER_ID=partner1 shim is the correct pre-launch behavior. Riffs #200, #191, and #226's activation all stay parked until then. Shipping any of them earlier regresses the verified booking flow.

The root problem (#200)

The AI planner suggests services by reading Strapi directly (Riff #197 Part A, 6d48ece). Strapi's partner relation only exposes a documentId (24-char alphanum) — not a real partner-service UUID. Each PlanSlot therefore carries a non-UUID partner_id.

Riff #191 (7c32a2a) guards checkout: if partner_id isn't UUID-shaped it falls back to FALLBACK_PARTNER_ID = 00000000-0000-4000-8000-000000000003 (the demo partner) so POST /bookings → /confirm doesn't 404 against partner_stripe_accounts (which is keyed by real UUIDs). The FE shim lives in frontends/public-fo/src/pages/TripPage/TripPage.container.tsx.

Consequence: every Strapi-sourced booking routes its Stripe transfer (the money) to the demo partner → wrong revenue attribution. Masked today only because partner1 (5e6c51f4-…) is the only partner with a live Connect account on qual.

The decision (José, 2026-05-26): Option B

Three sync directions were considered:

  • (A) Strapi holds partner_service_uuid, written by partner-service.
  • (B)chosen — partner-service is the system-of-record; Strapi mirrors partner_service_uuid via a CRUD webhook. Matches the data-ownership model (bookings/payments already trust partner-service UUIDs).
  • (C) in-process lookup (experience-service second hop) — rejected.

Why no code shipped — the two prerequisites (neither is an engineering task)

  1. The data linkage does not exist. Seeded Strapi partners (hotel-atlantic-lisbon, …) aren't linked to any partner-service partner row.
  2. Only one partner is Stripe-onboarded. partner1 is the lone row in partner_stripe_accounts (infrastructure/scripts/connect-onboarding-seed.sh seeds exactly one).

If you dropped the fallback today, every booking to a non-partner1 service would 404 at /confirm (no Stripe account) — strictly worse than today's "route everything to partner1," which at least lets bookings complete. Building now would create dormant, untested-against-real-data code. Hence the turnkey plan.

The 6-slice plan (executes when partner onboarding begins)

  1. Linkage — on partner onboard (gets UUID + Connect account), create/link its Strapi partner entry. The missing foundation everything else depends on.
  2. Strapi schema — add partner_service_uuid (string, optional, indexed) to the partner content type. Additive → one strapi-cms rebuild, no data migration.
  3. Mirror webhook — partner-service PATCHes the Strapi partner entry's partner_service_uuid via the Strapi Admin API on partner create/approve.
  4. Planner readtoPartnerService() prefers s.partner.partner_service_uuid (real UUID) over the uuidv5(documentId) shim; keep uuidv5 as fallback for un-mirrored partners. Unit-test both branches.
  5. Drop FE shim (closes #191) — once partners reliably carry real bookable UUIDs, drop FALLBACK_PARTNER_ID. booking/confirm must gracefully handle "partner has no Stripe account" (block + actionable message, not a silent 404).
  6. Verify — end-to-end booking to a non-partner1 onboarded partner routes the Stripe transfer to that partner's Connect account (payment_qual + Stripe dashboard attribution).

What this blocks downstream

Riff Status Relationship
#200 todo This sync. Blocked on the onboarding milestone (above).
#191 todo Drop the UUID-fallback shim. Gated on #200 slice 5.
#226 review (parked) Defer contract-service + document-signing-service. Parked on #200 — those services exist for partner-contract signing, which only matters once partners onboard. Same milestone.

The Stripe Connect Express onboarding mechanism already exists (Riff #83, Plan #020 — POST /payments/connect/accounts + account-links + KYC webhooks). The gap is operational: actually onboarding real partners and establishing the Strapi↔ partner-service linkage.

The unblock trigger

First real multi-partner onboarding — a business/product event, not an engineering decision. When it lands, execute the 6 slices above in order; until then this cluster stays parked and FALLBACK_PARTNER_ID=partner1 is correct.

Full decision record + analysis: Riff #200 comments (2026-05-26).