---
title: Changelog
description: Every release, every fix, every format change. What we shipped and when, in plain language for facility owners.
canonical_url: "https://www.collectivecadenceburden.com/changelog"
last_updated: 2026-08-13
---

## CCB AI Foundation

*2026-08-13*

- The platform now has a shared, typed boundary any future AI capability can use to talk to a model — every AI feature will inherit the same structured-output contract, the same stable error codes, and the same audit surface, so customers see consistent behaviour as AI features land.
- The boundary ships disabled in this release — no real AI processing is happening yet and no Athlete or Facility data leaves the platform; activation requires an explicit go-live step that is governed by the platform's privacy and processor controls.
- The first time a future AI capability activates, it will route through this boundary automatically — model output is validated, errors are typed (timeouts, rate limits, invalid output, provider errors are never silently swallowed), and the architecture test fails the build the moment any browser code tries to import the boundary.
- AI failures cannot corrupt existing behaviour — if the model is unavailable, timeouts out, returns malformed output, or is rate-limited, every existing Session, Race Practice, Competition, and Facility flow keeps working exactly as before because the architecture test forbids any core platform module from depending on the AI boundary.

## FIT Heart-Rate Import

*2026-08-10*

- Athletes can now upload a FIT activity file from their watch to see how their heart rate changed across stations and phases during a completed Session.
- Per-station summaries show coverage indicators — stations without enough heart-rate data display "coverage unavailable" instead of a misleading number.
- Removing the FIT import keeps the original CCB session result intact and deletes only the imported heart-rate data.
- Re-uploading the same file is safe — the platform recognises the file and surfaces the existing import without creating a duplicate.
- Heart-rate data stays private to the athlete; it never appears on coach, facility, or public surfaces and never affects official CCB results.

## Athlete Analytics

*2026-08-09*

- Each athlete now has a private `/me/analytics` view that splits Overall CCB Activity, Race Practice performance, and Group Training exposure into their own lanes — every metric is labeled with its context and never silently combines incompatible surfaces.
- Overall Activity counts both Race Practice sessions and Group Training sessions and surfaces an ISO-week streak — a Group Training-only week still counts as activity, so the streak reflects any week the athlete was active in either context.
- Race Practice analytics cover Solo and Team (Duo / Trio) end-to-end: session list, per-station profiles, target hit-rate / trend / variation classifiers, and "where to focus next" insights derived read-only from authoritative `race_practice_*` and `team_race_practice_*` rows.
- The server read model is the authorization boundary: every load filters on `athleteId` directly or transitively via an athleteId-gated `practiceId` set, so cross-athlete access is impossible by construction and no caller-supplied athlete id is ever trusted.
- Analytics is ephemeral by design — no analytics tables, no shared URLs, no third-party surface; page totals and insights are recomputed from authoritative CCB records on every request.

## Unified Operations Backend

*2026-08-08*

- Critical operations across the platform — magic-link auth, athlete joins, session lifecycle, work-phase freezes, penalty rounds, real-time broadcasts, and database writes — now land in a unified operations backend, so the team can correlate incidents end-to-end instead of stitching log lines by hand.
- Email alerts now fire within five minutes for any database failure, real-time broadcast failure, checksum-persistence failure, or work-phase / penalty-round timeout, so an incident doesn't have to wait for a user to report it.
- Browser error reporting is unchanged — the existing consent gate still owns the lifecycle, and the visitor's diagnostics decision is preserved exactly as before.

## Public Agent Readability

*2026-08-07*

- The public site now offers a clean Markdown version of every knowledge page, so AI assistants can read the official source directly instead of scraping rendered HTML.
- A Markdown sitemap at `/sitemap.md` lists every public page in a format AI tools understand, grouped the same way as the public content clusters.
- A curated `/llms.txt` index now points at the Markdown mirrors, not the rendered HTML pages.
- Every public page advertises its Markdown mirror, and `Accept: text/markdown` content negotiation on the canonical URL serves the same Markdown directly to agents.
- Existing privacy, authentication, and crawler boundaries are unchanged — no internal, authenticated, session, invite, recap, or other non-public surface has been newly exposed.

## Strict Content-Security-Policy with nonce

*2026-08-07*

- Every rendered page now ships with a strict, per-request Content-Security-Policy that rejects unauthorized inline scripts, closing a real XSS vector against the session cookie.
- The policy is nonce-based: a fresh random nonce is generated on every request, and the theme script plus every JSON-lD block carry a matching nonce attribute so they survive the strict policy.
- A new architecture guardrail fails the build the moment a future contributor adds an inline `<script>` without stamping the nonce — a CSP bypass cannot ship silently.
- The proxy matcher excludes static asset paths (Next.js bundles, favicon, robots.txt, sitemap, manifest, audio/, static/) so CSP rewriting never adds latency to image and font responses.

## Non-Production Test Dashboard

*2026-08-05*

- Internal testers in non-production environments now have a dedicated dashboard to walk a complete Session lifecycle — deterministic scenarios, real-time observations, and safe cleanup — without touching production or bypassing canonical commands.
- Every dashboard action runs through the canonical state machine; readiness, Athlete readiness, ownership, rotation, Evaluation, and Burden all stay enforced at the same boundaries a Coach and Athlete see in product.
- Dashboard-owned test data carries explicit provenance and can be cleaned up by scenario or by Facility, so no synthetic state lingers across sessions.

## Account Erasure Lifecycle Beyond the Core Transaction

*2026-08-03*

- Advances the eight frozen merge blockers from the implementation-record brief: pre-execution verification + lifecycle + hold gate; truthful + recoverable execution errors; terminal minimization; real anonymous-Athlete + retention mutations; capability-backed authorization; concurrency-safe transitions + idempotency uniqueness; restore-replay production-readiness boundary; truthful documentation. Merge remains blocked until every exported privileged seam resolves its actor from the authenticated server boundary rather than accepting a structurally constructible actor.
- The lifecycle's `executeLifecycleRequest` no longer calls `openAccountErasureRequest` + `executeAccountErasureServer` in sequence — it calls the Candidate 0016 convenience wrapper once and lets the wrapper handle the binding lookup. The lifecycle pre-looks-up the binding (read-only) so the lifecycle-to-Candidate-0016 correlation is durable in the success path.
- For the FIRST-request path (no existing binding), the lifecycle calls the new `reserveAccountErasureRequest` primitive — a narrow public-boundary extension that performs the locked-then-revalidated binding insert WITHOUT running the destructive transaction. The wrapper sees the new binding and resumes against its stored `requestId`. No `openAccountErasureRequest` fires after the reservation; the durable correlation is real on both paths.
- The verified User subject is derived from the lifecycle row (`requesterReference` for alternative-verification, session user for authenticated) — never from the operator's session user id. A privacy operator can execute a different User's verified request without erasing the operator.
- The typed Candidate 0016 refusal discriminator matches the brief's exact spec: only `AccountErasureError` instances with `code === 'erasure_refused'`, `reason !== 'in_progress'`, and a non-empty `blockers` array become `blocked_closed`. Every other surface — `receipt_insert_failed`, `unexpected`, `already_erased`, `in_progress`, ordinary runtime errors — becomes `unexpected_runtime_failure`.
- Authorization is derived from the session-derived actor's `kind`, not from caller-supplied booleans such as `actorIsCurrentFounderOrAuthorized`. `planFacilityOwnershipTransfer` requires the actor as a third argument and refuses when the actor's kind is not `facility_owner` or `facility_authorized_admin`. `recordCandidate0016Correlation` requires a `privacy_operator` actor.
- Privileged low-level functions (`verifyAccountErasureLifecycleRequest`, `closeBlockedLifecycleRequest`, `markLifecycleRequestCompleted`, `recordCandidate0016Correlation`, internal lifecycle reads) are no longer re-exported from `lib/server/account_erasure_lifecycle/index.ts`. The public surface exposes only the authoritative seams, each of which enforces its own actor gate.
- Retention mutations are routed through a per-kind adapter registry with both `inspectForRetention` (authoritative fact source) and `apply` (category-specific mutation). The lifecycle refuses plans whose kind has no registered adapter — a missing adapter MUST NOT silently mark work `applied` without doing the actual category-specific mutation. A re-run returns `noop`.
- The anonymous-Athlete path now consults a server-owned evidence-review record (`accountErasure_lifecycle_anonymous_athlete_evidence_reviews` table) that binds accepted evidence to the exact (Session, Athlete, Facility) triple, an authorized reviewer, and a limited verification lifetime. Athlete row state alone does NOT authorize minimization. The expected Facility is loaded from the evidence record, NOT from caller context — `callerFacilityId: null` cannot bypass Facility scope.
- The Anonymous-Athlete row mutation (`athletes.displayName = 'Deleted participant'`, `athletes.nodeFingerprint = null`, `athletes.userId = null`) AND the receipt insert run inside ONE atomic transaction. The UPDATE's WHERE clause re-checks `userId IS NULL` so a concurrent User-link race is rejected.
- External-obligation transitions use a CAS-shape: the UPDATE pins the expected current status in the WHERE clause so concurrent transitions cannot overwrite one another.
- Restore replay introduces nine focused per-kind handlers; the ledger entry is written only AFTER the handler succeeds. The final handler (`verify_invariant_checks`) verifies the restore-mode marker is still present; the marker is cleared only AFTER the ledger entry is durably written. `isRestoreReplayComplete` validates canonical ordering AND the active-marker state — nine labels being present is insufficient.
- Restore detection consults an authoritative `account_erasure_lifecycle_restore_mode` table. A restored database has exactly one row; the bootstrap's `/api/readiness` fails closed until the row is removed. The `RESTORE_REPLAY_LIFECYCLE_REFERENCE` env var is preserved as a test-only fallback.
- Authoritative blocker loader (`loadAuthoritativeBlockerFacts`) now throws on DB or module-load failure instead of silently returning `[]` — the lifecycle fails closed before invoking Candidate 0016.
- Migration `0011_capabilities_and_verified_subject_user_id.sql` adds authoritative lifecycle capabilities and canonical alternative-verification subject binding. Its generated snapshot retains all 55 schema tables; `drizzle-kit generate` reports no drift.
- Facility restore reconciliation now fails closed while the Facility module lacks authoritative transfer/termination services; unavailable integration can no longer be recorded as successful replay.
- Architecture candidate: docs/architecture/completed/0018-complete-account-erasure-lifecycle-beyond-core-transaction.md · ADR: 0044-account-erasure-lifecycle-beyond-core-transaction.md

## Facility Operations Foundation

*2026-07-30*

- Facility administration, coach roster, and founder screens each get a unified view of equipment, licenses, and open issues; equipment is now sorted into official, substitute, and general.
- Stopping a session, resuming it, and then stopping it again now records two real stop events; if a coach retries the same stop, the app safely treats it as a repeat and ignores it.
- When a coach corrects a session result after an issue was already marked resolved, that open issue is properly closed across the admin, overview, and history screens so nothing lingers.
- Coach handovers and account deletions for the same member can no longer clash — the system handles them one at a time and rejects any action that would not be safe to run while the other is in progress.

## Session Recovery and Ownership

*2026-07-22*

- The Coach dashboard now shows one explicit current Session Owner in the Preparation and Live views, so the room always knows who is running the Session.
- A permitted Coach can hand over ownership to another eligible Coach at the same Box with an optional note; a Founder at the Box can take over when the current Owner is unavailable, with a typed reason.
- After a browser refresh, realtime reconnect, handover, or takeover, a recovery banner surfaces the authoritative phase, round, current Owner, and timestamp — so a Coach can continue from server-confirmed state instead of recreating the Session.
- Stale ownership commands are rejected so two Coaches working in parallel cannot overwrite each other; repeated handovers and recovery commands are idempotent on the Session-scoped command key.
- Athlete recap surfaces are unchanged — Athletes see no Owner / handover detail, only the Session results and closeout they already saw.

## Equipment Issues and Session Closeout

*2026-07-21*

- Coaches can now record an equipment issue from the Live Session and Recap views — station-specific or whole-Session — picking a condition, when it happened, and a short description, without leaving the dashboard or halting the Session globally.
- Each issue carries a typed resolution (reserve the machine, switch athletes to a different machine, record a substitution, mark a result as not official, stop the station, or document a global halt) plus an optional Coach note; closing an issue with the substitution resolution also marks the affected results as non-comparable in the Athlete recap.
- Open issues can stay open after the Session ends for facility follow-up — the Session lifecycle itself is unchanged — and the recap now lists every open item with the action needed.
- A new Session Closeout panel surfaces the operational follow-up status for completed and halted Sessions: a clean signal, an open-items list, or an explicit "not available" label when a required closeout source cannot yet be evaluated.
- Athlete-facing recap pages show the same closeout summary the Coach sees, with no internal notes, peer names, or Coach-only audit fields exposed.

## Result Correction Audit

*2026-07-21*

- A Coach or Founder can now correct a submitted result through an explicit command in the Live Session and Recap views — the original Checksum fact stays immutable, and every correction is recorded as a versioned entry in an append-only audit ledger.
- Each correction carries the original value, the corrected value, the reason, the actor, and the timestamp; corrections stay idempotent on the Box-scoped command key, and stale values are rejected so two Coaches working in parallel can't overwrite each other.
- During Freeze a Session Owner or permitted Coach can correct results directly; after Evaluation the same operation requires Founder approval, and a post-Evaluation correction is flagged as a Burden-review exception so it surfaces for explicit handling instead of silently rewriting history.
- The Coach dashboard now derives per-Station Σ totalReps from the effective (latest correction, or original) values — Recap totals, Audit inputs, and the Coach burden map all stay consistent even after a correction is recorded.
- Athlete-facing recap pages and `/me` history show a neutral "N results were corrected after review" indicator without revealing the internal note or the actor who made the correction.

## Scaling and Result Comparability

*2026-07-20*

- A Coach can now record per-Athlete scaling during Preparation or live Session — official, scaled, or substituted — per Station. The classification is visible in the Session and survives account erasure through the same athlete-keyed rewrite path as every other participant row.
- Scaled and substituted results are clearly marked non-comparable throughout the experience — the live panel renders an amber/rose band per cell, and the Athlete recap explains in plain language that the rep total is training-valid but excluded from official direct comparison.
- Both Coach and Athlete history now reflect what was active at the moment each work block was reported — a Coach-edited scale change during the Session does not retroactively reclassify earlier reps, so the Coach can see each Athlete's actual execution trajectory (e.g. "scaled, then switched to official") and the Athlete sees a precise "N of M work blocks" count rather than a generic notice.

## Pre-session Readiness

*2026-07-19*

- Preparation now shows a compact "Pre-Session Readiness" card alongside the existing Preparation panel, so the Coach can see at a glance which operational items are ready, which need acknowledgement, and which block `Begin Grind`.
- `Begin Grind` is disabled while a blocker or unacknowledged warning remains, even after all Athletes are ready or the T+2s escape hatch unlocks — operational blockers cannot be bypassed by the same escape hatch that bypasses slow Athletes.
- A Coach can acknowledge a permitted warning straight from the readiness card; the acknowledgement is recorded against the Session and reflected on the next state refresh.
- When `Begin Grind` succeeds, the readiness state is captured as an append-only historical record, so audit and post-hoc recovery can show what was true at the moment the Session entered Phase II.
- Thirteen readiness items are tracked — six are evaluated today (benchmark, station targets, official burdens, roster, athlete identity, session owner); the remaining seven are reserved as `not_applicable` for v1 and become real checks in the PRDs that introduce their underlying concepts.

## Public Changelog Page

*2026-07-17*

- A new public `/changelog` page lists every release, every fix, and every format change — in plain language for facility owners.
- A year-grouped sidebar (desktop) or scrollable chip row (mobile) lets you jump to any release without scrolling the whole list.
- Shipped releases get a lime "Shipped" badge; internal plumbing changes get a muted "Architecture" badge so you can tell customer-visible releases from internal work.
- A new RSS feed at `/changelog/rss.xml` mirrors the blog feed, one entry per release, so feed readers and AI assistants stay current.
- The page is reachable from the public footer, the sitemap, and the site's AI-context file, so it surfaces wherever the rest of the public content does.

## Preserve shared results on account erasure

*2026-07-17*

- An athlete who deletes their account now has every trace of their identity removed in one go — sign-in links, coach invites, and the account itself disappear together, so nothing can ever point back to them.
- Past Group, Duo, and Trio Sessions you trained in stay complete — the erased participant is replaced by a fresh, unlinkable handle inside each shared record, and your Solo Race Practice is deleted with your account.
- Active commitments block deletion in the moment — a facility founder, an athlete currently in a group Session, or anyone in a team Race Practice (as owner or participant) is asked to resolve their open role before erasure can run, with a documented legal hold as a further block reason.
- After erasure, old session cookies stop working immediately, magic links issued before deletion can no longer be claimed, and retrying a successful deletion is a no-op.
- Two deletion attempts that race against the same account settle cleanly on the server — the deletion either happens once, in full, or it doesn't run at all.

## Privacy, Terms, and Cookies are published

*2026-07-16*

- A Privacy Policy page is now published at `/privacy`, describing what CCB collects, why, and the rights visitors and customers have over their data.
- A Terms of Use page is now published at `/terms`, with a pre-launch banner explaining that you'll be asked to accept the terms before you can register or use the service.
- The public site footer now links to Privacy, Cookies, and Terms, so those pages are reachable from anywhere on the site.
- The Cookies page now points to the Privacy Policy, so the storage choices and the rights behind them sit in one place.

## Sign-in tokens and Athlete identity, consolidated behind the scenes

*2026-07-15*

- Behind the scenes: every token used to join a Session or stay signed in now shares one canonical signing primitive, with replay-resistant expiry and a single rotation point if a secret ever needs to change.
- Coach invites and sign-in links now ship as opaque random references — no payload, no email, no identifier in the URL — and each link is single-use, so a guessed or stolen link can't be replayed.
- Athlete identity is consolidated into one system-wide module: joining a Session, claiming anonymous history into an account, and resolving who is viewing what now share a single source of truth.
- The join flow is now signed end-to-end — the Athlete ID presented to the server is verified against a signed credential rather than a client-provided value, so a tampered device can't impersonate another athlete.
- Joining the same Session twice produces the same Athlete row — a flaky tap or a retried network request no longer creates a duplicate.

## Realtime Session reliability

*2026-07-14*

- Live Session updates are now more reliable — phase changes, readiness counts, and station totals stay sync across every device in the room.
- If a live update ever fails to arrive, the app refetches the current Session state from the server, so a missed notification never leaves a stale view on your phone.
- Live updates are best-effort signals only — the server's record of what happened stays authoritative, even if a notification is dropped.

## The five official Benchmarks get a public page

*2026-07-13*

- A new Benchmarks page names the five official CCB Benchmarks — Classic, Engine, Grinder, Storm, Inferno — and the public purpose of each.
- The page explains the shared 12-station, fixed-order, 60-second Work Phase structure that every official Benchmark uses.
- Difficulty progression is described qualitatively — higher standardized Targets and heavier Burdens — without publishing exact values.
- Custom Sessions are clearly distinguished from the five official Benchmarks, and Benchmark versioning is explained in plain language.
- The new page links to Stations and Session Flow so readers can keep moving through the format explanation.

## Duo and Trio Race Practice

*2026-07-12*

- Run a Duo (two-athlete) or Trio (three-athlete) Race Practice — rehearse the full 12-station flow with one teammate or two, with no coach or Judge.
- Every Athlete submits only their own result — there's no editable team-total field, and one teammate can't see or change another's draft.
- The team total is computed by the server from confirmed individual results, so the team score is the same for every athlete at the recap, with no manual override by the Race Practice Owner.
- When the team total falls short of the team target, the official Burden is generated once for the whole team, and every athlete independently confirms completion before the team can advance.
- The Race Practice Owner drives the session — start, advance, stop, transfer — but never controls scoring, so the session driver stays separate from anything judge-like.
- Reload, backgrounding, or a network drop returns every athlete to the current Station from the server's current view of the Session, including their own pending submission.

## Public CCB Documentation

*2026-07-11*

- CCB now has a public documentation site at `/docs` — the format is readable without signing in, before any pilot or account.
- Nine pages cover the format in plain language: Overview, Session Flow, Stations, Results & Evaluation, Burdens, Roles, Formats, Race Practice, and Glossary.
- Each page marks whether what it describes is shipped, specified, planned, Competition-only, or not currently available — so readers can tell live behaviour from roadmap.
- "Read the format" links in the blog, compare, for, and glossary pages now point to `/docs`, so the canonical explanation is always one tap away.
- The site's AI-context file references `/docs`, so AI assistants and search systems can reach the canonical documentation directly.

## Your phone stays awake during the Work-Phase

*2026-07-11*

