# Architecture

## Overview

The `IamClient` is the central entry point. It creates a shared `HttpClient` and instantiates one service per IAM entity:

```
IamClient
  ├── http: HttpClient          (shared fetch + auth headers + response validation)
  ├── auth: AuthService          → /auth/*
  ├── users: UserService         → /users/*
  ├── tenants: TenantService     → /tenants/*
  ├── projects: ProjectService   → /projects/*
  ├── roles: RoleService         → /roles/*
  └── devices: DeviceService     → /devices/*
```

## HttpClient

All services share a single `HttpClient` instance that handles:

- **Automatic authentication**: reads the token from storage and adds the `Authorization: Bearer <token>` header
- **API key support**: if configured, sends the `x-api-key` header on every request
- **JSON serialization**: request body is automatically serialized; responses are parsed as JSON
- **Error handling**: HTTP 401/403 throw `FailureResponse.handled()`; other HTTP errors throw `FailureResponse.unhandled()`

### Two request methods

| Method                                 | Behavior                                                                                        |
| -------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `request<T>(path, options)`            | Raw HTTP request. Returns parsed JSON. Throws on HTTP errors.                                   |
| `requestAndValidate<T>(path, options)` | Same as `request()` but also verifies `responseCode === 'ok'`. Throws `FailureResponse` if not. |

All CRUD services use `requestAndValidate()`. The `AuthService` uses raw `fetch` directly for endpoints that require `application/x-www-form-urlencoded` content type.

### Request options

```typescript
type HttpRequestOptions = {
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
  body?: any;
  contentType?: 'json' | 'form';
  authenticated?: boolean; // default: true
  queryParams?: Record<string, string | number | boolean | undefined>;
};
```

## Project Structure

```
src/
  core/
    iam-client.ts              # IamClient class + createIamClient() factory
    http-client.ts             # Shared HttpClient
    errors.ts                  # FailureResponse
    services/
      auth.service.ts          # Authentication, session, impersonation, PIN
      user.service.ts          # User CRUD, roles, tenant/project assignment
      tenant.service.ts        # Tenant CRUD
      project.service.ts       # Project CRUD
      role.service.ts          # Role CRUD
      device.service.ts        # Device CRUD
    types/
      common.ts                # BaseResponse, Page<T>, IStorage, IamClientConfig
      auth.types.ts            # Auth DTOs
      user.types.ts            # User DTOs
      tenant.types.ts          # Tenant DTOs
      project.types.ts         # Project DTOs
      role.types.ts            # Role DTOs
      device.types.ts          # Device DTOs
    storage/
      local-storage.ts         # LocalStorage (browser)
      memory-storage.ts        # MemoryStorage (Node.js / testing)
    crypto/
      aes-util.ts              # AES encryption for PIN login
      base64.ts                # Base64 utility
  react-admin/
    auth-provider.ts           # ApplicaAuthProvider (thin wrapper over IamClient)
    types.ts                   # IApplicaAuthProvider interface
  index.ts                     # Main entry point (core + react-admin)
```
