[Admin] Waiver & forms enforcement at signup
Who's In enforces waiver acceptance at every new-member signup surface — free joins, paid Checkout, and waitlist joins. Existing members are grandfathered at the waiver version they accepted.
Where to configure your waiver:
- Clubs: Admin → Settings → Waiver section. Toggle "Require waiver at join" + enter your waiver text and upload the signed PDF.
- Studio: Admin → Settings → Waiver section (same shape).
What the member sees at signup:
- A required checkbox: "I have read and accept the {Club/Studio} waiver"
- A link to the full waiver text (rendered inline for quick read, with downloadable PDF if you uploaded one)
- No "Join" / "Continue to Payment" CTA until the box is ticked
What we record on every acceptance:
- `waiverAcceptedAt` (server-side Timestamp)
- `waiverVersion` (the version number active at signup — increments when you change the waiver text)
- `waiverTextSnapshot` (hash of the accepted text for legal audit)
If your waiver changes:
- `waiverVersion` bumps.
- Existing members keep their accepted version — they're grandfathered.
- New signups must accept the new version.
Legal best-practice alignment:
- Explicit consent (required checkbox, not a pre-checked box)
- Snapshot of accepted content at the exact moment of acceptance
- Immutable audit record via Firestore security rules
- Member can always re-download their signed version from the member dashboard
Free signups (joinClub): waiverAccepted flag required; backend rejects missing.
Paid signups (createClubMembershipPayment, studioCreatePlanCheckout): waiverAccepted passed through Stripe Checkout metadata; webhook stamps at membership creation. Frontend enforces at signup form.