# Data Model
This document describes the data model for the dalex-todo-proto application using Mermaid diagrams.
## Entity Relationship Diagram
```mermaid
erDiagram
USER ||--o{ TODO : owns
USER {
string id PK "Keycloak User ID"
string username "From Keycloak"
string email "From Keycloak"
}
TODO {
int id PK "Auto-increment primary key"
string userId FK "Reference to User (Keycloak ID)"
string title "Todo title (required)"
string description "Optional description"
datetime createdAt "Creation timestamp"
datetime completedAt "Completion timestamp (nullable)"
boolean isCompleted "Completion status"
}
```
## Database Schema
```mermaid
classDiagram
class Todo {
+int Id
+string UserId
+string Title
+string Description
+DateTime CreatedAt
+DateTime CompletedAt
+bool IsCompleted
+GetAge() TimeSpan
+IsOld() bool
}
class TodoDbContext {
+DbSet~Todo~ Todos
+OnModelCreating(ModelBuilder)
}
TodoDbContext --> Todo : manages
```
## Data Flow Architecture
```mermaid
flowchart TB
subgraph Client ["Frontend (Vue 3)"]
UI[User Interface]
KC_CLIENT[Keycloak Client]
API_CLIENT[API Client]
end
subgraph Keycloak ["Keycloak Server"]
AUTH[Authentication]
TOKEN[JWT Token Service]
end
subgraph Backend ["ASP.NET Core Backend"]
JWT_VALIDATE[JWT Validation]
API[REST API Endpoints]
BL[Business Logic]
end
subgraph Database ["SQLite Database"]
DB[(Todos Table)]
end
UI --> KC_CLIENT
KC_CLIENT <--> AUTH
AUTH --> TOKEN
TOKEN --> API_CLIENT
API_CLIENT --> JWT_VALIDATE
JWT_VALIDATE --> API
API --> BL
BL <--> DB
style Client fill:#e1f5ff
style Keycloak fill:#fff4e1
style Backend fill:#e8f5e9
style Database fill:#f3e5f5
```
## Todo Entity Details
### Fields
| Field | Type | Nullable | Description |
|-------|------|----------|-------------|
| `Id` | int | No | Primary key, auto-increment |
| `UserId` | string | No | Keycloak user identifier (from JWT token) |
| `Title` | string | No | Todo title/summary |
| `Description` | string | Yes | Optional detailed description |
| `CreatedAt` | DateTime | No | UTC timestamp when todo was created |
| `CompletedAt` | DateTime | Yes | UTC timestamp when todo was marked complete |
| `IsCompleted` | bool | No | Completion status flag |
### Indexes
- **Primary Key**: `Id`
- **Index**: `UserId` (for efficient user-specific queries)
### Constraints
- `UserId` is required (enforced at database and application level)
- `Title` is required (enforced at database and application level)
- `CreatedAt` is automatically set on creation
- `CompletedAt` is set when `IsCompleted` changes to `true`
- `CompletedAt` is cleared when `IsCompleted` changes to `false`
## API Data Transfer Objects (DTOs)
```mermaid
classDiagram
class TodoCreateDto {
+string Title
+string Description
}
class TodoUpdateDto {
+string Title
+string Description
+bool? IsCompleted
}
class Todo {
+int Id
+string UserId
+string Title
+string Description
+DateTime CreatedAt
+DateTime CompletedAt
+bool IsCompleted
}
TodoCreateDto ..> Todo : creates
TodoUpdateDto ..> Todo : updates
```
## Business Rules
### Sorting Logic
```mermaid
flowchart TD
START[Get Todos for User]
SPLIT{Group by Status}
INCOMPLETE[Incomplete Todos]
COMPLETE[Complete Todos]
SORT_INC[Sort by CreatedAt ASC
Oldest first]
SORT_COM[Sort by CompletedAt DESC
Newest first]
FILTER{Show Older?}
HIDE[Hide todos completed
> 1 week ago]
SHOW[Show all]
COMBINE[Combine Lists]
RESULT[Return Sorted List]
START --> SPLIT
SPLIT --> INCOMPLETE
SPLIT --> COMPLETE
INCOMPLETE --> SORT_INC
COMPLETE --> SORT_COM
SORT_INC --> COMBINE
SORT_COM --> FILTER
FILTER -->|No| HIDE
FILTER -->|Yes| SHOW
HIDE --> COMBINE
SHOW --> COMBINE
COMBINE --> RESULT
```
### User Isolation
- Each user can only see their own todos
- `UserId` is extracted from JWT token (Keycloak `sub` or `NameIdentifier` claim)
- All queries are filtered by `UserId`
- No cross-user data access is possible
## Storage
### SQLite Database
- **File Location**: `/app/data/todos.db` (in Docker container)
- **Persistence**: Docker volume `todolist-proto_backend-data`
- **Schema Management**: Entity Framework Core with automatic migration on startup
- **Connection String**: `Data Source=/app/data/todos.db`
### Table Structure
```sql
CREATE TABLE "Todos" (
"Id" INTEGER NOT NULL CONSTRAINT "PK_Todos" PRIMARY KEY AUTOINCREMENT,
"UserId" TEXT NOT NULL,
"Title" TEXT NOT NULL,
"Description" TEXT NULL,
"CreatedAt" TEXT NOT NULL,
"CompletedAt" TEXT NULL,
"IsCompleted" INTEGER NOT NULL
);
CREATE INDEX "IX_Todos_UserId" ON "Todos" ("UserId");
```
## Security Considerations
1. **Authentication**: All API endpoints require valid JWT token from Keycloak
2. **Authorization**: Users can only access their own todos (enforced by UserId filtering)
3. **Data Validation**:
- Title is required
- UserId is required
- All inputs are validated before database operations
4. **SQL Injection**: Protected by Entity Framework Core parameterized queries
5. **CORS**: Restricted to frontend origin only (`http://localhost:3030`)