suhail
spoecs
9eafd9f

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 user
  • email (string, unique, required): User's email address for authentication
  • name (string, required): User's display name
  • password_hash (string, required): Bcrypt-hashed password (never exposed in API)
  • created_at (datetime, auto): Timestamp of account creation
  • updated_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 task
  • user_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 status
  • created_at (datetime, auto): Timestamp of task creation
  • updated_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 backend
  • user (object, nullable): User profile information
    • id (integer): User ID
    • email (string): User email
    • name (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:

  1. User → Task (One-to-Many):

    • A user can have zero or more tasks
    • Each task belongs to exactly one user
    • Foreign key: Task.user_id references User.id
    • Cascade delete: Deleting a user deletes all their tasks
  2. 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:

  1. 001_initial.py: Created users and tasks tables (Spec 1)
  2. 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 signin
  • tasks.user_id: Fast filtering of user's tasks
  • tasks.completed: Fast filtering by completion status
  • tasks.(user_id, completed): Fast combined filtering
  • tasks.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.