Changelog

What we shipped, when. Newest first.

Safer SMS reply forwarding and Telegram retries

7 September 2026

Two-run database installation for this release

  • The pending member-services, Courses and sender changes can now be installed

with one SQL Editor apply file and one independent checker: 14 unchanged source units, nine postflight sections and one atomic apply transaction.

  • Commit and CI gates check the generated files against their sources. The

existing local/CI rehearsal proves double-apply, rollback on a late failure and rejection of a broken final authority, without adding another runner.

  • This does not repeat the completed insurance data copy, rerun old rollout

authorities, activate payment handovers or enable notifications. SQL still precedes application deployment; see the 7 September consolidated release note.

SMS and Telegram reply forwarding

  • An SMS owner-forward failure no longer closes the inbound webhook as a

success. The gateway can redeliver it; the existing per-recipient delivery ledger prevents accepted or uncertain Telegram sends being repeated.

  • SMS and Telegram replies now distinguish a definite recipient failure from a

different recipient's uncertain delivery, so a partial failure is not lost.

  • SMS receipt evidence records why forwarding was skipped (for example, no bot,

no enabled owner recipient, consent keyword or no prior outbound message).

  • Rejected SMS webhook authentication now records a fixed, rate-limited reason

in server logs. Keys, signatures, timestamps, contact identifiers and message contents are never logged. Signature verification and its five-minute replay window remain enforced; this diagnoses the phone's 401 rather than bypassing it.

  • This correction adds no SQL migration, environment variable or feature flag.

Existing provider-receipt and delivery-outcome SQL remains a prerequisite. It does not replay historic messages or change production configuration.

Creative Ways' live device/webhook setup remains subject to read-only diagnosis and an owner-operated end-to-end test. Local tests do not establish physical SMS receipt or Telegram delivery.

The missing temporary checkout's member-services and forwarding changes were recovered into a permanent checkout. The separate member-services SQL-first rollout remains required; see the 7 September recovery evidence report for the fresh checks, rather than treating earlier temporary logs as current proof.

Club email senders and replies

  • Immediate, scheduled and attachment email now share one tenant-bound sender

resolver. A failed club lookup stops delivery with a safe, visible error; it no longer silently sends club content as AllSorted without a reply address.

  • Club email uses the club name (or its existing sender-name override) and

Club Details email as Reply-To. The sending address stays on the verified platform domain. Explicit platform account mail keeps platform branding.

  • Communications final checks show From and Replies go to, with an explicit

warning if the configured platform reply fallback is being used. Deliverability also checks club sender readiness rather than reporting domain-only readiness.

  • Outbox and scheduled-recipient ledgers retain the resolved sender before a

provider attempt. Failed/missing evidence writes block delivery. Preparation failures use the existing bounded retry path instead of claiming a time-budget continuation. No old sender is guessed or backfilled from current settings.

  • SQL before code: apply the new additive

club-email-sender-identity-01.sql, then its postflight. Existing rollout bundles have not been rewritten. No new env variable, flag, inbox, reply handling service or DNS change is introduced. Replies go to the chosen email mailbox; the member portal remains read-only correspondence.

Email sender lookup correction

  • Removed a nonexistent clubs.address column from both sender projections.

It caused valid club sender settings to be rejected before provider dispatch, leaving email jobs waiting on the existing bounded retry schedule.

  • The selected columns now have a compile-time schema check. Regression tests

simulate returned PostgreSQL unknown-column errors, including the optional legacy sender-name fallback, instead of always returning the fixture data.

  • Club identity, Reply-To validation, consent checks, tenant scope and delivery

idempotency remain enforced. No new SQL, environment variable or flag is required for this correction. It does not reset or replay queued messages.

Member Requirements insurance transition — pending activation

  • The Member Requirements summary and modal rows now show red for an expired

requirement, otherwise amber when one expires within 30 days (including today and day 30). Missing dates stay neutral and explicit; they never claim green. This display window does not change payment eligibility or attendance rules.

  • For an explicitly mapped club, the profile action opens the same Member

Requirements modal as the card. The old insurance editor is hidden and the server refuses stale-tab edits/imports into retired insurance fields.

  • Existing insurance read models and saved merge tags resolve the mapped

requirement's current date, exact membership-number field and current paid cycle. Register rows keep their original selected fields. Programme and member type restrictions remain combined; failed canonical reads never revive old data.

  • Mapped clubs no longer produce legacy insurance Action Centre entries or

