{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://oto-enterprise-os-dtp/rbac/apply_plan.schema.json",
  "title": "Run-book d'application RBAC unifié (agrégat des 3 volets)",
  "description": "Contrat de sortie de rbac_apply_plan.py. Validé par le validateur maison Publiciste (zéro pip) dans le job CI rbac-applyplan-tests. Consolide les manifestes des 3 générateurs RBAC (fixtures Role+DocPerm, plan User Permission, Role Profile) en un plan d'application VPS ordonné (SPEC §7) + un manifeste agrégé recoupant leur cohérence. Aucun chiffre recalculé : tout compte provient d'un builder source.",
  "type": "object",
  "additionalProperties": false,
  "required": ["manifest", "apply_plan"],
  "properties": {
    "manifest": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "generated_from",
        "source_version",
        "cible_rbac_roles",
        "counts",
        "confirmations_vps",
        "consistency"
      ],
      "properties": {
        "generated_from": { "type": "string", "const": "rbac_50_roles.json" },
        "source_version": { "type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$" },
        "cible_rbac_roles": { "type": "integer", "const": 50 },
        "counts": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "roles",
            "custom_docperm",
            "doctypes_uniques",
            "user_permission_templates",
            "role_profiles"
          ],
          "properties": {
            "roles": { "type": "integer", "minimum": 50, "maximum": 50 },
            "custom_docperm": { "type": "integer", "minimum": 1 },
            "doctypes_uniques": { "type": "integer", "minimum": 1 },
            "user_permission_templates": { "type": "integer", "minimum": 0 },
            "role_profiles": { "type": "integer", "minimum": 1 }
          }
        },
        "confirmations_vps": {
          "type": "object",
          "additionalProperties": false,
          "required": ["custom_doctypes", "companies", "roles_scope_equipe"],
          "properties": {
            "custom_doctypes": {
              "type": "array",
              "uniqueItems": true,
              "items": { "type": "string", "minLength": 1 }
            },
            "companies": {
              "type": "array",
              "uniqueItems": true,
              "items": { "type": "string", "minLength": 1 }
            },
            "roles_scope_equipe": {
              "type": "array",
              "uniqueItems": true,
              "items": { "type": "string", "minLength": 1 }
            }
          }
        },
        "consistency": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "sources_coherentes",
            "source_version",
            "cible_rbac_roles",
            "roles_fixtures",
            "userperm_plan_entries",
            "roleprofile_roles_couverts",
            "couverture_bijective"
          ],
          "properties": {
            "sources_coherentes": { "type": "boolean", "const": true },
            "source_version": { "type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$" },
            "cible_rbac_roles": { "type": "integer", "const": 50 },
            "roles_fixtures": { "type": "integer", "minimum": 0 },
            "userperm_plan_entries": { "type": "integer", "minimum": 0 },
            "roleprofile_roles_couverts": { "type": "integer", "minimum": 0 },
            "couverture_bijective": { "type": "boolean", "const": true }
          }
        }
      }
    },
    "apply_plan": {
      "type": "array",
      "minItems": 1,
      "items": { "$ref": "#/definitions/step" }
    }
  },
  "definitions": {
    "step": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "order",
        "id",
        "titre",
        "responsable",
        "statut",
        "commande",
        "produces",
        "depends_on",
        "confirmations",
        "doc"
      ],
      "properties": {
        "order": { "type": "integer", "minimum": 1 },
        "id": { "type": "string", "pattern": "^[a-z0-9-]+$" },
        "titre": { "type": "string", "minLength": 1 },
        "responsable": { "type": "string", "enum": ["worker", "vps", "worker+vps"] },
        "statut": { "type": "string", "minLength": 1 },
        "commande": { "type": ["string", "null"] },
        "produces": {
          "type": "array",
          "uniqueItems": true,
          "items": { "type": "string", "minLength": 1 }
        },
        "depends_on": {
          "type": "array",
          "uniqueItems": true,
          "items": { "type": "string", "pattern": "^[a-z0-9-]+$" }
        },
        "confirmations": {
          "type": "array",
          "uniqueItems": true,
          "items": { "type": "string", "enum": ["custom_doctypes", "companies", "roles_scope_equipe"] }
        },
        "doc": { "type": "string", "minLength": 1 }
      }
    }
  }
}
