Changelog

What we shipped, when. Newest first.

Update — 2026-08-28

28 August 2026

28 August 2026

Safer member links

  • Portal sign-in and account-activation links now open a confirmation page

without consuming the one-time credential. The credential is used only when the member deliberately continues, preventing email security scanners from invalidating a valid link before the member opens it.

  • Confirmation pages prevent caching and referrer leakage, and malformed,

expired or replayed credentials still fail closed.

More predictable learning pathways

  • Opening a member's learning pathway is now read-only. Any LMS completion

synchronization is performed through an explicit protected write, while the page still updates automatically when it detects that the recorded pathway and completed course evidence differ.

  • Portal course purchases, packages and progress writes now honour the active

member's module, programme and current-stage access before payment or progress state is created. Existing subscriptions remain visible when access changes so a household can still manage or cancel them, including archived packages that remain billable. New and temporarily paused members now use the same canonical status rules as the rest of the member portal.

  • Demo clubs can continue to view published forms without creating persistent

responses, members, activity or automation records.

Clearer feature access and assessment controls

  • Smart Planning and Video Reviews are now enforced by the server as well as

hidden in the interface when a club does not have the module.

  • The Register page now hides its lesson-plan card when Smart Planning is not

enabled, so it no longer advertises an action the server will refuse.

  • Assessment scoring now combines colour with cross, warning and check icons,

accessible names and selected-state announcements. Touch controls remain comfortably sized, while the desktop matrix stays compact.

  • Form Builder dialogs now trap keyboard focus correctly. Smart Planning's

mobile steps show overflow cues and keep the active step in view, member lists sort consistently by surname, and several small mobile actions have larger tap targets.

More truthful public and operational states

  • Returning from GoCardless no longer claims that setup succeeded before the

provider webhook confirms it.

  • The enrolment-complete screen now proves the completed enrolment from the

server before showing success, and no longer places member names or internal identifiers in its URL.

  • Active clubs are redirected away from the suspended-billing screen, and a

future trial end is no longer described as an expired trial.

  • Email health no longer reports “ready” when the Resend domain check is

unavailable or the domain still needs attention.

Faster, safer staff data loading

  • Returning to the Households directory now restores the last same-club result immediately and

refreshes it in the background. If that refresh fails, the previous result stays visibly marked as older instead of disappearing or looking current.

  • Once the accompanying Household read-model SQL is applied, large Household directories load in

exact server pages instead of transferring the whole club at once. Search, filters, summary counts and both member-assignment pickers remain complete across every page; malformed or failed reads show as unavailable rather than an empty family list.

  • Member directory refreshes now update one stable same-club cache entry instead of retaining a

separate whole-directory payload after every profile edit. Confirmed member and household changes continue to request fresh server data, and switching clubs still clears the session cache.

  • The public website now lives at /, while signed-in club operations have a

dedicated /dashboard address. Sign-in, onboarding and staff navigation all use the same destination without adding a second navigation shell.

  • Staff startup now uses one guarded server snapshot for club access, role,

modules, terminology and shared reference data instead of a browser fan-out. Explicit club switching remains separately authorised.

  • Dashboard membership, programme-lens membership, Today, attention and

contactability data now revalidate through one guarded request. Selected programmes are proved against the signed-in club and incomplete lens reads fail closed; optional failures stay visibly unavailable and cannot erase a valid core dashboard or appear as reassuring zeroes.

  • Member profiles now make one initial snapshot request instead of immediately

invalidating it and requesting the same data again. Saves and other explicit changes still refresh from the server.

  • The dashboard now waits for shared club reference data before calculating its

figures, and an older club or programme request can no longer replace the latest view if it finishes late.

  • Dashboard figures are now committed to their exact club and programme before

they can be shown, so switching context cannot briefly display the previous club's totals. Failed reference or dashboard reads stop loading with a clear unavailable message; same-club last-known-good figures remain visibly marked instead of being replaced or cached as believable zeroes.

  • Register setup now starts its independent staff, lesson, rank and event reads

