# Lovelii System Architecture

## Purpose and current scope

Lovelii is a private one-to-one messaging interface built from the design handoff in
`design/`. The current application is a working UI prototype with real authentication
and profile identity storage. It is not yet a real-time or end-to-end encrypted
messaging system.

## Technology

- Laravel 13 and PHP 8.3+
- Inertia 3 with Vue 3.5 and Vite 8
- Tailwind CSS 4, configured in `resources/css/app.css`
- MySQL for application data; PHPUnit 12 for feature tests

## Request and rendering flow

`routes/web.php` divides guest authentication routes from routes requiring a session.
Controllers validate requests, perform application work, and render Inertia pages or
redirect. `HandleInertiaRequests` shares the authenticated user's public identity and
flash messages. `resources/js/app.js` resolves page names under `resources/js/Pages`.

The chat and profile pages use `Layouts/AppLayout.vue` with the shared sidebar and
header. Login and registration use `Layouts/GuestLayout.vue`. Calls use full-screen
pages without the dashboard shell. Shared design tokens live in the CSS `@theme`
block; components should use those tokens and existing shared components.

## Domain model

- `User` stores credentials, editable identity, and private profile photo and cover-photo
  paths. Authenticated users receive profile images through a controlled media route.
- `Conversation` represents a unique pair of users. Participant IDs are stored in
  ascending order; `Conversation::between()` is the canonical lookup/create path.
- `Message` belongs to a conversation and sender and supports text, voice, image, and
  video metadata.

The database schema and Eloquent models provide durable chat storage. Registered users
can be browsed or searched by name or handle, and a one-to-one conversation is created
between the two accounts when connected. Messages are read and written through the conversation's
Eloquent relationship. Active chat pages refresh through Inertia polling every few
seconds. Voice notes are recorded in the browser, uploaded as multipart requests, and
stored on Laravel's private local disk behind participant-checked routes. Senders can
mark text, voice notes, photos, and videos View Once; access is recipient-only, the sender
sees an Opened receipt, and private media is deleted when opened. Photos are limited to
10 MB; videos and supported document files are limited to 16 MB. Documents are
download-only. PHP upload limits are set in `public/.user.ini`.
No WebSocket broadcast transport or end-to-end-encryption protocol is configured.

## Current behavior and boundaries

- Login, registration, logout, and route access use Laravel session authentication.
- Profile identity updates persist in `users`; the connection panel shows the latest
  persisted conversation or an empty state.
- Profile and cover photos are uploaded to private storage and appear in user search, chat,
  account navigation, and profile/connection views.
- Clicking the signed-in user's avatar opens a read-only My Profile page; Profile & Presence
  opens the editable settings page. Clicking a chat partner's avatar opens their read-only
  profile, limited to existing conversation partners.
- Message and conversation timestamps are sent as UTC instants and formatted in each
  viewer's browser time zone.
- Conversations and sent text messages and voice-note metadata are stored in the database
  and scoped to their registered participants. Voice audio remains private. There are no
  seeded chat contacts or starter transcripts.
- Text, voice notes, photos, and videos can be marked View Once. The recipient gets one
  server-enforced reveal or playback, then the message shows Opened.
- Audio/video pages remain visual previews without call transport. Chat updates use
  short-interval polling, so delivery is near-current rather than push-based instant.
- The reference designs include encryption language, but no cryptographic protocol is
  implemented. Keep live UI copy aligned with implemented behavior.

## Data and authorization rules

- All chat routes require authentication.
- A conversation must be associated with the current user before reading or writing
  messages. Never trust a client-supplied sender ID as authorization.
- Validate message kind and content at the HTTP boundary. Take the sender from the
  authenticated session, and use Eloquent relationships for persistence.
- Keep output props deliberately shaped for the Vue components; do not serialize
  credentials or internal user records to the browser.
- Search results include only registered accounts other than the current user and never
  expose email addresses to other users.

## Main code map

| Concern | Location |
| --- | --- |
| Routes | `routes/web.php` |
| HTTP controllers | `app/Http/Controllers/` |
| Chat behavior | `app/Support/ChatService.php` |
| Eloquent models | `app/Models/` |
| Database schema and demo account | `database/migrations/`, `database/seeders/` |
| Inertia pages and shared components | `resources/js/Pages/`, `resources/js/Components/` |
| Layouts and Tailwind theme | `resources/js/Layouts/`, `resources/css/app.css` |
| Design references | `design/`, `docs/` |

## Direction for future system design

Next, replace short-interval refresh with a WebSocket broadcast transport. Each slice should preserve authentication and participant
authorization and define its data contract. End-to-end encryption requires a separately
reviewed protocol and key lifecycle; UI labels alone are not encryption.
