102 lines
6.4 KiB
Markdown
102 lines
6.4 KiB
Markdown
# Launch Readiness
|
|
|
|
**Status as of 2026-04-18.** 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`.
|
|
|
|
---
|
|
|
|
## Current state
|
|
|
|
- Vitest: 577/577 passing.
|
|
- Helcim plan consolidation migration ran against prod 2026-04-18 (Monthly plan id `50302`, Annual plan id `50303`). All six paid-flow manual tests pass via tunnel.
|
|
- Remaining launch blockers: see lists below.
|
|
|
|
---
|
|
|
|
## P0 — Must fix before launch
|
|
|
|
None outstanding. Privacy/Terms pages shipped, duplicate-customer bug fixed, pre-deploy migrations run.
|
|
|
|
---
|
|
|
|
## P1 — Strongly preferred before launch
|
|
|
|
### UX polish on the paid `/join` flow (noted 2026-04-18 during Test 1)
|
|
- Code entry points: `app/pages/join.vue` (form + `handleSubmit:478`, `processPayment:532`), `app/composables/useHelcimPay.js` (modal trigger at 137).
|
|
- Flow works end-to-end, but the single most important conversion point has three rough spots:
|
|
- **Join form sits too low on the page.** First-time visitors have to scroll to find it. Raise it above the fold, or lead the page with the form and move supporting copy below.
|
|
- **"Open Helcim modal" button is placed oddly.** After the first form submit, the next action (trigger the HelcimPay.js iframe) is easy to miss. Needs clearer visual hierarchy, ideally auto-opened or prominently CTA'd.
|
|
- **Return-to-join-page flash after payment success.** After HelcimPay.js reports SUCCESS, the user briefly sees the join form again before the redirect to `/member/dashboard` fires. Reads as an error.
|
|
- **Ideal:** wrap the whole flow (form submit → HelcimPay.js → success → dashboard) in a modal or at least an overlay with a clear step indicator, so the user never returns to the join page between states.
|
|
- Not blocking launch — flow works — but should land before inviting the full pre-registrant list, since this is where first impressions happen.
|
|
|
|
---
|
|
|
|
## Deploy checklist
|
|
|
|
Pre-deploy migrations have all been run. What's left:
|
|
|
|
- [ ] Merge `feature/helcim-plan-consolidation` into `main`.
|
|
- [ ] Set `NUXT_HELCIM_MONTHLY_PLAN_ID=50302` in Netlify production env.
|
|
- [ ] Set `NUXT_HELCIM_ANNUAL_PLAN_ID=50303` in Netlify production env.
|
|
|
|
**Env vars required in production (reference):**
|
|
- `MONGODB_URI`
|
|
- `JWT_SECRET` (or `NUXT_JWT_SECRET` — the `NUXT_` variant wins)
|
|
- `RESEND_API_KEY`
|
|
- `HELCIM_API_TOKEN`
|
|
- `NUXT_HELCIM_MONTHLY_PLAN_ID`
|
|
- `NUXT_HELCIM_ANNUAL_PLAN_ID`
|
|
- `SLACK_BOT_TOKEN`
|
|
- `BASE_URL`
|
|
- `OIDC_COOKIE_SECRET`
|
|
- `NUXT_PUBLIC_HELCIM_PORTAL_URL`
|
|
|
|
---
|
|
|
|
## Manual browser tests still needed
|
|
|
|
Cannot be verified by Vitest. All require a real browser + real Helcim test card + real email.
|
|
|
|
- [ ] **Event ticket purchase with payment** (HelcimPay.js iframe; use cloudflared tunnel or ngrok HTTPS).
|
|
- [ ] **Pre-registrant invite → accept flow** with paid tier (exercises Helcim customer creation during acceptance).
|
|
- [ ] **Magic-link login** including 15-min expiry and jti burn on reuse.
|
|
- [ ] **Guest event signup** — four branches: new email + consent, new email without consent, existing guest, existing active member. Confirms cookie only sets for new/guest, and confirmation email appends `/login` link for real members.
|
|
- [ ] **Mobile responsive layout** — sidebar hides ≤1024px, nav works on phone.
|
|
- [ ] **`--text-dim` / `--text-faint` WCAG AA contrast check.**
|
|
|
|
---
|
|
|
|
## Bylaws decoupling — follow-ups (added 2026-04-18)
|
|
|
|
Context: bylaws are being amended to remove automatic termination for nonpayment. Membership status will be fully decoupled from payment status; failed payments trigger committee outreach, not status change. Copy + UI access gates already aligned in `useMemberStatus.js` and `account.vue` (2026-04-18). Server-side status gating shipped as B2 (see archive). The behavioral changes below remain.
|
|
|
|
Not blocking launch — the amendment hasn't passed yet, and the user-visible copy/UI is already consistent. Pick up once the amendment is ratified.
|
|
|
|
### B1. `cancel-subscription` flips status to `pending_payment`
|
|
- `server/api/members/cancel-subscription.post.js:31,48`
|
|
- When a member cancels their paid subscription, status is set to `pending_payment` and tier to `'0'`. Under the new model, cancelling a payment plan moves the member to the $0 tier — status should stay `active`.
|
|
- **Fix:** change `status: 'pending_payment'` → `status: 'active'` in both the `findByIdAndUpdate` payload (line 31) and the response (line 48). Comment at line 26 also needs updating ("(not cancelled) so member can re-subscribe" → reflect new framing).
|
|
- Add coverage in `tests/server/api/cancel-subscription.test.js` if it doesn't already exist.
|
|
|
|
### B3. Vestigial `pending_payment` status
|
|
- Once payment is fully decoupled, `pending_payment` no longer gates anything and is functionally equivalent to `active`. Consider removing it from the enum (`server/models/member.js:38`, `server/utils/schemas.js:299`) and treating new signups as `active` from the moment of account creation.
|
|
- Touches: signup flow (`helcim/customer.post.js:34`, `invite/accept.post.js:48`), admin filter UI (`app/pages/admin/members/index.vue:45,382,499,1145`, `[id].vue:69,286`), admin alerts (`server/utils/adminAlerts.js:22,100-116`, `server/models/adminAlertDismissal.js:6`), and a data migration to flip existing `pending_payment` rows to `active`.
|
|
- Larger refactor — break out into its own ticket once B1 lands.
|
|
|
|
### B4. Admin "Pending Payment" filter label (cosmetic)
|
|
- `app/pages/admin/members/index.vue:45,499`, `[id].vue:69` show `pending_payment` as "Pending Payment". If B3 removes the status entirely, this disappears too. If we keep `pending_payment` for now, rename in admin UI to "Payment setup incomplete" so admins also stop conflating it with membership state.
|
|
|
|
---
|
|
|
|
## Post-launch backlog
|
|
|
|
See `docs/TODO.md` for:
|
|
- Button minimum target size (WCAG AAA 2.5.5).
|
|
- `/oidc/interaction/[uid]` routing quirk.
|
|
- Admin layout migration from `guild-*` tokens to zine spec.
|
|
- Admin dashboard quick-action button contrast.
|
|
- Members table NAME column clipping.
|
|
- 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.
|