Release Notes — Jun 25, 2026 — dev → prod promotion (Event Check-in + backend hardening)

What this release is. The dev → prod promotion candidate (draft MR membervu/membervu-saas!223) — everything accumulated on dev since the Jun 19 release (!200). 94 commits · 149 files · ~36 issues. Verify it on staging (https://stg-rcme.membervu.com; admin portal https://stg-admin.membervu.com), which builds from dev. The headline is a new feature — Event Check-in (a staff "access code" model, EPIC #412); the rest is a two-wave backend quality-hardening sweep (money totals, status engine, tenant isolation, uploads) plus a small frontend bug sweep.

🧭 New to MemberVu? Start here

MemberVu is a multi-tenant membership platform with two web apps: the org portal (stg-rcme.membervu.com — admins + members of a club) and the super-admin portal (stg-admin.membervu.com, separate login — Zeniark platform operators).

This release adds Event Check-in. The twist worth understanding before testing: a check-in "access code" is not an account or a role. An admin generates a short-lived code for a specific event; on-site staff open a public page, type the code + their name, and get a scoped session that can only check people in for that one event. No login, no RBAC role.

Recommended path: (1) read the env + login box; (2) test the Event Check-in flow end-to-end (§🎟️); (3) test money parity (§🛡️ #443/#450) — a high-blast-radius hardening change; (4) test the membership status engine (§🛡️ #447/#453); (5) work the rest top-to-bottom. Full module re-review map: campaign note (see footer) §5.

⚙️ Before you start — environment & logins

SurfaceURLLogin to use
Org portal (tenant)stg-rcme.membervu.comAdmin admin@rcme.membervu.com / Admin123!; Events Mgr events@demo.membervu.com / Events123!
Staff check-in (NEW)stg-rcme.membervu.com/rcme/events/<eventId>/check-in/staffNo login — enter the access code + your name
Super-admin portalstg-admin.membervu.comSuper Admin superadmin@zeniark.com / SuperAdmin123!
Email inbox (MailHog)stg-webmail.membervu.com
Scope notes — read before testing.

🎟️ Event Check-in — NEW feature (EPIC #412) — #413–#428

Before you test this — what it is & where. Event staff run an on-site check-in station using a time-boxed access code — no account, no RBAC role.
Admin side (generate/manage codes): org portal → Events → Check-in (/admin/events/check-in; roles ADMIN / EVENT_MANAGER / SUPER_ADMIN).
Staff side (redeem a code, no login): public page /<tenant>/events/<eventId>/check-in/staff. Enter code + name → scoped check-in portal.
Pre-req: an event with registered attendees, and an access code generated by an admin.

✨ The flow

#ChangeWhat to verify on stage
#417 / #418 / #420 / #422Staff access-code session model — admin generates a time-boxed, event-scoped code; staff redeem code + name to enter a scoped portal.As admin, generate a code for an event. Open the staff page (no login) → enter the code + a name → you land in the check-in portal for that event only. A wrong/expired code is rejected.
#419Scoped-token middleware enforces the event boundary (B1 security) + immutable audit trail.The scoped session cannot act on a different event (try reusing the session against another event's check-in API → denied). Every check-in writes an audit entry that can't be edited/deleted from the portal.
#414 / #423Attendee search in the portal.Search a registrant by name/email → result appears → check them in.
#415Member / guest designation pill on results.Each result shows whether the attendee is a member or a guest.
#426 / #424 / #425Walk-in tab + walk-in registration; paid walk-ins create a real Invoice + Payment via a shell guest member; best-effort welcome email.In the Walk-in tab, register an on-site guest. For a paid walk-in → confirm an Invoice + Payment record is created; a welcome email arrives (check stg-webmail.membervu.com).
#421Audit-trail viewer panel.Open the audit panel → every check-in / walk-in / undo action is listed with who + when. Export works (#419).
#416Reconciliation — consolidated reconcile stats on the attendance report.Run reconcile → the attendance report shows consolidated stats (checked-in vs no-show vs registered) in one place.
#427 / #428Platform parity — super-admin portal check-in (codes, walk-in, audit).On stg-admin.membervu.com, do the same code/walk-in/audit flow for a tenant's event — same isolation + audit guarantees.
Security gate. Confirm: (a) a redeemed code is scoped to one event and can't touch another; (b) codes are revocable and a revoked/expired code is rejected at redemption; (c) the audit log is immutable from the portal; (d) the public staff page exposes only the scoped check-in surface — no member/billing data.

🛡️ Backend quality-hardening — #431–#453 (two sweeps)

Mostly invisible correctness/security work, but several items change behavior testers should re-verify. Grouped by what to check.

#AreaChange & what to verify
#443 / #450money high-blastAll invoice totals now flow through one canonical projector. Open the same invoice in detail view, the listing, a reporting export, and the finance summary → every total must match. Spot-check an invoice with discounts / line-items / credits.
#447 / #453membershipUnified status-transition engine + single expiry calc. Drive activate / suspend / reactivate / expire → only valid transitions allowed; the expiry date is identical across all activation paths (approval, renewal, admin reactivation).
#446auth securityDeactivate now revokes JWTs immediately. Deactivate a logged-in user → their next request is 401 (no waiting for token expiry).
#448eventsRegistration idempotency + memberOnly tickets. Register → cancel → re-register the same member → no duplicate. A memberOnly ticket rejects a non-member. Quantity = 0 is rejected.
#444 / #451uploads securityFilename sanitization on every upload (#444/G16) + presign for logos/avatars; proofUrl is now key-only (#451/G11). Upload a file with a hostile name (../, control chars, =cmd) → neutralized; the audit row stores the sanitized name. Existing stored images/proofs still render.
#433 / #449communicationsBroadcast preview + Send-Test wiring (#433); resolveBroadcastRecipients + segment-filter validation + token strip (#449). Preview/Send-Test render; an invalid segment filter is rejected; merge-tag tokens are stripped/escaped (carries last release's #252 XSS hardening).
#445infraattachTenantPrisma wired into production server + startup catalog check (tenant-isolation NFR-10). No direct UI behavior; backend should boot cleanly and stay tenant-isolated.
#436 / #438 / #431 / #432miscTwo-token member search (#436); DRAFT-event past-start guard (#438 — can't set a draft's start in the past); member status-history dedup (#431); membership-type amount rejects whitespace/invalid currency (#432); createManualInvoice with a bad memberId returns 404, not 500.

🐛 Frontend bug sweep — #430, #434, #437, #439

#FixWhat to verify on stage
#430Confirmation-page buttons are block-level (full clickable area).On a confirmation page, the whole button area is clickable (not just the text).
#434Prospects edit-status modal resets on close/save.Open the prospect status modal, change something, close → reopen → it's reset (no stale state). Same after save.
#437Robust 404 for public event detail.Open a bad/nonexistent public event slug → a graceful "not found", not a crash.
#439Member /events/:slug not redirected to the public view during session hydration.As a logged-in member, open an event by slug → you stay on the member event view (no flash/bounce to the public page while the session loads).
Default membership-type pre-select in approve-prospect modal; full-width clickable /invoices rows.Approve-prospect modal pre-selects the default type; clicking anywhere on an invoice row opens it.

🔐 Platform — #427/#428 (check-in parity) + tenant-detail fields

ChangeWhat to verify on stage (admin portal)
Super-admin check-in parity (codes / walk-in / audit) — #427/#428.Covered in the Event Check-in section above — run it from stg-admin.membervu.com against a tenant's event.
Split + attestation fields exposed to SUPER_ADMIN in tenant detail.On a tenant's detail page in the admin portal, the commercial split + attestation fields are visible to a super-admin (and only to a super-admin).

Suggested review order

  1. New feature: Event Check-in end-to-end (#413–#428) — generate code → staff redeem → search → check in → walk-in → audit → reconcile; isolation + revoke + audit-immutability gates.
  2. Money parity: same invoice across detail / list / export / finance summary (#443/#450).
  3. Membership status engine: transitions + single expiry calc (#447/#453).
  4. Auth: deactivate → immediate 401 (#446).
  5. Registration idempotency + member-only tickets (#448).
  6. Uploads/security: hostile filename neutralized; existing images/proofs still render (#444/#451).
  7. Communications: broadcast preview/Send-Test + segment validation (#433/#449).
  8. Frontend sweep + misc (#430/#434/#437/#439, #432/#436/#438).
  9. Skip: live gateway/webhook flows (inert — paid walk-in creates records only).

🚀 Deploy / migration notes (ops + reviewer gate)

Five migrations — deploy via prisma migrate deploy only; never reset/reseed on prod.
  1. add_event_checkin_access_code (#413) — new table. Additive.
  2. add_event_checkin_audit_log (#413) — new enum + table. Additive.
  3. add_registration_walkin_fields (#413) — 7 nullable columns + 1 nullable FK. Additive.
  4. ticket_type_member_only (#448) — memberOnly BOOLEAN DEFAULT false. Additive.
  5. ⚠️ event_registration_unique_idempotency (#448) — runs a defensive dedup DELETE before creating a partial unique index. No-op on a healthy DB, but the DELETE is not auto-reversible🔴 take a prod DB snapshot before deploying.
⚠️ Merge conflict (expected, 1 file): auth-service/src/utils/rateLimiter.ts — keep prod's env-tunable limits and add the new #418 check-in session limiter. Do not revert prod's env-driven values.
🔙 Rollback: redeploy prod from rollback/prod-pre-release-2026-06-25 (d447c58c) — code rollback only; do not reverse-migrate a live DB.

Source of truth: the membervu/membervu-pm tracker + draft MR membervu/membervu-saas!223. This page is the tester/reviewer-facing view; the full campaign note (focused test plan, deploy gate, module re-review matrix) is tester-files/03_EXECUTION_REPORTS/prod-release-2026-06-25/RELEASE_NOTES.md; the permanent archive entry is tester-files/07_RELEASE_NOTES/2026-06-25-release-notes.md. Builds on the Jun 19, 2026 release. Verified present on dev on 2026-06-25. Gateway flows inert in all QA environments.