{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://vibebase.me/contracts/policy/decision/0.1.0",
  "title": "PolicyDecision",
  "description": "판단 결과. deny는 의무를 가질 수 없고(모순), allow는 의무(행 필터·필드 마스킹)를 동반할 수 있다. reason은 항상 필수 — 정직한 판단.",
  "type": "object",
  "additionalProperties": false,
  "required": ["decision", "reason"],
  "properties": {
    "decision": { "enum": ["allow", "deny"] },
    "reason": { "type": "string", "minLength": 1 },
    "obligations": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["type"],
        "properties": {
          "type": { "enum": ["fieldMask", "rowFilter"] },
          "fields": { "type": "array", "items": { "type": "string", "minLength": 1 }, "minItems": 1 },
          "where": { "type": "object" }
        },
        "allOf": [
          { "if": { "properties": { "type": { "const": "fieldMask" } }, "required": ["type"] }, "then": { "properties": { "fields": true }, "required": ["fields"] } },
          { "if": { "properties": { "type": { "const": "rowFilter" } }, "required": ["type"] }, "then": { "properties": { "where": true }, "required": ["where"] } }
        ]
      }
    }
  },
  "if": { "properties": { "decision": { "const": "deny" } }, "required": ["decision"] },
  "then": { "properties": { "obligations": false } }
}