together. A failed core read now stops with a retryable unavailable message instead of looking like an empty register; the optional staff picker remains non-blocking.

  • Public marketing effects and authenticated staff navigation now load only on

the screens that use them. Once the signed-out home view is resolved, its text is independent of the decorative 3D download; reduced-motion visitors do not download that scene, and background-tab safeguards remain in place.

  • The signed-out landing page now keeps a page-shaped fallback while its

separate marketing bundle loads, rather than briefly becoming blank.

  • Register, calendar and event opening states now use their matching page

skeletons, making progress clear without briefly showing an empty screen.

More trustworthy high-volume totals

  • Member, finance, product-sales, feedback, SMS and portal reports now load every

available page instead of silently stopping at the database API's first 1,000 rows.

  • If a report reaches its deliberate high-volume safety ceiling, it now shows as

unavailable rather than presenting a believable but incomplete total. The member directory keeps its existing clearly labelled partial-list mode and disables exports until the complete directory can be loaded.

  • Dashboard and household fallback reads, today's attendance totals and member portal-access

history now recover records beyond the first database page. Communications adoption uses exact counts, and Class Pulse labels stay club-bound and complete.

  • A failed Class Pulse refresh now removes the cached tile instead of leaving an older score

looking current.

  • Once the accompanying database unit is applied, external-event lists, SMS reply badges and the

dashboard attendance chart use live grouped reads instead of transferring histories or issuing repeated count requests. The existing complete reads remain available automatically until then.

  • Staff pages with several permission-sensitive panels now resolve one fresh, request-local

permission snapshot instead of re-reading the same club and override settings for every panel. Search, Action Centre and external-event detail responses also expose anonymous server phase timings for performance diagnosis without including club, staff or member identifiers.

  • Course audience saves validate all selected programmes in one club-scoped read, pathway lists

batch their entitlement checks, and grading snapshots batch rank ownership and assessor lookups. All three paths still fail closed when an authority read is unavailable.

  • Large pathway/course entitlement lists and grading snapshots now page through every source row.

Grading attendance is grouped in the database when the optional read model is available and is otherwise folded exactly one page at a time, removing the former lifetime-history ceiling without keeping the full history in memory. A failed page returns unavailable instead of a plausible but incomplete roster, syllabus, score, attendance or grading history.

  • SMS dashboard totals now use a fixed-window keyset walk, so new webhook rows cannot shift pages

while a request is running. Only displayed contacts are name-enriched, recent content is limited to staff with the content-view permission, and segment figures are explicitly labelled as retained-body estimates rather than complete historical billing totals.

  • Once the accompanying read-model SQL is applied, the SMS operational dashboard computes its

fixed-window totals inside PostgreSQL and returns only bounded summaries plus 25 recent rows; message history is no longer transferred to the application for aggregation. The weekly attendance read model now also proves the requesting staff member belongs to the session club.

Safer switching and fresher programme lists

  • Switching clubs now waits for the server to confirm access before changing

anything in the browser. A rejected or interrupted switch leaves the current club intact; a confirmed switch clears cached member, register, dashboard and API snapshots before a fresh page is shown. Other open tabs follow the same confirmed club and sign-out boundary.

  • A browser without a remembered club now chooses the same primary membership

in the page gate and every protected action. The next successful startup restores the secure club cookie automatically, while an unreadable membership never falls back to a potentially different club.

  • Staff and member-portal sign-out now reports failures honestly, clears every

local identity cache only at the appropriate authority boundary, and prevents data from the previous account remaining mounted after expiry or a new login.

  • Cross-tab sign-out and club switching now purge caches even when a tab is still

bootstrapping or parked on a portal URL. Old in-flight VAT-policy reads cannot repopulate a newly signed-in club's cache, and ordinary non-session 401 errors no longer sign every tab out.

  • A confirmed member-portal login now clears household caches in every other

portal tab before reloading it, and page caches are scoped to the confirmed club and household instead of a shared pre-authenticated bucket.

  • A temporary reference-data failure no longer replaces known ranks, lessons or

membership plans with believable empty lists. The last confirmed same-club data remains available while the refresh is reported as unavailable.

  • Fresh reference data from staff startup now updates an already-mounted screen

