> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wethehivers.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Cycle de vie d'un recruteur

> États d'un compte recruteur, validation admin et règles

# Cycle de vie d'un recruteur

Un compte recruteur ne peut publier d'offres qu'après **double validation** : email + admin.

## Diagramme d'états complet

```mermaid theme={null}
stateDiagram-v2
    [*] --> PENDING_EMAIL_VERIFICATION: POST /recruiters/register
    PENDING_EMAIL_VERIFICATION --> PENDING_ADMIN_APPROVAL: GET /auth/validate-email
    PENDING_EMAIL_VERIFICATION --> PENDING_EMAIL_VERIFICATION: resend-validation-email

    PENDING_ADMIN_APPROVAL --> ACTIVE: admin approve
    PENDING_ADMIN_APPROVAL --> REJECTED: admin reject

    REJECTED --> PENDING_ADMIN_APPROVAL: admin revalidate

    ACTIVE --> SUSPENDED: admin suspend
    SUSPENDED --> ACTIVE: admin reactivate

    ACTIVE --> DEACTIVATED: user delete own account
    DEACTIVATED --> [*]

    note right of PENDING_EMAIL_VERIFICATION
        Aucune action possible
    end note
    note right of PENDING_ADMIN_APPROVAL
        Email OK, attente admin
    end note
    note right of ACTIVE
        Peut publier des offres
    end note
```

## États

| État                         | Peut publier | Peut login          | Peut recevoir candidatures     |
| ---------------------------- | ------------ | ------------------- | ------------------------------ |
| `PENDING_EMAIL_VERIFICATION` | Non          | Non                 | Non                            |
| `PENDING_ADMIN_APPROVAL`     | Non          | Oui (lecture seule) | Non                            |
| `ACTIVE`                     | Oui          | Oui                 | Oui                            |
| `REJECTED`                   | Non          | Oui (voir motif)    | Non                            |
| `SUSPENDED`                  | Non          | Non                 | Non (offres passées en CLOSED) |
| `DEACTIVATED`                | Non          | Non                 | Non                            |

## Inscription complète

```mermaid theme={null}
sequenceDiagram
    autonumber
    participant R as Recruteur
    participant API as Backend
    participant M as MailService
    participant A as Admin
    participant DB as DB

    R->>API: POST /v1/api/recruiters/register\n {email, pw, firstName, lastName, phone,\n   entreprise: {nom, rccm, secteur, ville, ...}}
    API->>DB: INSERT users (status=PENDING_EMAIL)\n INSERT recruteurs\n INSERT entreprises
    API->>M: Envoi email validation\n (lien token 24h)
    API-->>R: 201 Created

    R->>API: GET /v1/api/auth/validate-email?token=
    API->>DB: UPDATE users SET status=PENDING_APPROVAL
    API->>M: Notification admins\n "Nouveau recruteur"
    API-->>R: 200 OK

    A->>API: GET /v1/api/admin/recruiters?status=PENDING_APPROVAL
    A->>API: POST /v1/api/admin/recruiters/42/approve
    API->>DB: UPDATE status=ACTIVE
    API->>M: Email recruteur: "Validé"
    API-->>A: 200 OK

    R->>API: POST /v1/api/auth/login
    API-->>R: 200 {accessToken, refreshToken}

    R->>API: POST /v1/api/offres (titre, desc, ...)
    API-->>R: 201 DRAFT
```

## Validation admin — critères

```mermaid theme={null}
flowchart TD
    A[Admin ouvre fiche recruteur] --> V1{Email domaine\n = email entreprise?}
    V1 --> V2{RCCM / registre\n cohérent avec nom?}
    V2 --> V3{Site web existe\n et cohérent?}
    V3 --> V4{LinkedIn entreprise\n présent?}
    V4 --> V5{Secteur plausible?}
    V5 --> D{Décision}
    D -->|Approuver| APP[POST /approve]
    D -->|Rejeter| REJ[POST /reject + motif]
    D -->|Demander infos| REQ[Email manuel hors-API]
```