mirror canonical payments into the old member paid flag. Requirement payment tasks and generic events retain their existing idempotent processing.

  • Deployment boundary: the binding-table preparation has already been

applied, but Creative Ways has not been activated. Deploy and verify the compatible code before a separately reviewed, owner-applied activation. Existing payment records and late-settlement handlers are retained; this change does not cancel charges, publish automations, send messages or move additional member data. No new environment variable or feature flag.

Course progress across the club

  • Courses now has a Progress tab: filter by member, course, programme and

recorded progress, with an optional past/future-access and archived-course view.

  • Desktop uses a member-by-course matrix with the member column kept visible

while scrolling. Mobile uses expandable member cards. Course headings focus the view on that course; errors provide retry rather than showing an empty list.

  • One server-scoped database read returns each 25-member / eight-course window

and exact matching counts. Duplicate access sources count once. Programme filters use formal programme enrolments, not timetable rosters.

  • This is recorded learning progress, not an access grant or a new certificate

decision. Existing enrolments, learning, assessments and certificates are unchanged. Practical-development and assessor sign-off remain a separate stage.

  • SQL before code: apply the additive course-progress-overview-01.sql and

its read-only postflight. No new environment variable or feature flag. The new read requires the existing Courses module and effective course-view permission.

Optional course development and assessment — local, not yet released

  • Course setup now supports versioned practical-session minimums, grouped

competencies, staff-verified learning and an optional final conversation. Learner details in Courses → Progress support dated evidence, audited corrections, development actions and authorised staff sign-off.

  • Existing learners retain their earlier requirements; future grants use the

published version. Changing a learner's version is explicit and is refused after practical evidence or completion. Referenced learning and quizzes are preserved; later editions use new learning items rather than rewriting them.

  • Server-side completion requires every enabled condition. Final decisions,

corrections and certificate claims are serialised. Private assessor notes are omitted from the member portal; only explicitly shared feedback appears.

  • Versioned certificates retain their course/template snapshot, stable number

and create-only storage path. Staff can recover a missing certificate without re-completing the course or overwriting an issued PDF. Existing course certificate templates and private storage are reused.

  • Owner-approved erasure: permanently deleting a member removes their course

evidence and assessment history. Archiving preserves it. Certificate files are transactionally queued for retryable cleanup after a 15-minute render grace; the existing safeguarding and financial-retention policy is unchanged. The new course data is also included in staff subject-access exports.

  • SQL before code: the additional course-development-01.sql and

course-development-certificates-01.sql, course-member-erasure-01.sql and their final postflight are required, alongside the earlier progress-overview unit. No new environment variable, feature flag, automatic attendance credit, AI assessment or public certificate verification is introduced.

Member requests, household caps and optional portal notifications

6 September 2026

Member services — household caps, request communications and portal alerts

  • Member-request automations gain editable draft starters and readable request,

campaign and programme filters. Verified membership-administration messages use the essential-mail path; ordinary marketing retains its consent rules. Retries recheck current request state and contact ownership. Email/SMS steps can explicitly retain a private portal copy; Telegram cannot.

  • Household pricing gains an optional combined cap across selected membership

plans/programmes, after existing discounts and agreement caps and before VAT. Caps apply only to matching periods/currency and aligned billing dates; negotiated overrides and non-membership charges are excluded. Existing behaviour stays unchanged unless an owner schedules a future rule. Previously prepared snapshots and external provider collections are not repriced.

  • Portal push gains a member-only invitation, explicit browser permission,

category choices, quiet hours, contact-bound devices and generic lock-screen messages. Requests, shared timetable messages, renewal reminders and reviewed videos are derived from current records. Email remains independent. A provider acceptance is not described as device delivery, and ambiguous sends do not automatically replay. Unsupported bulk push jobs no longer report “sent”.

  • Deployment requires reviewed additive SQL before code. No remote SQL,

per-club activation, provider migration or live notification has been performed. PORTAL_PUSH_ENABLED defaults off. The old Pulse/test fan-out additionally requires PORTAL_LEGACY_PUSH_ENABLED; leave it unset/off. Configuring the new VAPID keys must not activate the old unbound subscription list.