immediately through the same club-scoped cache, without polling or another network request.

  • Programme member lists are invalidated after confirmed membership changes, so

moving or adding a member is reflected without waiting for the cache timeout.

  • Returning to a browser tab now coalesces its focus and visibility signals into

one member-profile refresh, avoiding a duplicate background request while keeping explicit post-save refreshes authoritative.

  • After membership is established, independent club-suspension, role and module

authority reads now start together. Every deny and unavailable outcome remains fail-closed; only the avoidable network waiting time has been removed.

  • The local performance journey now records each completed route immediately and

retains an explicitly incomplete report if the suite reaches its time limit, so a slow run no longer discards all earlier evidence.

  • The remaining browser-native confirmation and alert pop-ups have been replaced

with the accessible AllSorted confirmation and toast surfaces. Consequential actions now state exactly what will happen, rapid duplicate confirmations fail closed, and settings errors no longer freeze the whole browser tab.

  • Scenario names and rich-text links now use accessible AllSorted forms instead

of browser prompts. Link editing keeps safe web, email, telephone, page and section links available, with unsafe protocols rejected before insertion.

  • Confirmations opened from another modal now use the correct nested layer.

Supported actions can run inside the confirmation, keeping failures visible and retryable instead of closing before the operation result is known.

  • Once the second optional live read-model unit is applied, dashboard finance,

programme revenue, Product Sales and Portal Analytics calculate complete live totals inside PostgreSQL instead of transferring invoice, order, session and page-view histories into the application. Browser permissions and club scope are unchanged, integer-pence money remains authoritative, and each caller keeps its complete fallback until the SQL is available.

  • Product Sales date ranges now include the entire final UTC day, including

sub-second orders in its last second, instead of stopping at exactly 23:59:59.

  • Product Sales now keeps historical orders for a renamed product or variant in

one rollup, identified by its immutable catalogue ID and labelled with its current catalogue name. Deleted catalogue items retain a deterministic order snapshot label, so money and unit totals remain complete without duplicate rows after a rename.

  • The optional finance, programme revenue, Product Sales and Portal Analytics

database read models now validate the server-derived staff identity against the selected club as well as accepting only the service role. Their original club-only overloads are removed, direct foreign actors are denied, and every JSON result is bounded before it can reach the application.

  • Portal activity analytics now accepts only bounded member-portal pathnames,

and Portal Analytics displays Unknown for a legacy household with no name rather than discarding the complete database aggregate.

Clearer authority failures

  • The Action Centre now returns a retryable unavailable response when custom

permission settings cannot be read, rather than silently showing a narrower and believable feed. Capability-gated routes use the same fail-closed rule.

  • Existing safeguarding-lead resolution remains intentional: omitted options

resolve the caller's real club setting, while an explicit false value still denies safeguarding-only access.

  • Multiple entitlement sources now agree across single-resource and batched

checks: any valid, unexpired grant allows access; a lapsed row cannot mask a current grant.

Deployment note

  • The optional live-query-read-models-01.sql unit now contains five

actor-bound, service-role-only grouped reads, one locked internal helper and an explicit dependency preflight. External-event entry counts validate the authenticated staff actor as well as event ownership. Apply the unit only through the owner checklist, then require the read-only 6/6 postflight. All application callers retain exact fallbacks, so no feature flag is needed.

  • The optional live-query-read-models-02.sql unit contains four additional

actor-bound, service-role-only report aggregates. Apply it through the owner checklist and require the read-only 4/4 postflight. Application-first and SQL-first are both safe because all four routes reject malformed results and retain complete fallbacks; no feature flag is required.

  • Register setup now arrives in one bounded request, current attendance is

counted in PostgreSQL rather than downloaded to the browser, and realtime bursts coalesce into one final refresh without rebuilding the subscription after each tap. Attendance marking now validates the club, occurrence, lifecycle, lock, programme and package-usage choice in one transaction with deterministic mark-versus-seal ordering; legitimate multi-club staff are accepted through their selected-club access row.

  • register-performance-authorities-01.sql is migration-first. Apply it and

