Changelog

What we shipped, when. Newest first.

Membership pricing, capacity and timetable changeovers

2 September 2026

What's new

Settings are clearer on tablets and long forms

  • Annual Requirements are now called Member Requirements throughout the

settings, staff and member views, reflecting that clubs can track insurance, registrations, qualifications and other checks—not only annual renewals.

  • Member Type actions no longer wrap awkwardly at tablet widths, and shared

confirmation dialogs now keep every close and footer action at least 44px tall for reliable touch use.

  • Trial Settings show a sticky unsaved-changes action after an edit, so club

staff can save a long programme form without scrolling back to the top.

Video Review limits now match each membership

  • Clubs can set a default number of Video Review submissions per member each

Monday-to-Sunday week, or choose unlimited submissions.

  • Each membership can exclude Video Reviews, inherit the club default, set its

own limit from one to 100, or allow unlimited submissions. When more than one current included membership covers a member, the highest allowance applies.

  • Weekly places are reserved safely before an upload begins, including when a

member has several tabs open. Cancelling an unfinished upload releases its place; a submitted video continues to count if it is later withdrawn or deleted.

  • Final submission creation and upload-intent consumption now settle together,

so a temporary database failure cannot use an upload token without creating the matching review.

Deployment note

  • Apply and verify video-review-weekly-quota-01.sql before deploying the

matching application code. The routes fail closed if its service-only authorities are unavailable. No environment variable or feature-flag change is required.

Family pricing now grows with the household

  • Membership plans can add consecutive family-price tiers beyond the second

and third member. The last configured tier continues to later family members, so clubs do not need to predict a maximum household size.

  • A fixed family price now consistently means the final price charged for that

member. Existing plans that stored the older amount-off format remain compatible and are converted when opened for editing.

  • Clubs can optionally cap the membership total for one household agreement in

one full billing period. Partial periods reduce both the membership charges and the cap by the same proportion. The cap is applied before an agreement-specific override; other memberships, events, courses, requirements and invoice fees remain outside it.

  • Family members with the same link time are ordered deterministically, keeping

their price-tier positions stable between invoice runs and member views.

  • Member profiles now derive family position from the same agreement coverage

union as invoice generation, including additional and junction-only plan links. Database read failures show as unavailable rather than as an empty family or a missing membership.

  • The household headline is labelled as plan base rates, rather than claiming a

monthly invoice total before family pricing, caps, frequencies and overrides have been applied.

Deployment note

  • Apply membership-plan-family-pricing-01.sql and confirm its postflight

before deploying application code, because plan reads and writes name the new household_cap_pence column.

Timetable changeovers

  • Classes can now have optional inclusive start and end dates, so clubs can prepare a replacement timetable before the old one finishes without showing both schedules on the same day.
  • Calendar, register fallback, dashboard, trials, portal session booking, lesson-capacity forecasting and attendance-break analysis use the same date-window rule. Existing classes with no dates remain ongoing.
  • Changing a class window is refused when it would hide a future trial or portal session booking; those bookings must be moved or cancelled first.
  • Future-start classes remain available for advance joining, while ended classes are removed from public choices and cannot issue waitlist offers. Pending stale offer deliveries are suppressed without sending a message.
  • Closure previews, trial-pause expansion, member next-session cards and momentum calculations now observe the same inclusive window.
  • Deployment is SQL-first: apply and verify lesson-date-windows-01.sql before deploying the application code. This foundation does not schedule future roster assignments or membership choices.

Plan places are protected during membership changes

  • Club owners can set an optional member capacity on each membership plan and

define the minimum and maximum number of regular classes members should pick.

  • The member portal shows live places remaining. A full plan cannot be selected,

and clubs may optionally let the household join or leave its waiting list.

  • Capacity counts people rather than billing agreements. Current members and

accepted future changes reserve places; choices awaiting staff review are shown separately as demand and reserve a place only when approved.

  • The capacity rule is enforced at the database boundary for staff, imports,

enrolment and portal changes. Concurrent requests for the final place have one durable winner instead of allowing the plan to be oversubscribed.

  • Capacity coverage, household-plan links and legacy student-plan links are now

required to belong to the same club. Direct signed-in writes to the coverage junction have been retired; guarded server authorities retain write access.

Deployment note

  • Run membership-plan-capacity-preflight.sql and require all three tenant

mismatch counts to be zero before applying membership-plan-capacity-01.sql. This migration must be applied before deploying the capacity application code.

Future membership and class choices are easier to review

  • Members can explicitly apply a membership or regular-class change now, or

