Files
L-Ami-Fiduciaire/docs/architecture.md

201 lines
9.9 KiB
Markdown
Raw Permalink Normal View History

# Architecture — L'Ami Fiduciaire
> Generated: 2026-03-08 | Scan Level: Quick
## Executive Summary
L'Ami Fiduciaire is a full-stack web application built for fiduciary/accounting firm client management. It provides a multi-tenant workspace system where firms can manage clients, folders (dossiers), and document exchanges with external clients via email-based invitation links.
The application follows a **server-driven SPA** architecture using Laravel 12 as the backend with Inertia.js v2 bridging to a Vue 3 frontend. This eliminates the need for a separate API layer — controllers render Vue pages directly via Inertia, while Wayfinder generates TypeScript route functions for type-safe navigation.
## Architecture Pattern
**Pattern:** Full-Stack Monolith with Server-Driven SPA (Inertia.js)
```
┌─────────────────────────────────────────────────────┐
│ Browser (SPA) │
│ Vue 3 + TypeScript + Tailwind CSS 4 + shadcn-vue │
│ Inertia.js Client → Page Components │
└──────────────────────┬──────────────────────────────┘
│ XHR / Inertia Protocol
┌──────────────────────▼──────────────────────────────┐
│ Laravel 12 (PHP 8.4) │
│ ┌─────────────────────────────────────────────┐ │
│ │ Middleware Pipeline │ │
│ │ (Auth, Workspace, Admin, Inertia, etc.) │ │
│ └──────────────────┬──────────────────────────┘ │
│ ┌──────────────────▼──────────────────────────┐ │
│ │ Controllers → Inertia::render('Page', props)│ │
│ └──────────────────┬──────────────────────────┘ │
│ ┌──────────────────▼──────────────────────────┐ │
│ │ Eloquent ORM → Models + Relationships │ │
│ └──────────────────┬──────────────────────────┘ │
└──────────────────────┼──────────────────────────────┘
┌──────────────────────▼──────────────────────────────┐
│ MySQL 8.4 (via Docker/Sail) │
└─────────────────────────────────────────────────────┘
```
## Technology Stack
| Category | Technology | Version |
|----------|-----------|---------|
| Backend Framework | Laravel | 12.x |
| Backend Language | PHP | 8.2+ (8.4 runtime) |
| Frontend Framework | Vue.js | 3.5+ |
| Frontend Language | TypeScript | 5.2+ |
| SPA Bridge | Inertia.js | v2 |
| CSS Framework | Tailwind CSS | 4.x |
| UI Components | shadcn-vue (reka-ui) | 2.4+ |
| Build Tool | Vite | 7.x |
| Database | MySQL | 8.4 |
| Authentication | Laravel Fortify | v1 |
| Route Generation | Laravel Wayfinder | 0.1.x |
| File Management | Spatie Media Library | 11.x |
| Activity Logging | Spatie Activity Log | 4.x |
| Enums | bensampo/laravel-enum | 6.x |
| Testing | Pest | 4.x |
| Code Style (PHP) | Laravel Pint | 1.x |
| Code Style (JS) | ESLint 9 + Prettier 3 | - |
| Containerization | Docker / Laravel Sail | - |
| WebSockets | Soketi | latest |
| Mail Testing | Mailpit | latest |
## Data Architecture
### Eloquent Models
| Model | Table | Key Relationships |
|-------|-------|-------------------|
| User | users | belongsToMany(Workspace), hasMany(Client) |
| Workspace | workspaces | belongsToMany(User) via WorkspaceUser |
| WorkspaceUser | workspace_user | Pivot: user_id, workspace_id, role |
| Client | clients | belongsTo(Workspace), hasMany(Folder) |
| Folder | folders | belongsTo(Client), hasMany(Message), hasMany(FolderInvitation), media |
| FolderInvitation | folder_invitations | belongsTo(Folder) — token-based access |
| Message | messages | belongsTo(Folder) |
### Business Enums
| Enum | Purpose |
|------|---------|
| ActorType | Distinguishes user types in activity logs |
| ClientStatus | Client lifecycle status |
| FolderPriority | Folder urgency level |
| FolderStatus | Folder workflow status |
| FolderType | Category of folder/dossier |
| LegalForm | Legal entity type for clients |
| MessageType | Type of message in folder |
| UserGroup | User permission group |
| WorkspaceUserRole | Role within a workspace |
### Database Migrations (16 files)
- Core: users, cache, jobs tables
- Auth: two-factor columns on users
- Multi-tenant: workspaces, workspace_user
- Business: clients, folders, folder_invitations, messages
- Packages: activity_log, media tables
- Extensions: confirmation fields on folders, responsable/suivi fields on clients
## Authentication & Authorization
- **Laravel Fortify** provides headless auth: login, registration, password reset, email verification, two-factor authentication (TOTP)
- **Custom Middleware:**
- `EnsureUserIsAdmin` — Admin-only route protection (users, workspaces management)
- `EnsureUserHasWorkspace` — Workspace context enforcement
- `ValidateFolderInvitation` — Token-based access for external client portal
- `HandleInertiaRequests` — Shares auth/workspace data with frontend
- `HandleAppearance` — Theme/appearance persistence
## Route Architecture
### Authenticated Routes (auth + verified)
- `GET /dashboard` — DashboardController (invokable)
- `POST /workspace/switch` — WorkspaceSwitchController (invokable)
### Workspace-Scoped Routes (auth + verified + workspace)
- `CRUD /clients` — ClientController (resource)
- `CRUD /folders` — FolderController (resource)
- `POST /folders/{folder}/messages` — FolderMessageController
- `POST /folders/{folder}/media` — FolderMediaController (upload)
- `GET /folders/{folder}/media/{mediaId}` — FolderMediaController (download)
### Admin Routes (auth + verified + admin)
- `CRUD /users` — UserController (resource)
- `CRUD /workspaces` — WorkspaceController (resource)
### Public Client Portal (/c/ prefix, folder.invitation middleware)
- `GET|POST /c/upload/{token}` — Client file upload
- `GET|POST /c/confirm/{token}` — Client folder confirmation
- `GET|POST /c/refuse/{token}` — Client folder refusal
### Settings Routes (auth / auth+verified)
- `GET|PATCH /settings/profile` — Profile management
- `DELETE /settings/profile` — Account deletion
- `GET|PUT /settings/password` — Password change (throttled)
- `GET /settings/appearance` — Appearance/theme settings
- `GET /settings/two-factor` — Two-factor authentication management
## Email System
5 folder-related mailables handle client communication:
- **FolderInviteMail** — Invitation to access a folder
- **FolderFileRequestMail** — Request for file upload
- **FolderConfirmationMail** — Folder confirmation notification
- **FolderSituationMail** — Folder status update
- **FolderTextMessageMail** — Text message notification
## Frontend Architecture
### Component Organization
- **Pages** (31 Vue components): Mapped to routes via Inertia, organized by domain (auth, clients, folders, users, workspaces, settings, client portal)
- **Layouts** (8 components): AppLayout (sidebar/header variants), AuthLayout (card/simple/split variants), SettingsLayout
- **UI Components**: shadcn-vue design system with 20+ component groups (Button, Card, Dialog, Dropdown, Input, Select, Table, Tabs, Tooltip, etc.)
- **Business Components**: ClientForm, FolderForm, UserForm, WorkspaceForm, WorkspaceSwitcher, Pagination
- **Composables** (4): useAppearance, useCurrentUrl, useInitials, useTwoFactorAuth
### State Management
- No client-side store (Redux/Pinia) — state is server-driven via Inertia props
- `useForm()` from Inertia handles form state and submission
- Composables for shared client-side logic
### Type System
- TypeScript strict mode across all frontend code
- Type definitions in `resources/js/types/` (auth, navigation, UI types)
- Wayfinder generates typed route functions
## Testing Strategy
- **Framework:** Pest 4 (PHPUnit 12 compatible)
- **Test Suites:** Feature (13 test files) + Unit
- **Coverage Areas:** Authentication, settings, dashboard, user groups
- **Factories:** Model factories for test data generation
- **CI Matrix:** PHP 8.4 and 8.5
## CI/CD Pipeline
### Lint Workflow (`lint.yml`)
- Triggers: push/PR to develop, main, master, workos
- Steps: PHP setup → Composer install → npm install → Pint → Prettier → ESLint
### Test Workflow (`tests.yml`)
- Triggers: push/PR to develop, main, master, workos
- Matrix: PHP 8.4, 8.5
- Steps: PHP setup → Node 22 → Composer install → npm install → env setup → key generation → Vite build → Pest
## Deployment Configuration
### Docker Compose (Laravel Sail)
- **laravel.test** — PHP 8.5 application container (port 80, Vite 5173)
- **mysql** — MySQL 8.4 database (port 3306)
- **mailpit** — Email testing UI (ports 1025, 8025)
- **soketi** — WebSocket server / Pusher-compatible (port 6001)
### SSR Support
- Inertia SSR is enabled (`inertia.php``ssr.enabled = true`)
- SSR entry point: `resources/js/ssr.ts`
- SSR server URL: `http://127.0.0.1:13714`