require the read-only 7/7 postflight before deploying its three new route callers; no production SQL or feature switch is performed by the application.

  • Register removal and sealing now share the same occurrence fence, including

after the final low-level attendance revokes. Live attendance failures show an explicit unavailable state instead of leaving an old count looking current, while an unavailable or oversized optional coach list no longer blocks the lesson, rank and event setup needed to use the register.

  • Register package usage again follows the conservative roster rule for any

matching booking history, and malformed recurring lessons with no weekday no longer pass occurrence checks unless they have an exact dated make-up pin. Different-member taps can proceed together, while sealing still waits for all in-flight changes. If the optional coach list cannot refresh, the register now says so without blocking attendance.

Update — 2026-08-27

27 August 2026

27 August 2026

Clearer, more reliable staff setup

  • Invite staff now opens in a focused, accessible dialog instead of

expanding inside the staff list.

  • Staff password links now recover correctly whether Supabase supplies a URL

token, a PKCE code or establishes the recovery session before the page loads.

  • Opening a recovery link is no longer presented as an active account. The

staff list distinguishes Invite pending, Setup started, Setup complete and historical Access used states, and setup links can be resent until password completion is recorded.

More trustworthy registers and event records

  • A sealed register now keeps the exact member record that was submitted. Later

class assignments or membership-status changes no longer alter the displayed official register or its expected count.

  • When an official register is unlocked for correction, its recorded attendance

rows remain visible even if a member has since paused or left; resealing then preserves those facts alongside any newly expected members.

  • Draft events clearly remain drafts and cannot accept members until published.

General events no longer show or store grading targets, while grading events keep each member's explicitly selected target rank.

  • Grading-event rosters now load their promotion steps through the protected

server record, keeping the dashboard and award workflow in agreement.

  • Automatic register closure can now be enabled for one reviewed club at a

time. The platform-wide switch alone cannot close registers for clubs that have not explicitly joined the pilot.

Clearer payment operations

  • Platform Health now distinguishes a reconciliation run that is active,

unfinished, stale, failed, or returned an HTTP error. Failed runs show the persisted category counts and a safe operator reason without displaying raw provider errors or personal/payment details.

Clearer member and import editing

  • Member profile edits send only the fields that changed, so clearing one value

cannot accidentally overwrite unrelated information.

  • A member can now be moved back to “No program”, and class editing keeps its

save controls clear of the floating member-actions button.

  • Data Import reports grading counts from the correct member scope and explains

that mapped class assignments begin immediately.

Planning and navigation polish

  • Smart Planning watch lists count people once, using their highest-priority

concern, instead of counting the same person once per tag.

  • Setup and Smart Planning timetable links now open the current Timetable

settings tab.

  • The lesson timer's exit control remains clickable above the full-screen timer

surface.

Safer AI pilots

  • Smart Planning and Communications writing assistants now stay hidden and

inaccessible unless the platform switches are on and the active club has been explicitly opted in.

  • A club-setting read failure leaves the assistants unavailable and never

reaches the AI provider, so a deployment or database problem cannot silently widen a pilot to other clubs.

Update — 2026-08-25

25 August 2026

25 August 2026

Safer consent, drafts and account changes

  • Club-wide Telegram invitations now respect both Telegram and bulk-email

opt-outs. Suppressed members are skipped before any invitation token or message is created.

  • Old child incident and health drafts no longer survive beyond their seven-day

privacy window when read through the current draft format.

  • Sensitive club identity, reply-to and payment-currency changes now require an

active account and create both application and database forensic evidence.

  • Portal sign-in links are consumed through hash-only storage, so the database

no longer needs to retain usable bearer credentials.

Recoverable payment choices

  • A declined card attempt no longer permanently blocks later invoice collection.

Its exact provider evidence remains recorded while the billing schedule moves forward once.

  • An abandoned, unconfirmed card form can be released before a member switches

to Direct Debit or staff issue a credit note. Processing, successful or uncertain provider states remain blocked for review.

  • GoCardless Success+ retries stay pending until the provider reaches a terminal