- Your phone screen stays awake throughout the Work-Phase — no more mid-round lock cutting off your rep count.
- A heavy haptic slam at the Freeze gives Android users a kinesthetic confirmation they can feel even with the phone face-down.
- An aggressive buzzer at the Freeze plays so you hear the lock fire in a loud gym.
- On iOS Safari the vibration is silent (Apple doesn't allow it), but the buzzer still plays — and the Work-Phase completes correctly on any platform that can't keep the screen awake.
- Every signal respects your device's volume and vibration settings, plus the OS's Do-Not-Disturb mode.

## Warm-up before the timed protocol

*2026-07-11*

- A Session now opens with a single warm-up round — every Athlete does every one of the 12 pre-assigned movements together, in Station-number order, before the protocol begins.
- The Coach controls when the room moves from warm-up to the timed protocol — a manual Begin Grind button is the only path; nothing auto-advances on a timer or readiness count alone.
- The 60-second Work-Phase timer, Freeze, round summary, Collective Burden counter, Penalty Round, and Station Rotation all run only during the protocol phase — the warm-up round has none of that machinery, so the room is free to move at its own pace.
- If one Athlete takes too long to tap "I'm Ready," the Coach can fire Begin Grind after a two-second grace window — the slowest member doesn't hold the rest of the room.
- After Begin Grind, every Athlete's device lands on the first protocol round within about a second — no stale view, no missed rotation.

## The Traffic Light is gone

*2026-07-10*

- The Traffic Light is gone — Athletes work at maximum effort until the Freeze, mirroring the official-competition model with no live indicator of where the Station is on target.
- At the Freeze you see your final rep count and a submit form; tap-mode Athletes tap to submit, and machine-mode Athletes type the machine's distance reading and submit.
- After submitting you see a passive "Waiting for round to complete" until the Coach drives the round transition — Athletes don't learn the per-Station result until the round summary runs.
- Post-round, you either see your assigned Burden (if your Station fell short of the target) or your next Station's name along with your assignment (if you passed).
- The new "I'm Ready" button on the next-Station screen is how Athletes tell the system they're set — once everyone at the Station is ready, the Coach can advance the round.

## Live updates reach every device

*2026-07-10*

- Live phase transitions now reach every Athlete's device and the Coach Dashboard within about a second of the Coach advancing the round.
- Returning to a backgrounded tab on iOS lands you on the current phase state — no stale view, no missed transitions to replay.
- Live updates are signals only — the server's record of what happened stays authoritative, so a missed update always self-corrects on the next refresh.

## Coach Dashboard with live controls

*2026-07-10*

- The Coach's Live Session view now updates in real time — phase changes, readiness counts, and per-Station Collective Burden refresh on their own as the room works.
- A Coach control panel lets the Coach globally halt the Session or manually inject a penalty if something goes wrong on the floor.
- The Coach Roster lets the facility owner invite another Coach by email — the link is single-use, expires in 24 hours, and lands the new Coach at the facility on first tap.
- The new Session Recap page shows the room's per-Station totals and running Collective Burden after the Session closes.
- If the readiness check stalls, the Coach can force-close it two seconds after End Round — the room gets a moment to finish tapping before the next round begins.

## Station Rotation & Collective Burden

*2026-07-10*

- Coaches now have an End Round button to close the round between Work-Phases — the press is the only path; nothing auto-fires.
- The Collective Burden counter advances by the count of Stations that missed the target — one honest number per round, not per Athlete.
- When the Burden increment is non-zero, every Athlete does every Penalty Round movement together — collective cost, based on which Stations missed.
- Empty Stations (no one there this round) don't count against the group — the rotation happened, but no collective debt was incurred.
- Athletes rotate to the next Station every Work-Phase, in Station-number order; the server pushes the rotation via live updates so every device refreshes within about a second.

## Your reported rep count is preserved

*2026-07-10*

- The rep count you report at the Freeze is now the canonical record — the server stores it verbatim, never recomputed from a counter it doesn't have.
- A flaky gym-wifi drop during the report no longer corrupts the recap — your phone retries the same number, the server recognises the duplicate, and your recap shows what you actually did.
- The post-Session recap sums every Athlete's reported count per Station, so the room sees a single total per Station and your facility gets an honest picture of how the round went.

## Work-Phase timing and Freeze reporting

*2026-07-10*

- The 60-second Work-Phase timer locks to a shared starting time across every device — even on a flaky network, the Freeze fires at the right time.
- Your tap counter belongs to you alone — there's no peer visibility or per-rep broadcast, so Athletes work at maximum effort without comparison.
- If reporting your final rep count hits a network blip, your phone retries up to three times and queues the result locally if every retry fails, so a hiccup at the worst possible moment is still recoverable.
- Every athlete at a Station hits the Freeze within about a second of each other, because the timer reads from a shared starting time rather than each device's own clock.
- Athletes who background the browser mid-Work-Phase on iOS return to a correct view within about a second — the phone refetches the current Session state and submits if the Work-Phase ended during the background.

## Sign-in moves in-house

*2026-07-09*

- Sign-in now runs entirely on CCB's own infrastructure — the email link you receive and the session cookie you keep never leave our servers.
- Your sign-in cookie is named to follow browser security rules in production, and stays valid for seven days from the moment you sign in.
- Two magic-link clicks in quick succession now behave correctly — the second click lands on the sign-in page with an "already used" status, and an expired link lands with an "expired" status, so failure modes are obvious instead of silent.
- Rotating the sign-in secret invalidates every active session at once, so a suspected leak no longer leaves any cookie alive on a stranger's device.
- Users who signed in before the upgrade are signed out once, then prompted to sign in again — the next sign-in just works.

## In-App Coach Manual

*2026-07-09*

- Coaches now have an in-app Coach Manual — six sections of operational guidance, open from the Dashboard at any time.
- Each section leads with the action to take and follows with the reasoning, so the right line is findable in the moment.
- Setup and Decision-Point surfaces link directly into the relevant manual section — one tap to the right guidance without leaving the page.
- "Individual scaling is always allowed in training" sits at the top of the scaling guidance, so the rule is impossible to miss.
- The Coaching Behaviour section prohibits public blame terms and ships a verbatim room-briefing template — the same copy surfaced on the Preparation screen.

## Behind the scenes: error reporting

*2026-07-09*

- Behind the scenes: the development team gets a single email per new error type — one alert per bug, not a flood of duplicate notifications.
- If an error report is ever generated, it never includes your email, sign-in link, or any other personal identifier — your data stays out of the developer's dashboard.
- When something does break, the developer gets the information they need to ship a fix quickly.
- Every kind of error — browser, form-submission, or service-side — reaches the same dashboard, so a real bug never slips through silently.

## Abuse protection for sign-in and join forms

*2026-07-09*

- Sign-in, sign-up, and join forms now show a friendly "try again in X minutes" message if you retry too fast, instead of failing silently or looking broken.
- A stolen or guessed sign-in link can only be tried five times before it's rejected, even from a different network.
- Automated abuse of the join page is now blocked with a "too many requests" response, so a real athlete can still join mid-Session.

## Cross-Session Athlete History

*2026-07-09*

- Your Sessions now follow your account — `/me` shows every Session you've trained at, across every facility, with totals and a one-tap link back to each recap.
- If you trained anonymously before signing up, you can link those past Sessions from `/me/claim`, so your history becomes one continuous record instead of per-device scraps.
- After a Session ends, a one-tap modal offers to save your recap to a permanent account — no separate sign-up wall, no forced detour.
- Coaches now see the Athletes who've claimed into their facility on the Dashboard, with one tap into each Athlete's cross-Session history for context-aware coaching.
- Anonymous recaps stay private — only the device that originally joined a Session can claim that row, so no one else can peek at your numbers.

## Solo Race Practice

*2026-07-08*

- Athletes can now run a Solo Race Practice — pick an official Benchmark and rehearse the full 12-Station race flow on their own, with no coach or Judge.
- The same 60-second Work-Phase timer, local rep counter, and deliberate Freeze reporting you know from group Sessions.
- A missed target generates the official Burden — you self-confirm when you've completed it, no coach approval required.
- Pause-safe recovery — reload, backgrounding, or a network drop returns you to your current Station from the server's current view of the Session.

## Session setup and Athlete sign-in

*2026-07-08*

- Coaches can now run a Session end-to-end — create a Session from a Benchmark (Classic / Engine / Grinder / Storm / Inferno / Custom), edit the 12 Station rows, and display a scannable QR code for Athletes to join.
- Athletes scan the QR, enter a display name, and pick a starting Station (1-12) right from their phone — no app install, just a browser.
- Athletes can sign up with an email and a magic link from the landing page before joining any facility; on first sign-in they pick a display name, and `/me` becomes their cross-facility home.
- Before round 1 starts, the Coach gets a clear warning if the Athletes-per-Station split would make the rotation unworkable — singletons under an even total, or more than one odd-count Station, are flagged up front so the Coach can rebalance before tapping Start.
- After a Session ends, the recap shows each Athlete's own row plus the Session's group total — never who else was at which Station.

## Sitemap

- [CCB sitemap (Markdown)](https://www.collectivecadenceburden.com/sitemap.md)
