# Time Track — Architecture Diagrams
## System Architecture
Time Track is a time-tracking web application with a SolidJS frontend and a Spring Boot backend. The client communicates with the server exclusively via a REST API, and authentication is handled through JWT tokens stored in HTTP-only cookies.
```mermaid
graph TD
Browser["Browser
(SolidJS + TanStack Router/Query)"]
Server["Spring Boot Server
(REST API on :8080)"]
DB["H2 In-Memory Database"]
Vite["Vite Dev Server
(:5173)"]
Browser -->|"REST API calls (JSON)"| Server
Server -->|"HTTP-only JWT cookie"| Browser
Server --> DB
Browser -.->|"HMR in development"| Vite
```
---
## Data Model
The core domain revolves around users who belong to organizations. Organizations own projects, and time entries are logged against projects. Each user has at most one active timer at a time.
```mermaid
erDiagram
users {
UUID id PK
string name
string username
string password
}
organizations {
UUID id PK
string name
}
organization_members {
UUID id PK
UUID organization_id FK
UUID user_id FK
string role "OWNER | ADMINISTRATOR | MEMBER"
}
projects {
UUID id PK
string name
UUID organization_id FK
}
times {
UUID id PK
UUID project_id FK
datetime start_time
datetime end_time
}
timers {
UUID id PK
UUID user_id FK
}
timer_start_pauses {
UUID id PK
UUID timer_id FK
datetime started_at
datetime paused_at "null when running"
}
users ||--o{ organization_members : "belongs to"
organizations ||--o{ organization_members : "has"
organizations ||--o{ projects : "owns"
projects ||--o{ times : "has"
users ||--o| timers : "has active"
timers ||--o{ timer_start_pauses : "tracks"
```
---
## REST API Endpoints
The API is grouped by resource. All endpoints require a valid JWT cookie except sign-in and sign-up.
```mermaid
graph LR
subgraph Auth ["/api — Auth"]
A1["POST /sign-ins"]
A2["POST /sign-ups"]
A3["POST /sign-outs"]
end
subgraph Users ["/api/users — Users"]
U1["GET /current/id"]
U2["GET /{userId}/organizations"]
U3["POST /{userId}/organizations"]
U4["PUT /{userId}/organizations/{orgId}/name"]
U5["GET /{userId}/projects"]
U6["POST /{userId}/organizations/{orgId}/projects"]
U7["PUT /{userId}/projects/{projectId}"]
U8["GET /{userId}/times"]
U9["POST /{userId}/projects/{projectId}/times"]
U10["PUT /{userId}/times"]
U11["DELETE /{userId}/times"]
end
subgraph Timer ["/api/users/{userId}/timer — Timer"]
T1["GET /"]
T2["POST /start"]
T3["POST /pause"]
T4["POST /stop"]
T5["DELETE /"]
T6["DELETE /entries/{entryId}"]
end
subgraph Orgs ["/api/organizations — Organizations"]
O1["POST /"]
O2["GET /{orgId}"]
O3["DELETE /{orgId}"]
O4["GET /{orgId}/users"]
O5["POST /{orgId}/members/registrations"]
O6["DELETE /{orgId}/members/{userId}"]
O7["PUT /{orgId}/members/{userId}/role"]
end
```
---
## Timer State Machine
The timer follows a clear lifecycle. When stopped, all start/pause intervals are converted into permanent time entries and the timer is deleted.
```mermaid
stateDiagram-v2
[*] --> Idle : no timer exists
Idle --> Running : POST /timer/start
note right of Running : Creates timer + first entry
Running --> Paused : POST /timer/pause
note right of Paused : Sets pausedAt on current entry
Paused --> Running : POST /timer/start
Paused --> Idle : POST /timer/stop
note left of Idle : Converts entries to time records, deletes timer
Running --> Idle : DELETE /timer (discard)
Paused --> Idle : DELETE /timer (discard)
Paused --> Paused : DELETE /timer/entries/{id}
```
---
## Authentication Flow
Sign-in uses HTTP Basic Auth in the request header. On success the server returns a short-lived JWT in an HTTP-only `Strict` same-site cookie that the browser attaches automatically to every subsequent API call.
```mermaid
sequenceDiagram
participant B as Browser
participant S as Spring Boot Server
B->>S: POST /api/sign-ins
Note right of B: Authorization: Basic base64(user:pass)
S->>S: Verify credentials & generate JWT
S-->>B: 200 OK — body: userId
Note left of S: Set-Cookie: jwt=... (HttpOnly, SameSite=Strict)
Note over B,S: Subsequent authenticated requests
B->>S: GET /api/users/{userId}/projects
Note right of B: Cookie: jwt=...
S->>S: JwtAuthenticationFilter validates token
S-->>B: 200 OK — project list
```
---
## Frontend Route Structure
The client uses TanStack Router with a file-based route tree. Protected routes are nested under `_app`, which handles authentication checks. Unauthenticated users are redirected to `/sign-in`.
```mermaid
graph TD
Root["__root
(layout + navigation)"]
Root --> Index["/
(redirect)"]
Root --> SignIn["/sign-in"]
Root --> SignUp["/sign-up"]
Root --> App["/_app
(auth guard)"]
App --> Timer["/_app/timer
Active timer & controls"]
App --> Times["/_app/times
Time entry history"]
App --> Projects["/_app/projects
Project list"]
App --> Orgs["/_app/organizations
Organization list"]
App --> Settings["/_app/settings"]
Orgs --> OrgNew["/organizations/new"]
Orgs --> OrgEdit["/organizations/:id/edit"]
Orgs --> OrgMembers["/organizations/:id/members"]
OrgMembers --> AddMember["/organizations/:id/members/add"]
Projects --> ProjectNew["/projects/new"]
Projects --> ProjectEdit["/projects/:id.edit"]
Times --> TimeNew["/times/new"]
```
---
## Organization Roles & Permissions
Organizations support a three-tier role system that controls who can manage members and projects.
```mermaid
graph LR
subgraph Actions
ViewOrg["View organization"]
ManageMembers["Add / remove members"]
ChangeRoles["Change member roles"]
DeleteOrg["Delete organization"]
ManageProjects["Create / edit projects"]
end
MEMBER -->|can| ViewOrg
MEMBER -->|can| ManageProjects
ADMINISTRATOR -->|can| ViewOrg
ADMINISTRATOR -->|can| ManageMembers
ADMINISTRATOR -->|can| ManageProjects
OWNER -->|can| ViewOrg
OWNER -->|can| ManageMembers
OWNER -->|can| ChangeRoles
OWNER -->|can| DeleteOrg
OWNER -->|can| ManageProjects
```