See the member-services implementation plan and release checklist for exact verification results and owner-only rollout steps. Local verify:release and verify:critical pass; the separate disposable database class passes all 32 files, and the consolidated SQL apply/reapply/checker has executed successfully. Mobile, tablet and desktop component checks passed with synthetic context. This does not certify production deployment, real member authentication or delivery to a physical device; those require the owner-run opt-in QA checks after rollout.

Membership changeovers and family pricing

5 September 2026

What's new

Rollout bundle freshness — commit and CI protection

  • Relevant SQL, rollout-bundle or generator changes now trigger the existing

bundle consistency check before commit. Missing/stale bundles fail closed with a manual regeneration instruction; the guard never writes SQL.

  • CI runs the same file-only check once in the existing lint job, with no new

runner, Docker startup or database access. Local release checks retain it too.

  • Recorded the owner's completed page-evidence rollout results (11/11, 6/6,

16/16) and the boundary for new additive corrections to applied SQL. The separate household-billing handover SQL is still pending. This process-only correction itself requires no SQL application, ENV setting or feature flag.

Household pricing and invoice handover — opt-in, SQL first

  • Added and tested a shared calculation contract for highest-price-first,

joining-order, existing per-agreement or no family-tier discounts, with an optional programme boundary. Each membership keeps its own discount table.

  • Settings → Memberships now has household pricing, before/after previews and

a separately confirmed monthly invoice handover. Installation changes no billing rules. Mandates, joining dates and payment history are retained.

  • Creative Ways uses Xero invoices, not GoCardless subscriptions. The owner must

stop external collection before activating a handover. Provider history, retries and local billing state are checked before future anchors are set.

  • Frozen period evidence and atomic writes prevent partial household bills

being collected. Mid-cycle changes use next-boundary pricing plus a separately reviewed top-up, not the old one-plan automatic adjustment.

  • Member profiles label standard plan prices rather than showing the obsolete

single-agreement discount estimate when shared household pricing applies.

  • Apply household-family-pricing-01/02 and household-billing-handover-01, then

their postflight before deployment. No new ENV or flags. See docs/plans/household-family-pricing-policy-2026-09-05.md for the rollout.

Member requirement reports and dashboard warnings

  • Reports now has a Member requirements group with an overview and individual

requirement reports. The owner-approved Legacy Insurance report is removed; old report bookmarks and saved favourites open Member Requirements instead.

  • Reports and the dashboard share the same canonical requirement read model.

Expired, due in 0–30 days, due in 31–60 days, not recorded and paid-awaiting- processing are distinct. Programme enrolment AND member-type scope apply. The old inline dashboard insurance counters are removed to avoid stale, competing warnings. This does not retire the separate Action Centre producer.

  • Choose a requirement, filter/search its members, open their profile or use

the existing permission-checked, audited CSV/XLSX requirements export (including custom fields). Dashboard counts link to the exact requirement/status report.

  • The 60-day warning does not open payment early: the configured renewal window

remains authoritative (30 days for Creative Ways). No automatic message, payment, new task or historical record change is triggered by these reports.

  • No new SQL, environment setting or feature flag for this reporting change.

Payment-routing activation and other pre-existing SQL-first work remain separate. Legacy scheduled reports/renewals/data-quality readers and payment compatibility are not claimed as retired by removing this report page.

Member requirements and review counts

  • Requirement creation explains that member fields come next, with a

“Create & add member fields” button and a direct field-editor link when editing. The two saves remain separate. “Renewal opens” now explains the same window controls member renewal eligibility and reminders.

  • Member profiles have a compact Member requirements tile opening the applicable

requirements in the existing dialog/edit/renew workflow. Mobile rows wrap and edit dialogs cannot be dismissed during a save. Legacy Insurance remains visible until its payment and writer cutover is verified.

  • Member Requests navigation shows a badge only for positive totals awaiting

staff approval. Totals are capability-guarded, scoped to the current club and fetched only while navigation is open. No contact records are fetched for it.

  • Owner-specific Creative Ways expiry/Membership Number copy was applied and

verified by the owner: 165 exact matches each, with legacy records retained. Payment cutover was not performed. Do not retire old links/settings or automations on the strength of the data copy alone. See the dated testing note.

  • These UI/count changes require no new SQL, environment variable or flag.

Insurance payment transition preparation — not activated

  • Owner confirmed the three old Creative Ways attempts were already resolved.

