Changelog

What we shipped, when. Newest first.

Family calendar feeds repaired for external events

4 August 2026

What's new

Family calendar subscriptions work again

  • Family calendar (.ics) feeds had been silently failing whenever a club had

external-event entries: the feed asked the database for a column that has never existed (location instead of the real venue). Calendar apps never show subscription errors, so feeds simply stopped updating.

  • The feed now reads the real venue column, so external events in a family's

calendar finally carry their venue as the event location.

  • A new contract test pins every column the feed selects to the generated

database schema, so a misspelt column in this feed can never again pass the test suite while failing in production.

Secret-scan workflow repaired on pull requests

  • The pull-request secret scan regained the single read permission the new

least-privilege lockdown had removed; scans on pull requests run again.

Release bundle now carries its cancelled-booking grading prerequisite

3 August 2026

What's new

The consolidated database release is self-contained

  • The release bundle now installs the reviewed grading no-resurrection guard

before its multi-rank grading authority.

  • Cancelled grading bookings therefore remain terminal while existing v2 and

new v3 grading flows share the same protected status boundary.

  • The final postflight also checks that all four protected v2 grading functions

still contain the cancelled-booking guard.

Recovery note

  • A production attempt correctly stopped when it discovered the prerequisite

had not previously been applied.

  • Earlier bundle sections are idempotent. Recovery is to run the corrected

bundle in full and then re-run the post-deploy Form Builder authority file.

  • No remote SQL was applied by an agent.

Scheduled sends recovered and a database census added

  • Scheduled communications stalled in "processing" after the release because

the outbound-provider lifecycle unit was missing from the deploy bundle; the worker deliberately refused to send anything it could not durably record, so nothing was delivered twice or lost. The owner applied the reviewed unit and the queue drained on its own.

  • A read-only applied-state census

(docs/ops/applied-state-census-2026-08-03.sql) now fingerprints every proposed database unit — 96 units, 411 catalogue checks — so the owner can verify at any time which units a database actually has, with missing-but-code-referenced units surfaced first.

  • The census is generated from the repository, contains only SELECT

statements, and was validated end-to-end against the local stack. No remote SQL was applied by an agent.

Security boundaries strengthened across the application

  • Sensitive staff routes now require a strong, session-bound login and enforce

the club's effective permissions consistently.

  • Private files, reports, grading records and payment-plan selections are

checked against the active club before use.

  • HTML previews cannot run scripts or contact external sites, while logs,

browser caches and monitoring data now receive stronger member-data and credential scrubbing.

  • Outbound downloads, uploads and webhooks have tighter redirect, file-type,

size, account-binding and retry-safety controls.

  • Repository secrets, package advisories and CI dependencies are now checked by

strengthened automated security gates. No remote configuration or SQL was applied; the additive proposed SQL remains owner-controlled.

  • The Stripe request-budget guard no longer shells out to ripgrep, so the full

verification battery runs green on any development machine, not only on CI runners that ship the binary.

  • The secret-scan workflow regained the one read permission it needs to list a

pull request's commits; the new least-privilege lockdown had removed it, which failed the scan before it could run rather than weakening it.

  • The route security registry was re-verified for the two routes this patch

hardened further (external-event updates now validate document storage paths; grading-criteria creation is capability-gated with tenant-checked belt systems), keeping the registry staleness guard green.

Provider, token and tenant boundaries tightened again

  • Stripe and GoCardless webhook deliveries now have exclusive, recoverable

database claims; late GoCardless events cannot overwrite newer provider state.

  • All supported payment creation is tied to a named, server-priced operation.

The old generic client-priced fallback has been removed.

  • Provider calls now share explicit time, redirect and size limits. Uploads of

coach review clips are inspected and bound to the exact club, coach and submission before they can be attached.

  • Remaining foreign-versus-missing response differences were collapsed, and

YouTube/Vimeo embeds now require exact provider host names.

  • Legacy calendar and public-token storage has a guarded retirement path. It

