Quand un module doit en déclencher un autre — un formulaire qui crée une tâche dans Work, une candidature retenue qui provisionne un employé dans RH — l'appel passe par une route interne protégée par un secret partagé, jamais par l'API publique.
Principe¶
Forms ──POST {Work}/api/work/internal/ingest──► Work
en-tête : X-Internal-Secret: <secret partagé>
corps : { tenantId, title, description, projectId? }
- La route interne est
[AllowAnonymous](pas de JWT), mais exige le secret. - Le tenant est porté par le corps de la requête (puisqu'il n'y a pas de JWT).
- Fail-closed : si le secret n'est pas configuré côté récepteur, la route est fermée (401). Le même secret doit être renseigné des deux côtés.
Best-effort¶
Les ponts sont best-effort : si le module cible est indisponible, l'action principale
n'échoue pas. Exemple : une soumission de formulaire est toujours enregistrée même si Work
est momentanément injoignable ; l'workItemId reste simplement nul.
Ponts existants¶
| Source → Cible | Route interne | Effet |
|---|---|---|
| Forms → Work | POST /api/work/internal/ingest | Crée une tâche/ticket depuis une soumission |
| Careers → RH | POST /api/rh/internal/employees | Provisionne un employé quand un candidat est embauché |
| Cloud (usage) | POST /api/cloud/internal/usage | Comptabilise le quota de stockage |
| Docs / Slides | POST /api/docs/internal/provision, /api/slides/internal/* | Provision/rename/delete de documents |
| Connect | POST /api/connect/internal/* | Indexation, recherche et suppression transverses |
| IA (serveurs) | POST /api/ai/internal/infer | Inférence IA pour les services non-web (ex. VR) |
| Hub (activité) | POST /api/internal/activity-sync | Synchronisation d'activité |
| Chat | POST /api/internal/messages-sync | Synchronisation de messages |
Convention d'implémentation¶
- En-tête :
X-Internal-Secret. - Lecture du corps brut quand une signature est en jeu (webhooks) — ne pas laisser un
[FromBody]consommer le flux avant vérification. - Un secret vide côté récepteur = route fermée (401), pas ouverte : c'est volontaire.
Réseau¶
En production, les services se joignent par leur nom interne (work-api, ia-api,
rh-api…) sur le réseau plateforme, et non par leur domaine public. Le secret et l'URL
cible sont fournis par configuration (ex. Work__BaseUrl, Work__InternalSecret).