Keep their records unchanged and do not put those members on hold.

  • Prepared an explicit, owner-controlled requirement/field binding. When

activated after approval, legacy renewal entry points will use the generic exact-requirement/cycle checks and old uncycled checkout links will direct members to Member Requirements. Existing settlement handlers remain intact.

  • The old profile Insurance tile is replaced only for server-confirmed mapped

clubs. Other clubs retain the existing tile; loading errors fail closed.

  • The additive empty binding table has a local apply/reapply/grants/tenant

rehearsal and read-only postflight. No activation SQL is ready yet. The owner has instead requested canonical reports and dashboard readers; automatic canonical-to-legacy synchronisation is not approved or installed. Remaining legacy readers still need a controlled transition. No clearing triggers were added. Prepare SQL, compatible deployment and reviewed activation are separate steps; do not infer a live payment switch from the earlier successful data copy.

Dated Member Requests and optional class restrictions

  • Membership editors now include optional start and expiry dates for choices in

Member Requests. For example, an old plan ending 30 September is not offered for a 1 October change, while a new 1 October plan can be selected in advance. The current membership remains visible as context. Existing payments are not cancelled, and public sign-up visibility still uses Show on enrolment.

  • Regular-class requests have an optional “Apply age and level restrictions”

checkbox, off by default. Unrestricted classes still appear; configured bounds are checked against the member's age on the change date and recorded level. Approval and delayed application recheck changed eligibility atomically.

  • Each membership group shows its programme. Formal programme compatibility is

retained and legacy-only plans cannot cross into a different lens. Household details remain a single household-wide check.

  • SQL before this code: apply member-request-choice-policy-01.sql, then

member-request-choice-policy-02.sql, then its read-only postflight. No new env or flag. These are separate from the already-applied page-evidence rollout.

Choose an amount off for additional family members

  • Membership family pricing now has three distinct choices: percentage off,

amount off in the club's currency, or a fixed final price. For example, £5 off a £30 standard price gives £25; if the standard price becomes £40, it gives £35.

  • Amount-off values are validated on the server and stored as integer minor

units. The editor, member price previews and household-agreement invoice calculation use the same contract. Existing percentage, fixed final-price and legacy fixed-discount records retain their meaning.

  • Only the final tier is labelled “+”, making 2nd, 3rd and 4th+ clearer. Switching

discount modes cannot save hidden values from another mode. Blank, negative and above-standard-price deductions are rejected before a plan write.

  • Per-member discounts still apply within one membership agreement, before

pro-rata, its family cap and agreement overrides. Existing issued invoices are not rewritten. Highest-price-first discounts across different plans are a separate requested extension, pending confirmation of the discount rule; they are not claimed as implemented here.

Amount-off deployment notes

  • No new SQL migration, environment variable, feature flag or provider call is

needed for the amount-off pricing addition. The existing text/JSONB pricing columns are reused. Read-only pricing censuses and the generated Stage A preflight now recognise the new shape. This does not require repeating the already-applied rollout SQL.

  • Deploy all amount-off readers together before using this mode. Do not roll

back to code that predates it while amount-off plans are in use: older pricing code does not understand this type. Any downgrade requires an owner-reviewed pricing conversion first. No live plan has been changed by this development.

Clearer member requests

  • Each portal task keeps its own heading: membership choice, household details

and regular-class selection. The shared campaign reason appears once above its related tasks, rather than replacing every task heading.

  • Member Requests is now in the Members navigation group. The competing desktop

shortcut is removed from the crowded member-count toolbar; selection-based request creation remains available.

  • Approval cards show current household phone/address alongside the requested

values. Before values use amber and requested values green, with text headings so colour is not the only distinction. Failed current-detail reads cannot appear as empty data or be approved from an incomplete comparison.

  • The readiness step is labelled Check choices and explains its purpose:

compatible options, duplicates and skipped requests. Its checks and separate create confirmation remain intact.

  • These presentation and guarded-read changes require no SQL or new flag.

The subsequent dated-choice and optional restriction extension is described above and does require its two new SQL units before deployment. Its dates govern request choices, not cancellation of existing billing.

Contact-specific portal previews and accurate SMS history

  • Opening the member portal from a staff profile now offers the household’s

currently authorised portal contacts. Staff explicitly choose when there is more than one; a member email alone does not grant access. Missing contacts are explained rather than replaced with a synthetic login.

  • The preview banner identifies the actual contact being viewed. Message copies