choose a future date, and their submitted receipt keeps the selected plan, classes and effective date visible.

  • A membership can validly allow zero to 100 regular classes. Lesson-only

requests use the member's real current or scheduled plan and the same class bounds whether the change is immediate or scheduled.

  • Staff review shows the current and requested plan and classes, including

class day, time, effective date and the selected plan's capacity position.

  • Scheduled changes are split into attention and upcoming lists with paging.

Only retryable failures can be retried; terminal failures direct staff to review the member and issue a fresh request.

  • Membership plan editing now includes an ordered waiting-list view. It never

changes a membership or creates a charge automatically; staff contact the household and send a fresh member request when a place is available.

Confirmed future class choices now reserve real places

  • A member's accepted future class choice now shares one dated capacity rule

with portal session bookings, class waiting-list claims and staff/import roster changes. Concurrent attempts for the last place have one winner.

  • The saved change is tied to the exact household membership and pending plan

state that the member confirmed. If that state later changes, the automatic update stops and asks staff to review it instead of applying an obsolete choice.

  • Staff can cancel or rebase a stopped future class change with a required

reason and a before/after audit record. Classes with confirmed future places cannot be archived, shortened or reduced below those commitments first.

  • Future class submissions and approvals now serialise against membership

expiry, cancellation and plan changes. A concurrent membership change wins cleanly rather than leaving an obsolete capacity reservation.

  • The Member Requests control centre now exposes those recovery actions with a

current-versus-revised class preview. Completed and cancelled changes remain available in paged history, and memberships that allow zero regular classes can be corrected to an empty future roster without a false validation error.

  • Due changes are claimed in recoverable leases and shared fairly between

clubs. The scheduled worker drains a bounded number of pages, reports the remaining backlog and fails visibly when work needs attention.

Changeover demand is visible before places are committed

  • A read-only capacity forecast for each Member Request campaign separates the

current roster, confirmed future or held places, choices awaiting staff review and waiting-list demand for every offered membership and class.

  • Remaining places still come from the same dated plan and lesson authorities

that enforce the final place. The report does not reserve a place or turn an unanswered choice into demand.

  • Full choices and choices where review or waiting-list demand could use every

remaining place are clearly identified. Large class lists are loaded in bounded pages, and a failed census is shown as unavailable rather than as an empty or healthy result.

Deployment note

  • Apply and verify portal-future-lesson-rosters-02.sql, then

portal-future-lesson-rosters-03.sql, after portal-future-lesson-rosters-01.sql and before deploying the application code. The upgrades refuse ambiguous duplicate live schedules, backfill the exact membership snapshot for valid unit-01 work already waiting and add the service-only recovery preview.

  • Apply and verify changeover-capacity-forecast-01.sql after the future-roster

unit. Its application route fails closed as not ready until the read authority is present.

Member requests can be checked before they are sent

  • Staff now preview the exact selected members and deduplicated households,

the actions that will be created, existing requests that will be skipped and the effective-date bounds before creating a member-action campaign.

  • Membership requests offer only the compatible plans deliberately selected by

staff. Each household's current membership remains available as an explicit keep-current choice, and every option is stored as an immutable versioned snapshot so later plan edits cannot silently change what the member saw.

  • A successful creation remains visible with its confirmed membership,

household-details, regular-class and skipped counts instead of closing the dialog before staff can verify the result.

Deployment note

  • Follow CHANGEOVER-CONTROL-CENTRE-SQL-CHECKLIST.md as one SQL-first

sequence. Capacity and lesson-date-window authorities precede the campaign readiness unit; the future-roster units and member-request eligibility roll-forward have their own required postflights. Do not deploy the matching callers after only the older portal member-request units. Until the complete sequence is verified, every new path fails closed.

Changeover work is recoverable and easier to operate

  • The Member Requests screen now prioritises changes awaiting staff approval,

keeps scheduled class changes split into upcoming, attention and history, and shows the staff reason recorded for a cancellation or correction.

  • Staff can update or cancel a confirmed future class choice without changing

today's roster. Recovery rechecks the member, membership dates, active plan, programme, club lens, class dates and capacity before accepting a revision.

  • Campaign previews and creation now use the same effective-date and programme

rules. Plans ending before the change, inactive members and classes outside their date window are safely excluded.

  • Large histories and forecasts page independently. A failed page keeps the

already-loaded information visible and reports the affected section instead of presenting a false empty result.

  • The changeover evidence now covers mixed households and programmes, the exact

12-choice limit, creation races, plan/lesson drift and future-roster terminal history.

Deployment note

  • This is one SQL-first release unit. Follow

