{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://local.dev/schemas/app-blueprint/v1.json",
  "title": "AppBlueprint",
  "description": "AI 生成 → 用户确认 → 中台执行的唯一契约（v1）",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "version",
    "meta",
    "storage",
    "entities",
    "apis",
    "pages",
    "security"
  ],
  "properties": {
    "version": {
      "type": "string",
      "const": "1.0"
    },
    "meta": {
      "type": "object",
      "additionalProperties": false,
      "required": ["name", "slug", "locale"],
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 64,
          "description": "应用显示名"
        },
        "slug": {
          "type": "string",
          "pattern": "^[a-z][a-z0-9_]{1,47}$",
          "description": "应用标识，用于路径与资源前缀"
        },
        "description": {
          "type": "string",
          "maxLength": 500
        },
        "locale": {
          "type": "string",
          "default": "zh-CN"
        },
        "source": {
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "prompt": { "type": "string" },
            "image_refs": {
              "type": "array",
              "items": { "type": "string" },
              "maxItems": 10
            },
            "excel_ref": { "type": "string" },
            "layout_refs": {
              "type": "array",
              "items": { "type": "string" }
            },
            "screenshot_faithful": { "type": "boolean" },
            "vision_summary": { "type": "string" },
            "layout_summary": { "type": "string" },
            "llm_provider": { "type": "string" },
            "llm_model": { "type": "string" },
            "data_format": { "type": "string" },
            "row_count": { "type": "number" }
          }
        },
        "ui_preset": {
          "type": "string",
          "enum": ["default", "screenshot_faithful", "ops_monitor"]
        },
        "platform_title": { "type": "string", "maxLength": 64 },
        "project_context": { "type": "string", "maxLength": 120 },
        "ui": {
          "type": "object",
          "additionalProperties": true
        },
        "confidence": {
          "type": "number",
          "minimum": 0,
          "maximum": 1,
          "description": "AI 整体置信度，低于阈值应强制人工确认"
        }
      }
    },
    "storage": {
      "type": "object",
      "additionalProperties": false,
      "required": ["mode", "engine"],
      "properties": {
        "mode": {
          "type": "string",
          "enum": ["schema_per_app", "database_per_app"],
          "description": "schema_per_app=共享实例独立 schema；database_per_app=独立库（更高隔离）"
        },
        "engine": {
          "type": "string",
          "enum": ["postgres", "mysql"]
        },
        "schema_name": {
          "type": "string",
          "pattern": "^app_[a-z0-9_]{1,48}$",
          "description": "由平台生成或校验；禁止用户/AI 指定任意库名"
        }
      }
    },
    "entities": {
      "type": "array",
      "minItems": 1,
      "maxItems": 20,
      "items": { "$ref": "#/$defs/entity" }
    },
    "apis": {
      "type": "object",
      "additionalProperties": false,
      "required": ["base_path", "resources"],
      "properties": {
        "base_path": {
          "type": "string",
          "pattern": "^/api/v1/apps/[a-z][a-z0-9_]{1,47}$"
        },
        "resources": {
          "type": "array",
          "minItems": 1,
          "items": { "$ref": "#/$defs/apiResource" }
        }
      }
    },
    "pages": {
      "type": "array",
      "minItems": 1,
      "items": { "$ref": "#/$defs/page" }
    },
    "security": {
      "type": "object",
      "additionalProperties": false,
      "required": ["visibility", "roles", "row_policies"],
      "properties": {
        "visibility": {
          "type": "string",
          "enum": ["private", "org", "public_readonly"]
        },
        "roles": {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["name", "permissions"],
            "properties": {
              "name": {
                "type": "string",
                "enum": ["owner", "editor", "viewer"]
              },
              "permissions": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "app.read",
                    "app.write",
                    "app.admin",
                    "row.create",
                    "row.read",
                    "row.update",
                    "row.delete",
                    "row.export",
                    "row.import"
                  ]
                }
              }
            }
          }
        },
        "row_policies": {
          "type": "array",
          "description": "行级规则，中台强制注入，不可被前端绕过",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["entity", "rule"],
            "properties": {
              "entity": { "type": "string" },
              "rule": {
                "type": "string",
                "enum": ["tenant_isolated", "owner_only", "org_shared"]
              }
            }
          }
        }
      }
    },
    "seed": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "import_excel": {
          "type": "boolean",
          "default": true
        },
        "max_rows": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100000,
          "default": 5000
        }
      }
    }
  },
  "$defs": {
    "entity": {
      "type": "object",
      "additionalProperties": false,
      "required": ["name", "table", "label", "fields", "primary_key"],
      "properties": {
        "name": {
          "type": "string",
          "pattern": "^[a-z][a-z0-9_]{1,47}$",
          "description": "逻辑实体名"
        },
        "table": {
          "type": "string",
          "pattern": "^[a-z][a-z0-9_]{1,47}$",
          "description": "物理表名（不含 schema 前缀）"
        },
        "label": { "type": "string", "maxLength": 64 },
        "primary_key": {
          "type": "string",
          "pattern": "^[a-z][a-z0-9_]{1,47}$"
        },
        "fields": {
          "type": "array",
          "minItems": 1,
          "maxItems": 80,
          "items": { "$ref": "#/$defs/field" }
        },
        "indexes": {
          "type": "array",
          "maxItems": 20,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["name", "columns"],
            "properties": {
              "name": {
                "type": "string",
                "pattern": "^idx_[a-z0-9_]{1,48}$"
              },
              "columns": {
                "type": "array",
                "minItems": 1,
                "maxItems": 5,
                "items": { "type": "string" }
              },
              "unique": { "type": "boolean", "default": false }
            }
          }
        }
      }
    },
    "field": {
      "type": "object",
      "additionalProperties": false,
      "required": ["name", "type", "label"],
      "properties": {
        "name": {
          "type": "string",
          "pattern": "^[a-z][a-z0-9_]{1,47}$"
        },
        "label": { "type": "string", "maxLength": 64 },
        "type": {
          "type": "string",
          "enum": [
            "string",
            "text",
            "int",
            "bigint",
            "decimal",
            "boolean",
            "date",
            "datetime",
            "enum",
            "json",
            "file_ref"
          ]
        },
        "nullable": { "type": "boolean", "default": true },
        "unique": { "type": "boolean", "default": false },
        "default": {},
        "max_length": {
          "type": "integer",
          "minimum": 1,
          "maximum": 4000
        },
        "precision": { "type": "integer", "minimum": 1, "maximum": 38 },
        "scale": { "type": "integer", "minimum": 0, "maximum": 10 },
        "enum_values": {
          "type": "array",
          "items": { "type": "string" },
          "maxItems": 50
        },
        "ui": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "widget": {
              "type": "string",
              "enum": [
                "input",
                "textarea",
                "number",
                "select",
                "switch",
                "datepicker",
                "upload",
                "hidden"
              ]
            },
            "listable": { "type": "boolean", "default": true },
            "filterable": { "type": "boolean", "default": false },
            "sortable": { "type": "boolean", "default": false },
            "width": {
              "type": "string",
              "enum": ["sm", "md", "lg"]
            }
          }
        },
        "from_excel": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "column": { "type": "string" },
            "sample_values": {
              "type": "array",
              "items": { "type": "string" },
              "maxItems": 5
            }
          }
        }
      }
    },
    "apiResource": {
      "type": "object",
      "additionalProperties": false,
      "required": ["entity", "path", "operations"],
      "properties": {
        "entity": { "type": "string" },
        "path": {
          "type": "string",
          "pattern": "^/[a-z][a-z0-9_]{1,47}$"
        },
        "operations": {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "string",
            "enum": ["list", "get", "create", "update", "delete", "import", "export"]
          }
        },
        "list": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "default_page_size": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            },
            "max_page_size": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 100
            },
            "allowed_filters": {
              "type": "array",
              "items": { "type": "string" }
            },
            "allowed_sorts": {
              "type": "array",
              "items": { "type": "string" }
            }
          }
        }
      }
    },
    "page": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "title", "route", "type", "entity"],
      "properties": {
        "id": {
          "type": "string",
          "pattern": "^[a-z][a-z0-9_]{1,47}$"
        },
        "title": { "type": "string", "maxLength": 64 },
        "route": {
          "type": "string",
          "pattern": "^/[a-z0-9\\-_/:]{1,64}$",
          "description": "支持 :id 这类路径参数"
        },
        "type": {
          "type": "string",
          "enum": ["list", "detail", "form_create", "form_edit", "dashboard"]
        },
        "entity": { "type": "string" },
        "layout": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "preset": {
              "type": "string",
              "enum": ["default", "screenshot_faithful", "ops_monitor"]
            },
            "action_labels": {
              "type": "object",
              "additionalProperties": { "type": "string" }
            },
            "filter_style": { "type": "string" },
            "columns": {
              "type": "array",
              "description": "list 页展示列（字段名）",
              "items": { "type": "string" }
            },
            "filters": {
              "type": "array",
              "items": { "type": "string" }
            },
            "actions": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": ["create", "edit", "delete", "export", "import", "refresh"]
              }
            },
            "form_fields": {
              "type": "array",
              "items": { "type": "string" }
            },
            "widgets": {
              "type": "array",
              "description": "dashboard 组件",
              "items": {
                "type": "object",
                "additionalProperties": true,
                "required": ["type", "title"],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": ["kpi", "bar_chart", "line_chart", "pie_chart", "table", "status_strip"]
                  },
                  "title": { "type": "string" },
                  "metric": { "type": "string" },
                  "metrics": {
                    "type": "array",
                    "items": { "type": "string" }
                  },
                  "group_by": { "type": "string" },
                  "x_field": { "type": "string" },
                  "y_unit": { "type": "string" },
                  "entity": { "type": "string" },
                  "columns": {
                    "type": "array",
                    "items": { "type": "string" }
                  },
                  "label_field": { "type": "string" },
                  "value_field": { "type": "string" },
                  "warn_field": { "type": "string" },
                  "filter_field": { "type": "string" },
                  "filter_op": { "type": "string" },
                  "filter_value": {}
                }
              }
            }
          }
        }
      }
    }
  }
}
