---
auto_generated: true
created: 2026-05-18
manual_updated_at: 2026-05-18
modified: 2026-05-18
name: Developer_Manual
status: active
tags:
- client/loreal
- domain/analytics
- domain/security
- tech/azure-ad
- tech/docker
- tech/node
- tech/postgresql
- type/sop
type: sop
---

# L'Oréal SLA Calculator Developer Manual

## Architecture Overview
The application is a hybrid architecture:
- **Frontend**: Vanilla JavaScript/HTML applications (`index.html`, `client.html`) that fetch configuration and track user events.
- **Backend**: A Node.js/Express server handling authentication (MSAL SSO), JWT verification, and anonymous event tracking.
- **Infrastructure**: Dockerized deployment with PostgreSQL for potential future state persistence (though current logic is largely client-side/config-driven).

## Tech Stack
- **Frontend**: HTML5, CSS3, Vanilla JS, Flatpickr (date picker).
- **Backend**: Node.js, Express.js, MSAL.js (for SSO), JWT, Cookie Parser.
- **Database**: PostgreSQL 16 (Alpine image).
- **Deployment**: Docker Compose.

## Local Setup

1. **Clone the repository**.
2. **Install Dependencies**:
   ```bash
   npm install
   ```
3. **Environment Configuration**:
   Create a `.env` file in the `server/` directory. Required variables typically include:
   - `PORT`: Port for the Node app (default 3000).
   - `POSTGRES_USER`, `POSTGRES_DB`: Database credentials.
   - `JWT_SECRET`: Secret for token verification.
   - `MSAL_*`: Client ID and Authority details (found in `auth.js` configuration object).
4. **Run the Application**:
   ```bash
   # For development (local host bypasses auth)
   npm start
   ```

## Environment Variables
| Variable | Description | Required |
|----------|-------------|----------|
| `PORT` | App listening port (3100 in prod) | Yes |
| `NODE_ENV` | `development` or `production` | Yes |
| `SERVE_STATIC` | Set to `false` if behind Apache/Nginx | Yes |
| `POSTGRES_*` | DB connection details | Yes |
| `JWT_SECRET` | Signing secret for access tokens | Yes |

## Key Services & Entry Points

### Authentication (`server/middleware/auth.js` & `auth.js`)
- **Flow**: Handles MSAL redirect, silent refresh via httpOnly cookies, and password fallback.
- **Token Storage**: Access tokens are kept in memory only (`currentAccessToken`) for security.
- **Verification**: `verifyAccessToken` in `services/jwtService.js` validates Bearer tokens.

### Configuration (`config.json`)
- The single source of truth for business logic.
- Contains:
  - Brief types and their stage matrices.
  - Production cross-reference tables (Complexity x Volume).
  - Syndication tables (Complexity x EAN Volume).
  - Translation word count ranges.
- **Versioning**: The frontend caches this file; update the cache-busting query param in `loadConfig()` if immediate updates are needed.

### Usage Tracking (`server/routes/events.js`)
- **Anonymous Fingerprinting**: Uses `crypto.subtle.digest` on non-PII navigator/screen data to generate a stable `visitor_id`.
- **API**: POST to `/api/events` with `{ event, page, visitor_id, metadata }`.
- **Dev Mode**: Tracking is disabled on `localhost`.

### Backend Server (`server/index.js`)
- Serves `/api/auth` and `/api/events`.
- Provides `/api/health`.
- Conditionally serves static files if `SERVE_STATIC` is not `false`.

## API Reference

### Auth
- `POST /api/auth/login`: Handles email/password login.
- `GET /api/auth/msal`: Initiates MSAL flow (handled client-side via redirect).

### Events
- `POST /api/events`: Accepts usage telemetry. Payload: `{ event: string, page: string, visitor_id: string, metadata: object }`.

### Health
- `GET /api/health`: Returns `{ status: 'ok' }`.

## Deployment
1. **Docker Compose**: The `docker-compose.yml` defines two services:
   - `postgres`: PostgreSQL 16 with persistent volume `postgres_data`.
   - `app`: Builds from the root `Dockerfile` and maps port 3100.
2. **Reverse Proxy**: In production, the app runs behind Apache/Nginx (`SERVE_STATIC=false`). The proxy handles static file delivery and reverse proxies `/loreal-sla-calculator/api/*` to the Node app.
3. **SSO Config**: Ensure the redirect URI in the Azure AD App Registration matches `window.location.origin + '/loreal-sla-calculator'`.

## Known Gotchas
- **Auth Bypass**: Authentication is explicitly bypassed on `localhost` and `127.0.0.1` for development convenience.
- **Token Refresh**: The frontend attempts one silent token refresh on 401 errors before logging the user out.
- **Config Caching**: Browsers may aggressively cache `config.json`. Use the timestamp query string (`?v=...`) to force updates during development.
- **Password Encoding**: Passwords are Base64 encoded before transmission in the legacy email/password flow to avoid WAF issues with special characters.

## Related
- [[01 Projects/olivas/DEVELOPER_MANUAL.md]]