cannot run until a 45-day, actively measured zero-use window has completed.

Security-wave review repairs

  • GoCardless mandate and subscription ordering functions now validate only

their own identities; the disposable rehearsal executes the functions rather than accepting catalogue presence as proof.

  • Batched or already-current mandate events still run the necessary idempotent

switch-bank and cancellation side effects, while a recovered active mandate cannot emit a false cancellation alert.

  • Retrying an abandoned Direct Debit setup now recovers the existing billing

request named by GoCardless and opens a fresh hosted journey instead of returning a generic error.

  • The isolated 55321/55322 rehearsal applies both webhook SQL units twice,

executes all eight authorities, runs real two-worker claim races and resets the disposable database before the standard database lane.

  • The release checklist now records the four SQL-before-code units, environment

decisions, production read-only probes, atomic deployment boundary and the explicitly deferred plaintext-token cleanup.

One-paste security-wave database bundle

  • The four reviewed SQL-before-code units are now available as one generated,

Supabase SQL Editor-safe bundle in their required order.

  • A single abort-before-writes preflight checks the shared prerequisites, while

a consolidated postflight requires all four units and their service-only authority boundaries to pass before deployment.

  • Source hashes prevent the bundle silently drifting from the reviewed SQL.

Plaintext-token retirement remains explicitly excluded until its measured 45-day observation gate and owner approval are complete.

Production assurance has started

  • The owner confirmed the security revision is live and supplied the complete

4/4 production database postflight.

  • Passive production checks confirmed private/no-store, no-referrer and noindex

behaviour on representative public-token routes without using a real token.

  • Fresh npm and OSV checks report no known application-package vulnerabilities,

and the local secret scan found no credential.

  • The newer local Supabase container set still carries upstream package

findings, so that supply-chain item remains open rather than being hidden by the successful database rehearsal.

  • The Phase 11 checklist now separates completed installation evidence from the

controlled two-club, browser, upload, provider and Sentry smokes still needed. Plaintext-token cleanup remains prohibited until the full observation window ends on or after 18 September 2026 and every zero-use gate passes.

Public forms stay available through the lifecycle rollout

2 August 2026

What's new

Public submissions now tolerate both release schema states

  • Public form submission uses the immutable published-version rules once the

form lifecycle columns are present.

  • During the short pre-deploy or rollback window before those additive columns

exist, legacy non-archived forms continue to accept responses instead of appearing missing.

  • Permission, database and unexpected read failures remain fail-closed; only a

recognised missing-column response uses the legacy compatibility query.

Verification note

  • The DB-14 service-write authority fixture now adapts to the pre- and

post-lifecycle schemas without weakening its RLS, grant or public-submission assertions.

  • No remote SQL or deployment action was performed by this repair.

Explainable attendance attention is ready for local review

1 August 2026

What's new

Report totals and failure states are now trustworthy

  • Financial reporting now includes invoices created before the selected period

when they were paid or refunded inside it, and includes every instant on the selected final club-calendar day.

  • Membership month charts no longer shift or duplicate months around British

Summer Time. Programme attendance now follows the programme recorded on each register mark, with a lesson fallback only for older rows that predate that snapshot.

  • Insurance records with no expiry are shown separately as No Expiry Set

instead of being counted as expired. Programme-scoped insurance and renewals also fail closed when their membership lens cannot be loaded.

  • The Communications automation breakdown now loads rule metadata separately,

avoiding a broken embedded relationship, and its adoption snapshot can no longer turn an unavailable response into believable zeros.

  • Renewals, communication activity, waiting lists, scheduled reports, portal

analytics and schedule insights now show an explicit load error when a required read fails instead of presenting an empty report.

  • Current-state reports now say what they cover instead of displaying a date

picker they do not use. Counts that deliberately include both active and new members are labelled Current Members; the Membership report retains the stricter Active Members label.

Report custom ranges now apply exactly as selected

  • Reports that support a shared date range now use visible native date fields,