outcome, avoiding a second local collection attempt while GoCardless is still retrying the first payment.

  • Nightly Direct Debit collection now safely releases an exact abandoned card

form before collecting, and checks the live GoCardless payment before replacing any earlier failed attempt.

Complete local page-scenario environment

  • Local QA now has a generated catalogue for all 143 application page

templates, including the durable states, actor boundaries, failure cases and end-to-end process branches that can change each page's result.

  • The scenario seed combines the rich multi-vertical club with separate new,

empty, demo, suspended, paused and cancelled clubs plus owner, coach, read-only and platform-administrator personas.

  • Trial-one/trial-two outcomes, event lifecycles, task reminder evidence,

automation states and unsent communication drafts are available as named synthetic fixtures. Loading, race, invalid-token and real-provider cases are honestly labelled for fault automation or separately approved sandbox tests.

  • The seed is hard-gated to loopback Supabase, preserves an existing rich club

unless a destructive reset is explicitly requested, and cannot enable sends or payment collection.

Responsive interface polish

  • Shared dialogs, navigation drawers, menus and the command palette now stay

within short desktop and narrow mobile viewports, own their internal scroll, trap keyboard focus and return focus to the opening control.

  • Repeating-event cancellation, staff trial booking and member editing now use

the same accessible dialog behaviour and cannot be dismissed mid-save.

  • Destructive series choices and assessment invitations now have synchronous

action guards, preventing rapid taps from dispatching the same work twice.

  • Smart Planning filters and programme controls, report selectors, event forms,

student actions and public enrolment controls now wrap cleanly at 320 pixels and use reachable mobile touch targets.

  • Page shells no longer subtract a fixed viewport height beneath variable

banners, preventing the bottom of long screens from being clipped.

  • The visual QA matrix now documents desktop, tablet and four phone sizes plus

long-copy, keyboard, modal, loading/error and reduced-motion checks.

  • Calendar search, grading/event actions and member-editing dialogs now share

the same named, focus-contained and save-locked interaction pattern.

  • Certificate-template fields can be selected, positioned and removed by

keyboard, while certificate downloads recover when a browser blocks a new tab.

  • Segmented page filters now use one keyboard stop with Arrow, Home and End

navigation, matching their visual radio-group behaviour.

  • Assessment comments and invitations now use bounded, save-locked dialogs;

student-video playback and telestrator controls remain reachable on the narrowest supported phones.

  • Calendar closures and member form-link delivery cannot be dismissed while a

request is unsettled. Form links list active programmes without archived progression-system duplicates.

  • No-payment enrolment and Stripe-dashboard actions now recover cleanly when a

browser blocks an asynchronously opened tab.

Update — 2026-08-24

24 August 2026

24 August 2026

Safer payments and recoverable provider work

  • Card and Direct Debit collection now share one invoice-level authority. A

short reservation/dispatch lease prevents two rails from collecting the same balance while allowing an abandoned pre-dispatch attempt to expire safely.

  • Once provider dispatch starts, retries keep the same frozen operation and

provider idempotency key. Verified webhook/capture evidence heals a lost local response without creating a second payment.

  • Issued credit notes are reflected consistently in payment pages, portal

balances, reminders and provider collection. A credit cannot be issued while a collection is actively dispatching or linked, avoiding silent amount drift.

  • Provider settlement records the exact event that completed it. Exact replay is

harmless; conflicting terminal events are held for staff reconciliation.

  • Free-event waitlist promotion remains available to booking managers. Paid

promotion and invoice repair require the separate effective financial permission, with the final free/staff decision enforced by the locked database authority.

More honest consent, audit and permission behavior

  • Member email suppression now uses the canonical suppression ledger throughout.

If consent or suppression cannot be established, no message is sent and the work remains visible for retry or review.

  • Turning off portal push notifications is shown as complete only after both the

server subscription and the browser subscription are removed successfully.

  • Attendance summary recalculation no longer creates duplicate member history,

while a genuine attendance change still produces one redacted forensic audit record.

  • Member pause recovery lifecycle triggers can no longer be called directly by

application roles; their authority is limited to the database trigger path.

  • Live grading-group changes require the effective grading permission, validate