docs/rollout/CHANGEOVER-CONTROL-CENTRE-SQL-CHECKLIST.md and require every preflight and postflight to pass before deploying application code. No new environment variable is required, and automatic expiry generation remains a per-club owner decision.

Member changeover dialogs are ready for repeatable responsive QA

  • Every deep-linked Settings section now exposes its section name as the page

heading to assistive technology, matching the Settings home and group views.

  • Opening a confirmation dialog from a row menu now keeps keyboard focus in

the dialog instead of returning it to the closed menu's trigger.

  • Forms opened in a dialog now keep their intended first field focused, while

confirmations without an initial field focus the close control. Closing either returns keyboard focus to the control that opened it.

  • Trial Settings now gives its colour picker and editable hex value distinct

names for screen-reader and voice-control users.

  • Trial journeys no longer accept a blank booking-button label; any legacy

blank value safely falls back to “Book trial”.

  • Requirement setup now connects every visible field label to its control and

names the member-type selector as one group, improving keyboard, screen-reader and voice-control navigation without changing the form layout.

  • Requirement lists now switch to readable action cards at tablet widths, so

the final status and row actions no longer sit beyond the visible Settings workspace beside its navigation rail.

  • Assistive technology can now identify each member's selection control by the

member name, while the compact mobile action remains unchanged.

  • The five member-request and future-roster dialogs now have isolated local QA

fixtures for desktop, tablet and phone. They use a run-owned club and staff session, stop before any consequential submit and require zero fixture residue before their evidence can count.

  • The remaining owner lifecycle, suspended billing, platform administration and

household Portal views now share one repeatable local evidence campaign. It verifies a live isolated app, real local auth states and desktop/tablet/phone results, then removes the run-owned clubs, sessions and audit activity before those observations can count.

  • Release evidence now displays the earliest expiry across both ordinary

fixtures and the authenticated lifecycle campaign, so its human-readable reuse deadline cannot outlast any evidence that contributes to the result.

SMS replies now reach the club's Telegram owners reliably

  • A signed inbound SMS reply is forwarded to every enabled Telegram

owner/admin recipient for that same club. Each recipient has a durable key derived from the provider receipt, so a webhook replay or partial fan-out cannot notify the same person twice.

  • The separate SMS-only forwarding chat has retired from Settings. Telegram

reply recipients are now managed in Club Details, keeping one recipient list for owner notifications instead of two lists that could drift apart.

  • The message screen no longer labels a quiet gateway phone as “offline”. It

reports recent activity, no recent gateway update, a queued backlog or an unavailable status using only evidence the database can prove.

  • Failed gateway-health reads now show as unavailable instead of presenting

zero queued messages as though the read succeeded.

SMS reply rollout note

  • No SQL or new environment variable is required. Before relying on reply

forwarding, confirm the club has inbound SMS enabled, a unique webhook signing key, a connected Telegram bot and at least one enabled owner/admin Telegram recipient. The provider's webhook registration remains an external setup check; Allsorted does not infer it from a lack of message traffic.

Faster, quieter member requirement pages

1 September 2026

What's new

Payment tools load only when they are needed

  • The member portal no longer loads Stripe while a household is simply viewing

its requirements. The payment library is fetched only after the member starts an eligible paid renewal and the club's server has returned a valid checkout. Tracking-only and future requirements therefore stay lighter without changing the protected payment flow.

  • The installable app's service worker is now served as a public static asset

instead of being redirected to the staff login screen, so production browser registration can complete before a staff session exists.

  • Portal pages now own their main heading while the club name remains the

persistent portal brand. This gives assistive technology one clear page title, and labelled choice controls are recognised correctly by the QA accessibility evidence probe.

  • Payment return and invoice-history screens now give assistive technology

clearer page and expandable-invoice structure without changing how payment status is confirmed.

  • A rejected member request now presents its decision reason as a distinct,

readable line beneath the reason label.

  • Suspended club owners can now load the authenticated workspace details needed

by the billing recovery screen, without reopening any normal club actions.

  • Staff and member sign-in screens now expose one clear main area, properly

labelled fields and an accessible keyboard-contained help dialog. Portal retry links also explain that sign-in should be attempted again rather than implying access was completed.

  • Staff password sign-in now ignores repeated submissions while the first

attempt is still running and clearly shows its pending state.

  • Portal email links now keep their secure confirmation page styling before a

member signs in; the stylesheet is public, while the credential itself still requires the existing POST confirmation authority.

  • Public signup now shows and enforces the same password requirements as the

server, so a password accepted by the form is no longer rejected only after submission. Its fields also expose clear labels to assistive technology.

  • Portal sign-in help now gives both its help link and Close action comfortable