remain private to that contact, and staff previews still do not mark messages as read or change contact preferences.

  • SMS audit mirrors no longer appear a second time under Email provider history.

Gateway-accepted SMS rows awaiting a receipt count as accepted, not delivered.

  • These corrections need no SQL, environment variables or feature flags. Deploy

the picker and route together; the POST now requires an explicit contact. Close any old preview and reopen it after deployment. No messages were resent, backfilled or changed. Unrelated pending SQL in this workstream still retains its own deployment ordering.

Insurance cutover handoff

  • Added an exact-club, read-only reminder/payment census and a staged cutover

checklist. The census is rehearsed on synthetic local data; it does not copy data again, activate payment routing or change any reminder.

  • The checklist explicitly records the remaining legacy readers, saved-template

compatibility and old staff editor entry point. These must be resolved before activation. Live acceptance remains after deployment as requested by the owner.

  • Mixed-plan highest-price-first billing is opt-in through the workflow above;

existing per-agreement amounts do not silently change.

Clearer settings and safer draft saves

4 September 2026

What's new

Reliable disposable CI verification

  • The video-upload security rehearsal now reuses CI's already captured

disposable database credentials instead of requiring an npm-installed Supabase CLI. Local use supports the installed CLI or an explicitly selected pinned npm fallback. Missing credentials and incorrect targets still fail closed; real JWT, tenant and concurrency proofs remain required.

  • This harness correction needs no SQL or application environment changes.

The pending feature rollout still requires its reviewed SQL before deployment.

Reliable private uploads and video submissions

  • Requirement documents now consume their upload intent and attach in one

database transaction. Retrying a lost response cannot delete the saved file, attach twice, or restore a subsequently removed/replaced document.

  • Video cancellation proves the exact household/member/intent/item/path under

the same locks as submission. Revoked access no longer deletes unproven paths. Both early video routes now enforce the same club/system scope as final SQL.

  • Coach tasks and member activity are committed with the video. Automation

events have leased, durable retry work using the existing five-minute continuation cron and existing delivery-idempotency/live-send gates.

  • Private file cleanup is queued only after transactional retirement/detachment;

returned Storage errors remain retryable. The existing upload cleanup cron drains the queue. No new flags, credentials, provider or cron schedule.

  • SQL FIRST: the new private-upload-cleanup-01.sql prerequisite is included in

corrected Stage A, ahead of requirements and video authorities. Its two new upload-intent columns are required by shared upload validation. Deploying the new code before SQL would fail uploads closed. Existing v1 attachment signature remains compatible during deployment; new code uses atomic v2.

  • Video permission postflight now includes every displayed required predicate,

exact callable signatures, client/column grants and service permissions. The requirements postflight now correctly permits no legacy reference field when a requirement has no legacy reference label.

Dependency security maintenance

  • Updated Browserslist and fast-uri to compatible patched versions, including

Browserslist's required browser-data packages. The existing high/critical security gate remains unchanged, with no advisory exceptions added.

  • This dependency correction needs no SQL, environment variable or feature flag.

It does not change the SQL-first ordering of the pending feature rollout.

Simpler, guarded production SQL rollout

  • The 18 pending SQL units are packaged into two ordered SQL Editor files

and one read-only final checker, reducing the owner rollout to three complete paste-and-run steps.

  • Existing transaction, timeout and dependency boundaries remain intact. The

generated bundle guard fingerprints every source and fails release checks if a source changes without rebuilding the consolidated files.

  • Stage A must return READY_FOR_STAGE_B; Stage B must return

APPLIED_AND_VERIFIED; the independent checker must return 16/16 and PASS. No environment variable or feature flag is changed by these files.

Consistent dialogs across club, member and admin screens

  • Settings, member records, Communications, video reviews and platform Pricing

reuse the same bounded dialog behaviour. Keyboard focus enters the dialog, returns to its opener, and Escape closes only the frontmost dialog.

  • Pending saves prevent accidental dismissal; failed saves retain the entered

information. Existing permissions, payment actions and confirmation wording remain authoritative.

  • Member Portal sheets keep reachable controls on smaller screens, Pathways

uses the app theme, and long session rows wrap. Admin navigation closes after selection and its forms use clearer labels and consistent content spacing.

  • Dashboard time charts keep long date labels and large value tooltips within

