Authorization — Workflows d’Approbation

Le système d’approbation permet de soumettre des actions à un processus de validation multi-approbateur avec quorum configurable.

Module : src.module.authorization.application.approval_service

Modèles

class src.module.authorization.application.approval_service.ApprovalRequest(models.Model)

Demande d’approbation créée quand une politique ABAC a requires_approval=True.

policy_id: UUIDField

Politique ayant déclenché la demande.

policy_name: CharField
requester_id: UUIDField

Utilisateur ayant initié l’action.

tenant_id: UUIDField

Fixé à la création — l’auto-exécution utilise ce tenant.

action: CharField

Action demandée (ex: "delete").

resource_type: CharField
resource_id: UUIDField(nullable)
status: CharField

pendingapproved / rejected / expired / cancelled

request_data: JSONField

Contexte au moment de la demande.

approval_config_snapshot: JSONField

Snapshot de la configuration d’approbation au moment de la création.

required_approvals: IntegerField

Nombre d’approbations requises (quorum).

current_approvals: IntegerField

Nombre d’approbations reçues.

expires_at: DateTimeField
class src.module.authorization.application.approval_service.ApprovalDecision(models.Model)

Décision individuelle d’un approbateur.

approval_request: ForeignKey ApprovalRequest
approver_id: UUIDField
decision: CharField

"approved" ou "rejected"

comment: TextField(nullable)

ApprovalOrchestrationService

class src.module.authorization.application.approval_service.ApprovalOrchestrationService

Orchestre le cycle de vie complet des demandes d’approbation.

create_request(policy, requester, action, resource_type, resource_id, request_data) ApprovalRequest

Crée une nouvelle demande d’approbation. Émet ApprovalRequested.

approve(request_id, approver_id, comment=None) ApprovalDecision

Enregistre une décision d’approbation.

  • Vérifie que l’approbateur est autorisé

  • Vérifie que l’approbateur n’est pas le demandeur (SelfApprovalError)

  • Incrémente current_approvals

  • Si quorum atteint → statut approved, émet ApprovalGranted

  • Si auto_execute=True → exécute l’action automatiquement

Raises:
  • SelfApprovalError – Auto-approbation interdite

  • UnauthorizedApproverError – Approbateur non autorisé

  • ApprovalNotPendingError – Demande déjà résolue

reject(request_id, approver_id, comment=None) ApprovalDecision

Rejette une demande. Émet ApprovalRejected.

cancel(request_id, requester_id) None

Annule une demande (par le demandeur). Émet ApprovalCancelled.

expire_pending() int

Expire les demandes dont expires_at est passé. Émet ApprovalExpired pour chaque demande. Retourne le nombre de demandes expirées.

Flux d’approbation

Utilisateur                     PEP                    Approval Service
    │                            │                            │
    ├── DELETE /invoices/123 ────►│                            │
    │                            ├── PDP: requires_approval ──│
    │                            │                            │
    │                            │◄── ApprovalRequiredError ──┤
    │                            │    (approval_request_id)   │
    │                            │                            │
    │◄── 202 Accepted ──────────┤                            │
    │    {approval_request_id}   │                            │
    │                            │                            │
    │                            │                            │
Approver                         │                            │
    │                            │                            │
    ├── POST /approval-requests/<id>/approve/ ───────────────►│
    │                                                         │
    │                            ├── Quorum atteint ?         │
    │                            │   ├── Oui → auto_execute   │
    │                            │   └── Non → attente        │
    │                            │                            │
    │◄── 200 OK ─────────────────┤                            │

Tâches Celery

Module : src.module.authorization.tasks

src.module.authorization.application.approval_service.execute_approved_action(request_id: str) None

Exécute l’action approuvée dans le contexte du tenant original.

src.module.authorization.application.approval_service.expire_pending_approvals() None

Expire les demandes d’approbation passées. À planifier via Celery Beat.

src.module.authorization.application.approval_service.send_approval_notification(request_id: str) None

Envoie une notification aux approbateurs.

src.module.authorization.application.approval_service.cleanup_expired_approvals() None

Nettoie les demandes d’approbation anciennes.

API REST

GET    /api/v1/approval-requests/           Liste les demandes
GET    /api/v1/approval-requests/<id>/      Détail d'une demande
POST   /api/v1/approval-requests/<id>/approve/   Approuver
POST   /api/v1/approval-requests/<id>/reject/    Rejeter
POST   /api/v1/approval-requests/<id>/cancel/    Annuler
GET    /api/v1/approval-requests/pending/         Demandes en attente

Configuration

MULTITENANT = {
    'APPROVAL_ENABLED': True,
    'APPROVAL_DEFAULT_EXPIRATION_HOURS': 72,
    'APPROVAL_DEFAULT_REQUIRED_APPROVALS': 1,
    'APPROVAL_AUTO_EXECUTE_DEFAULT': True,
}