{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://casan.local/schemas/project-manifest.schema.json", "title": "CASAN Project Manifest", "type": "object", "additionalProperties": false, "required": [ "schema_version", "project_id", "display_name", "domain_root", "requirements", "architecture", "quality_profile", "feature", "source_roots", "commands", "verification" ], "properties": { "$schema": { "type": "string" }, "schema_version": { "const": 1 }, "project_id": { "type": "string", "pattern": "^[a-z][a-z0-9-]{1,62}$" }, "display_name": { "type": "string", "minLength": 2, "maxLength": 120 }, "domain_root": { "$ref": "#/$defs/path" }, "requirements": { "$ref": "#/$defs/path" }, "architecture": { "$ref": "#/$defs/path" }, "quality_profile": { "$ref": "#/$defs/path" }, "feature": { "type": "object", "additionalProperties": false, "required": ["id", "module_id", "slug", "title"], "properties": { "id": { "type": "string", "pattern": "^[0-9]{3}-[a-z0-9-]+$" }, "module_id": { "type": "string", "pattern": "^MOD-[0-9]{2,}$" }, "slug": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*$" }, "title": { "type": "string", "minLength": 2, "maxLength": 160 } } }, "source_roots": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "$ref": "#/$defs/path" } }, "commands": { "type": "object", "additionalProperties": false, "required": ["build", "test"], "properties": { "build": { "$ref": "#/$defs/commands" }, "test": { "$ref": "#/$defs/commands" } } }, "verification": { "type": "array", "minItems": 1, "items": { "type": "object", "additionalProperties": false, "required": ["path_prefix", "commands"], "properties": { "path_prefix": { "$ref": "#/$defs/path" }, "commands": { "$ref": "#/$defs/commands" } } } }, "artifacts_root": { "$ref": "#/$defs/path" }, "implementation_evidence": { "type": "array", "uniqueItems": true, "items": { "$ref": "#/$defs/path" } }, "tech_stack": { "type": "string", "minLength": 2, "maxLength": 240 } }, "$defs": { "path": { "type": "string", "minLength": 1, "pattern": "^(?!/)(?!.*(?:^|/)\\.\\.(?:/|$))(?!.*\\\\)[^\\u0000]+$" }, "command": { "type": "array", "minItems": 1, "items": { "type": "string", "minLength": 1, "maxLength": 500 } }, "commands": { "type": "array", "items": { "$ref": "#/$defs/command" } } } }