so staff can either choose from the calendar or type both dates before applying the range. Invalid, incomplete and reversed ranges are blocked with an inline explanation.

  • Preset boundaries now use the club calendar date instead of converting local

midnight through UTC, preventing the first day of a British Summer Time month from appearing as the previous day.

  • Reports with their own fixed period no longer show a misleading shared picker.

Their header now names the period they actually use, such as rolling overview, next 90 days or current timetable.

  • On phones, the From and To fields stack at full width so the entered dates and

native calendar controls remain readable without horizontal scrolling.

Local help-video review now reflects the current production line

  • The loopback review workspace now condenses every help guide into one card.

Opening it reveals an explicit Script sign-off followed by a separate Video sign-off, so approved wording is no longer confused with approval of the rendered visuals, narration and captions.

  • Script decisions can now be completed from the local page, including the

complete-beginner checklist and precise change requests. They are stored in the script-review registry; video decisions remain in the video registry. Neither action publishes anything.

  • The audio-only check now says Listen to just audio instead of carrying a

narrator name from the retired Emma proof, and the review page no longer calls the current 1080p Forms-and-Settings collection a 720p Forms-only batch.

  • Four review-sized settings batches are now scheduled. The next batch is

Deliverability, Memberships, Invoices & VAT and Payments; later batches cover club/progression foundations, member operations and specialist operations.

  • Rendering remains paused while the current six Settings drafts await owner

decisions. Scripts must pass the beginner-content gate before any narration or rendering, and no local approval publishes an asset.

Credential-renewal releases no longer depend on SQL landing first

  • The application now keeps the existing insurance fee, link and portal-renewal

journeys working when the additive configurable-credential columns have not reached an environment yet. Previously, the first configuration read could fail every renewal request during that release window.

  • Previously issued renewal links also retry against the legacy token shape, so

an old link remains usable before or after the additive token columns arrive.

  • Settings continues to load and save the established annual-requirement fields

in that window. Configurable online-renewal controls remain hidden, and a new client attempting to save those controls receives a scrubbed unavailable response instead of silently losing configuration.

  • Compatibility is deliberately narrow: only errors that name one of this

migration's additive columns use the legacy path. Permission, tenancy and unexpected database failures continue to fail closed.

Deployment note

  • Code-first and SQL-first deployment are both supported. Apply

supabase/_proposed/configurable-credential-renewal-01.sql before enabling a club's configured renewal journey; the proposed SQL remains unapplied to any remote environment by this work.

Attendance changes can become clear, manageable follow-up

  • The local Action Centre can now explain when an active member attended at

least four of six active weeks and then none of the latest three.

  • Each item shows the member, the exact arithmetic, the threshold and the rule

version. Closure weeks, incomplete registers and missing history never produce a signal.

  • Authorised owners can assign an item, snooze it with a reason and date, choose

an exact resolution outcome and inspect its in-app history. Re-attendance or a paused/ended membership can resolve the same occurrence automatically.

  • Future snoozes stay out of the current attention list while remaining linked

to source recovery.

Noise and privacy controls are built in

  • A club can receive no more than three new retention items in a day and hold no

more than ten active items. Extra candidates stay measurable for review rather than being discarded.

  • Retention attention has separate owner-first permissions and every server read

reasserts the signed-in club. Foreign and missing identifiers look the same.

  • Retention items are in-app only and are explicitly excluded from daily email

and Telegram Action Centre briefs.

Deployment note

  • The forward-history and retention occurrence SQL is additive, proposed and

rehearsed against the existing local Docker database only. Reapply, authority, tenant-isolation, deletion, lifecycle and concurrent-cap checks pass.

  • No production SQL, feature flag, pilot row or notification was applied or sent.

A real CWTKD pilot remains owner-controlled and requires nine trustworthy completed weeks, two shadow weeks and the documented six-week review gate.

Help videos — full-width 1080p treatment and owner voice (local drafts)

  • All six Forms guides re-authored to the owner-approved full-width treatment:

the real product screen fills the frame (fresh 1600×900 Vertical Test Club captures, dev chrome scrubbed), camera-follow zoom anchored on measured click targets, and settle-then-hold idle scenes that keep 1080p files small.

  • Narration switched from the Kokoro bf_emma voice to the owner's own cloned

voice (Chatterbox, MIT-licensed, fully local, Perth-watermarked as synthetic). The reference recording lives only in the gitignored drafts area and is never committed. Same reviewed guide texts; captions and transcripts regenerated from the new timings; scene durations retimed to the new take.

  • Production renders bumped to 1920×1080 (H.264 CRF 22 slow fast-start MP4 +

VP9 WebM archival). Registry entries re-pointed at the new assets with updated durations, captures, voice and resolution metadata; all six reset to local draft for owner review on the loopback approval page.

  • New tooling: scripts/help-video/capture-form-help-screens.ts (session-mint

capture printing measured control boxes) and scripts/help-video/generate-chatterbox-narration.py (drop-in narration sibling emitting the same wav/timings/transcript artefacts). remotion.config.ts added so the bundler resolves the @/ alias (rendering was broken without it once the help catalogue gained value imports). Narration regenerates only when guide text changes — visual re-renders reuse the approved take. Owner review stays local-only per ODR-020; publication stays the ODR-021 path.

Settings help videos — Terminology guide produced (local draft)

  • First settings guide off the production line: Terminology

(settings.terminology.flip, guide key terminology), authored in app/lib/help/settings-video-guides.ts with copy verified against TerminologyTab, app/lib/terminology.ts and the guarded /api/settings/terminology route: saved words re-word the app and member portal straight away; some Settings screens deliberately show neutral labels (for example "Stages") until configured; certificates and emails keep their own template wording and issued documents are never rewritten.

  • New read-only capture script

scripts/help-video/capture-terminology-screens.ts (sibling of the Forms capture script; nothing typed or saved). Choreography is a two-target point-and-zoom over the member-term field and the Live preview card — no click ripple, because the capture is a single still.

  • The full-bleed screen chip now reads "Real settings screen" and the header

area label follows the guide's area (Settings vs Form Builder). Terminology fields gained stable element ids (terminology-group-people etc.) so contextual help "Show me" can target them.

  • Rendered 1080p in the owner's cloned voice and registered as local_draft

(settings-terminology-v1-chris.*) awaiting owner review; nothing published.

Settings help videos — Closed Dates guide produced (local draft)

  • Second settings guide off the production line: Closed Dates

(settings.closures.dates, guide key closures), authored in app/lib/help/settings-video-guides.ts with copy verified against ClosuresTab, the guarded /api/settings/closures route and app/lib/engagement/expected-opportunities.ts: closed dates are excluded from expected attendance (register day-snapshot, attendance-break weeks and the consistency denominator all skip them — a closure is never counted against a member); closed days stop taking trial and portal session bookings; after adding a closure the Affected Bookings check lists enrolled students and booked trials, regulars notification sends one idempotency-keyed email per member per missed class (Lesson Cancelled automation template or built-in default), and cancelled trials each get a reschedule-link email. Closures touch no billing or invoicing code, so the guide says nothing about money.

  • New read-only capture script

scripts/help-video/capture-closures-screens.ts (the seeded club has no closures, so the Add Closure panel is opened client-side to frame the add form — nothing typed or saved). Choreography is a two-target point-and-zoom over the Start Date and Reason fields — no click ripple, single still. The add-closure controls gained a stable element id (closures-add-controls) for contextual help "Show me".

  • Rendered 1080p in the owner's cloned voice and registered as local_draft

(settings-closures-v1-chris.*, 27.6s, 5.2MB) awaiting owner review; nothing published.

Settings help videos — Timetable guide produced (local draft)

  • Third settings guide off the production line: Timetable

