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>
7.0 KiB
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:
alembic revision --autogenerate -m "description"
alembic upgrade head
Seeding
On first startup, SeedService.seed_all() reads:
config/exercises.yaml— exercise catalog + warmups + workout daysconfig/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.