Add offline meal journal and secure sync
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
-- User-owned meal journal. Photos are deliberately not stored in these rows.
|
||||
-- Apply after migrations 001-004 with a verified database backup.
|
||||
|
||||
CREATE TABLE meal_entries (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT NOT NULL,
|
||||
client_meal_uuid CHAR(36) NOT NULL,
|
||||
name VARCHAR(180) NOT NULL,
|
||||
meal_type ENUM('breakfast', 'lunch', 'dinner', 'snack') NOT NULL,
|
||||
calories DECIMAL(8,2) NOT NULL,
|
||||
protein_grams DECIMAL(7,2) NOT NULL DEFAULT 0,
|
||||
carbohydrate_grams DECIMAL(7,2) NOT NULL DEFAULT 0,
|
||||
fat_grams DECIMAL(7,2) NOT NULL DEFAULT 0,
|
||||
consumed_at DATETIME NOT NULL,
|
||||
source ENUM('manual', 'photo_ai') NOT NULL DEFAULT 'manual',
|
||||
notes VARCHAR(1000) NOT NULL DEFAULT '',
|
||||
revision INT UNSIGNED NOT NULL DEFAULT 1,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uq_meal_user_client_uuid (user_id, client_meal_uuid),
|
||||
INDEX idx_meals_user_consumed (user_id, consumed_at DESC),
|
||||
CONSTRAINT fk_meals_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
CHECK (calories >= 0 AND calories <= 10000),
|
||||
CHECK (protein_grams >= 0 AND protein_grams <= 1000),
|
||||
CHECK (carbohydrate_grams >= 0 AND carbohydrate_grams <= 1000),
|
||||
CHECK (fat_grams >= 0 AND fat_grams <= 1000)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
@@ -124,6 +124,46 @@ CREATE TABLE training_session_exercises (
|
||||
CONSTRAINT fk_session_exercises_exercise FOREIGN KEY (exercise_id) REFERENCES exercises(id) ON DELETE RESTRICT
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE training_content_audit (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
entity_type ENUM('exercise', 'plan') NOT NULL,
|
||||
entity_uuid CHAR(36) NOT NULL,
|
||||
action ENUM('create', 'update', 'publish', 'unpublish') NOT NULL,
|
||||
previous_value JSON NULL,
|
||||
new_value JSON NOT NULL,
|
||||
actor_user_id INT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
INDEX idx_content_audit_entity_time (entity_type, entity_uuid, created_at),
|
||||
INDEX idx_content_audit_actor_time (actor_user_id, created_at),
|
||||
CONSTRAINT fk_content_audit_actor FOREIGN KEY (actor_user_id)
|
||||
REFERENCES users(id) ON DELETE SET NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE meal_entries (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT NOT NULL,
|
||||
client_meal_uuid CHAR(36) NOT NULL,
|
||||
name VARCHAR(180) NOT NULL,
|
||||
meal_type ENUM('breakfast', 'lunch', 'dinner', 'snack') NOT NULL,
|
||||
calories DECIMAL(8,2) NOT NULL,
|
||||
protein_grams DECIMAL(7,2) NOT NULL DEFAULT 0,
|
||||
carbohydrate_grams DECIMAL(7,2) NOT NULL DEFAULT 0,
|
||||
fat_grams DECIMAL(7,2) NOT NULL DEFAULT 0,
|
||||
consumed_at DATETIME NOT NULL,
|
||||
source ENUM('manual', 'photo_ai') NOT NULL DEFAULT 'manual',
|
||||
notes VARCHAR(1000) NOT NULL DEFAULT '',
|
||||
revision INT UNSIGNED NOT NULL DEFAULT 1,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uq_meal_user_client_uuid (user_id, client_meal_uuid),
|
||||
INDEX idx_meals_user_consumed (user_id, consumed_at DESC),
|
||||
CONSTRAINT fk_meals_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
CHECK (calories >= 0 AND calories <= 10000),
|
||||
CHECK (protein_grams >= 0 AND protein_grams <= 1000),
|
||||
CHECK (carbohydrate_grams >= 0 AND carbohydrate_grams <= 1000),
|
||||
CHECK (fat_grams >= 0 AND fat_grams <= 1000)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Phone OTP challenges contain keyed digests, never the plaintext code.
|
||||
CREATE TABLE otp_challenges (
|
||||
challenge_uuid CHAR(36) PRIMARY KEY,
|
||||
|
||||
Reference in New Issue
Block a user