Files
SneakySwole/docs/database_schema.md
Phillip Tarrant 53e62f694f docs: replace implementation plans with architecture and API reference docs
Remove phase implementation plans, design notes, and source spreadsheet
that are no longer needed. Add architecture.md, API_REFERENCE.md, and
database_schema.md for ongoing development and debugging reference.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 14:19:49 -06:00

203 lines
7.0 KiB
Markdown

# Database Schema
SQLite database at `data/sneakyswole.db`, managed by SQLModel ORM with Alembic migrations.
---
## Tables
### `users`
User profiles (admin and regular). Admin has login credentials; regular profiles are managed by the admin.
| Column | Type | Constraints | Description |
|--------|------|------------|-------------|
| `id` | INTEGER | PK, auto-increment | |
| `username` | VARCHAR | UNIQUE, indexed | Login identifier |
| `password_hash` | VARCHAR | default="" | bcrypt hash (admin only) |
| `display_name` | VARCHAR | default="" | Name shown in UI |
| `height` | VARCHAR | nullable | e.g., "6'0\"" |
| `weight` | VARCHAR | nullable | e.g., "260 lbs" |
| `goals` | VARCHAR | nullable | Free-text training goals |
| `is_admin` | BOOLEAN | default=False | Admin privileges flag |
| `created_at` | DATETIME | auto | Record creation time |
| `updated_at` | DATETIME | auto | Last update time |
**Model:** `app/models/user.py:User`
---
### `exercises`
Exercise library catalog. Each exercise belongs to a workout day.
| Column | Type | Constraints | Description |
|--------|------|------------|-------------|
| `id` | INTEGER | PK, auto-increment | |
| `name` | VARCHAR | indexed | e.g., "DB Chest Press (Floor)" |
| `muscle_group` | VARCHAR | default="" | e.g., "Chest", "Shoulders" |
| `workout_day` | VARCHAR | indexed | "Push", "Pull", "Lower", "Full Body" |
| `sets` | INTEGER | default=3 | Default number of sets |
| `tempo` | VARCHAR | default="" | e.g., "3-1-2" (eccentric-pause-concentric) |
| `form_cues` | VARCHAR | default="" | Detailed form instructions |
| `created_at` | DATETIME | auto | Record creation time |
**Model:** `app/models/exercise.py:Exercise`
---
### `warmups`
Standardized warmup routine displayed before every workout.
| Column | Type | Constraints | Description |
|--------|------|------------|-------------|
| `id` | INTEGER | PK, auto-increment | |
| `name` | VARCHAR | indexed | e.g., "Cat / Cow" |
| `type` | VARCHAR | default="" | Category: "Thoracic Mob", "Hip Mobility", etc. |
| `reps` | VARCHAR | default="" | e.g., "8 reps", "8 each side" |
| `form_cues` | VARCHAR | default="" | Detailed form instructions |
| `sort_order` | INTEGER | default=0 | Display order in warmup sequence |
| `created_at` | DATETIME | auto | Record creation time |
**Model:** `app/models/warmup.py:Warmup`
---
### `workout_days`
The 4-day training split definition.
| Column | Type | Constraints | Description |
|--------|------|------------|-------------|
| `id` | INTEGER | PK, auto-increment | |
| `name` | VARCHAR | UNIQUE, indexed | "Push", "Pull", "Lower", "Full Body" |
| `day_number` | INTEGER | UNIQUE | Order in rotation (1-4) |
| `description` | VARCHAR | default="" | Brief focus description |
**Model:** `app/models/workout_day.py:WorkoutDay`
---
### `user_exercise_programs`
Per-user programming targets linking users to exercises with week 1/4 goals.
| Column | Type | Constraints | Description |
|--------|------|------------|-------------|
| `id` | INTEGER | PK, auto-increment | |
| `user_id` | INTEGER | FK → `users.id`, indexed | Profile this applies to |
| `exercise_id` | INTEGER | FK → `exercises.id`, indexed | Exercise being programmed |
| `wk1_reps` | VARCHAR | default="" | Week 1 target reps (e.g., "10", "30 sec") |
| `wk4_reps` | VARCHAR | default="" | Week 4 target reps |
| `wk1_weight` | VARCHAR | default="" | Week 1 target weight (e.g., "30 lbs", "BW") |
| `wk4_weight` | VARCHAR | default="" | Week 4 target weight |
| `created_at` | DATETIME | auto | Record creation time |
| `updated_at` | DATETIME | auto | Last update time |
**Model:** `app/models/user_exercise_program.py:UserExerciseProgram`
---
### `workout_sessions`
A completed workout session — ties a user to a workout day on a date.
| Column | Type | Constraints | Description |
|--------|------|------------|-------------|
| `id` | INTEGER | PK, auto-increment | |
| `user_id` | INTEGER | FK → `users.id`, indexed | Who did the workout |
| `workout_day_id` | INTEGER | FK → `workout_days.id` | Which day was trained |
| `date` | DATE | default=today | Date the workout was performed |
| `notes` | VARCHAR | nullable | Free-text session notes |
| `created_at` | DATETIME | auto | Record creation time |
**Model:** `app/models/workout_session.py:WorkoutSession`
---
### `workout_logs`
Individual set logs within a session. Each row = one set of one exercise.
| Column | Type | Constraints | Description |
|--------|------|------------|-------------|
| `id` | INTEGER | PK, auto-increment | |
| `session_id` | INTEGER | FK → `workout_sessions.id`, indexed | Parent session |
| `exercise_id` | INTEGER | FK → `exercises.id` | Which exercise |
| `set_number` | INTEGER | default=1 | Set number (1, 2, 3...) |
| `reps_completed` | INTEGER | default=0 | Actual reps performed |
| `weight_used` | VARCHAR | default="" | Weight used (e.g., "30 lbs", "BW") |
| `felt_easy` | BOOLEAN | default=False | Progression signal |
| `notes` | VARCHAR | nullable | Per-set notes |
| `created_at` | DATETIME | auto | Record creation time |
**Model:** `app/models/workout_log.py:WorkoutLog`
---
### `progress_log`
Progression tracking — what the engine suggested vs what the user actually did.
| Column | Type | Constraints | Description |
|--------|------|------------|-------------|
| `id` | INTEGER | PK, auto-increment | |
| `user_id` | INTEGER | FK → `users.id`, indexed | Profile being tracked |
| `exercise_id` | INTEGER | FK → `exercises.id` | Exercise being tracked |
| `date` | DATE | default=today | Date of progression entry |
| `suggested_reps` | INTEGER | nullable | Engine recommendation |
| `suggested_weight` | VARCHAR | nullable | Engine recommendation |
| `actual_reps` | INTEGER | nullable | What user actually did |
| `actual_weight` | VARCHAR | nullable | What user actually used |
| `progression_applied` | VARCHAR | nullable | Type: "reps_increase", "weight_increase", "deload" |
| `created_at` | DATETIME | auto | Record creation time |
**Model:** `app/models/progress_log.py:ProgressLog`
---
## Relationships
```
users
├── user_exercise_programs (1:N via user_id)
├── workout_sessions (1:N via user_id)
└── progress_log (1:N via user_id)
exercises
├── user_exercise_programs (1:N via exercise_id)
├── workout_logs (1:N via exercise_id)
└── progress_log (1:N via exercise_id)
workout_days
└── workout_sessions (1:N via workout_day_id)
workout_sessions
└── workout_logs (1:N via session_id)
```
---
## Migrations
Managed by Alembic. Config at `alembic.ini`, migration scripts at `alembic/versions/`.
- **Initial migration:** `1855836abf6c_initial_schema_8_tables.py` — creates all 8 tables
To create a new migration:
```bash
alembic revision --autogenerate -m "description"
alembic upgrade head
```
---
## Seeding
On first startup, `SeedService.seed_all()` reads:
- `config/exercises.yaml` — exercise catalog + warmups + workout days
- `config/user_programs.yaml` — per-user week 1/4 targets
Admin user is created from `ADMIN_USERNAME` / `ADMIN_PASSWORD` env vars with bcrypt hash. Seeding is skipped if data already exists.