mobile touch targets while preserving Escape dismissal and focus return.

  • Page evidence now treats mocked refund-service tests as functional checks

only. Destructive refund proof remains visibly outstanding until it is backed by a genuine disposable run and zero-residue cleanup census.

  • Page-evidence fixtures now require three independent viewport runs, a private

checksummed local-runtime manifest and receipt-bound freshness. This prevents a single viewport, stale fixture or ambient provider/send configuration from being reported as current responsive release evidence.

Clear platform updates for club owners

31 August 2026

What's new

Clearer member requests, trials and annual requirements

  • Settings shortcuts now open the section named in the link immediately. This

fixes Annual Requirements links from Member Types and programme-specific question links from Trial Settings without requiring a refresh.

  • Historic member-type casing such as student is shown and saved as the

configured Student identity, without creating case-only duplicates.

  • Programme-scoped annual requirements now show a read-only coverage check.

It highlights timetable members who do not have the formal programme enrolment required by billing and expiry rules, without guessing that class attendance is consent to a commercial enrolment.

  • That coverage check now keeps its database reads and URL filters bounded even

for clubs with large timetables. Live requirements tied to an inactive or missing programme remain visible with a clear warning instead of disappearing from the census.

  • A member's archived member-type assignment remains visible in their editor as

a remove-only option. Staff can clean up historical assignments without being able to assign an archived type to anyone again.

  • Cancelling an edit to automatic expiring-membership requests now restores the

last saved settings, while request history can show exactly which households or members are still waiting without loading proposed contact changes.

  • The member-request editor now uses the standard keyboard-accessible dialog,

and annual requirements remain in readable cards through tablet widths. The requirement shortcuts and mobile section navigation now keep full-size touch targets as well.

  • Public trial selections follow each programme's configured accent colour with

readable contrast. Restoring a programme to the club defaults now asks for confirmation before removing its appearance and wording override.

  • Referral controls now meet the 44-pixel touch-target floor and flow into

full-width mobile actions where space is tight.

  • Staff delegated only the member-request review capability can now open the

approval queue without also needing permission to create or cancel requests. A failed queue read remains an error and is never presented as an empty queue.

  • Portal membership, lesson and contact-detail responses now share a protected

household submission allowance. Excess or unavailable rate-limit checks stop before any request is parsed or changed, without one household consuming another household's allowance.

  • Annual requirements can now describe more than one piece of member-specific

information using ordered text, date, number, selection and private-document fields. Membership numbers, policy numbers and evidence can therefore live together without overloading one reference box, and the same fields are available to requirement exports.

  • Clubs may optionally ask AllSorted to create one staff follow-up task when a

requirement renewal payment is received. It is off by default, applies to any requirement and remains one task when a payment webhook or repair is retried.

  • Renewal payment follow-up work now has a durable, tenant-bound lease. Parallel

webhook or confirmation workers converge on one opaque claim before activity, staff tasks or automations run; replays report completed or in-flight state and a crashed worker's lease can be reclaimed safely.

  • Member erasure now inventories private annual-requirement evidence before the

database cascade removes its pointers, then removes those files after the relational purge commits. An unavailable or incomplete inventory refuses before erasure, while a later Storage failure is reported honestly for administrator follow-up instead of claiming every private file was removed.

  • Existing requirement evidence remains available to authorised safeguarding

staff for viewing or explicit removal after a requirement, field or member scope changes. Those historic states cannot be used to upload a replacement.

Clearer club communication history

  • Communications history now starts with one item for each composed send rather

than mixing hundreds of individual recipient rows into the first view.

  • Email, SMS and Telegram badges make each send's channels immediately visible,

while scheduled, sending, sent, failed, cancelled and review-required states remain distinct.

  • Opening a send shows the next level of evidence: each recipient, email provider

webhook events, SMS gateway delivery timestamps and Telegram provider outcomes. Telegram acceptance is described as acceptance rather than inbox delivery, because Telegram does not provide an equivalent delivery-receipt webhook.

  • Older email records remain available in a clearly labelled legacy section, and

the history list now loads through a protected, club-scoped server route.

  • Static sends retain an exact recipient count in the summary without loading

or exposing their saved recipient snapshot. Dynamic sends remain labelled as resolving at send time.

  • History loads less sensitive data up front: recipient snapshots and retained

legacy message bodies are fetched only when staff open the relevant preview or delivery. Independent provider ledgers are also loaded concurrently.

  • History and scheduled-message previews now keep keyboard focus inside the