(settings.lessons.timetable, guide key timetable), authored in app/lib/help/settings-video-guides.ts with copy verified against TimetableTab, the guarded /api/settings/timetable route, TimeRangeField and app/lib/time-range.ts: the class editor derives the finish from a start + length (an inverted range is unrepresentable), a class past midnight shows "(next day)" and finishes tomorrow — an end time earlier than the start is a supported overnight class, never an error (the route re-checks with allowOvernight, and classLiveStatus keeps an overnight class's attendance on the day it started). The timetable feeds each day's register (day-snapshot queries lessons by weekday), the calendar, trial/bookable-session booking and expected attendance; edits apply to registers going forward and never rewrite recorded attendance. The timetable touches no billing code, so the guide says nothing about money.

  • New read-only capture script

scripts/help-video/capture-timetable-screens.ts: the timetable with the first class row hovered (revealing the Edit quick action), then the class editor reached by clicking that Edit link — the editor's mount path is pure reads, nothing typed or saved. Choreography is a click-through (Edit → class editor) with a second zoom on the time pair — the Starts at input, duration chips and "Runs …" summary — while the narration states the overnight rule. The Add Class control gained a stable element id (timetable-add-class) for contextual help "Show me".

  • Rendered 1080p in the owner's cloned voice and registered as local_draft

(settings-timetable-v1-chris.*, 31.8s, 6.2MB) awaiting owner review; nothing published.

Settings help videos — Annual Requirements guide produced (local draft)

  • Fourth settings guide off the production line: Annual Requirements

(settings.requirements.credentials, guide key requirements), authored in app/lib/help/settings-video-guides.ts with copy verified against RequirementsTab, app/lib/credential-renewal.ts, app/lib/insurance-renewal-configuration.ts and the guarded /api/settings/program-requirements route: activation is fail-closed — normaliseCredentialDefinition forces portal renewal and automation off whenever readiness fails, the route rejects early enablement, and the portal read side re-checks readiness before serving a definition, so the switches only take effect once every field is complete (and automation cannot be on without the portal flow). The annual cost set here is the amount families pay at renewal (amount_pence is pinned into each renewal token), and the renewal window is both how early families can renew in the portal and when chasing starts.

  • New read-only capture script

scripts/help-video/capture-requirements-screens.ts: the seeded club has no requirement definitions, so the "+ Insurance" preset create form is opened client-side and scrolled to the Activation section — the preset leaves exactly one setup item missing, so the frame shows both switches rendered disabled above the amber "Activation is locked until: …" line. Nothing typed, nothing saved, switches never clicked. Choreography is a two-target point-and-zoom over the Valid for (days) field and the locked Member portal renewal switch — no click ripple, single still. The definition editor gained a stable element id (requirements-definition-editor) for contextual help "Show me".

  • Rendered 1080p in the owner's cloned voice and registered as local_draft

(settings-requirements-v1-chris.*, 29.2s, 4.5MB) awaiting owner review; nothing published.

Settings help videos — Modules & Programs guide produced (local draft)

  • Fifth settings guide off the production line: Modules & Programs

(settings.modules.enable_vs_entitle, guide key modules), authored in app/lib/help/settings-video-guides.ts with copy verified against ModulesTab, the guarded /api/modules route and the shared capability core (app/lib/capabilities-core.ts): enablement and entitlement are two independent axes — the resolver fail-closes on the commercial gate before consulting club_modules/program_modules, so a feature's screens appear only when the account includes a module AND it is switched on (a switched-on but not-included module shows the "Not active" chip and stays hidden). The state vocabulary (Included / Granted / Active / Available / Not available — contact support) is narrated for the two states in the capture and covered in full in the dialog sections, the "switches control access only and never create a charge" rule is stated verbatim (no pricing or upgrade actions exist in the tab by design — commerce lives in Your Plan), and completed setup wizards flipping "Set up progression →" to "Progression settings →" (re-running the wizard IS the edit surface, read from module_setup_runs) carries the impact scene.

  • New read-only capture script

scripts/help-video/capture-modules-screens.ts: the settings content pane is scrolled 200px so one frame holds both teaching surfaces — the "Your enabled features" entitlement strip (the seeded club's Included + Granted chips, with the no-charge footer line legible) and the first program card's per-program switch cluster. The module switches write on click, so the script only asserts their presence and never clicks; wizard links never clicked. Choreography is a two-target point-and-zoom over a Granted chip and the first card's switch cluster — no click ripple, single still. The entitlement strip gained a stable element id (modules-enabled-features) for contextual help "Show me".

  • Rendered 1080p in the owner's cloned voice and registered as local_draft

(settings-modules-v1-chris.*, 32.2s, 5.6MB) awaiting owner review; nothing published.

Settings help videos — Roles & Permissions guide produced (local draft)

  • Sixth settings guide off the production line: Roles & Permissions

(settings.roles_permissions.pilot, guide key roles_permissions, an owner-only tab), authored in app/lib/help/settings-video-guides.ts with every stated behaviour verified against RolesPermissionsTab, the deterministic resolver (app/lib/permission-resolver.ts), the two-key pilot gate (app/lib/custom-rbac-gate.ts) and the permission API's shared save-path helpers (app/api/settings/permissions/_lib.ts): changes take effect only when the club joins the controlled pilot (environment master AND per-club flag, exactly the staged-pilot banner's promise); an individual deny beats every grant; provider connect and platform checkout are system-locked — presets are built to refuse them and the resolver ignores every override layer for locked capabilities; and every save runs the owner-lockout simulation, refusing (409) any change that would leave no owner able to manage permissions and staff. Presets-first is the recommendation, with the reason-required rule for high-risk/sensitive presets covered in the dialog sections.

  • New read-only capture script

scripts/help-video/capture-roles-permissions-screens.ts: one frame holds both teaching surfaces on the default Presets sub-view — the pilot banner (asserted verbatim so the capture fails loudly if enforcement ever goes live for the seeded club) and the top preset cards with risk chips (Billing Manager High with the system-locked exclusion note, Refund Manager Critical + Reason required). Preset assignment controls write, so nothing is clicked or toggled. Choreography is a two-target point-and-zoom over the banner and the Billing Manager card — no click ripple, single still. The presets grid gained a stable element id (roles-permissions-presets) for contextual help "Show me".

  • Rendered 1080p in the owner's cloned voice and registered as local_draft

(settings-roles-permissions-v1-chris.*, 32.2s, 6.1MB) awaiting owner review; nothing published. The production line now pauses at six settings drafts pending owner review.

Help-video scripts now stop before expensive production

  • Added a fingerprinted script-review gate before voice generation and video

rendering. Each guide must first pass a beginner checklist covering its purpose, recommended default, real on-screen action, automatic versus optional consequences, important boundaries and code-verified accuracy.

  • Any relevant wording or product-code change makes the approval stale, and an

unreviewed or change-requested script now stops before the voice model or Remotion starts. The Audience, Closed Dates and Timetable scripts passed the new gate; Closed Dates now makes optional family notifications explicit, and Timetable describes the actual start-time-plus-length control.

Household, member, arrears and calendar audit fixes

  • Calendar date headings still open the complete day agenda, while lesson and

event cards in month, week, day, agenda and search views now open their detail directly. The day route keeps the chosen item in a validated query parameter, resolves it only against the club-and-date-scoped payload, and shows a generic unavailable state for stale, malformed or foreign identifiers.

  • Reworked the full-page calendar day layout into a responsive agenda/detail

view with a compact mobile header, a clear Back to day action, visible load failures and no second click before bookings, trials or register actions.

  • Household and member reads now clear club-owned browser state before a club or

record switch, reject partial/failed snapshots instead of showing false empty states, and surface retry or truncation notices where totals and exports would otherwise be incomplete.

  • Arrears is now capability-gated, paged to completion, calculated in club-day

boundaries and net of issued credit notes. The same integer-pence balance is used on household summaries and manual/automatic Direct Debit collection, so a partially credited invoice collects only its remaining balance and a fully credited invoice cannot be collected.

  • Removed the unsafe household-wide “mark paid” mutation. Staff now open the

household and settle each invoice through the existing reasoned, audited action; provider-linked invoices remain in their provider lifecycle.

Multi-rank grading awards ready for owner review

  • Grading events can now award any higher rank in one ceremony while preserving

every crossed rank as its own ordered progression record and certificate. The confirmation screen names the full award path and certificate count before anything is committed.

  • Confirmation, correction and undo replace the full chain atomically. Every

certificate shares the grading issue date, progression anchors at the final rank, and member activity/automation runs once with the start and final ranks rather than once per certificate.

  • Event/session PDF batches, background rendering, portal certificates and the

member-experience feed now use one service-only award ledger row per rank. Manual rank changes remain single-hop and do not create grading certificates.

  • This is an SQL-first release: owner review and application of the consolidated

supabase/migrations/_DEPLOY-2026-08-02-release-bundle.sql must precede the app deployment. Local apply/reapply, catalogue postflight, five-rank runtime rehearsal and simultaneous-confirm concurrency coverage are green.

One database bundle now prepares the complete release

  • The owner now has one pre-deploy psql artifact covering configurable

credentials, editable trial answers, immutable form versions, multi-rank grading and the register/retention database foundations required by this branch. A prerequisite and legacy-certificate preflight runs before any section can write; recovery is always a complete re-run.

  • Form Builder's direct database privilege closure remains a separate,

clearly-named post-deploy file because the guarded server build must be live first. Neither SQL file enables a feature flag or retention pilot.

  • Reapplying the bundle can no longer stamp published_at onto live form drafts.

Certificate PDF batches also stop and name every rank missing a renderable template instead of silently returning an incomplete multi-rank batch.

Form and course builders now stay clear on smaller screens

31 July 2026

What's new

Course building now fits phones and tablets

  • The course outline and lesson editor now stack within the available screen

width on phones and tablets instead of forcing the whole page sideways.

  • Long lesson and section names shrink or wrap inside their own cards while

edit, reorder and row-action controls remain reachable.

  • Save lesson now uses the same clear, full-width mobile action treatment

as other protected save controls.

Trial booking keeps the next decision in view

  • Moving between the audience, class selection and booking-detail stages now

returns to the top and focuses the new heading for keyboard and screen-reader users.

  • Once a class is selected, the other class cards collapse and the date chooser

sits directly underneath. A clear Change class action restores the list.

  • Template descriptions that include a step count now use the number of steps

in the real rendered journey, including Allsorted's protected detail stage.

Forms are clearer and more accessible

  • Forms now warn before unsaved builder changes are lost through the Forms back

action, browser Back, ordinary navigation, refresh or tab close. Staying keeps the editor exactly as it was; leaving discards only the current local edits.

  • A small help control beside Form Builder now opens a concise in-page guide

explaining built-in journeys, steps, preview, drafts and publishing without taking users away from unsaved work.

  • The local Forms help-video review page now lets the product owner approve each

guide or save a specific change request directly into the versioned registry. It is bound to the local machine and has no production or publishing path.

  • Approved help videos now have a separate independent-review and release path.

Reviewed assets use immutable version URLs, while a checked-in manifest selects exactly one active version and retains the previous version for 90-day rollback.

  • Production video playback remains hidden until the owner separately creates the

reviewed storage bucket, uploads the assets and deploys the resulting manifest.

  • The revised Overview guide now demonstrates opening a captured form, loading

its editor and saving successfully. The Audience guide zooms into the relevant selector and shows the recommended whole-club choice, so both videos teach the action instead of relying on narration alone.

  • The pilot guide records non-sensitive opens and helpful/not-yet feedback so it

can be evaluated before help controls or videos are added elsewhere.

  • Opening or changing a form resets the independently scrolling Settings

workspace so the form name, status and save actions are never hidden above the viewport.

  • Mobile form building now uses a compact labelled step selector with dedicated

reorder controls instead of an easily missed horizontal card carousel.

  • Public and preview forms now connect labels, hints and errors to their

controls, mark invalid answers programmatically and focus the first problem when Next or Submit is pressed.

  • Unsaved-change protection now also covers automation, course and certificate

builders, communication and event editors, plus membership, program, timetable and venue settings. Browser Back, Cancel and ordinary navigation all use the same clear stay-or-leave choice.

Communication templates stay contained

  • The Templates header and Communications navigation now wrap within a phone

viewport, keeping the New Template action visible without page-level horizontal scrolling.

  • Automation-draft choices now include trigger, status, update date and a short

reference for untitled drafts, preventing otherwise identical options from being confused.

Actions now explain what is happening

  • Shared row actions now use the in-app confirmation dialog for consequential

work instead of handing control to the browser's native prompt.

  • Calendar, household, reporting, automation and grading workflows now present

confirmation, progress and failures through the same application language.

  • Toast messages queue cleanly, avoid duplicate messages, remain available

while hovered or focused and keep urgent failures visible for longer.

Mobile operational screens are easier to control

  • The staff wall chart can return directly to today, keeps that date in view

and shows when more of the chart exists off either edge.

  • Register calendar controls, grading-event actions and staff approval controls

now have phone-safe touch areas without making the desktop layouts bulky.

  • Shared horizontal navigation keeps the active destination visible and adds

subtle edge cues where more destinations can be reached by swiping.

Backlog and audit status is current

  • The canonical backlog now distinguishes completed source work from the

browser, independent-review and production evidence that is still owed.

  • Role, security, launch and UI audit documents now preserve their historical

findings while clearly identifying the current implementation authority.

  • The ten-phase programme now has a source-linked registry for all 126 normative

requirements and a shared product grammar. A build guard prevents an item, source hash or acceptance dependency from disappearing silently.

Member history now tells the truth about missing data

  • The member Timeline combines activity, attendance, progression, messages and

communication flows through one tenant-validated server read model.

  • Read failures now appear as partial or unavailable history instead of looking

like the member has no records. Older entries load through stable pagination.

  • Message recipient/content and billing activity respect their additional

effective permissions; stored message previews remain network-isolated.

  • The attendance-health foundation explicitly treats current roster history as

insufficient for retention alerts. No retention alert, notification or pilot flag has been created or enabled.

  • A proposed forward-only class-assignment history now records future roster

additions, removals and re-additions without pretending legacy assignment timestamps prove the past. Cross-club assignments fail closed and the history remains client-immutable.

  • Register entry remains fast: every expected regular member starts on Absent,

so staff normally tap only Present or Late. Before submission that visible default is still draft state, and failed saves restore it accurately.

  • Submit & Lock now states the exact untouched count, then one service-only

transaction records those members as explicit Absences and creates the lock. Existing marks are preserved, repeat seals are idempotent and a database guard rejects post-seal attendance writes, including concurrent late arrivals.

Deployment note

  • The interface work remains application-only. The optional help-video release

path adds supabase/_proposed/help-video-public-storage-01.sql; it has been rehearsed against the existing local Docker database only and has not been applied remotely.

  • The register-finalisation application code requires

supabase/_proposed/register-default-absence-finalisation-01.sql first. Its apply, roster materialisation, idempotency, lock guard and exact service-only authority checks passed against the existing local Docker database only; it has not been applied remotely.

  • Deploying with the empty release manifest is safe and keeps written help

unchanged. A production video requires separate owner-run bucket SQL, explicit service-role upload and deployment of the reviewed manifest. No new environment variable or feature flag is required.

  • The programme registry and member Timeline changes are application-only. They

add no migration, environment variable, feature flag, cron or remote operation.

  • Forward class-assignment capture requires

supabase/_proposed/member-class-assignment-history-01.sql before any future detector may read it. It has passed apply, reapply, lifecycle, tenant and ACL rehearsals on the existing local Docker stack only; it is not applied remotely and no application code consumes it yet.