instruction-des-dossiers
Interface synchrone (OpenAPI) — version 0.2.0. Producteur : conformite. Consommateurs déclarés : backoffice.
Le modèle est mixte — une grande part des modifications vient des utilisateurs : ouvrir un dossier, annoter le journal, qualifier une alerte, relier des dossiers, consigner une décision. Toute interface est authentifiée (401) ; le refus (403) est prononcé par le point d’application de la politique, dont le modèle peut évoluer sans toucher au contrat.
La spécification
Section intitulée « La spécification »openapi: 3.1.0info: title: conformite — instruction des dossiers version: 0.2.0 x-ruptures: - version: 0.2.0 rupture: "chemins déplacés : le préfixe /tenants/{tenant} disparaît de tous les chemins" motif: >- Le tenant n'entre jamais dans le chemin d'une interface : il est résolu à l'assemblage — routage par l'hôte, audience du jeton — jamais par une donnée d'appel. Le paramètre de chemin tenant disparaît avec le préfixe. summary: >- Consulter et conduire l'instruction : dossiers, journal typé, alertes et leur qualification, liaisons, décisions. description: >- Le modèle est mixte — une grande part des modifications vient des utilisateurs : ouvrir un dossier, annoter le journal, qualifier une alerte, relier des dossiers, consigner une décision. Toute interface est authentifiée (401) ; le refus (403) est prononcé par le point d'application de la politique, dont le modèle peut évoluer sans toucher au contrat. x-producteurs: - conformite x-consommateurs: - backofficepaths: /dossiers: get: operationId: rechercherDesDossiers summary: Rechercher des dossiers par attributs du domaine. security: [ { authentification: [conformite:dossiers] } ] parameters: - name: finalite in: query schema: { $ref: '#/components/schemas/Finalite' } - name: etat in: query schema: { $ref: '#/components/schemas/EtatDossier' } - name: sujet in: query description: Identifiant publié d'un sujet référencé par le dossier. schema: { type: string } - name: ouvert_depuis in: query schema: { type: string, format: date } - $ref: '#/components/parameters/page' responses: '200': description: La page de dossiers visibles de l'appelant (filtrage par le PEP). content: application/json: schema: { $ref: '#/components/schemas/PageDeDossiers' } '400': { $ref: '#/components/responses/Irrecevable' } '401': { $ref: '#/components/responses/NonAuthentifie' } '403': { $ref: '#/components/responses/NonAutorise' } post: operationId: ouvrirUnDossier summary: Ouvrir un dossier — motif, finalité, périmètre par références. description: >- Un dossier ne change jamais de finalité : pour une finalité nouvelle sur les mêmes faits, on ouvre un second dossier et on le relie. Idempotent par demande_id. security: [ { authentification: [conformite:dossiers] } ] requestBody: required: true content: application/json: schema: { $ref: '#/components/schemas/OuvertureDeDossier' } responses: '201': description: Le dossier est ouvert. content: application/json: schema: { $ref: '#/components/schemas/Dossier' } '400': { $ref: '#/components/responses/Irrecevable' } '401': { $ref: '#/components/responses/NonAuthentifie' } '403': { $ref: '#/components/responses/NonAutorise' } /dossiers/{dossier}: get: operationId: consulterUnDossier summary: Le détail d'un dossier — identité, périmètre, compteurs, épisode courant. description: >- Les dossiers liés n'apparaissent que par référence et état : une liaison ne propage aucun accès. Un dossier hors périmètre de l'appelant répond 404. security: [ { authentification: [conformite:dossiers] } ] parameters: - $ref: '#/components/parameters/dossier' responses: '200': description: Le dossier. content: application/json: schema: { $ref: '#/components/schemas/Dossier' } '401': { $ref: '#/components/responses/NonAuthentifie' } '403': { $ref: '#/components/responses/NonAutorise' } '404': { $ref: '#/components/responses/Inconnu' } /dossiers/{dossier}/journal: get: operationId: consulterLeJournal summary: Le journal d'instruction, chronologique et typé. security: [ { authentification: [conformite:dossiers] } ] parameters: - $ref: '#/components/parameters/dossier' - $ref: '#/components/parameters/page' responses: '200': description: La page d'éléments, du plus récent au plus ancien. content: application/json: schema: { $ref: '#/components/schemas/PageDeJournal' } '401': { $ref: '#/components/responses/NonAuthentifie' } '403': { $ref: '#/components/responses/NonAutorise' } '404': { $ref: '#/components/responses/Inconnu' } post: operationId: ajouterUnElementAuJournal summary: Ajouter un élément typé — jamais réécrire. description: >- L'élément déclare sa nature (fait source avec provenance, déclaration attribuée, résultat de contrôle, hypothèse, conclusion) et le serveur la conserve telle quelle. Une correction est un élément RECTIFICATIF qui pointe l'original (rectifie) ; l'original reste lisible. Idempotent par demande_id. security: [ { authentification: [conformite:dossiers] } ] parameters: - $ref: '#/components/parameters/dossier' requestBody: required: true content: application/json: schema: { $ref: '#/components/schemas/NouvelElement' } responses: '201': description: L'élément est au journal. content: application/json: schema: { $ref: '#/components/schemas/ElementDeJournal' } '400': { $ref: '#/components/responses/Irrecevable' } '401': { $ref: '#/components/responses/NonAuthentifie' } '403': { $ref: '#/components/responses/NonAutorise' } '404': { $ref: '#/components/responses/Inconnu' } /dossiers/{dossier}/liaisons: post: operationId: relierDeuxDossiers summary: Relier ce dossier à un autre — qualifié, daté, sans rien propager. description: >- La liaison porte sa nature et son motif ; elle n'ouvre pas le dossier lié, ne propage ni mesure, ni conclusion, ni conservation. Idempotent par demande_id. security: [ { authentification: [conformite:dossiers] } ] parameters: - $ref: '#/components/parameters/dossier' requestBody: required: true content: application/json: schema: { $ref: '#/components/schemas/NouvelleLiaison' } responses: '201': description: La liaison est établie. content: application/json: schema: { $ref: '#/components/schemas/Liaison' } '400': { $ref: '#/components/responses/Irrecevable' } '401': { $ref: '#/components/responses/NonAuthentifie' } '403': { $ref: '#/components/responses/NonAutorise' } '404': { $ref: '#/components/responses/Inconnu' } /dossiers/{dossier}/liaisons/{liaison}/revocation: post: operationId: revoquerUneLiaison summary: Révoquer une liaison par fait rectificatif — elle reste visible, inactive. security: [ { authentification: [conformite:dossiers] } ] parameters: - $ref: '#/components/parameters/dossier' - name: liaison in: path required: true schema: { type: string } requestBody: required: true content: application/json: schema: { $ref: '#/components/schemas/Revocation' } responses: '201': description: La liaison est révoquée ; son historique demeure. content: application/json: schema: { $ref: '#/components/schemas/Liaison' } '400': { $ref: '#/components/responses/Irrecevable' } '401': { $ref: '#/components/responses/NonAuthentifie' } '403': { $ref: '#/components/responses/NonAutorise' } '404': { $ref: '#/components/responses/Inconnu' } /dossiers/{dossier}/decisions: post: operationId: consignerUneDecision summary: Consigner une décision d'instruction — datée, motivée, signée. description: >- Classement, réouverture (nouvel épisode, conclusion précédente intacte), examen renforcé, demande de pièce, escalade. Selon la politique en vigueur, une décision peut rester SUSPENDUE à une seconde validation (réponse 202) — la politique appartient au PEP et au cœur, pas au contrat. Idempotent par demande_id. security: [ { authentification: [conformite:dossiers] } ] parameters: - $ref: '#/components/parameters/dossier' requestBody: required: true content: application/json: schema: { $ref: '#/components/schemas/NouvelleDecision' } responses: '201': description: La décision est consignée. content: application/json: schema: { $ref: '#/components/schemas/Decision' } '202': description: La décision est suspendue à une seconde validation. content: application/json: schema: { $ref: '#/components/schemas/Decision' } '400': { $ref: '#/components/responses/Irrecevable' } '401': { $ref: '#/components/responses/NonAuthentifie' } '403': { $ref: '#/components/responses/NonAutorise' } '404': { $ref: '#/components/responses/Inconnu' } /alertes: get: operationId: rechercherDesAlertes summary: Les alertes — dont celles à trier (sans dossier). security: [ { authentification: [conformite:dossiers] } ] parameters: - name: etat in: query schema: { $ref: '#/components/schemas/EtatAlerte' } - name: dossier in: query description: Restreindre aux alertes d'un dossier ; absent = toutes les visibles. schema: { type: string } - $ref: '#/components/parameters/page' responses: '200': description: La page d'alertes visibles de l'appelant. content: application/json: schema: { $ref: '#/components/schemas/PageDAlertes' } '400': { $ref: '#/components/responses/Irrecevable' } '401': { $ref: '#/components/responses/NonAuthentifie' } '403': { $ref: '#/components/responses/NonAutorise' } /alertes/{alerte}/qualification: post: operationId: qualifierUneAlerte summary: Qualifier une alerte — vers un dossier, classée motivée, ou annulée. description: >- Une alerte ne se supprime jamais. QUALIFIEE exige un dossier (existant ou ouvert dans le même geste, dossier_a_ouvrir) ; CLASSEE exige son motif codifié ; ANNULEE (créée par erreur) conserve le déclenchement et se compte à part des faux positifs. Idempotent par demande_id. security: [ { authentification: [conformite:dossiers] } ] parameters: - name: alerte in: path required: true schema: { type: string } requestBody: required: true content: application/json: schema: { $ref: '#/components/schemas/Qualification' } responses: '201': description: La qualification est enregistrée ; l'alerte et, le cas échéant, le dossier sont rendus. content: application/json: schema: { $ref: '#/components/schemas/ResultatDeQualification' } '400': { $ref: '#/components/responses/Irrecevable' } '401': { $ref: '#/components/responses/NonAuthentifie' } '403': { $ref: '#/components/responses/NonAutorise' } '404': { $ref: '#/components/responses/Inconnu' } '409': description: L'alerte n'est plus qualifiable (déjà classée ou annulée). content: application/json: schema: { $ref: '#/components/schemas/Erreur' }components: parameters: dossier: name: dossier in: path required: true description: Référence publiée du dossier. schema: { type: string } page: name: page in: query description: Curseur de pagination opaque, rendu par la page précédente. schema: { type: string } responses: NonAuthentifie: description: L'appelant n'est pas authentifié. content: { application/json: { schema: { $ref: '#/components/schemas/Erreur' } } } NonAutorise: description: Le point d'application de la politique refuse cette action sur ce périmètre. content: { application/json: { schema: { $ref: '#/components/schemas/Erreur' } } } Irrecevable: description: La demande est irrecevable — le motif nomme le champ. content: { application/json: { schema: { $ref: '#/components/schemas/Erreur' } } } Inconnu: description: L'objet est inconnu — ou hors du périmètre de l'appelant, sans distinction. content: { application/json: { schema: { $ref: '#/components/schemas/Erreur' } } } securitySchemes: authentification: type: openIdConnect openIdConnectUrl: https://exemple.invalid/.well-known/openid-configuration description: Exigence déclarée ici ; mécanisme décliné à l'assemblage. schemas: Finalite: type: string enum: [LCBFT, FRAUDE, SANCTIONS_GEL, REQUISITION, ECHANGE_REGLEMENTAIRE, CONTROLE] EtatDossier: type: string enum: [OUVERT, EN_INSTRUCTION, DECLARE, CLOTURE] EtatAlerte: type: string enum: [OUVERTE, A_AFFECTER, EN_ANALYSE, EN_ATTENTE_INFORMATION, QUALIFIEE, CLASSEE, ANNULEE] ReferenceVersionnee: type: object required: [domaine, type, identifiant, version] properties: domaine: { type: string } type: { type: string } identifiant: { type: string, description: "Identifiant publié — jamais une valeur (ni nom, ni IBAN)." } version: { type: integer, minimum: 1 } OuvertureDeDossier: type: object required: [demande_id, finalite, motif, sujets] properties: demande_id: { type: string, description: Clé d'idempotence du client. } finalite: { $ref: '#/components/schemas/Finalite' } motif: { type: string } sujets: type: array minItems: 1 items: { $ref: '#/components/schemas/ReferenceVersionnee' } echeance: { type: string, format: date } Dossier: type: object required: [reference, finalite, etat, motif, ouvert_le, sujets, episode] properties: reference: { type: string } finalite: { $ref: '#/components/schemas/Finalite' } etat: { $ref: '#/components/schemas/EtatDossier' } motif: { type: string } ouvert_le: { type: string, format: date-time } echeance: { type: string, format: date } sujets: type: array items: { $ref: '#/components/schemas/ReferenceVersionnee' } episode: type: integer minimum: 1 description: Une réouverture ouvre un nouvel épisode ; la conclusion précédente reste. liaisons: type: array description: Les dossiers liés, par référence et état seulement — rien ne se propage. items: { $ref: '#/components/schemas/Liaison' } compteurs: type: object properties: alertes: { type: integer } elements_journal: { type: integer } mesures: { type: integer } NouvelElement: type: object required: [demande_id, nature, texte] properties: demande_id: { type: string } nature: type: string enum: [FAIT_SOURCE, DECLARATION, RESULTAT_CONTROLE, HYPOTHESE, CONCLUSION] description: >- Le typage est la garde : une déclaration est attribuée et non tenue pour vérifiée, une hypothèse est à vérifier, une conclusion est validée selon la délégation. Un FAIT_SOURCE porte sa provenance. texte: { type: string } provenance: type: string description: Obligatoire pour un FAIT_SOURCE — le domaine ou la source qui atteste. references: type: array items: { $ref: '#/components/schemas/ReferenceVersionnee' } pieces: type: array description: Références de pièces à l'archive probatoire — jamais leur contenu. items: { type: string } rectifie: type: string description: Identifiant de l'élément corrigé, le cas échéant — l'original reste lisible. ElementDeJournal: allOf: - $ref: '#/components/schemas/NouvelElement' - type: object required: [element_id, auteur, consigne_le] properties: element_id: { type: string } auteur: { type: string, description: L'utilisateur ou l'agent nommé — jamais un compte partagé. } consigne_le: { type: string, format: date-time } NouvelleLiaison: type: object required: [demande_id, dossier_lie, nature, motif] properties: demande_id: { type: string } dossier_lie: { type: string } nature: type: string description: Nature codifiée (sujet commun, corrélation bancaire, tiers, mode opératoire, temporalité…). motif: { type: string } Liaison: allOf: - $ref: '#/components/schemas/NouvelleLiaison' - type: object required: [liaison_id, etablie_le, par, etat] properties: liaison_id: { type: string } etablie_le: { type: string, format: date-time } par: { type: string } etat: { type: string, enum: [ACTIVE, REVOQUEE] } etat_dossier_lie: { $ref: '#/components/schemas/EtatDossier' } Revocation: type: object required: [demande_id, motif] properties: demande_id: { type: string } motif: { type: string } NouvelleDecision: type: object required: [demande_id, type, motif] properties: demande_id: { type: string } type: type: string enum: [CLASSEMENT, REOUVERTURE, EXAMEN_RENFORCE, DEMANDE_PIECE, ESCALADE] description: >- Les décisions qui engagent l'extérieur ont leurs contrats propres : les mesures (administration des mesures), la déclaration (déclaratif, à naître). motif: { type: string } Decision: allOf: - $ref: '#/components/schemas/NouvelleDecision' - type: object required: [decision_id, etat, prise_le, decideur] properties: decision_id: { type: string } etat: type: string enum: [CONSIGNEE, SUSPENDUE_A_VALIDATION] prise_le: { type: string, format: date-time } decideur: { type: string } Alerte: type: object required: [reference, scenario, explication, sujet, survenue_le, etat, priorite_reglementaire] properties: reference: { type: string } scenario: type: object required: [identifiant, version] properties: identifiant: { type: string } version: { type: string } explication: type: string description: L'explication déterministe, autoportée — jamais nulle. sujet: { $ref: '#/components/schemas/ReferenceVersionnee' } survenue_le: { type: string, format: date-time } etat: { $ref: '#/components/schemas/EtatAlerte' } priorite_reglementaire: { type: integer } priorite_assistee: type: integer description: >- Absente quand l'apprentissage est débranché — champ séparé de la priorité réglementaire, jamais fusionné. echeance: { type: string, format: date-time } dossier: { type: string, description: "Référence du dossier de rattachement, le cas échéant." } Qualification: type: object required: [demande_id, decision] properties: demande_id: { type: string } decision: type: string enum: [QUALIFIEE, CLASSEE, ANNULEE] dossier: type: string description: Pour QUALIFIEE — le dossier de rattachement existant. dossier_a_ouvrir: $ref: '#/components/schemas/OuvertureDeDossier' description: Pour QUALIFIEE — ouvrir le dossier dans le même geste. motif: type: string description: Obligatoire pour CLASSEE (motif codifié) et ANNULEE. ResultatDeQualification: type: object required: [alerte] properties: alerte: { $ref: '#/components/schemas/Alerte' } dossier: { $ref: '#/components/schemas/Dossier' } PageDeDossiers: type: object required: [elements, servi_le] properties: elements: type: array items: { $ref: '#/components/schemas/Dossier' } page_suivante: { type: string } servi_le: { type: string, format: date-time } PageDAlertes: type: object required: [elements, servi_le] properties: elements: type: array items: { $ref: '#/components/schemas/Alerte' } page_suivante: { type: string } servi_le: { type: string, format: date-time } PageDeJournal: type: object required: [elements, servi_le] properties: elements: type: array items: { $ref: '#/components/schemas/ElementDeJournal' } page_suivante: { type: string } servi_le: { type: string, format: date-time } Erreur: type: object required: [code, message] properties: code: { type: string } message: type: string description: >- Nomme le champ ou la condition en cause. Ne révèle ni un critère de détection, ni l'existence d'un objet hors du périmètre de l'appelant.