101 lines
6.2 KiB
Markdown
101 lines
6.2 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
|
||
|
||
### In-app billing management; demote Helcim portal to escape hatch
|
||
- Helcim's hosted portal requires a separate password the member never set during `/join`. First-touch flow is "click link → see Helcim login → click Forgot password → wait for email → set password → sign in." Reads as broken.
|
||
- **Ship in-app equivalents for the 80% case:**
|
||
- Past invoices / receipts list on `/member/account` — new server route pulls from Helcim invoice API by `helcimCustomerId`; render a simple list with date, amount, download/view link.
|
||
- Change card — reuse `useHelcimPay` composable to get a new `cardToken`, then new server route updates the customer's default payment method and the active subscription's payment method.
|
||
- **Keep** the existing "Manage billing in Helcim →" link but relabel to something like "Advanced billing in Helcim →" so it reads as an escape hatch for disputes/edge cases, not the primary surface.
|
||
- Rough scope: 1–2 days. Two new `server/api/helcim/*` routes + two new sections on `/member/account`.
|
||
|
||
---
|
||
|
||
## 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.
|