SparkyFitness uses PostgreSQL 15+ as its primary data store. Row-Level Security (RLS) policies are the foundation of its multi-user isolation model — every user-specific table carries RLS policies that prevent one account from ever reading or modifying another account’s data. The schema follows a normalised design with audit timestamps on every table, UUID primary keys, and snake_case naming throughout.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/CodeWithCJ/SparkyFitness/llms.txt
Use this file to discover all available pages before exploring further.
Schema Design Principles
- Tables — snake_case, plural (e.g.
food_diary_entries,user_preferences) - Columns — snake_case (e.g.
created_at,user_id,total_calories) - Foreign keys —
{table_name}_idformat (e.g.user_id,food_item_id) - Indexes — descriptive names (e.g.
idx_food_diary_user_date) - Primary keys — UUID using
gen_random_uuid() - Audit fields —
created_atandupdated_aton every table, updated via triggers
Schema Overview
User Management
users — core account identity
users — core account identity
user_preferences — per-user application settings
user_preferences — per-user application settings
Food Tracking
food_items — master food catalogue
food_items — master food catalogue
nutrition_data — nutritional info per food item
nutrition_data — nutritional info per food item
food_diary — user daily food intake entries
food_diary — user daily food intake entries
Exercise Tracking
exercises — master exercise catalogue
exercises — master exercise catalogue
exercise_diary — user exercise session entries
exercise_diary — user exercise session entries
Measurements and Check-ins
measurements — body measurements and health metrics
measurements — body measurements and health metrics
Goals and Presets
goals — fitness and nutrition goals
goals — fitness and nutrition goals
AI Chat History
chat_history — AI assistant conversations
chat_history — AI assistant conversations
Integration Tokens and Provider Configuration
external_data_providers — configured API integrations
external_data_providers — configured API integrations
external_data_providers table stores the encrypted credentials and configuration for each user’s enabled integrations. API keys are always encrypted at rest using the SPARKY_FITNESS_API_ENCRYPTION_KEY.Family Sharing
family_access — delegation permissions
family_access — delegation permissions
Row-Level Security (RLS)
RLS is enabled on every user-specific table so that the database engine itself enforces data isolation — application-layer bugs cannot leak data across accounts. Two PostgreSQL session functions are initialised at the start of every pool-client transaction viapublic.set_app_context(userId, authenticatedUserId) before any query is executed:
authenticated_user_id() to prevent delegates from accessing data even when context-switched:
SparkyFitnessServer/db/rls_policies.sql.
Database Security Tiers
All tables are classified into one of three security tiers following the least-privilege principle.Tier 1 — Strictly Private
Onlyauthenticated_user_id() (the true account owner) can read or write. Family delegates have zero access.
Authentication & credentials
user, two_factor, verification, api_key, user_oidc_links, passkey, session, accountPrivate logs & preferences
sparky_chat_history, ai_service_settings, user_ignored_updates, admin_activity_logsCycle & reproductive health
cycle_settings, cycle_daily_entries, cycles, cycle_test_entries, user_cycle_display_preferences, user_mood_display_preferencesPregnancy
pregnancies, pregnancy_kick_sessions, pregnancy_contractions, pregnancy_photos, pregnancy_checklist_state, health_appointmentsTier 2 — View-Only Shared
Owner writes; switched delegates (context-switched viacurrent_user_id()) can read. Used for profiles, layout settings, and custom food/exercise libraries.
| Table | Readable by delegates with… |
|---|---|
profiles, user_preferences, user_dashboard_layouts | Any active delegation |
foods, food_variants, meals, meal_foods | can_view_food_library, can_manage_diary, or can_view_reports |
exercises, workout_presets, workout_preset_exercises | can_view_exercise_library, can_manage_diary, or can_view_reports |
external_data_providers | share_external_providers |
user_goals, weekly_goal_plans | can_manage_diary or can_view_reports |
family_access | Owner or switched delegate |
Tier 3 — Delegate-Writable
Caregivers and delegates with the appropriate permission can read and write on behalf of the owner. Organised into three sub-groups:Diary logs — can_manage_diary / can_view_reports
Diary logs — can_manage_diary / can_view_reports
food_entries, food_entry_meals, exercise_entries, exercise_preset_entries, exercise_entry_sets, exercise_entry_activity_details, water_intake, water_intake_entries, meal_plan_template_assignments, workout_plan_template_assignments, workout_plan_assignment_setsMedication & symptom logs — can_manage_medications / can_view_reports
Medication & symptom logs — can_manage_medications / can_view_reports
medications, medication_schedules, medication_entries, medication_pens, injection_entries, medication_titration_steps, user_custom_symptoms, symptom_entries, user_custom_symptom_locationsCheck-in & wellness logs — can_manage_checkin / can_view_reports
Check-in & wellness logs — can_manage_checkin / can_view_reports
check_in_measurements, check_in_photos, sleep_entries, sleep_entry_stages, sleep_need_calculations, daily_sleep_need, fasting_logs, mood_entries, day_classification_cache, custom_categories, custom_measurements, user_custom_moodsSystem / Global Reference Tables
These tables store global configuration and reference data. They carry no RLS because they contain no user-specific data. All authenticated users can read them; only admins can write.| Table | Description |
|---|---|
global_settings | Application feature flags and system configuration |
sso_provider | Active SSO providers (Google, Apple, etc.) |
oidc_providers | OpenID Connect integration settings |
external_provider_types | Search-provider configuration lookup |
medication_types | Medication category lookup |
backup_settings | Automated backup timing and storage credentials (admin-only read) |
Migrations
SparkyFitness uses a custom migration system that runs automatically on server startup.How it works
- On startup the server reads the
migrationstable to determine the current schema version. - Any migration files in
SparkyFitnessServer/db/migrations/that have not yet been applied are executed in order. - Each applied migration is recorded in the
migrationstable. - Results are logged for debugging.
Migration file naming
2024_03_15_14_20_add_meal_planning.sql
Creating a migration
Add RLS policies
SparkyFitnessServer/db/rls_policies.sql and classify it into the appropriate security tier.Migration best practices
- Always wrap in a transaction — if any statement fails, the entire migration rolls back.
- Add columns with defaults so existing rows are valid immediately.
- Use
CREATE INDEX CONCURRENTLY(outside a transaction) to avoid locking the table. - Document rollback steps in migration comments.
- Test on development data before applying to production.
Connection Configuration
SparkyFitness uses two database roles:| Role | Variable | Purpose |
|---|---|---|
| Admin user | POSTGRES_USER / DB_USER | Runs migrations and manages schema |
| App user | SPARKY_FITNESS_APP_DB_USER | Runtime queries — limited privileges |