Platform launch offer — implementation review
Prepared against desmotech/taikan main at 23bd209dbe09fc6a36cd658276143ff82d9da87e.
Implemented behavior
- Adds the
launch-eliteoffer: six calendar months at ₪0, twelve calendar months at ₪400/month including VAT, then the Elite monthly price displayed at acceptance (currently ₪499 including VAT). - Assumes monthly cancellation with no twelve-month minimum commitment. Standard price and legal text are snapshotted per purchase. Calendar boundaries use UTC and clamp short months without permanently drifting the anniversary.
- Adds platform-admin availability switches for Lite, Pro, Elite and Elite Launch. Normal plans default available; Launch defaults unavailable. Disabling an offer affects new checkout creation, not an already issued checkout or accepted subscription.
- Adds an owner onboarding plan/consent step behind the organization-scoped
platform-onboarding-offersPostHog flag, default OFF. It appears after organization setup. The billing route can be refreshed to resume verification; abandoning checkout does not prevent access to the existing Lite workspace and is not automatically resumed on later sign-in. - Uses existing platform Cardcom credentials, not organization/member-payment credentials. Launch uses hosted token-only registration: no subscription charge or tax document on activation. Regular paid offers charge their displayed monthly total; Lite needs no card.
- Requires server-validated ownership, current offer availability, quoted price, current legal-document ID, agreement version and independent trial acknowledgment. The API stores the exact localized order text, accepting account, business name, request metadata and linked Terms of Use version in transaction metadata.
- Activates only after server verification. Cardcom token-only registration can legitimately omit a payment transaction; completion requires provider-confirmed token registration and a matching zero-amount trial ledger entry. Browser redirect parameters cannot activate access.
- Preserves recurring-charge intent/idempotency handling; uses the accepted schedule for amounts and due dates. A sweep cannot charge before the trial ends. Cancellation and offer renewals serialize on the organization lock, and the recurring path re-reads subscription state.
- Blocks replacement of an unresolved paid checkout from the new offer flow. A hosted paid checkout may still collect money, so its ledger cannot safely be discarded merely because another plan was selected. Zero-charge registration sessions can be superseded locally; late callbacks do not reactivate cancelled records.
- Allows one launch offer per organization. Reversing a scheduled cancellation keeps the original dates; a completed cancellation does not create a new free trial.
- Adds English, Hebrew and Russian checkout/consent text, with Hebrew RTL layout. The admin app follows its existing English interface.
Follow-up: onboarding features and admin controls
Each onboarding offer has a localized, scrollable “View all features” tooltip. It opens on hover, focus or tap, lists the shared tier feature entitlements (including inherited features), member/coach/location limits and common capabilities, and preserves the existing PackagePicker coming-soon disclosures. Elite Launch uses the Elite feature list. The trigger is separate from the radio label, so viewing another tier does not select it or clear accepted checkboxes.
Admin cancellation/refund parity is not included in this patch. Owners can schedule cancellation at period end and reverse it before it takes effect. The existing admin payment-record cancellation does not stop the subscription or return money. Although the Cardcom provider adapter implements refunds, platform billing has no admin refund endpoint/UI and associated refund-ledger workflow. Full/partial refunds and admin immediate/end-of-period cancellation require separate implementation with provider confirmation, credit-document handling and an audit trail. The existing admin tier override changes access only, not the billing contract.
Legal document
See platform-launch-subscription-terms.md for the full localized agreement, separate unchecked acknowledgments and legal-review points.
The existing Terms of Use section 8 expressly disclaims an SLA. The implementation references those current availability/support terms and any separately signed SLA. It does not promise a new SLA. A numeric uptime target, response deadline, exclusions and remedies must be agreed and added to the Terms of Use if that is the intended product promise. Trial disclosures reduce ambiguity; they do not make Taikan immune from claims or remove mandatory legal rights.
Database and rollout
Generated, reviewed, not applied: libs/db/drizzle/0144_platform_launch_offers.sql adds the availability table and nullable subscription offer_schedule JSONB field, with Drizzle snapshot/journal updates. It does not rewrite existing subscriptions.
- Apply the patch to a full checkout at the pinned revision, then rebase/review against current main. If another migration took sequence 0144, regenerate the migration and metadata.
- Run the repository’s normal lint, typecheck, build and relevant test gates using its pinned dependencies.
- Complete legal review and resolve the SLA promise. Update the agreement version if copy changes.
- With explicit owner approval, apply the migration to the intended environment. Deploy the API before the web/admin changes; leave the rollout flag OFF.
- Verify the complete owner/admin flow against a test database and Cardcom test terminal. Ensure platform billing credentials and localized published Terms of Use records are configured. Do not use live cards for this verification.
- Test token-only return/webhook/reconciler activation, a missing webhook, duplicate callbacks, pending paid checkout recovery, trial cancellation, cancellation/renewal races, all 12 discounted charges and the full-price transition. Confirm provider VAT/document settings produce the displayed all-in total.
- Enable the launch offer in admin and enable the organization-scoped PostHog flag for a controlled cohort.
Turning the onboarding flag or availability switch off stops new offer starts. Existing accepted subscriptions still need their recurring scheduler and original price schedule; removing these would break accepted contracts.
Verification evidence and limits
Focused isolated Vitest runs passed 67 tests:
- 31 new API tests: owner/offer/legal validation, platform token-only checkout, verified-token activation, paid checkout replacement guard, calendar boundaries, VAT-inclusive phase amounts, cancellation and duplicate-charge behavior.
- 30 existing recurring/reconciler regression tests.
- 6 new checkout UI tests covering independent consent, request contents, server-confirmed completion, empty availability, feature tooltips and tap/keyboard dismissal without changing the selected plan or consent.
The harness used fetched production source and mocked external services. It was assembled outside the repository because authenticated terminal clone was unavailable; source files were read through the GitHub connector and checked against their Git blob hashes. The patch contains only feature changes, not the partial source baseline or temporary harness/dependencies.
A targeted TypeScript check found 34 missing-module diagnostics caused by the partial checkout/dependency set; it reported no other diagnostics. This is not a passing full-project typecheck. No full application build, live browser visual check, PostgreSQL concurrency integration test or Cardcom end-to-end test was run. No card was charged, migration applied, production setting changed or deployment made.
Review package
The package contains a unified Git patch, copies of changed files, this review note, the legal draft and focused test logs. The patch is based on the pinned GitHub source revision and was checked with git apply --check against the reconstructed pristine files. Changes are staged locally but uncommitted: repository AGENTS.md requires explicit user approval before creating commits.