{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://oto.dtp/schemas/chat_otoia/chat.schema.json",
  "title": "Contrat de sortie du générateur Chat OTOIA (custom_block + chat_mount + manifest)",
  "description": "Validé par le validateur maison Publiciste (draft-07, sous-ensemble). La cross-cohérence fine (portails métier, portée RBAC, endpoint null, cohérence avec les Has Role des Workspaces, déterminisme) est vérifiée par les invariants de chat_otoia_gen.py.",
  "type": "object",
  "required": ["custom_block", "chat_mount", "manifest"],
  "additionalProperties": false,
  "properties": {
    "custom_block": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "required": ["doctype", "block_name", "html"],
        "additionalProperties": false,
        "properties": {
          "doctype": {"type": "string", "const": "Custom Block"},
          "block_name": {"type": "string", "minLength": 1},
          "html": {"type": "string", "minLength": 1}
        }
      }
    },
    "chat_mount": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "required": [
          "portail", "workspace", "custom_block", "html_id", "persona",
          "langues", "lang_defaut", "ui_label", "roles_allowed",
          "knowledge_scope", "capabilities", "endpoint"
        ],
        "additionalProperties": false,
        "properties": {
          "portail": {"type": "string", "minLength": 1},
          "workspace": {"type": "string", "minLength": 1},
          "custom_block": {"type": "string", "minLength": 1},
          "html_id": {"type": "string", "pattern": "^otoia-chat-"},
          "persona": {
            "type": "object",
            "required": ["nom", "voix"],
            "additionalProperties": false,
            "properties": {
              "nom": {"type": "string", "const": "Amélie"},
              "voix": {"type": "string", "const": "multilingual_v2"}
            }
          },
          "langues": {
            "type": "array",
            "minItems": 1,
            "items": {"type": "string", "enum": ["fr", "en", "es"]}
          },
          "lang_defaut": {"type": "string", "enum": ["fr", "en", "es"]},
          "ui_label": {
            "type": "object",
            "required": ["fr", "en", "es"],
            "additionalProperties": false,
            "properties": {
              "fr": {"type": "string", "minLength": 1},
              "en": {"type": "string", "minLength": 1},
              "es": {"type": "string", "minLength": 1}
            }
          },
          "roles_allowed": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {"type": "string", "minLength": 1}
          },
          "knowledge_scope": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {"type": "string", "minLength": 1}
          },
          "capabilities": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {"type": "string", "enum": ["aec.py", "knowledge.py", "prompt_engine.py", "chat.py"]}
          },
          "endpoint": {"type": "null"}
        }
      }
    },
    "manifest": {
      "type": "object",
      "required": [
        "deliverable", "sprint", "roadmap_ref", "generated_from", "carrier",
        "persona", "langues", "lang_defaut", "capabilities", "endpoint_statut",
        "counts", "portails", "brand", "handoff_vps"
      ],
      "additionalProperties": false,
      "properties": {
        "deliverable": {"type": "string", "minLength": 1},
        "sprint": {"type": "string", "minLength": 1},
        "roadmap_ref": {"type": "string", "minLength": 1},
        "generated_from": {"type": "string", "minLength": 1},
        "carrier": {
          "type": "object",
          "required": ["doctype", "workspace_content_block_type", "note"],
          "additionalProperties": false,
          "properties": {
            "doctype": {"type": "string", "const": "Custom Block"},
            "workspace_content_block_type": {"type": "string", "const": "custom_block"},
            "note": {"type": "string", "minLength": 1}
          }
        },
        "persona": {
          "type": "object",
          "required": ["nom", "voix"],
          "additionalProperties": false,
          "properties": {
            "nom": {"type": "string", "const": "Amélie"},
            "voix": {"type": "string", "const": "multilingual_v2"}
          }
        },
        "langues": {"type": "array", "minItems": 1, "items": {"type": "string", "enum": ["fr", "en", "es"]}},
        "lang_defaut": {"type": "string", "enum": ["fr", "en", "es"]},
        "capabilities": {"type": "array", "minItems": 1, "items": {"type": "string"}},
        "endpoint_statut": {"type": "string", "const": "a_confirmer"},
        "counts": {
          "type": "object",
          "required": ["portails", "custom_blocks", "mounts", "roles_couverts", "knowledge_doctypes_uniques"],
          "additionalProperties": false,
          "properties": {
            "portails": {"type": "integer", "minimum": 1},
            "custom_blocks": {"type": "integer", "minimum": 1},
            "mounts": {"type": "integer", "minimum": 1},
            "roles_couverts": {"type": "integer", "minimum": 1},
            "knowledge_doctypes_uniques": {"type": "integer", "minimum": 1}
          }
        },
        "portails": {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "object",
            "required": ["portail", "workspace", "custom_block", "nb_roles", "nb_knowledge_doctypes"],
            "additionalProperties": false,
            "properties": {
              "portail": {"type": "string", "minLength": 1},
              "workspace": {"type": "string", "minLength": 1},
              "custom_block": {"type": "string", "minLength": 1},
              "nb_roles": {"type": "integer", "minimum": 1},
              "nb_knowledge_doctypes": {"type": "integer", "minimum": 1}
            }
          }
        },
        "brand": {
          "type": "object",
          "required": ["fond", "accent", "polices"],
          "additionalProperties": false,
          "properties": {
            "fond": {
              "type": "object",
              "required": ["valeur", "source"],
              "additionalProperties": false,
              "properties": {
                "valeur": {"type": "string", "const": "#0a0a12"},
                "source": {"type": "string", "minLength": 1}
              }
            },
            "accent": {
              "type": "object",
              "required": ["valeur", "source"],
              "additionalProperties": false,
              "properties": {
                "valeur": {"type": "string", "const": "#f0b429"},
                "source": {"type": "string", "minLength": 1}
              }
            },
            "polices": {
              "type": "array",
              "minItems": 2,
              "items": {
                "type": "object",
                "required": ["valeur", "source"],
                "additionalProperties": false,
                "properties": {
                  "valeur": {"type": "string", "minLength": 1},
                  "source": {"type": "string", "minLength": 1}
                }
              }
            }
          }
        },
        "handoff_vps": {
          "type": "array",
          "minItems": 1,
          "items": {"type": "string", "minLength": 1}
        }
      }
    }
  }
}