the complete event set and update examiner state atomically.

  • Voice Notes and class recording are fully removed, including their API,

settings, registry and test surfaces.

Update — 2026-08-23

23 August 2026

23 August 2026

Security and privacy hardening

  • Communications AI now checks contact details carried inside safe email link

attributes as well as visible copy, before provider dispatch and before a generated result can reach the editor.

  • Staff email-OTP proof cookies now use a dedicated secret rather than sharing

the cron bearer key, with an explicit short-lived compatibility switch for a controlled production rotation.

  • AI drafting reservations that expire before provider dispatch release their

monthly allowance; dispatched or ambiguous calls remain terminal evidence.

  • Club Insights allowances now follow the Europe/London calendar month, and an

expired pre-dispatch reservation no longer consumes a report run.

  • Club Insights programme reports now start every membership movement at zero

when the selected programme has no members, and independent club reservations no longer queue behind one tenant's settings lock.

  • Smart Planning revision history now has exact service-role privileges and a

database immutability backstop.

  • Smart Planning AI metadata retention now uses one captured 24-month timestamp

boundary in the nightly sweep; activity usage no longer triggers retention deletion and club removal cannot silently erase the ledger. The sweep drains repeated bounded batches and reports a failing cron health signal with an exact residual count if the time/batch ceiling leaves a backlog.

  • Email and SMS suppression checks now fail closed before provider dispatch,

grouped household messages honour every represented member's preferences, and communications-flow checkpoints advance only after complete processing.

  • Attendance-derived member updates no longer create no-op audit churn; the

proposed redaction authority also removes sensitive student payload fields from future audit rows.

  • Voice Notes and class recording have been removed from the product rather

than remaining as a hidden, retired workflow. Historical database rows and private blobs remain covered by GDPR erasure cleanup, and existing API tokens remain visible and revocable without permitting new issuance.

  • Safeguarding timeline entries and grading-session setup now write only through

capability-gated server routes; browser-direct table changes are blocked.

  • Event pricing, waitlist promotion, assessment records, Telegram helpers and

test-push actions now enforce their effective staff capabilities.

  • Portal magic-link credentials are stored as hashes rather than reusable raw

bearer values, and sensitive onboarding edits require step-up MFA.

  • Event cancellation and rescheduling now stop before changing an event when a

booking, grading-outcome or notification-recipient census is unavailable.

  • Club Insights now blocks every provider request for a club or programme with

fewer than ten active members, not only named sub-cohorts.

  • API audit attribution no longer trusts unsigned session or active-club cookie

values; unauthenticated proxy logging is anonymous and volume-bounded.

  • Push unsubscribe and bulk communications now report failed or incomplete

database changes instead of claiming success or silently narrowing a request.

  • GoCardless subscription creation now requires exactly one member or household

mandate subject and refuses oversized provider metadata. An owner-reviewed, fail-closed repair/XOR SQL unit is prepared for any malformed legacy rows; production census and application remain owner actions.

  • The portal login verification page now applies no-store, no-referrer and

noindex policy headers to every redirect. Hash-at-rest migration remains an owner-reviewed apply-before-cutover step, so the credential registry records the current mixed legacy state rather than claiming deployment.

  • DOMPurify and the dev-only Trigger/Prisma deep-merge dependency have been

upgraded to advisory-fixed versions. Secret scanning now has zero current or historical findings using only exact reviewed historical fingerprints.

Safer invoice collection and payment recovery

  • The retired generic member-history endpoint is now a stable no-op conflict

response. Timeline evidence is created by origin-specific server/RPC writers, transactionally where that origin has completed its authority migration.

  • Every invoice now uses one shared collection authority across Stripe and

GoCardless, so card and Direct Debit cannot both be prepared for the same outstanding balance.

  • Issued credit notes are deducted inside the database immediately before a

collection is reserved. Automated, staff and member collection paths all use the same post-credit pence amount.

  • Provider-success/local-link failures recover the same payment on retry rather

than creating a second collection.

  • New GoCardless invoice payments send only the opaque AllSorted club and