narrow screens. All columns remain available, with tap-to-view values on mobile; no data or page content is hidden to mask overflow.

  • This UI correction requires no SQL, new environment variable or feature flag.

The separately pending authority work still requires its SQL-first rollout.

Keep message recipients in view

  • Desktop Communications keeps its recipient list within the available screen

height. Loading more members scrolls the list rather than extending the whole page; Back and Continue stay reachable beside it.

  • Mobile keeps normal page scrolling. User-controlled pinch zoom remains

available, and the existing larger input text prevents accidental focus zoom.

  • No recipient, consent, delivery or tenant-access behaviour changes.

Find the right setting

  • Settings now has one catalogue and seven related areas: Club setup,

Programmes & timetable, Members & memberships, Joining & growth, Communications, Payments, and Team, security & connections.

  • A local search finds settings already available to you, without extra database

requests. Existing tab links still work and preserve programme context.

  • Navigation uses consistent bold controls, wrapping labels, visible keyboard

focus and larger touch targets. Existing permissions and feature gates remain authoritative; search does not grant access.

  • Failed settings reads show a retryable message rather than editable empty

defaults. Delayed results from a previously selected club cannot replace the current club's settings, and internal database details are not displayed.

Keep unfinished configuration safe

  • Trial Settings asks before discarding changes when moving between programmes

or opening questions. Discarded club-only changes no longer reappear later.

  • Trial saves share one in-flight guard, including Enter submission. Fractional

trial limits are rejected rather than silently rounded.

  • Member Requirement rules and custom fields keep separate saved baselines:

saving one section preserves unfinished work in the other. Dirty notices and exit confirmation make outstanding edits explicit.

  • Member Types also protects unfinished modal edits on Cancel, Escape, backdrop

and browser Back; a confirmed save closes normally.

  • Requirement saves validate the server's returned definitions and member

values. An incomplete or mismatched receipt keeps the draft and explains that the save could not be confirmed, rather than incorrectly reporting success.

Private, accurately described message copies

  • Exact-recipient portal email copies now include additional portal-enabled

household contacts, with bounded tenant-scoped reads and failure protection.

  • Subjects and bodies omit credential links, including token paths and encoded

parameters. Ordinary authenticated action/renewal destinations remain usable.

  • Copies are described as prepared, not proof of provider delivery. The portal

archive is email/SMS only; Telegram and replies remain excluded.

Rollout

Apply and verify inbox SQL01 followed by the additive member-communications-inbox-02.sql before deploying this communications code. Do not re-run 01 alone afterwards. SQL02 expands only future legacy negative opt-out writes; it does not silently reset historical contact choices. Unexpected non-email/SMS snapshots require owner review, not deletion.

No new API key or feature flag is needed for this settings/correctness batch. Local implementation is not evidence that production has been changed. See the member-communications rollout checklist and Phase 1 closure ledger for exact verification and remaining checks.

Safer membership changes and clearer connected setup

3 September 2026

What's new

QA review correction — 4 September

  • Test evidence no longer derives observed access decisions from expected

permissions. Unit regression results cannot stand in for tenant or destructive database proof; incomplete evidence remains blocked.

  • Local platform checks with MFA bypass no longer certify platform access.

Required checks remain in the ledger until genuine MFA evidence exists.

  • Structural accessibility is labelled precisely, and the ledger explicitly

separates local development/CSP-bypass checks from production assurance.

  • Scenario proof requirements are explicit, not inferred from display wording.

Existing receipts need fresh execution against the changed plan.

  • This changes QA reporting only. It does not relax product authorization,

alter money or capacity rules, apply remote SQL, or complete the settings information-architecture redesign.

Member messages and clearer sending choices

  • Communications now separates essential membership information, optional event

invitations, and newsletters/marketing. Essential email requires the effective bulk-send permission, an affected static audience, a service reason and a no-marketing confirmation. Hard-bounce/complaint blocks and SMS STOP still apply.

  • Portal → Messages shows recipient-private text copies of new opted-in composer

email sends and unambiguously matched SMS sends. Copies are prepared before dispatch, so availability is not a delivery receipt. Portal read status is separate.

  • Contact preferences separate event emails from marketing and also govern new

