# 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 ```