invoice identifiers as provider metadata. Recovery adopts a conflicting provider object only after exact immutable-field and metadata comparison.

  • Legacy Stripe captures with missing invoice metadata are counted and locked

across every invoice status; zero, ambiguous and terminal bindings create a staff reconciliation finding instead of guessing or broadly marking paid.

  • Reconciliation closes only the exact finding kind that was repaired, failed

tenants or phases make the scheduled run red, and Stripe warning-only dispute closures no longer reopen a settled invoice.

  • Event waitlist promotion now uses one database authority across paid member,

free public, staff and invite paths. A captured payment that loses the final place reserves its exact refund before any other path can promote the booking; active refund holds, demo clubs and terminal events fail closed.

  • Staff-promoted paid event bookings now create one recoverable issued invoice.

Cancelling before collection creates one exact issued credit note—including the frozen VAT treatment—before the invoice and booking are closed.

  • External-event settlement now proves and locks the canonical entry, pair,

division and tenant set before atomically settling the invoice. Issued credits are honoured, exact capture replays return frozen evidence without rewriting history, and mismatches are held for staff review with clear do-not-pay-again copy rather than asking the payer to retry.

  • External-event cancellation, organiser rejection and division replacement now

stop with clear active-payment guidance while a provider dispatch is reserved; they send no refund, replacement booking or rejection email on that blocked path.

  • Stripe invoice success now treats an unprovable invoice as retryable and a

durably recorded money mismatch as terminal review. Neither case can leak into booking, membership-card, insurance, task or notification success effects.

  • Manual invoice creation and editing now send exact integer-pence inputs to one

activity-aware SQL transaction. VAT policy, controlled overrides, line/header totals, audit adjustment and member history either commit together or not at all; pre-SQL application code fails closed with no table-write fallback.

  • Communications-flow enrolment now scopes ranks through their owning belt

system instead of querying a non-existent rank tenant column, preserving the club boundary while allowing the enrolment check to complete.

  • Add-on trial starts now use one atomic club/module claim. A failed authority

read or write stops the request, concurrent first-use attempts produce one trial, and an authorized restart remains distinguishable in the audit trail.

  • Database-mutating runtime proofs now run only through the preflighted isolated

database class. Ordinary Vitest discovery cannot fall back to the shared local Supabase stack.

Optional AI writing in Communications

  • Communications now offers an optional Draft with AI assistant alongside

the existing manual editor. Clubs can create a coordinated email, SMS and Telegram draft from one brief or improve the message they have already written.

  • The writing assistant returns editable content only. A staff member must explicitly choose

Use this draft, and AllSorted's existing review step still applies before any message can be scheduled or sent.

  • Email presentation remains under the club's control: the assistant writes safe,

semantic content while the selected saved email style is applied locally by AllSorted. Attachments and reusable snippets are left unchanged.

  • Before a draft is used, the review now clearly labels and shows the proposed

email subject, inbox preview text and rendered message. Email results missing any of those three parts are rejected rather than shown as complete.

  • The assistant uses the same purple AI identity and full-screen progress

treatment as Club Insights and Smart Planning, including keyboard and reduced motion support.

  • Recipient lists, member records, contact details, attachments, email skins and

previous communications are never added to the AI request. Allowlisted merge tags are protected during drafting, and input and output pass local privacy checks before a result can reach the editor.

  • Each club has 300 Communications AI calls per Europe/London calendar month.

The metadata-only usage ledger records draft/rewrite and channel adoption but stores no message content or recipient data.

Pause trials for specific class dates

  • Clubs can now pause new trial bookings for one class date or a selected date

range directly from the calendar, without closing the club or changing the recurring timetable.

  • The impact preview shows the real class occurrences in the range and how many

existing trial bookings will remain in place before anything is changed.

  • Paused dates are clearly marked across calendar views and on the class detail

page. They can be resumed from the same screens.

  • Public trial bookings and reschedules into a paused date are blocked. Staff

can still book by exception, but must deliberately confirm the override and record a reason.

  • Pausing or resuming trials never cancels an existing booking and never sends a

cancellation or other communication.