{ "openapi": "3.1.0", "info": { "title": "SIOP V2 API", "version": "0.1.0", "description": "GMAO ascenseurs — contrat R0 (auth, démo-login ADR-002, profil, santé). Généré depuis packages/shared/src/contract.ts — NE PAS ÉDITER À LA MAIN." }, "paths": { "/auth/login": { "post": { "operationId": "login", "summary": "Connexion par e-mail et mot de passe", "tags": [ "auth" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LoginRequest" } } } }, "responses": { "200": { "description": "Jeton émis", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthResponse" } } } }, "401": { "description": "Identifiants invalides ou compte inactif" } } } }, "/auth/demo-accounts": { "get": { "operationId": "listDemoAccounts", "summary": "Comptes de démonstration (ADR-002 — jamais de secret)", "tags": [ "auth", "demo" ], "x-demo-only": true, "description": "ADR-002 : cette route est absente (404) quand DEMO_MODE n’est pas actif.", "responses": { "200": { "description": "Comptes isDemo actifs", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DemoAccountsResponse" } } } } } } }, "/auth/demo-login": { "post": { "operationId": "demoLogin", "summary": "Connexion 1 clic sur un compte de démonstration (ADR-002)", "tags": [ "auth", "demo" ], "x-demo-only": true, "description": "ADR-002 : cette route est absente (404) quand DEMO_MODE n’est pas actif.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DemoLoginRequest" } } } }, "responses": { "200": { "description": "Jeton émis", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthResponse" } } } }, "403": { "description": "Le compte n’est pas un compte de démonstration" }, "404": { "description": "Compte inconnu" } } } }, "/users/me": { "get": { "operationId": "getMe", "summary": "Profil courant + matrice de permissions du rôle", "tags": [ "users" ], "security": [ { "bearerAuth": [] } ], "responses": { "200": { "description": "Profil", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MeResponse" } } } }, "401": { "description": "Non authentifié" } } } }, "/health": { "get": { "operationId": "getHealth", "summary": "État des dépendances (base, Redis, stockage)", "tags": [ "health" ], "responses": { "200": { "description": "État agrégé", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HealthResponse" } } } } } } } }, "components": { "schemas": { "AuthResponse": { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "accessToken": { "type": "string" }, "user": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "email": { "type": "string", "format": "email", "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$" }, "displayName": { "type": "string" }, "role": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "name": { "type": "string", "enum": [ "Administrateur", "Dispatcher", "Technicien", "Technicien limité", "Gestionnaire", "Demandeur", "Vue seule" ] } }, "required": [ "id", "name" ], "additionalProperties": false }, "isDemo": { "type": "boolean" } }, "required": [ "id", "email", "displayName", "role", "isDemo" ], "additionalProperties": false } }, "required": [ "accessToken", "user" ], "additionalProperties": false }, "LoginRequest": { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "email": { "type": "string", "format": "email", "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$" }, "password": { "type": "string", "minLength": 1 } }, "required": [ "email", "password" ], "additionalProperties": false }, "DemoAccountsResponse": { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "accounts": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "displayName": { "type": "string" }, "roleName": { "type": "string", "enum": [ "Administrateur", "Dispatcher", "Technicien", "Technicien limité", "Gestionnaire", "Demandeur", "Vue seule" ] }, "initials": { "type": "string", "minLength": 1, "maxLength": 3 } }, "required": [ "id", "displayName", "roleName", "initials" ], "additionalProperties": false } } }, "required": [ "accounts" ], "additionalProperties": false }, "DemoLoginRequest": { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "userId": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" } }, "required": [ "userId" ], "additionalProperties": false }, "MeResponse": { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "email": { "type": "string", "format": "email", "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$" }, "displayName": { "type": "string" }, "role": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "name": { "type": "string", "enum": [ "Administrateur", "Dispatcher", "Technicien", "Technicien limité", "Gestionnaire", "Demandeur", "Vue seule" ] } }, "required": [ "id", "name" ], "additionalProperties": false }, "isDemo": { "type": "boolean" }, "permissions": { "type": "array", "items": { "type": "object", "properties": { "objectCategory": { "type": "string", "enum": [ "WORK_ORDERS", "REQUESTS", "ASSETS", "LOCATIONS", "METERS", "PARTS", "PURCHASE_ORDERS", "PEOPLE_TEAMS", "ANALYTICS", "SETTINGS" ] }, "canView": { "type": "boolean" }, "canViewOther": { "type": "boolean" }, "canCreate": { "type": "boolean" }, "canEdit": { "type": "boolean" }, "canDelete": { "type": "boolean" } }, "required": [ "objectCategory", "canView", "canViewOther", "canCreate", "canEdit", "canDelete" ], "additionalProperties": false } } }, "required": [ "id", "email", "displayName", "role", "isDemo", "permissions" ], "additionalProperties": false }, "HealthResponse": { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "status": { "type": "string", "enum": [ "ok", "degraded" ] }, "services": { "type": "object", "properties": { "database": { "type": "string", "enum": [ "up", "down" ] }, "redis": { "type": "string", "enum": [ "up", "down" ] }, "storage": { "type": "string", "enum": [ "up", "down" ] } }, "required": [ "database", "redis", "storage" ], "additionalProperties": false } }, "required": [ "status", "services" ], "additionalProperties": false } }, "securitySchemes": { "bearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT" } } } }