<Info>
  La validation admin vise à éviter les **fausses offres**. Les critères ne sont pas automatisables — jugement humain requis.
</Info>

## Motifs de rejet fréquents

| Motif                                  | Recours                                  |
| -------------------------------------- | ---------------------------------------- |
| RCCM invalide ou introuvable           | Fournir justificatif par email support   |
| Entreprise inexistante en ligne        | Fournir preuves d'activité               |
| Email non professionnel (gmail, yahoo) | Utiliser email `@entreprise.com`         |
| Doublon d'entreprise                   | Contacter admin existant de l'entreprise |
| Activité non conforme                  | Irrévocable                              |

## Revalidation après rejet

```mermaid theme={null}
sequenceDiagram
    participant R as Recruteur rejeté
    participant S as Support
    participant A as Admin
    participant API as Backend

    R->>S: Email à support@wethehivers.com\n avec justificatifs
    S->>A: Transfert dossier
    A->>API: POST /v1/api/admin/recruiters/42/revalidate
    API-->>A: status=PENDING_APPROVAL
    A->>A: Re-examen + approve ou reject
```

## Suspension

Un recruteur peut être suspendu pour :

* Publication d'offres frauduleuses répétées
* Contact direct des candidats hors-plateforme (bypass)
* Violation RGPD signalée
* Plainte candidat confirmée

```mermaid theme={null}
flowchart LR
    I[Incident signalé] --> R[Review admin]
    R --> DEC{Décision}
    DEC -->|Warning| W[Email warning]
    DEC -->|Suspend 30j| S30[SUSPENDED 30j\n reactivate auto]
    DEC -->|Suspend permanent| SP[SUSPENDED sans date]
    DEC -->|Ban| BAN[DEACTIVATED\n + IP ban]

    S30 --> OFF[Toutes offres PUBLISHED → CLOSED]
    SP --> OFF
    BAN --> OFF
```

## Multi-recruteurs par entreprise

Une entreprise peut avoir plusieurs recruteurs. Le premier recruteur inscrit est le **propriétaire** (owner), les suivants sont rattachés en tant que `MEMBER`.

```mermaid theme={null}
erDiagram
    ENTREPRISE ||--o{ RECRUTEUR : "a"
    RECRUTEUR {
        long id
        string role "OWNER | MEMBER"
        long entrepriseId
    }
```

```mermaid theme={null}
flowchart TD
    E[Entreprise existante] --> R2[2e recruteur s'inscrit\n avec même RCCM]
    R2 --> D[Backend détecte doublon RCCM]
    D --> Q{Owner accepte?}
    Q -->|oui| M[Ajouté en MEMBER]
    Q -->|non| REJ[Inscription rejetée]
```

## Permissions intra-entreprise

| Action                           | OWNER | MEMBER |
| -------------------------------- | ----- | ------ |
| Publier offre                    | Oui   | Oui    |
| Éditer offre (la sienne)         | Oui   | Oui    |
| Éditer offre (d'un collègue)     | Oui   | Non    |
| Modifier logo / infos entreprise | Oui   | Non    |
| Inviter nouveau recruteur        | Oui   | Non    |
| Révoquer membre                  | Oui   | Non    |
| Supprimer compte entreprise      | Oui   | Non    |

## Audit trail

Toutes les transitions sont loggées :

```sql theme={null}
CREATE TABLE recruiter_status_history (
  id BIGSERIAL PRIMARY KEY,
  recruiter_id BIGINT,
  from_status VARCHAR(30),
  to_status VARCHAR(30),
  reason TEXT,
  changed_by BIGINT,
  changed_at TIMESTAMPTZ DEFAULT NOW()
);
```

Accessible via `GET /v1/api/admin/recruiters/{id}/status-history`.