open dialog, close with Escape, restore focus to the opener and use larger touch targets. Their tab strips also remain usable on narrow screens.

Annual requirements can hold the information each club actually needs

  • Each annual requirement can now define up to 20 member-specific text, date,

number, selection or private-document fields. For example, one insurance requirement can hold an expiry date, membership number, governing-body status and evidence without creating parallel member fields.

  • Requirement settings and member values have separate, clearly labelled save

actions. Existing membership-reference information is carried into the new field list once and is never shown twice.

  • Private evidence uses a signed 10 MiB PDF/image upload. Staff can view,

replace or remove it from the member record; cross-club paths cannot be signed, and exports contain only the filename and availability status.

  • CSV and Excel requirement exports include the selected requirements' custom

fields, retain formula-injection protection and still refuse to return a file unless the required semantic audit succeeds.

  • Portal-card requirements can optionally create one staff processing task

after each online renewal payment. Invoice and track-only requirements do not show this option, because those collection routes do not use the same settlement authority.

AllSorted can communicate directly with club owners

  • Platform administrators can compose operational notices or optional product

updates for one club, selected clubs, or a safely filtered group.

  • Messages can be delivered by email, inside AllSorted, or both. The recipient

list is previewed before publication and frozen at publish time so its audit history always explains who was included.

  • Reusable templates support club-account merge tags such as club name, owner

name, plan, trial date and direct settings links. Member, household, attendance, health and payment-instrument data are never exposed to the composer.

  • Product updates honour each recipient's separate email and in-app choices.

Essential account, security and service notices are unaffected.

  • A staff recipient can still read or dismiss their own AllSorted message and

manage their own product-update choices if their club role later changes; they never gain access to another staff member's message occurrence.

  • Delivery history shows queued, sent, failed, cancelled-before-send and read

totals. A future campaign can be cancelled, but only email occurrences that have not started are suppressed; already processed provider outcomes are never relabelled.

  • Test emails go only to the currently authenticated platform administrator.

Demo clubs remain excluded from campaigns and read-only for preferences.

  • Publishing now persists the draft identity before creating any deliveries.

Retrying after an uncertain response cannot create a second campaign or send; the existing campaign remains available in History for reconciliation.

  • Club-owner message banners and inbox actions now recover honestly from a

dropped connection. Failed dismissals remain visible, inbox loading always settles, and a failed load offers a clear retry instead of an empty-state message.

Deployment note

  • Apply supabase/_proposed/platform-communications-01.sql and

supabase/_proposed/communications-history-recipient-count-01.sql, then require PASS from both postflights listed in the deployment checklist before deploying this application code. Until the SQL is present, every new route fails closed and no legacy messaging fallback is used.

  • No new environment variable or provider credential is required. Email uses

the existing Resend configuration and durable email-outbox worker.

  • The settings navigation, member-type canonicalisation and programme coverage

check require no additional SQL or environment variable.

  • Apply supabase/_proposed/requirement-custom-fields-01.sql and require PASS

from supabase/_verify/requirement-custom-fields-postflight.sql before deploying custom-field callers. No new storage bucket is required; documents use the existing private member-credentials bucket. The legacy insurance/reference data remains compatibility-linked; this release does not delete it.

  • Then apply

supabase/_proposed/requirement-renewal-side-effect-claims-01.sql and require PASS from its production postflight before deploying renewal settlement callers. The SQL-first window remains compatible with the old caller.

Clearer attendance, referrals and platform billing

30 August 2026

What's new

Member Requests can require staff approval

  • Staff can send a named request to one member, a household or a selected group

asking for a membership choice, household-details check and/or regular-class selection. Progress is tracked as awaiting response, awaiting approval, completed, rejected, cancelled or overdue.

  • Each request can either apply valid changes immediately or hold genuine

changes for authorised staff approval. Confirming that nothing changed completes immediately and does not create unnecessary review work.

  • Reviewers see a dedicated approval list. Rejecting requires a clear reason

which is shown to the member; rejection never changes membership, contact details or regular classes.

  • Member Request automations can notify households when a request is created,

submitted, approved, rejected, completed or overdue. Proposed phone/address values never enter automation or audit payloads and expire after 30 days if they are not reviewed.

  • Automation wording is now frozen when each event occurs instead of being

rebuilt from a later request state. A created notification is emitted once per household request and lists all included action types. Temporary claim failures stay queued for a safe retry, while an unknown provider outcome is held for reconciliation rather than being sent twice.

  • The overdue scan now skips identities already present in the durable outbox,

so more than 500 older requests cannot permanently hide later work. Cron backlog reporting uses an extra-row sentinel and no longer claims the queue is empty merely because one processing page completed.

  • Expiring-membership requests are optional and off by default. When enabled,

