{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://oto-enterprise-os-dtp/rbac/userperm.schema.json",
  "title": "Plan User Permission (row-level) généré depuis rbac_50_roles.json",
  "description": "Contrat de sortie de userperm_gen.py. Validé par le validateur maison Publiciste (zéro pip) dans le job CI rbac-userperm-tests. Un template User Permission n'est présent que pour la portée `entite` ; les portées own/groupe/equipe portent user_permission_template=null (mécanisme documenté par `mechanism`).",
  "type": "object",
  "additionalProperties": false,
  "required": ["manifest", "plan"],
  "properties": {
    "manifest": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "generated_from",
        "source_version",
        "cible_rbac_roles",
        "counts",
        "companies_a_confirmer",
        "roles_scope_equipe_a_confirmer"
      ],
      "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": ["plan_entries", "user_permission_templates", "by_mechanism"],
          "properties": {
            "plan_entries": { "type": "integer", "minimum": 50, "maximum": 50 },
            "user_permission_templates": { "type": "integer", "minimum": 0 },
            "by_mechanism": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "docperm_if_owner",
                "user_permission_company",
                "none_consolidated",
                "vps_confirm_team"
              ],
              "properties": {
                "docperm_if_owner": { "type": "integer", "minimum": 0 },
                "user_permission_company": { "type": "integer", "minimum": 0 },
                "none_consolidated": { "type": "integer", "minimum": 0 },
                "vps_confirm_team": { "type": "integer", "minimum": 0 }
              }
            }
          }
        },
        "companies_a_confirmer": {
          "type": "array",
          "uniqueItems": true,
          "items": { "type": "string", "minLength": 1 }
        },
        "roles_scope_equipe_a_confirmer": {
          "type": "array",
          "uniqueItems": true,
          "items": { "type": "string", "pattern": "^OTO " }
        }
      }
    },
    "plan": {
      "type": "array",
      "minItems": 50,
      "maxItems": 50,
      "items": { "$ref": "#/definitions/plan_entry" }
    }
  },
  "definitions": {
    "plan_entry": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "erpnext_role_name",
        "scope_donnees",
        "entite_principale",
        "mechanism",
        "user_permission_template"
      ],
      "properties": {
        "erpnext_role_name": { "type": "string", "pattern": "^OTO " },
        "scope_donnees": { "type": "string", "enum": ["own", "equipe", "entite", "groupe"] },
        "entite_principale": { "type": "string", "minLength": 1 },
        "mechanism": {
          "type": "string",
          "enum": [
            "docperm_if_owner",
            "user_permission_company",
            "none_consolidated",
            "vps_confirm_team"
          ]
        },
        "user_permission_template": {
          "type": ["object", "null"],
          "additionalProperties": false,
          "required": [
            "doctype",
            "user",
            "allow",
            "for_value",
            "apply_to_all_doctypes",
            "is_default",
            "hide_descendants"
          ],
          "properties": {
            "doctype": { "type": "string", "const": "User Permission" },
            "user": { "type": "string", "const": "__ASSIGN_PER_USER__" },
            "allow": { "type": "string", "const": "Company" },
            "for_value": { "type": "string", "minLength": 1 },
            "apply_to_all_doctypes": { "type": "integer", "enum": [0, 1] },
            "is_default": { "type": "integer", "enum": [0, 1] },
            "hide_descendants": { "type": "integer", "enum": [0, 1] }
          }
        }
      }
    }
  }
}
