Spaces:
Sleeping
Data Model: Full-Stack Integration & UI Experience
Feature: 002-fullstack-ui-integration Date: 2026-01-09 Status: Reference Only (No New Entities)
Overview
This feature does not introduce new data entities. It integrates and polishes existing functionality from Specs 1 (Task CRUD) and 2 (Authentication & API Security). This document references the existing data model for completeness.
Existing Entities
User (from Spec 2: Authentication & API Security)
Purpose: Represents an authenticated user with task management capabilities
Attributes:
id(integer, primary key): Unique identifier for the useremail(string, unique, required): User's email address for authenticationname(string, required): User's display namepassword_hash(string, required): Bcrypt-hashed password (never exposed in API)created_at(datetime, auto): Timestamp of account creationupdated_at(datetime, auto): Timestamp of last profile update
Relationships:
- One-to-Many with Task: A user can have multiple tasks
Validation Rules:
- Email must be valid RFC 5322 format
- Email must be unique across all users
- Password must be at least 8 characters with uppercase, lowercase, and number
- Name must be 1-100 characters
Security:
- Password is hashed with bcrypt (cost factor 12) before storage
- Password hash is never returned in API responses
- User ID is extracted from JWT token for all authenticated requests
Database Table: users
Indexes:
- Primary key on
id - Unique index on
email
Source: backend/src/models/user.py
Task (from Spec 1: Task CRUD)
Purpose: Represents a todo item belonging to a specific user
Attributes:
id(integer, primary key): Unique identifier for the taskuser_id(integer, foreign key, required): Owner of the task (references User.id)title(string, required): Task title (max 200 characters)description(string, optional): Task description (max 1000 characters)completed(boolean, default false): Completion statuscreated_at(datetime, auto): Timestamp of task creationupdated_at(datetime, auto): Timestamp of last task update
Relationships:
- Many-to-One with User: Each task belongs to exactly one user
Validation Rules:
- Title is required and must be 1-200 characters
- Description is optional, max 1000 characters
- Completed defaults to false
- User ID must reference an existing user
Business Rules:
- Users can only access their own tasks (enforced by JWT authentication)
- Tasks are automatically filtered by authenticated user_id in all queries
- Deleting a user cascades to delete all their tasks
Database Table: tasks
Indexes:
- Primary key on
id - Index on
user_id(for filtering by user) - Index on
completed(for filtering by status) - Composite index on
(user_id, completed)(for combined filtering) - Index on
created_at(for sorting)
Source: backend/src/models/task.py
AuthSession (Frontend Only - from Spec 2)
Purpose: Client-side session state for authenticated users
Attributes:
token(string, nullable): JWT token from backenduser(object, nullable): User profile informationid(integer): User IDemail(string): User emailname(string): User display name
Storage: Browser localStorage (key: auth_session)
Lifecycle:
- Created on successful signin (POST /api/auth/signin)
- Persisted across page refreshes
- Cleared on signout or 401 Unauthorized response
- Expires when JWT token expires (7 days)
Security:
- Token is included in Authorization header for all API requests
- Session is cleared on any authentication error
- No sensitive data stored (password never stored client-side)
Source: frontend/src/lib/auth.ts
Entity Relationships
User (1) ----< (Many) Task
|
| JWT Token (stateless)
|
v
AuthSession (Frontend)
Relationship Details:
User → Task (One-to-Many):
- A user can have zero or more tasks
- Each task belongs to exactly one user
- Foreign key:
Task.user_idreferencesUser.id - Cascade delete: Deleting a user deletes all their tasks
User → AuthSession (Stateless):
- JWT token contains user_id and email
- No server-side session storage
- Frontend stores token and user profile in localStorage
- Token is verified on every API request
Data Flow
Authentication Flow
1. User signs up/signs in
↓
2. Backend creates JWT token with user_id
↓
3. Frontend stores token + user profile in AuthSession
↓
4. Frontend includes token in Authorization header
↓
5. Backend verifies token and extracts user_id
↓
6. Backend filters all queries by user_id
Task Management Flow
1. User creates/updates/deletes task
↓
2. Frontend sends request with JWT token
↓
3. Backend verifies token → extracts user_id
↓
4. Backend performs operation (filtered by user_id)
↓
5. Backend returns result
↓
6. Frontend updates UI (optimistic or after response)
Data Isolation
Critical Security Requirement: All task queries MUST be filtered by authenticated user_id
Implementation:
- JWT token contains user_id in 'sub' claim
get_current_user()dependency extracts user_id from token- All task endpoints use
current_user_id = Depends(get_current_user) - SQLModel queries include
.where(Task.user_id == current_user_id)
Verification:
- User A cannot access User B's tasks
- API returns 404 (not 403) for unauthorized task access
- No data leakage through error messages
State Transitions
Task State Transitions
[New Task]
↓
[Active] ←→ [Completed]
↓
[Deleted]
Transitions:
- New → Active: Task created with
completed=false - Active → Completed: User marks task as done (
completed=true) - Completed → Active: User marks task as not done (
completed=false) - Any → Deleted: User deletes task (hard delete from database)
No Soft Deletes: Tasks are permanently deleted (no deleted_at field)
User State Transitions
[New User]
↓
[Active]
↓
[Deleted] (future - not implemented)
Current Implementation:
- New → Active: User signs up successfully
- No user deletion implemented yet (out of scope)
Schema Migrations
Existing Migrations:
001_initial.py: Created users and tasks tables (Spec 1)002_add_user_password.py: Added password_hash to users table (Spec 2)
No New Migrations Required: This feature does not modify the database schema
Data Validation
Backend Validation (Pydantic Schemas)
User Validation (backend/src/schemas/auth.py):
- Email: RFC 5322 format validation
- Password: Min 8 chars, uppercase, lowercase, number
- Name: 1-100 characters
Task Validation (backend/src/schemas/task.py):
- Title: Required, 1-200 characters
- Description: Optional, max 1000 characters
- Completed: Boolean (defaults to false)
Frontend Validation
Client-Side Validation:
- Email format validation (regex)
- Password strength validation (min 8 chars, complexity)
- Form field required/optional indicators
- Inline error messages
Note: Backend validation is authoritative - frontend validation is for UX only
Performance Considerations
Indexes (already implemented):
users.email(unique): Fast user lookup during signintasks.user_id: Fast filtering of user's taskstasks.completed: Fast filtering by completion statustasks.(user_id, completed): Fast combined filteringtasks.created_at: Fast sorting by creation date
Query Patterns:
- Most common: Get all tasks for user (filtered by user_id)
- Second most common: Get active/completed tasks for user
- Sorting: By created_at or updated_at
No N+1 Queries: All queries are direct (no nested loops)
Summary
This feature reuses the existing data model from Specs 1 and 2:
- User: Authentication and ownership
- Task: Todo items with user isolation
- AuthSession: Frontend session state
No new entities, relationships, or migrations are required. The focus is on UI integration and polish rather than data model changes.