docs(launch): condense LAUNCH_READINESS and ignore prereg dump script
Collapse completed launch sections (receipts Phase 1, cadence UX, contribution-amount manual tests) into one-liners; move them to the archive memory. Move the three known post-launch gotchas to their own subsection. Ignore the local one-off preregistration dump script.
This commit is contained in:
parent
b222b14e61
commit
886c62e7b1
2 changed files with 15 additions and 81 deletions
|
|
@ -2,32 +2,17 @@
|
|||
|
||||
**Status as of 2026-04-20.** Target launch: before 2026-05-01.
|
||||
|
||||
Single source of truth for work that must happen before cutover. P0 blocks launch. P1 is strongly preferred but survivable. Completed items have been archived — see `~/.claude/projects/-Users-jennie-Sites-ghostguild-org/memory/project_launch_readiness_archive.md`. Post-launch backlog lives in `docs/TODO.md`.
|
||||
Single source of truth for work remaining before cutover. P0 blocks launch; P1 is strongly preferred but survivable. Completed items are archived — see `~/.claude/projects/-Users-jennie-Sites-ghostguild-org/memory/project_launch_readiness_archive.md`. Post-launch backlog lives in `docs/TODO.md`.
|
||||
|
||||
---
|
||||
|
||||
## Current state
|
||||
|
||||
- Vitest on `main`: **652/658 passing**. 6 pre-existing failures in `tests/server/api/helcim-payment.test.js` — unrelated to launch-blocking work, noted in the deploy checklist for visibility.
|
||||
- `main` is now caught up locally (2026-04-20): `feature/helcim-plan-consolidation` (40 commits) and `feature/contribution-amount-redesign` (17 commits) fast-forwarded in. Not pushed — site is not on Netlify yet.
|
||||
- Helcim plan consolidation migration ran against prod 2026-04-18 (Monthly plan id `50302`, Annual plan id `50303`). **Contribution-amount migration has NOT yet been run against prod.**
|
||||
- Cadence/contribution UX unified across signup + edit surfaces 2026-04-20. Uncommitted in working tree — see "Cadence UX refinements" below.
|
||||
- **Charitable receipts Phase 1 built on `feature/receipts-phase-1` (commits `bf5a333..91711aa`, 2026-04-20). Unmerged.** All four spec items shipped: `Payment` model + idempotent `upsertPaymentFromHelcim` helper, synchronous payment logging on both new paid subscriptions and free→paid upgrades, nightly reconciliation script, `/join` charity note, and `taxReceiptPreferences` schema field (no UI — Phase 2). Resend-owned confirmation email (`server/emails/paymentConfirmation.js`) is CRA-safe. Remaining work is deploy-time only (merge branch, disable Helcim default email on plans 50302 + 50303, backfill, real staging charge) — tracked in Deploy checklist.
|
||||
|
||||
### Cadence UX refinements (2026-04-20, uncommitted)
|
||||
|
||||
Shipped across `accept-invite.vue`, `join.vue`, `member/account.vue`, `welcome.vue`, `member/dashboard.vue`, and a new shared `SignupFlowOverlay.vue`:
|
||||
|
||||
- **Shared SignupFlowOverlay component.** Extracted from `/join` progress overlay; now used by both `/join` and `/accept-invite`.
|
||||
- **Static "Monthly Contribution" label** on all three contribution inputs (previously dynamic — flipped to "Annual Contribution" when annual cadence was selected, which was misleading because the stored value is always the monthly base).
|
||||
- **"Per Year" / "Per Month"** toggle copy (was "Annual" / "Monthly"). On `/accept-invite`, Per Year is now the default; `/join` stays on Per Month by default.
|
||||
- **Live billing-summary card** below the contribution input on both signup flows — reads e.g. "You'll be charged $180 today ($15/month × 12). Then $180 every year, until you cancel."
|
||||
- **Welcome heading on dashboard** for new signups: `/member/dashboard?welcome=1` renders "Welcome to Ghost Guild, {name}" instead of "Welcome back, {name}". `/welcome` redirect now always carries the param; `/accept-invite` navigates to the dashboard with the param directly.
|
||||
- **$0 member polish on `/member/account`**: Payment History section hidden for $0 members with no prior charges (condition now `contributionAmount > 0 || paymentHistory.length > 0` — fixes a regression where paid-then-$0 members lost visibility of their past payments). Solidarity-Fund sentence in the Danger Zone also hidden at $0.
|
||||
- **Next charge row above payment history** on `/member/account`: When a member has an upcoming charge, a "Next charge: $X on DATE" row renders above the transaction list (dashed `--candle` border). Separate from the existing compact "Next payment" row in the Membership Card summary.
|
||||
- **Fixed `subscription.get.js` Helcim field mapping.** Helcim's GET `/subscriptions/:id` returns `data` as a single object (not array) with the field `dateBilling` (not `nextBillingDate`). The lazy refresh endpoint now handles both shapes — previously it returned empty strings, so neither the Membership-card "Next payment" nor the new "Next charge" row rendered for any member whose cached `nextBillingDate` was missing. Note: `subscription.post.js` and `update-contribution.post.js` still read `subscription.nextBillingDate` from Helcim's CREATE response (same wrong field), which is why the cache was empty to begin with. Left unfixed in this pass — the lazy GET refresh now masks it. Worth cleaning up post-launch.
|
||||
- **State-aware contribution-change hint** on `/member/account`: "You'll be charged $X today to start your subscription." ($0 → paid) / "Your paid subscription will be cancelled." (paid → $0) / "Changes apply on your next billing cycle." (paid → paid, different amount).
|
||||
- **Server-side invite accept** now creates the Helcim customer and sets the auth cookie before returning, for both free and paid branches.
|
||||
- Vitest on `main`: **652/658 passing**. 6 pre-existing failures in `tests/server/api/helcim-payment.test.js` — unrelated to launch-blocking work, flagged in the Deploy checklist.
|
||||
- All launch code is on local `main`: Helcim plan consolidation, contribution-amount redesign, cadence UX unification, and receipts Phase 1. Not pushed — site is not on Netlify yet.
|
||||
- Helcim plan consolidation migration **ran against prod 2026-04-18** (Monthly plan id `50302`, Annual plan id `50303`).
|
||||
- Contribution-amount migration has **NOT** yet been run against prod.
|
||||
- Receipts Phase 1 code is shipped; remaining work is deploy-time only (see Deploy checklist).
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -39,23 +24,7 @@ None outstanding.
|
|||
|
||||
## P1 — Strongly preferred before launch
|
||||
|
||||
### Charitable receipts — Phase 1 ✅ COMPLETE (`docs/specs/receipts-launch-spec.md`)
|
||||
|
||||
Built on `feature/receipts-phase-1`, commits `bf5a333..91711aa` (2026-04-20). **Unmerged.** All four spec items shipped; remaining work is deploy-time only (tracked in Deploy checklist).
|
||||
|
||||
Shipped:
|
||||
- **Payment logging.** New `Payment` model (`server/models/payment.js`) + idempotent `upsertPaymentFromHelcim` helper keyed on unique `helcimTransactionId` (`server/utils/payments.js`). Synchronous write paths:
|
||||
- New paid subscription → `server/api/helcim/subscription.post.js` fetches the newest paid Helcim tx and upserts a Payment with `paymentType` from cadence + `sendConfirmation: true`. Wrapped in try/catch so a logging failure cannot break subscription creation.
|
||||
- Free → paid upgrade → `server/api/members/update-contribution.post.js` (Case 1 branch) does the same.
|
||||
- Paid → paid amount change (Case 3) is intentionally **not** wired synchronously — no new tx at the moment of change; the next recurring charge is captured by the reconciliation script.
|
||||
- **Confirmation email via Resend, not Helcim.** Spec alternative (b) chosen. `server/emails/paymentConfirmation.js` is CRA-safe: charity name "Baby Ghosts Studio Development Fund" + "not an official donation receipt / tax receipts available later in 2026" disclaimer. Triggered only on new Payment inserts; send failures are swallowed. Helcim's default confirmation must be disabled on plans 50302 + 50303 at cutover (Deploy checklist).
|
||||
- **Join page copy.** Factual charity note below contribution tiers on `/join` only (`app/pages/join.vue:83`). `/accept-invite` and `/member/account` intentionally untouched per spec §3.
|
||||
- **Member schema field.** `taxReceiptPreferences` nested object added to `server/models/member.js` (filesCanadianTaxes, middleInitial, confirmedAddress sub-object, setupCompletedAt). Defaults null/false — existing members read as "not set up." Schema-only; no Zod, no route, no UI. Phase 2 binds to it without migration.
|
||||
- **Reconciliation script.** `scripts/reconcile-helcim-payments.mjs` iterates every Member with `helcimCustomerId`, pulls recent Helcim transactions, and upserts via the same helper. Idempotent. Dry-run by default; `--apply` to write. No confirmation emails sent during reconcile. Dual purpose: launch-day backfill for the ~34 pre-existing members, and nightly cron post-launch to catch recurring charges that bypass the synchronous write paths.
|
||||
|
||||
Remaining (deploy-time, not code):
|
||||
- [ ] Merge `feature/receipts-phase-1` into `main`.
|
||||
- Manual Helcim-dashboard step + prod reconcile + staging test charge — see Deploy checklist.
|
||||
None outstanding.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -88,49 +57,7 @@ Applies when the site is connected to Netlify / production hosting. Nothing here
|
|||
|
||||
## Manual browser tests still needed
|
||||
|
||||
Cannot be verified by Vitest. Both require a real browser + real Helcim test card + real email, via cloudflared tunnel or ngrok HTTPS (Helcim requires HTTPS for the pay.js iframe).
|
||||
|
||||
**Shared setup (do once):**
|
||||
- `npx nuxi dev --https` in one terminal, `cloudflared tunnel --url https://localhost:3000` (or `ngrok http https://localhost:3000`) in another. Use the tunnel URL as `BASE_URL` in `.env`.
|
||||
- Helcim sandbox test card: see `~/.claude/projects/-Users-jennie-Sites-ghostguild-org/memory/reference_helcim_sandbox.md`.
|
||||
- Apply the contribution-amount migration against local Mongo first so seeded members match the new schema:
|
||||
```
|
||||
node scripts/migrate-contribution-amount.cjs # dry-run
|
||||
node scripts/migrate-contribution-amount.cjs --apply # apply
|
||||
```
|
||||
After applying, confirm in mongosh: `db.members.countDocuments({ contributionAmount: { $exists: true } })` should equal total member count; `db.members.countDocuments({ contributionAmount: { $type: 'string' } })` must be `0`.
|
||||
|
||||
---
|
||||
|
||||
- [x] **Pre-registrant invite → accept flow with a paid contribution amount.** ✅ Passed 2026-04-20 — both Monthly $7 and Annual $15 variants completed end-to-end. DB verified programmatically: `contributionAmount` stored as Number, `billingCadence` correct, `helcimCustomerId` + `helcimSubscriptionId` populated, `status: active`, no `contributionTier` field, preReg transitioned to `accepted` with `memberId` set.
|
||||
|
||||
- **Contribution-amount redesign end-to-end.** Covers the full surface of the `contributionTier` → `contributionAmount` rename.
|
||||
|
||||
- [x] **Signup flows — `/join`:** ✅ Passed 2026-04-20. All 5 variants ran functionally clean (welcome-heading regression was caught, fixed via `?welcome=1` propagation through `/welcome`, not retested — trusted):
|
||||
1. `$0` Monthly — Member created with no Helcim subscription.
|
||||
2. `$5` Monthly (preset) — Helcim `recurringAmount: 5`.
|
||||
3. `$17` Monthly (non-preset) — Helcim `recurringAmount: 17`, `$15` chip label via `findLast`.
|
||||
4. `$17` Annual — Helcim `recurringAmount: 204`, `billingCadence: 'annual'`, Mongo stores monthly-equivalent `17`.
|
||||
5. `$50` Annual (top preset) — Helcim `recurringAmount: 600`.
|
||||
|
||||
- [x] **Edit flows — `/member/account` as an active paid member:** ✅ Passed 2026-04-20 against Cleo's Annual subscription (Helcim sub 138682).
|
||||
- Raise $15 → $30 annual: `updateHelcimSubscription` hit with `recurringAmount: 360`, Mongo `contributionAmount: 30` (Number).
|
||||
- Lower $30 → $5 annual: `recurringAmount: 60`, Mongo `contributionAmount: 5` (Number).
|
||||
- ~~Switch cadence (Monthly $17 ↔ Annual $17).~~ **Deferred from launch.** Server (`update-contribution.post.js:184-189`) explicitly rejects cadence changes on existing subscriptions; no UI toggle exists on `/member/account`. Re-scope post-launch if/when we want to support cadence switch (would need Helcim subscription replacement flow, not a plain update).
|
||||
|
||||
- [x] **Admin flow — `/admin/members/[id]` edit:** ✅ Passed 2026-04-20.
|
||||
- Changed Cleo $5 → $15 via admin PUT. Mongo wrote `contributionAmount: 15` (Number). `contributionTier` field absent across all 34 members (`countDocuments({ contributionTier: { $exists: true } }) === 0`).
|
||||
- Known non-blocker: admin edit does not sync the change to Helcim's `recurringAmount`. Admin override is direct Mongo-only by design; had to PATCH Helcim manually to re-sync Cleo post-test. Worth noting in docs or surfacing in admin UI post-launch.
|
||||
|
||||
**Assert across all flows:**
|
||||
- Mongo `contributionAmount` is always `Number`, never `String`.
|
||||
- No `contributionTier` values written anywhere (greppable: `db.members.findOne({}, { contributionTier: 1 })` should return whatever the migration left; no *new* writes to that field).
|
||||
- No "save $X", "2 months free", or discount copy appears in any UI surface. Annual is just `amount × 12` exactly.
|
||||
- Guidance chip labels (`$0`/`$5`/`$15`/`$30`/`$50`) are matched via `findLast`, so $17 lands on the `$15` label, $49 lands on `$30`, $51 lands on `$50`.
|
||||
|
||||
**Key files if debugging:** `app/pages/join.vue`, `app/pages/member/account.vue`, `app/pages/admin/members/[id].vue`, `server/api/helcim/subscription.post.js`, `server/api/members/update-contribution.post.js`, `server/api/admin/members/[id].put.js`, `app/config/contributions.js` + `server/config/contributions.js`.
|
||||
|
||||
**Cosmetic follow-ups noted in Post-launch backlog below** — won't block this test (they're naming, not behavior).
|
||||
None outstanding. All launch-blocking flows verified via local dev or cloudflared tunnel with real Helcim test card + real email (see archive for the full log). The one remaining browser verification is the staging test charge bundled into the Deploy checklist above.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -167,6 +94,12 @@ See `docs/TODO.md` for:
|
|||
- OWASP ASVS L1 Phase 4 (file-upload validation pipeline, granular RBAC, credential encryption).
|
||||
- `tickets/available.get.js:115` `memberSavings` block reports `$0 saved` for inactive members — cosmetic; suppress comparison block when `!hasMemberAccess(member)` if it ever surfaces in UI.
|
||||
|
||||
### Known gotchas worth addressing post-launch
|
||||
|
||||
- **Subscription cache fed wrong field on CREATE.** `subscription.post.js` and `update-contribution.post.js` read `subscription.nextBillingDate` from Helcim's CREATE response, but Helcim returns `dateBilling`. The lazy refresh in `subscription.get.js` masks this (handles both shapes), so next-charge rendering works — but the cache starts empty. Fix at the CREATE sites so the cache is correct from first write.
|
||||
- **Admin edit does not sync Helcim `recurringAmount`.** `/admin/members/[id]` PUT writes `contributionAmount` direct to Mongo by design. Admins must PATCH Helcim manually. Worth surfacing in admin UI or docs.
|
||||
- **Cadence switch rejected on active subscriptions.** `update-contribution.post.js:184-189` refuses cadence changes mid-subscription; no UI toggle exists on `/member/account`. Adding cadence switch would require a Helcim subscription replacement flow, not a plain update.
|
||||
|
||||
### Contribution-amount redesign — cosmetic cleanup (naming only, not behavior)
|
||||
- Rename admin members column header "Tier" → "Contribution" (`app/pages/admin/members/index.vue:265`).
|
||||
- Delete dead `app/components/TierPicker.vue`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue