Skip to content

UNDA — Data Inventory

Status: Draft. Every personal-data field must appear here. Update in the same PR that adds/changes a field. Last reviewed: 2026-08-08 Owner: Product engineering (TBD) Legend for Classification: IDENTITY · SENSITIVE_HEALTH (Article 9) · FITNESS · SETTINGS · OPERATIONAL

Legal basis defaults, to be confirmed by counsel:

  • IDENTITY and SETTINGS → GDPR Art. 6(1)(b) contract
  • SENSITIVE_HEALTH and FITNESS (used for personalisation) → Art. 6(1)(b) contract plus Art. 9(2)(a) explicit consent

Fields

profiles.id

  • Source: UNDA (UUID generated at onboarding finish)
  • Classification: IDENTITY (pseudonymous)
  • Purpose: Primary key for cross-table joins
  • Database: profiles.id; FK on every user-owned table
  • Retention: Life of account
  • Processors: Local device only (Supabase when sync is enabled)
  • Analytics: NEVER
  • User editable: No
  • User deletable: Yes (via delete-account flow — pending B1)
  • Exported: Yes
  • Legal basis: Art. 6(1)(b) contract

profiles.last_period_start

  • Source: User-reported (onboarding + Settings)
  • Classification: SENSITIVE_HEALTH
  • Purpose: Anchor date for phase computation
  • Retention: User-controlled; on account deletion, purged
  • Analytics: NEVER
  • User editable: Yes (Settings)
  • User deletable: Yes
  • Exported: Yes
  • Legal basis: Art. 6(1)(b) + Art. 9(2)(a) explicit consent

profiles.avg_cycle_length, profiles.avg_period_length

  • Source: User-reported (onboarding + Settings)
  • Classification: SENSITIVE_HEALTH
  • Purpose: Scale phase model to the user's cycle length
  • Retention/analytics/edit/delete/export: as above
  • Legal basis: as above

profiles.on_hormonal_contraception

  • Status: Not currently collected (removed from onboarding for data minimisation).
  • Note: The column exists in the model as a placeholder for the "flat programming" toggle. If we re-introduce collection, we must add a data-inventory entry with justification and a specific consent event.

profiles.fitness_level, profiles.goals, profiles.equipment, profiles.sports

  • Source: User-reported (Personalize screen) or inferred by ProfileInferenceService (marked as unda_inferred after B2).
  • Classification: FITNESS
  • Purpose: Individualize the workout recommender
  • Retention: Life of account, user-editable
  • Analytics: NEVER as raw values. Aggregate counts (once analytics is added) are on the allowlist.
  • Legal basis: Art. 6(1)(b) contract

profiles.notifications_enabled

  • Classification: SETTINGS
  • Legal basis: Art. 6(1)(a) consent (notifications-specific)

profiles.sync_enabled

  • Classification: SETTINGS
  • Purpose: Whether Supabase sync is on
  • Legal basis: Art. 6(1)(b) + Art. 9(2)(a) explicit consent for cross-device replication of health data (health-data sync is a separate consent event)

profiles.onboarding_complete, profiles.updated_at

  • Classification: OPERATIONAL
  • Purpose: Boot routing + sync bookkeeping

cycle_days (date, flow, symptoms, mood, energy, sleep_hours, notes)

  • Source: User-reported (Calendar tab symptom log). notes currently unused.
  • Classification: SENSITIVE_HEALTH
  • Purpose: Log per-day symptoms and per-day energy, feed Insights and the recommender's felt-score history
  • Retention: User-controlled; retained while account exists
  • Analytics: NEVER
  • User editable: Currently only for today (planned: any date)
  • User deletable: Yes (per-row toggle; full via delete-account)
  • Exported: Yes
  • Legal basis: Art. 6(1)(b) + Art. 9(2)(a) explicit consent

cycles (start_date, end_date, period_length_days, cycle_length_days, notes)

  • Status: Table exists in schema, not yet written to.
  • Classification: SENSITIVE_HEALTH
  • Planned purpose: Historical cycle records for length distribution and prediction confidence

workout_sessions (workout_slug, date, phase_at_time, day_of_cycle_at_time, completed, felt_score, notes)

  • Source: User action ("Mark completed")
  • Classification: FITNESS + inferred SENSITIVE_HEALTH via phase_at_time snapshot
  • Purpose: History for Insights, felt-score training signal for the recommender
  • Retention: Product-useful period (TBD in retention-policy.md); user-deletable
  • Analytics: NEVER as raw rows
  • Provenance: workout_slug is UNDA-catalog; phase_at_time is unda_inferred at time of completion; felt_score is user_reported
  • Legal basis: Art. 6(1)(b) + Art. 9(2)(a)

imported_activity (from Strava/Intervals.icu — planned)

  • Status: Interface exists (ActivityHistoryImporter); no data ingested outside MockImporter.
  • Classification: FITNESS + SENSITIVE_HEALTH (avg HR, HRV where present)
  • Purpose: Profile inference (sport interests, level)
  • Provenance: provider_imported
  • When wired: re-enter here with vendor, scope, retention, disconnect behaviour.

consents

  • Fields: id, profile_id, consent_type, policy_version, granted, granted_at, withdrawn_at, source, updated_at
  • Classification: OPERATIONAL (evidence of consent)
  • Source: UNDA-recorded from user's affirmative action (onboarding checkboxes, Settings toggles)
  • Retention: Life of account; deleted with account
  • Analytics: NEVER
  • User editable: Users flip the underlying consent via Settings (planned Privacy Center will expose every type); UNDA never rewrites past rows
  • Exported: Yes
  • Legal basis: Art. 7 GDPR (records of consent)

profiles.age_confirmed_18_plus, profiles.age_confirmed_at

  • Source: User attestation at onboarding
  • Classification: OPERATIONAL (eligibility attestation)
  • Purpose: §16 minors policy — UNDA v1 is 18+
  • Retention: Life of account
  • Analytics: NEVER
  • User editable: No (attestation is immutable once made; delete-account and re-onboard to re-attest)
  • Exported: Yes
  • Legal basis: Art. 6(1)(b) contract (eligibility to enter into service)

Fields we deliberately do NOT collect

  • Email / real name at account level — only when Supabase sync is enabled and the user signs in.
  • Precise location — not required for any current feature.
  • Contacts, messages, or unrelated device categories — never requested.
  • Basal body temp, cervical mucus, LH tests — schema extension point noted in docs/DATA_MODEL.md; not currently collected. If added, gets a separate explicit-consent event (§4.2).
  • Pregnancy status — out of scope; if added, requires legal review (§26).
  • Sexual activity / partner data — out of scope.

Change control

Add or modify a row here in the same PR that adds/modifies the field. PR checklist (§22) enforces this.

UNDA is a fitness and training support product. It is not a medical device.