1. Pre-launch notice
This page is published before Collective Cadence Burden is registered as a Swedish limited company (Aktiebolag, "AB") with Bolagsverket. The business is currently operated by David Söderberg as an individual. David Söderberg is the current controller of the personal data described in this policy. The business is intended to be transferred to Collective Cadence Burden AB after the company has been formed and registered with Bolagsverket. The intended Collective Cadence Burden AB does not yet exist, no organisation number has been issued, and no registered company address is available. The required business-identity and address disclosures will be re-reviewed and republished before registration, service use, or paid access opens.
The full name, country, and contact method for the current operator are:
- Controller: David Söderberg
- Operating name / project: Collective Cadence Burden
- Location: Sweden
- Contact:
info@collectivecadenceburden.com
2. Who we are
Collective Cadence Burden ("CCB", "we", "us") is the operating name of a B2B software-as-a-service product that helps facility owners run a zero-sum, athlete-rotating HIIT protocol during group sessions. It is currently operated by David Söderberg as an individual before incorporation.
- Controller: David Söderberg
- Operating name / project: Collective Cadence Burden
- Location: Sweden
- Contact:
info@collectivecadenceburden.com
The application is hosted in the United Kingdom (London). All other processors are in the EEA or the UK. No processing takes place outside the EEA or the UK.
If you are reading this Privacy Policy, you are one of:
- a Visitor of the public CCB marketing surfaces (this website, our blog, our docs);
- a Coach or Facility Owner who signed up to use the service;
- an Athlete participating in a Session at a facility that uses CCB; or
- a recipient of a transactional email from us (magic-link sign-in, Coach invite).
This policy describes what personal data we collect from each of these roles, why we collect it, who we share it with, how long we keep it, and the rights you have over it.
3. The short version
If you only read one section, read this one.
- We collect the minimum data needed to run the service. CCB's central product decision is to make the data we hold small.
- We do not collect payment, health, or biometric data. We are not a medical device and we do not record heart rate, oxygen, or video.
- We do not place advertising pixels and we do not build advertising profiles.
- The first-party analytics on this site is cookieless and consent-gated. The
/api/trackrequest usescredentials: "omit", so no application cookie is intentionally sent by the tracker, and the endpoint does not accept or emit an explicit User, Athlete, Session, or Facility identifier. User-Agent and Referer are sanitized before logging. The endpoint only fires when you have made an affirmative analytics-consent decision in the consent banner — see §7. - The Facility you train at is the recipient of your in-Session data (display name, results). CCB stores it; the Facility reads it.
- You can ask us to delete your account, change your email, or export your data. We will action each request within 30 days of receipt.
4. Contact us
Privacy, support, security, and legal enquiries: info@collectivecadenceburden.com.
The mailbox is hosted in Stockholm, Sweden. The same address is used for privacy and data-subject requests, support, security disclosures, legal notices, payment or subscription enquiries, account-security notifications, and pre-launch questions.
5. Roles in this policy
| Role | Relationship to CCB |
|---|---|
| Visitor | Anyone visiting a public CCB page that is not behind sign-in. |
| Coach | An authenticated user with the Coach role at a Facility. May also be the Facility Owner. |
| Athlete (authenticated) | An authenticated user with the Athlete role. Has an account. Can sign up directly for Race Practice without a Facility intermediary. |
| Athlete (anonymous) | A person who joined a Session at a Facility without an account. The row carries a self-chosen display name; the Facility is the holder of any link to the real identity. |
| Facility | The legal customer — the entity that pays for access. The Facility is the data controller for its in-Session data; CCB is the processor for that data on the Facility's behalf. See §10. |
CCB is B2B-only. The Facility is the customer; the Athlete is a user of the Facility's installation. CCB does not sell any service directly to consumers.
6. What we collect and why
We collect the data below for the stated purposes. We do not use the data for any other purpose without re-prompting you.
6.1 Visitors
| What | Why | Required? |
|---|---|---|
| Page view, CTA click, outbound-link click (no identifier) | Aggregate product understanding | No |
| IP address, browser identifier (User-Agent), and the page that linked you here (Referer) | Operational debugging, incident response | No |
| Unhandled error reports | Stability | No |
6.2 Coaches and Facility Owners (account)
| What | Why | Required? |
|---|---|---|
| Email address | Sign-in and operational notices | Yes |
| Display name | Greeting and Coach identification in the dashboard | Yes |
| Sign-in events (sign-in, sign-out, IP, browser identifier) | Security audit | No |
| Coach-of-Facility membership | Multi-Facility support, billing attribution | Yes |
6.3 Athletes (authenticated account)
| What | Why | Required? |
|---|---|---|
| Email address | Sign-in | Yes |
| Display name | Cross-Session history identification | Yes |
| Race Practice results and Burdens | Practice record | Yes (opt-in) |
| Team Race Practice participation | Team results | Yes (opt-in) |
| Age attestation ("I confirm I am at least 13") | Compliance with applicable age-of-consent rules | Yes (for sign-up) |
6.4 Athletes (anonymous join)
| What | Why | Required? |
|---|---|---|
| Self-chosen display name | Coach and other Athletes see this during a Session | Yes |
| Per-Athlete proof-of-join token (an HMAC-signed value over the Box, Session, Athlete identifier, expiry, and nonce) | Authorise the anonymous Athlete for this Session | Yes |
| Join-attempt token (a short-lived HMAC-signed value bound to the verified Box, Session, and Athlete identifier) | Authorise a single join submission; reused across retries during its 5-minute lifetime so the same athleteId is resolved on every retry | Yes |
A client-supplied diagnostic browser string (the first 200 characters of the browser's User-Agent) | Operational signal — see §6.4a below | Yes |
| Station-by-Station results, Burdens, checksums, penalty rounds | Session record | Yes |
| Session state (joined → claimed → in progress → complete) | Live protocol state | Yes |
Pseudonymity notice. An anonymous Athlete's display name is a pseudonym, not an anonymous identifier. The Coach of the Facility can read it; CCB cannot link it to a real identity. The Facility is the holder of the mapping from pseudonym to real identity.
§6.4a — what the proof-of-join token is and is not. The token is an HMAC-SHA256 signature over {purpose, boxId, sessionId, athleteId, exp, nonce}. It proves possession of the join credential for one Session on one Facility. The token is stored in an HttpOnly cookie. It is not cryptographically bound to a physical device or browser. A copied token remains usable from another browser until its expiry. The token may support tamper detection for its signed payload, but it is not a device-binding or device-copy prevention mechanism.
§6.4b — what the diagnostic browser string is and is not. The string is supplied by the Athlete's own browser at join time. It is the first 200 characters of the browser's User-Agent header. It is client-supplied, easily spoofed, derived from User-Agent, low-entropy, not cryptographic, not stable across browser updates, and not an authentication or authorization input. CCB stores the value on the Athlete row as diagnostic metadata. It is not used to detect duplicate join attempts, it is not used to detect tampering, and it is not used for any enforcement decision. The string is logged in the Athlete row for one reason only: it is the simplest, low-cost diagnostic the system has if a Facility later reports a join-time problem. The signal is loose; the security boundary for anonymous join is the proof-of-join token above, not this column.
6.5 Everyone
| What | Why | Required? |
|---|---|---|
| Magic-link sign-in email (recipient + URL) | Authentication | Yes (for sign-in) |
| Coach-invite email (recipient + URL) | Onboarding | Yes (for invites) |
| Inbound support email | Reply to you | No (opt-in) |
Token notes (magic-link and Coach Invite). The URLs in the magic-link and Coach Invite emails each carry an opaque, high-entropy, database-backed bearer reference. The reference is the unique lookup key for a single database row; it is not a signed payload, not derived from your email or any other personal data, and not the database row's primary key. The reference is unreadable to anything but our servers — it does not encode your email address, the Facility identifier, or anything else about you. The reference becomes invalid after the first use, and after the link's expiry window (15 minutes for magic-link, 24 hours for Coach Invite). The reference's sole role is to look up the database row that carries the email and the single-use, expiry-enforced state.
7. Cookies and analytics
CCB's browser storage is a small, typed set. The complete, current inventory — the keys, the storage mechanism, the purpose, the retention, and the rationale for every entry — is the single source of truth on the Cookies and browser storage page. That page renders directly from the canonical inventory in lib/domain/privacy/clientStorage.ts. This policy does not maintain a second list, so the two cannot drift.
Categories. Every entry in the inventory is one of four purposes, all defined in the same source of truth:
- Strictly necessary — sign-in, anonymous Athlete proof, recovery queues, the join-attempt retry cache, and the visitor's anonymous consent record (the per-purpose decision the visitor made in the consent banner). The product cannot function correctly without the first three; the consent record is strictly necessary so the visitor is not re-prompted on every page load. Authentication cookies are set by the server. Recovery queues and the join-attempt retry cache are written by first-party CCB application code in the browser. None of these entries is written by analytics or marketing code.
- Functional preferences — UI choices the visitor made themselves (theme, language). The product continues to work without them.
- Analytics — there are no current entries in this category. The first-party analytics transport (
/api/track) is consent-gated and writes no client storage; see "First-party analytics" below. - Marketing — there are no current entries in this category.
Consent model. Two optional purposes are consent-gated: analytics (first-party cookieless events) and diagnostics (browser error reports). Three states per purpose: unknown (no decision yet), accepted (affirmative opt-in), declined (explicit rejection). The default for every purpose is unknown. Until a visitor makes an affirmative decision, no optional-purpose activity fires.
The visitor's decision is recorded in a first-party localStorage entry under the key ccb.consent. The record carries the canonical CURRENT_CONSENT_VERSION (the consent policy version). An obsolete record (one recorded under a previous policy version) is treated as unknown and the visitor is re-prompted — we never silently carry a previous decision into a new consent regime.
When the visitor changes a decision, a structured pending mutation record is also written to localStorage under the key ccb.consent.pending. The pending record is a fail-closed marker — if the page reloads, navigates, or crashes before the in-progress change finishes syncing, the next page load replays the pending mutation rather than treating the half-applied local decision as final. The pending record carries no Visitor identifier and no cross-session identifier; it only carries the mutation in flight (mutationId, the per-purpose decision, the surface that produced it, and a timestamp). Once the change is confirmed (for signed-in Users: by a successful server write; for anonymous Visitors: by completion of the local-only write), the pending marker is cleared.
For signed-in Users, the decision is also recorded on the server in the user_consent table. The server record is authoritative across devices when it is at the current version; the anonymous record is authoritative when no server record exists. The reconciliation rule never silently converts a rejection into an acceptance — an obsolete server declined purpose remains declined, an obsolete accepted purpose becomes unknown (re-prompt), and the visitor is never silently re-accepted after a rejection.
Anonymous versus signed-in write flow. For anonymous Visitors the only authoritative store is the local localStorage record — there is no server record to confirm against, and the cross-device sync a server write provides is not meaningful for a Visitor with no session. An anonymous change therefore completes by writing the local decision plus the pending marker; the marker is then cleared synchronously, and there is no "submitting" / error UI to surface. For signed-in Users the change performs the same local write, then dispatches a server write that, on success, clears the pending marker, or — on failure with the marker still present — keeps the marker so the next page load replays the change. In neither flow does the visitor see an error UI for an in-progress change: anonymous changes cannot fail at the network boundary, and signed-in changes retry on the next page load via the pending marker.
Login reconciliation. When a Visitor with an anonymous consent record signs in, and the User does not yet have a server-side consent row, the anonymous decision is persisted to the User's user_consent row under surface: "reconcile". The User is not re-prompted on the banner merely because they signed in. Login alone does NOT create consent — an all-unknown anonymous record is skipped. A pre-existing server row (any version) is never overwritten by login reconciliation.
The consent banner offers two equally prominent actions ("Accept all" and "Reject optional") and a third tertiary action ("Customize") that opens a purpose-specific dialog. The two equal-weight actions share the same size, weight, variant, border emphasis, color treatment, and placement — neither biases the visitor toward acceptance. The "Customize" action is visually tertiary (plain text link) but available directly from the initial surface, so the visitor can choose any combination of analytics and diagnostics (both accepted, both declined, or one of each) without first committing to a bulk action. The per-purpose settings panel lives on the Cookies and browser storage page at #privacy-settings. Both surfaces pin the source-of-truth invariants:
- "Accept all" and "Reject optional" buttons share the same size, weight, variant, border emphasis, color treatment, and visual prominence — neither biases the visitor toward acceptance.
- No purpose is preselected — the dialog's switches start in the OFF position and the visitor must affirmatively toggle each.
- The two purposes (
analytics,diagnostics) are independent — a visitor can accept one and decline the other from the dialog without ever pressing "Accept all" or "Reject optional". - Closing the dialog (via backdrop, Cancel, or Escape) does NOT record a consent decision — only the explicit Save action commits.
- The decision is revisable at any time. The "Withdraw all optional consent" action on the settings panel clears both purposes in a single click.
- The visitor can switch between decisions across sessions and across devices; the server record (for signed-in Users) carries the latest authoritative decision.
Authentication cookies. Two cookies carry authentication material. Both are set by the server, are not readable by JavaScript, and are sent only to our origin. The production session cookie is __Secure- prefixed.
- The session cookie holds a signed JWT identifying the User. Lifetime: 7 days. SameSite=Lax.
- The Athlete proof-of-join cookie holds the anonymous Athlete's HMAC token. Lifetime: scoped to the Session. SameSite=Lax. See §6.4a for what the token is and is not.
First-party analytics. The public CCB pages send a single anonymous event per page view, CTA click, and outbound-link click to the first-party endpoint at POST /api/track. The endpoint is cookieless: the request uses credentials: "omit", so no application cookie is intentionally sent by the tracker. The endpoint does not accept or emit an explicit User, Athlete, Session, or Facility identifier. User-Agent and Referer are sanitized before the event is logged. We do not use Google Analytics, Meta Pixel, Hotjar, FullStory, Segment, or similar; a static guardrail at lib/domain/privacy/guardrails/third-party-sdks.test.ts blocks the import of any such SDK. See the Cookies and browser storage page for the full first-party analytics disclosure.
The endpoint is consent-gated: it only fires after you make an affirmative analytics-consent decision in the consent banner. While your analytics state is unknown or declined, no page_view, cta_click, or outbound_link event is sent — neither by an explicit emit nor by replay of pre-consent activity. The architecture guardrail at lib/domain/__architecture__/analytics-consent-boundary.test.ts pins this at the source level.
If you would like to opt out of the first-party analytics after accepting, open Cookies and browser storage and flip the analytics switch off (or use the "Withdraw all optional consent" button). The decision takes effect on the same page load — the tracker stops emitting events immediately. Blocking POST /api/track in a browser extension or at the network level still works as a defence-in-depth measure, but the in-product opt-out is the supported path.
8. Error reporting
We use a third-party error reporter so we can fix bugs. For the browser, the error reporter is consent-gated: it only initialises after you make an affirmative diagnostics-consent decision in the consent banner. While your diagnostics state is unknown or declined, no error event leaves the browser — and a previously-initialised SDK is torn down on any transition to unknown (for example after a consent-policy version bump, after clearing the consent record, or any reconciliation that returns unknown). The architecture guardrail at lib/domain/__architecture__/sentry-init-boundary.test.ts pins this at the source level — Sentry.init(...) is allowed in exactly four files: lib/observability/browserSentry.ts (the browser boundary, called by the consent bootstrap), sentry.server.config.ts (server runtime), sentry.edge.config.ts (edge runtime), and instrumentation.ts (Next.js instrumentation hook).
For the server and edge runtimes there is no visitor to ask, so the error reporter initialises on first invocation. The configuration is errors-only with an event-level filter applied before anything leaves the browser or server:
- We do not record page sessions (replay is off).
- We do not record performance traces.
- We do not send default personally identifying information.
- A
beforeSendfilter strips PII from the four surfaces it covers — top-levelevent.extra, top-levelevent.user, top-levelrequest.cookies, and the top-leveldataobject on each breadcrumb. On those surfaces it deletesathleteId,sessionId,boxId,userIdfromevent.extra; redacts email addresses and magic-link URLs from string values inevent.extraand breadcrumbdata; deletesuser.id,user.email,user.ip_address,user.usernamefrom the user object; deletes auth / session / token-shaped cookie keys; and replaces magic-link URLs in cookie strings. - Other event surfaces are not touched by the filter —
event.message,event.tags,event.contexts,event.exception.values,event.request.url,event.request.headers, nestedextraor breadcrumb objects, and breadcrumbmessagestrings. CCB never sets personal data on those surfaces; the gap is by construction, not by accident. - The error reporter is hosted in the EU (Frankfurt).
- Retention is 30 days at most.
The data the error reporter receives is therefore the minimum needed to fix the bug, and only after you have opted in. The error reporter is a subprocessor; see §9.
9. Who we share your data with
We do not sell personal data. We share data only with the subprocessor categories below and only to the extent needed to run the service.
| Recipient | Data shared | Region | Why |
|---|---|---|---|
| The Facility you train at | Your display name (anonymous Athlete), your Station results, your Burdens, your Session state | n/a — the Facility is a recipient, not a subprocessor | The Facility is the recipient of its own Session data |
| Other Athletes in the same Session | Your display name, your in-Session results, your Session state | n/a | Live protocol legibility |
| Application host | All application data | UK (London) | Application runtime, request logs |
| Database provider | All persistent application data | EU or UK | Database hosting |
| Realtime and rate-limit provider | IP address (rate-limit keys); Session IDs (Realtime channels) | EU | Rate-limit and live protocol fanout |
| Email provider and mailboxes | Recipient email and message body; inbound support mail | Sweden (Stockholm) | Transactional email and mailboxes |
| Error reporter | Error events with personal information stripped | EU (Frankfurt) | Stability |
| Counsel, on request | As needed to defend a legal claim | n/a | Legitimate interest |
| Authorities, on a valid legal demand | As compelled | n/a | Legal obligation |
The Facility is a controller of the data its Coaches and Athletes generate during a Session, and CCB acts as a processor for that data on the Facility's behalf. The Facility's own privacy notice to its Athletes should describe this relationship; CCB's Privacy Policy does not speak for the Facility.
10. International transfers
All processing occurs in the EEA + UK. The application host is in the United Kingdom (London). The UK is recognised by the European Commission as adequate for personal-data transfers (Decision 2021/1772, renewed 2025). All other processors are in the EEA. No Standard Contractual Clauses are required for any current subprocessor.
If a future subprocessor is added outside the EEA + UK, we will update this page at least 30 days before the change takes effect, and we will put the appropriate transfer mechanism (SCCs or BCRs) in place.
11. Retention
We keep personal data only as long as we have a reason to. The schedule below is the public summary.
| Category | Retention |
|---|---|
| Account identity and personal access | Erased on a verified deletion request (atomic — no 30-day delay) |
| Active sign-in / Coach-invite tokens for the erased account | Deleted with the account |
| Completed shared Session / Duo / Trio record (results, Burdens, checksums, penalty rounds) | Retained in minimized, pseudonymized form for 24 months from Session close, so other participants' records and protocol integrity are preserved. The retained record does not include the erased participant's name, email, original User id, original Athlete id, device/browser metadata, or any cross-Unit replacement identifier. Aggregate-anonymisation at the 24-month boundary remains separate from this. |
| Solo Race Practice record | Deleted with the account (atomic) |
| Sign-in email token | 15 minutes |
| Coach-invite token | 24 hours |
| Session token | 7 days |
| Error-report events (EU) | 30 days |
| Hosting request logs (UK) | 30 days |
/api/track analytics lines | 30 days |
Anonymous consent record (ccb.consent localStorage) | Until the visitor clears browser storage, calls the in-product "withdraw all optional consent" action, or the consent-policy version is bumped (whichever happens first) |
User consent record (user_consent table, signed-in Users) | Lifetime of the users row + 30 days |
| Inbound support email | 24 months |
| Terms-acceptance record (when wired) | 7 years |
When the 24-month session-history retention ends, we aggregate-anonymise the shared records (drop identifiers, coarsen timestamps, suppress small cells). When we erase an account, we remove the account identity and personal access in one transaction, delete the user's Solo Race Practice records in the same transaction, and rewrite the erased participant's references in completed shared records to per-Record-scoped identifiers — a fresh random identifier for each shared historical Unit, with no global deleted-user-… mapping.
12. Your rights
Depending on where you live, you have some or all of the following rights over your personal data:
- Access (Art. 15 GDPR) — request a copy of the personal data we hold about you.
- Rectification (Art. 16) — correct data that is wrong.
- Erasure (Art. 17) — ask us to delete your data. We will action this within 30 days of receipt. When we erase your account we remove your identity and personal access, delete your Solo Race Practice records, and rewrite your participant references in any completed shared Group / Duo / Trio records to per-Record-scoped identifiers so the rest of the room's history remains intact. A small, non-identifying erasure receipt is kept only for idempotency / proof-of-work — it carries no email, no name, no old User id, and no reversible identity mapping. The receipt records the policy version under which erasure ran and the aggregate counts of affected records; it does not record any of your personal data.
- Restriction (Art. 18) — ask us to pause processing while a dispute is resolved.
- Portability (Art. 20) — receive your data in a portable format. We will provide an export within 30 days of receipt.
- Objection (Art. 21) — object to processing based on legitimate interest. For analytics and diagnostics, see §7 — the supported opt-out is the in-product consent switch on Cookies and browser storage.
- Withdraw consent (Art. 7(3)) — withdraw any consent you previously gave, at any time, as easily as you gave it. The "Withdraw all optional consent" button on the settings panel clears both purposes in a single click. Withdrawal does not affect the lawfulness of processing carried out before the withdrawal.
- Automated decision-making (Art. 22) — there is none. CCB does not assign fault, calculate effort, or recommend Burden overrides. The protocol is recorded, not adjudicated.
To exercise any of these, contact info@collectivecadenceburden.com. We may need to verify your identity before we act — typically by sending a sign-in link to the email we have on file.
Anonymous Athletes: erasure requires cooperation from the Facility that holds the display-name mapping. We will coordinate with the Facility and confirm completion within 30 days.
If you are unhappy with our response, you can complain to your local data-protection authority. The relevant authority for Sweden is Integritetsskyddsmyndigheten (IMY).
13. Children and minors
CCB does not verify the age of an Athlete at sign-up. The sign-up form requires the Athlete to confirm they are at least 13 years old; CCB does not independently verify this. The Facility is responsible for the lawful enrolment of any minor at its premises, including obtaining any required parental consent (COPPA in the US, UK Age-Appropriate Design Code in the UK, GDPR Art. 8 in the EEA, and the equivalent rule in other jurisdictions).
CCB is not intended for Athletes under 13. If we learn that we have collected personal data from a child under 13 without verifiable parental consent, we will delete it within 30 days.
14. Security
We protect personal data with a defence-in-depth approach:
- All cookies that carry authentication material are set by the server, not readable by JavaScript, and sent only to our origin; the production cookie is
__Secure-prefixed. - Sign-in tokens are short-lived, single-use, and atomically claimed at the database level.
- The first-party analytics endpoint applies the same personal-information strip list to every event before logging, and the request uses
credentials: "omit"so no application cookie is intentionally sent. - Database access is via parameterised queries only.
- The Athlete proof-of-join token and the Join-attempt token are short-lived HMAC-signed credentials scoped to a single Facility, Session, and Athlete identifier. Neither is bound to a physical device or browser — see §6.4a. The Join-attempt token is reused across retries during its 5-minute lifetime so the same
athleteIdis resolved on every retry.
No security control is perfect. If you discover a vulnerability, please email info@collectivecadenceburden.com.
15. Changes to this policy
We will post material changes at least 30 days before they take effect, and email the Coach-of-record at the address on file.
16. Governing law and disputes
This Privacy Policy is governed by the law of Sweden. The courts of Sweden have exclusive jurisdiction over any dispute arising out of or relating to this policy, subject to the data-subject right under Art. 79 GDPR to bring an action in the courts of the Member State of the data subject's habitual residence.
Appendix A — what we do not collect
For completeness, the following are common SaaS data categories that CCB does not collect:
- Payment card data, bank account data, or any financial identifier. CCB has no payment flow at the time of writing; the post-trial paywall is described in the Terms §8.
- Health or medical data. CCB is not a medical device and does not record heart rate, oxygen saturation, ECG, or any biometric signal.
- Video, audio, or photograph of an Athlete.
- Location data beyond coarse IP geolocation in the hosting logs.
- Government identifiers (passport, national ID, social security number).
- Free-text "notes" fields beyond display names and invite messages; we ask Facilities not to put health or injury information there.
- Data from advertising pixels, social-login providers, or third-party trackers.