{ "$schema": "http://json-schema.org/draft-07/schema#", "$id": "https://oto.dtp/schemas/seo/seo.schema.json", "title": "Contrat de sortie du generateur SEO (bundle keywords + schema.org + hreflang)", "description": "Valide par le validateur maison Publiciste (draft-07, sous-ensemble). La cross-coherence fine (sources resolubles, anti-invention, mapping projets) est verifiee par les invariants de seo_gen.py.", "type": "object", "required": ["keywords", "schema_org", "hreflang", "manifest"], "additionalProperties": false, "properties": { "keywords": { "type": "array", "minItems": 1, "items": { "type": "object", "required": ["term", "lang", "scope", "projet", "intent", "category", "sources"], "additionalProperties": false, "properties": { "term": { "type": "string", "minLength": 1 }, "lang": { "type": "string", "enum": ["fr", "en", "es"] }, "scope": { "type": "string", "enum": ["global", "projet"] }, "projet": { "type": ["string", "null"] }, "intent": { "type": ["string", "null"] }, "category": { "type": ["string", "null"] }, "sources": { "type": "array", "minItems": 1, "items": { "type": "string", "minLength": 1 } } } } }, "schema_org": { "type": "object", "required": ["@context", "@graph"], "additionalProperties": false, "properties": { "@context": { "type": "string", "const": "https://schema.org" }, "@graph": { "type": "array", "minItems": 1, "items": { "type": "object", "required": ["@type", "@id"], "additionalProperties": true, "properties": { "@type": { "type": "string", "minLength": 1 }, "@id": { "type": "string", "pattern": "^https://" } } } } } }, "hreflang": { "type": "object", "required": ["base_url", "x_default_lang", "pages"], "additionalProperties": false, "properties": { "base_url": { "type": "string", "pattern": "^https://" }, "x_default_lang": { "type": "string", "minLength": 1 }, "pages": { "type": "array", "minItems": 1, "items": { "type": "object", "required": ["page", "canonical", "alternates"], "additionalProperties": false, "properties": { "page": { "type": "string", "minLength": 1 }, "canonical": { "type": "string", "pattern": "^https://" }, "alternates": { "type": "array", "minItems": 2, "items": { "type": "object", "required": ["hreflang", "href"], "additionalProperties": false, "properties": { "hreflang": { "type": "string", "minLength": 1 }, "href": { "type": "string", "pattern": "^https://" } } } } } } } } }, "manifest": { "type": "object", "required": ["deliverable", "base_url", "langs", "default_lang", "counts", "targets"], "additionalProperties": true, "properties": { "deliverable": { "type": "string", "const": "seo" }, "base_url": { "type": "string", "pattern": "^https://" }, "langs": { "type": "array", "minItems": 1, "items": { "type": "string" } }, "default_lang": { "type": "string", "minLength": 1 }, "counts": { "type": "object", "required": ["keywords_total", "schema_org_nodes", "hreflang_pages", "projects"], "additionalProperties": true, "properties": { "keywords_total": { "type": "integer", "minimum": 0 }, "schema_org_nodes": { "type": "integer", "minimum": 0 }, "hreflang_pages": { "type": "integer", "minimum": 0 }, "projects": { "type": "integer", "minimum": 0 } } }, "targets": { "type": "object", "required": ["min_keywords_total", "min_keywords_per_lang"], "additionalProperties": false, "properties": { "min_keywords_total": { "type": "integer", "minimum": 0 }, "min_keywords_per_lang": { "type": "integer", "minimum": 0 } } } } } } }