{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://oto.dtp/schemas/rbac/rbac.schema.json",
  "title": "Contrat RBAC · OTO Enterprise OS DTP (50 rôles)",
  "description": "Design machine-lisible des 50 rôles RBAC (CLAUDE.md · roadmap Sprint 2 · ERPNext Backend). Chaque rôle cible un Role natif Frappe v15 + un jeu de permissions par DocType. Les bindings sont la CIBLE à appliquer sur le VPS par l'agent ERPNext (bench/fixtures) — ce document ne touche jamais la prod (contrainte worker).",
  "type": "object",
  "required": ["version", "generated_at", "cible_rbac_roles", "portails_business", "roles"],
  "additionalProperties": false,
  "properties": {
    "version": { "type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$" },
    "generated_at": { "type": "string", "format": "date-time" },
    "cible_rbac_roles": {
      "type": "integer",
      "const": 50,
      "description": "Cible non-négociable CLAUDE.md « RBAC 50 rôles ». La longueur de roles[] DOIT valoir 50 (contrôlé par le test)."
    },
    "portails_business": {
      "type": "array",
      "minItems": 5,
      "maxItems": 5,
      "uniqueItems": true,
      "items": { "type": "string", "enum": ["ventes", "construction", "achat", "compta", "direction"] },
      "description": "Les 5 portails rôle métier de la roadmap Sprint 4. « plateforme » est une console technique transversale, hors de ce compte de 5."
    },
    "roles": {
      "type": "array",
      "minItems": 50,
      "maxItems": 50,
      "items": { "$ref": "#/definitions/role" }
    }
  },
  "definitions": {
    "role": {
      "type": "object",
      "required": [
        "id", "nom_fr", "famille", "portail", "entite_principale",
        "niveau", "erpnext_role_name", "scope_donnees", "description",
        "modules", "permissions_cibles"
      ],
      "additionalProperties": false,
      "properties": {
        "id": {
          "type": "string",
          "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
          "minLength": 3,
          "description": "Identifiant kebab-case unique (unicité vérifiée par le test)."
        },
        "nom_fr": { "type": "string", "minLength": 1 },
        "famille": {
          "type": "string",
          "enum": ["direction", "ventes", "marketing", "construction", "achat", "finance", "faisabilite", "legal", "plateforme"]
        },
        "portail": {
          "type": "string",
          "enum": ["ventes", "construction", "achat", "compta", "direction", "plateforme"],
          "description": "Console de rattachement. Les 5 premières = portails métier (roadmap S4) ; « plateforme » = console technique transversale."
        },
        "entite_principale": {
          "type": "string",
          "enum": ["WAF", "WAG", "WA SRL", "AC Arias Cuevas", "Consortium ECR DR", "Helios RD", "Ploutos", "9060 QC", "Groupe"],
          "description": "Entité juridique de rattachement principal (CLAUDE.md §Entités). « Groupe » = périmètre consolidé transversal."
        },
        "niveau": {
          "type": "integer",
          "minimum": 1,
          "maximum": 5,
          "description": "Niveau hiérarchique/sensibilité : 1 externe/opérationnel → 5 direction/système."
        },
        "erpnext_role_name": {
          "type": "string",
          "minLength": 4,
          "pattern": "^OTO ",
          "description": "Nom du DocType Role Frappe v15 à créer (préfixe « OTO » pour ne pas entrer en collision avec les rôles natifs). Unicité vérifiée par le test."
        },
        "scope_donnees": {
          "type": "string",
          "enum": ["own", "equipe", "entite", "groupe"],
          "description": "Row-level (User Permissions Frappe) : own=ses docs · equipe=son équipe · entite=sa Company · groupe=consolidé."
        },
        "description": { "type": "string", "minLength": 1 },
        "modules": {
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "items": { "type": "string", "minLength": 1 },
          "description": "Modules/Workspaces ERPNext visibles pour ce rôle."
        },
        "permissions_cibles": {
          "type": "array",
          "minItems": 1,
          "description": "Bindings CIBLES par DocType (à appliquer sur VPS via fixtures). Verbes = actions de permission Frappe v15.",
          "items": {
            "type": "object",
            "required": ["doctype", "actions"],
            "additionalProperties": false,
            "properties": {
              "doctype": { "type": "string", "minLength": 1 },
              "custom": {
                "type": "boolean",
                "description": "true = DocType OTOV7/DTP à créer (non natif ERPNext) — à confirmer VPS avant application."
              },
              "actions": {
                "type": "array",
                "minItems": 1,
                "uniqueItems": true,
                "items": {
                  "type": "string",
                  "enum": [
                    "read", "write", "create", "delete", "submit", "cancel",
                    "amend", "print", "email", "export", "import", "report",
                    "share", "set_user_permissions"
                  ]
                }
              }
            }
          }
        }
      }
    }
  }
}
