Files
slp-modular-cms/aidlc-docs/features/cms-frontend/construction/unit-1/functional-design/business-logic-model.md
T

3.3 KiB

Business Logic Model — Unit 1: Project Scaffold & Infrastructure

This model describes the core application flows for the frontend scaffold based on your choices:

  • Package manager: pnpm
  • Router: TanStack Router
  • UI: Tailwind v4 + shadcn/ui (primary color #ac0000)
  • HTTP: Fetch-based ApiClient with credentials: 'include'
  • Session: Silent refresh on app mount (httpOnly cookie), access token in memory
  • Lint/format: ESLint + Prettier (4 spaces indentation)

1) App Initialization + Silent Refresh (Session Bootstrap)

sequenceDiagram
    participant A as App (main.tsx)
    participant R as Router (TanStack)
    participant C as AuthContext
    participant H as ApiClient (fetch)
    participant B as Backend API

    A->>R: Create Router + Providers
    A->>H: silentRefresh() with credentials: include
    H->>B: POST /api/v1/auth/refresh (cookie only)
    alt 200 OK
        B-->>H: { accessToken, expiresAt, user }
        H-->>C: setAuth(user, accessToken, expiresAt)
        C-->>R: set state: authenticated
    else 401 Unauthorized
        B-->>H: 401
        H-->>C: clearAuth()
        C-->>R: set state: guest
    end

Text alternative: Bij het starten vraagt de app een silent refresh via cookie; bij succes wordt de gebruiker/auth-state gezet, anders blijft de app in guest-modus.

2) Protected Request Flow with 401 Intercept + Retry

graph LR
    UI[UI Component<br/>useAuth/useQuery] -->|call ApiClient| API[ApiClient fetch<br/>Authorization: Bearer]
    API -->|200 OK| OK[Resolve Promise]
    API -->|401| RFR[Try Refresh via Cookie]
    RFR -->|200 OK| TOK[Update in-memory token]
    TOK --> RETRY[Retry original request]
    RFR -->|401| OUT[Clear auth + Redirect /login]

    classDef ui fill:#c6f6d5,stroke:#22543d,stroke-width:2px,color:#22543d;
    classDef infra fill:#cbd5e0,stroke:#1a202c,stroke-width:2px,color:#1a202c;
    classDef ok fill:#9ae6b4,stroke:#22543d,stroke-width:2px,color:#22543d;
    classDef warn fill:#fde68a,stroke:#92400e,stroke-width:2px,color:#92400e;
    classDef err fill:#feb2b2,stroke:#742a2a,stroke-width:2px,color:#742a2a;

    class UI ui;
    class API infra;
    class OK ok;
    class RFR warn;
    class TOK ok;
    class RETRY infra;
    class OUT err;

Text alternative: Een beveiligd verzoek gebruikt het in-memory access token; bij 401 wordt een refresh via cookie geprobeerd en vervolgens herhaald; als dat faalt volgt een logout/redirect.

3) Routing Shell (Layouts + Guards)

graph TD
    Root[__root.tsx<br/>Providers: QueryClient + AuthContext] --> Guard[Init/Silent Refresh]
    Guard -->|guest| Pub[Public routes: /login, /setup]
    Guard -->|auth| Auth[_authenticated.tsx<br/>AppLayout + Sidebar]
    Auth --> Dash[Dashboard]
    Auth --> Users[Users]
    Auth --> Profile[Profile]

    
    classDef rootElement fill:#e9d5ff,stroke:#6b21a8,stroke-width:2px,color:#6b21a8;
    classDef guard fill:#fde68a,stroke:#92400e,stroke-width:2px,color:#92400e;
    classDef route fill:#c6f6d5,stroke:#22543d,stroke-width:2px,color:#22543d;

    class Root rootElement;
    class Guard guard;
    class Pub,Auth,Dash,Users,Profile route;

Text alternative: De root route initialiseert providers; een guard bepaalt guest vs authenticated en leidt naar publieke of beschermde routes (AppLayout met Sidebar).