they are generated once for the exact membership/end-date cycle and never assume which replacement membership the household wants.

  • Staff approval, member submission and cancellation now share the same

household-first locking order, preventing a simultaneous response and review from deadlocking. One invalid expiring membership is isolated and reported without preventing later clubs or already-queued notifications from running.

  • Retries are now accepted only when the exact action-specific response matches;

changing a plan, contact answer or class list on the same completed/submitted request returns a clear conflict rather than a false success.

  • Class choices are rechecked against the live timetable and the member's class

allocation before approval. Moving a member to another household cancels and removes their name from the old household's outstanding class request.

  • Large request batches now show exact progress rather than stopping at an API

row ceiling. Request history, the approval queue and previous portal decisions have clear Load more controls, while current member actions remain visible.

  • Viewing proposed phone/address changes now creates a privacy-safe audit event;

the audit stores only how many submissions were viewed, never their contents.

  • Apply supabase/_proposed/portal-member-requests-02.sql, then

supabase/_proposed/portal-member-requests-03.sql, after the existing portal household-actions and lesson-capacity authorities, then require PASS from supabase/_verify/portal-member-requests-postflight.sql, before deploying this application code.

Households can resolve membership choices in the portal

  • Staff can offer a household a controlled list of compatible membership plans

instead of assuming which plan they want after a timetable or pricing change.

  • While a response is pending, the portal shows a temporary Action needed

destination with a count, a reminder and separate Choose your membership and Check your household details tasks.

  • The optional data check lets households confirm or correct their phone number

and address. Their portal email stays read-only so a contact-data check cannot silently change a sign-in credential.

  • Staff can see that a response is outstanding and cancel the request without

changing the household's current membership.

  • Apply supabase/_proposed/portal-household-actions-01.sql before using the

staff request. Until it is applied, the portal feature remains hidden and the staff mutation fails closed.

Birthday alerts can use any configured channel

  • Birthday automations now evaluate members who have a date of birth but no

email address.

  • Admin-only Telegram and member SMS actions can still run for those members.
  • An email action without a usable destination is visibly skipped in the run

log and never calls the email provider; other actions continue normally.

Missing-in-action attendance now counts catch-up sessions

  • Choosing a programme narrows which members appear in the report; it no

longer narrows what counts as attendance.

  • A Present or Late mark at any session in the same club—including an ad-hoc

or catch-up class—clears that member from MIA.

  • Ad-hoc sessions can now be attributed to a programme for reporting, while

still counting as club-wide attendance.

Club referral links are self-service

  • Authorised club administrators can create their club's referral code from

the existing Refer a Club settings page.

  • The server always takes the club from the signed-in session; a browser cannot

create or read a code for another tenant.

  • Approved referral credit can now be applied to the club's AllSorted Stripe

customer balance once the SQL authority is installed and the rollout flag is enabled.

  • A retry now reconciles the exact Stripe customer-balance transaction before

creating anything. Ambiguous, changed or repeatedly failing credits stop in an operator-review state instead of risking a duplicate or blocking newer referral credits.

  • Platform administrators can now see those held credit applications in the

referral console, including the club, exact credit, amount and hold reason.

  • After checking Stripe, an administrator can either release a proven-absent

credit for a safe retry or record a compensated provider credit as closed. Both outcomes require an evidence note and are revalidated by the database authority before the operation moves.

Simpler AllSorted subscription upgrades

  • Platform administrators can choose a configured plan on the club record;

Stripe customer, subscription and price identifiers are resolved and checked by the server.

  • The upgrade writes the established Starter/Pro/Scale product subscription;

the separate founder/paid/paused/cancelled account lifecycle remains intact.

  • Upgrades take effect immediately with Stripe proration. Downgrades and

currency or billing-interval changes remain deliberately blocked in this workflow.

  • Pricing setup can create and bind the Stripe Product and Price directly when

a plan has not yet been connected.

  • A platform administrator can now reconcile a pending plan change from the

club record. AllSorted reads the exact Stripe item back: an applied change is settled, an unchanged item is safely released, and any third state remains blocked for review.

  • Pricing creation now rejects fractional minor units, non-GBP platform prices

and duplicate current tier/interval rows before creating anything in Stripe.

  • Plan upgrades now update Stripe's billed price and canonical plan metadata in

the same provider request. Subscription webhooks independently verify exactly one Starter, Pro or Scale price line before changing entitlements, so stale metadata or ambiguous base lines are held for reconciliation instead of silently reverting a club's tier. Separate module and vertical add-ons remain independent.