optional portal copies. Existing opt-outs stay off until that contact chooses; choices are club-specific and audited. Staff previews cannot change preferences or mark messages read. Scanner visits no longer unsubscribe: GET confirms, POST acts.

  • SQL-first: apply member-communications-inbox-01.sql and its postflight

before this code. No new environment key or flag is required. Existing send, provider, demo and unsubscribe-secret configuration stays in force.

  • First version deliberately excludes Telegram copies (chat links do not identify

the parent contact), historical backfill, attachments, owner alerts, sign-in links, conversations/replies and acknowledgement workflows. Existing provider transports are retained; portal copies require explicit adoption through the composer.

  • See docs/rollout/MEMBER-COMMUNICATIONS-INBOX-SQL-CHECKLIST.md for verification

and the local-only evidence/remaining owner checks.

Clubs decide whether a paused member keeps a capped-plan place

  • A capped membership now has a “Paused members keep their place” setting.
  • The default remains that pausing releases the place, which suits clubs that

stop charging during a pause. Clubs that promise a member their place can enable the setting on that specific membership.

  • Uncapped memberships do not show a meaningful pause-capacity choice. Existing

memberships retain their current release-place behaviour.

  • Membership waiting lists remain opt-in per capped plan. They show demand to

staff but do not move a member or take a payment automatically.

Changeover invoice generation fails safely

  • Invoice generation remains compatible while the family-pricing database unit

is being introduced, rather than losing every agreement read when the family cap column is not present yet.

  • A scheduled membership change is only priced as the new membership after its

tenant-scoped database update succeeds. Capacity, tenant or database failures now stop that agreement's invoice run instead of charging the new price while retaining the old membership.

  • Uncapped membership updates retain their plan-row serialization fence but no

longer repeat the full member-capacity census.

  • If a released place is filled before a paused member returns, individual and

bulk reactivation now show a clear membership-full conflict instead of a generic server error.

Member Request SQL delivery is additive

  • The zero-class membership and regular-class policy has moved out of the

previously handed-off Member Requests unit into a new additive roll-forward. Existing databases therefore receive the same behaviour as fresh databases.

  • A member whose chosen membership allows zero regular classes can submit an

empty class choice without a false roster error.

Deployment note

  • Apply and verify membership-plan-paused-capacity-policy-02.sql and

portal-member-requests-roster-policy-05.sql in the exact order documented in the Changeover Control Centre SQL checklist before deploying the matching application code.

Timetable dates follow members through the portal and enrolment

  • Regular classes on the portal calendar respect their first and last dates,

inclusive. Historical dates remain available; ended classes no longer appear as current classes or new enrolment choices.

  • Future classes remain selectable and their start/end dates are visible.
  • A failed timetable read shows a retryable error instead of silently presenting

an empty class list.

Membership waiting-list interest survives a changeover request

  • Completing, cancelling or deleting a source request no longer removes a

household's waiting-list interest. The same applies to expiry once the Member Requests expiry unit is installed.

  • The portal's Action Needed page shows active membership waiting lists, with an

explicit Leave waiting list control that works even without the old request.

  • A link from Payments keeps requests and waiting lists reachable after the

pending-action navigation badge disappears. Joining/leaving refreshes the shared paged list as well as the choice cards.

  • Selecting the target plan still closes its waiting-list entry. No place is

reserved, no membership is changed and no payment is taken by joining.

  • Previously withdrawn entries are not revived automatically.
  • SQL first: apply membership-plan-waitlist-lifecycle-03.sql and its composed

postflight after the capacity unit and before this UI. A missing withdrawal authority fails closed. No new environment variables or feature flags.

Connected Settings and clearer SMS diagnostics

  • Memberships, programmes, timetable, requirements, member types, trials, forms

and SMS settings now offer compact Connected setup links to related visible settings. These are guidance, not claims that setup is complete.

  • SMS settings distinguish sending configuration, receiving configuration,

the last recorded inbound reply and Telegram recipient setup. Technical connection details are expandable; missing diagnostics never masquerade as saved settings being switched off.

  • A configured gateway is not a delivery test or proof that the phone is online.

No messages are sent by opening the diagnostics.

QA reports distinguish mapped checks from application coverage

  • Evidence summaries now show required, unmapped and unresolved-persona slots.

Passing the mapped checks no longer labels the whole application ready.

  • If the scenario catalogue is unavailable, coverage is explicitly unknown,

rather than assumed complete. Existing evidence certification rules remain.