Attendance-report MIA contract simplified

  • Programme filters still narrow which current members are considered, while

attendance recency always comes from every Present or Late club session.

  • The report no longer performs or retains a contradictory programme-specific

attendance calculation after the complete club-wide read-model has loaded.

Deployment note

  • Follow docs/database/platform-growth-billing-deployment-checklist-2026-08-30.md

before deploying this application code: apply the two original SQL units, then supabase/_proposed/platform-referral-credit-reconciliation-02.sql.

  • Keep REFERRAL_STRIPE_CREDITS_ENABLED off until the Stripe test-mode smoke

checks in that checklist pass.

Update — 2026-08-29

29 August 2026

29 August 2026

Clearer automation drafts and publishing

  • Automation builders now show one unambiguous next action. New edits are saved

as a draft first; a complete saved draft then offers Publish automation or Publish changes. A clean live automation simply shows Published, rather than asking the club to save a draft that does not exist.

  • Preview always uses the exact saved version named on screen. It is temporarily

unavailable while there are unsaved edits, and an older preview disappears as soon as the automation changes.

  • Publish readiness now checks trigger conditions and reminder timing as well as

the event and action steps. A blank condition, zero-length reminder or unknown event cannot be made live through either the screen or a direct request.

  • Switching between Simple setup and the Advanced builder preserves the same

draft without falsely reporting an edit. Names are visibly editable, condition controls use appropriate operators and accessible labels, one-day delays read naturally, and Pro Shop triggers have their own category.

  • Every available trigger now has a separate Starts when explanation that

names the exact committed action or scheduled processor which causes it. The membership labels now match their real scope: insurance renewal confirmation, household-plan pause, cancellation scheduling and plan-change confirmation are no longer presented as general member-status changes.

  • Scheduled member-status changes are explicitly described as running only when

the due status step is applied. Saving or cancelling the future schedule does not send a status-changed automation.

  • Household plan-change messages now receive the target plan and the actual

requested effective date (or “next billing period”), rather than the old plan and the date the schedule was created. Pause copy also correctly describes the supplied date as the end of the hold.

Requirement-specific renewal payments

  • Each annual requirement can now choose one collection route: track only,

household invoice, or member portal card payment. A requirement cannot use both invoice and portal card collection, preventing the same renewal from being collected twice.

  • Clubs can name the paid state and choose a compact colour and icon for it.

The same accessible badge is shown in Settings, the staff member profile and the member portal, so labels such as Insurance paid — awaiting processing or Licence paid refer to the exact requirement rather than a generic member-wide flag.

  • Payment evidence is now keyed by requirement UUID, member and renewal cycle.

Multiple programmes and multiple annual requirements therefore keep separate paid and processed states. Replays return the original record instead of creating a second payment state.

  • Portal-card setup now derives its Stripe idempotency identity from the durable

renewal token, not the browser's event label. The two legacy labels therefore resolve to one PaymentIntent, and an existing different provider pointer is never overwritten.

  • Staff processing and provider settlement now take the same requirement,

member and cycle fence before any row lock. An offline action racing a card settlement cannot deadlock or poison webhook retries: the payment is attached to the one durable record and a late arrival is marked for reconciliation without reviving a cancelled or refunded renewal.

  • The member portal now lists all applicable annual requirements, shows whether

each is club-managed, invoiced or payable online, and only opens card payment inside that requirement's own renewal window. Staff can process a paid renewal or record an approved offline renewal from the member profile.

  • Requirement automations can select an exact requirement from a named list and

receive its UUID, programme scope, collection method and paid-status label. Existing insurance-renewal automations remain supported during migration.

  • Existing published automations that used the old contains operator on

status, Direct Debit, gender or bulk-opt-out fields continue to execute. New drafts retain the stricter operator choices. The requirement event-key cutover also recognises the former key, preventing a first-deploy duplicate renewal message.

Faster complete CI evidence

  • Full CI and the security gate now execute against the proposed PR merge and

can still be repeated manually, but no longer rerun after that same merge reaches main. Superseded commits on one PR are cancelled automatically. Releases must use Create a merge commit; direct pushes, squash merges and rebase merges are outside this evidence contract.

  • Database rehearsals remain mandatory on every pull request, but now run as

two exact, isolated rehearsal shards while the database test class runs on a third fresh stack. All 29 rehearsals still execute exactly once.

  • Fast template restores now hand the stack back after one authenticated,

JSON-validated clubs table read. Full resets and fallback resets retain the five-consecutive-green restart gate. This removes repeated idle waits without weakening the restart-race protection.

Role-specific requirements and member references

  • Annual requirements can now apply to every member or to selected club member

types. Programme and member-type scopes work together, so clubs can separately track student insurance, instructor insurance, DBS checks, first-aid courses and volunteer credentials without showing or charging the wrong people.

  • A requirement can define one labelled member reference, such as **British

Taekwondo membership number**. Staff maintain the value against that exact member and requirement; it is not stored in a shared or ambiguous member field.

  • Staff can correct a recorded expiry date, last-renewed date or reference value

from the member profile. This correction does not create a payment, invoice, renewal ledger entry or automation event; Mark renewed remains a separate, explicit action.

  • The Members screen can filter by an exact requirement and its Not recorded,

Valid, Expiring or Expired state, then sort the selected requirement by its recorded date. Applicability is calculated from the same programme and member- type rule used by the portal, nightly engine, attendance blocking and owner actions.

  • Editing an existing annual requirement now opens a focused page instead of

expanding the full editor inside the settings list. A consistent top-right Back to annual requirements action returns to the matrix; quick creation and presets remain available from the matrix.

  • Requirement cards keep their complete programme and member-type scope visible

on narrow screens instead of truncating the applicability rule.

Member types on registers

  • Club-defined member types can identify which people may appear as lesson

leaders or helpers. Register setup reads those definitions from the same tenant-scoped authority used by Settings, so labels such as Coach, Instructor or Volunteer are not hard-coded and another club's people cannot appear.

  • The register continues to support the previous leader/helper setup while the

newer member-type directory is being deployed. Once the SQL authority is present, the richer role labels and choices are returned in the same setup snapshot without an extra browser request.

Programme-specific trial journeys

  • Trial configuration now has its own Trial Settings destination instead of

being mixed into Club Details. The club keeps one main public trial link, and can also copy a programme link that opens with that programme selected.

  • Each programme can inherit the club defaults or define its own booking status,

audience, wording, confirmation copy, accent colour and visual style. A club with several active programmes asks the visitor what they want to try before showing suitable classes; a class-specific link derives its programme where possible.

  • Trial questions now use the versioned Form Builder. Clubs can publish one

club-wide Trial form and override it for an exact programme without replacing the capacity, closure, guardian-consent or booking authority underneath it.

  • Opening questions from Trial Settings now carries an explicit club or

programme scope. An inherited programme starts an independent programme form family; it cannot silently retarget or replace the published club default.

  • Programme trial links and preview/copy actions remain fully readable and

tappable on narrow screens, including long public URLs.

  • Public and staff bookings durably record the chosen programme. Shared classes

require an explicit programme choice in multi-programme clubs, and enrolment invitations inherit that attribution without using email as identity or guessing from a programme name.

  • Disabling online trials for one programme removes only that programme from the

public chooser. Historic bookings remain readable and rescheduling preserves their programme rather than silently moving them across programme boundaries.

  • Member types now use durable keys with editable display labels. Renames are

reflected in member profiles, filters and exports; archived types remain readable for existing assignments and settings warn when requirements still target them.

  • Requirements can be exported for selected members and selected requirement

definitions as CSV or Excel. The export is tenant-scoped, formula-safe, size-bounded and withheld unless its durable safeguarding audit succeeds.

  • Existing legacy credential configuration remains editable from Member Types

while clubs move tracking to Annual Requirements, avoiding a headless or destructive evidence migration.

Deployment note

  • The automation-builder UI work itself needs no environment or feature-flag

change. The requirement-specific payment state is SQL-first: apply configurable-credential-renewal-01.sql, then requirement-renewal-authority-01.sql, before deploying its application code.

  • Role-specific requirement targeting and editable references are also SQL-first:

apply member-type-directory-01.sql after its register-snapshot prerequisite, then apply requirement-member-types-and-details-01.sql after the renewal authority and review its four-boolean postflight before deploying the follow-on code.

  • After configuring Creative Ways' exact insurance requirement, the owner may

run requirement-renewal-legacy-insurance-backfill.sql with that requirement's UUID. The script never guesses by name and ends with a legacy/canonical census for review.

  • After applying the renewal authority, capture the fresh production function

census before refreshing the production authority manifest; unapplied functions must never be represented as already live.

  • No new environment variable or feature flag is required for requirements.
  • Programme-specific Trial Settings are SQL-first: after the existing form-

lifecycle and trial-pause authorities, apply trial-program-settings-01.sql and require every row in trial-program-settings-postflight.sql to pass before deploying callers of book_trial_booking_v5 and move_trial_booking_v5. No new environment variable or feature flag is required.