{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://zddc.varasys.io/schema/zddc.schema.json",
  "title": ".zddc policy document",
  "description": "Machine schema for the .zddc grammar (see GRAMMAR.md). Each property carries x-zddc-tier: 'structure' (the project shape an end user should not change — paths, WORM, tools, behaviors) or 'option' (the blanks an operator fills — role members, field-code vocabularies, names, labels). A form view renders option fields editable and structure fields read-only. NOTE: not all keys are valid at every level; the cascade + the per-location form decide relevance. Server-side validation still lives in validate.go (this draft-2020-12 schema uses $ref + patternProperties, which the in-tree validator does not yet support); the schema drives the form + client today.",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "title": {
      "type": "string",
      "description": "Human title for this directory.",
      "x-zddc-tier": "option"
    },
    "created_by": {
      "type": "string",
      "description": "Email of the user who created this folder. Set by the server; audit only.",
      "x-zddc-tier": "structure"
    },
    "admins": {
      "type": "array",
      "items": { "type": "string" },
      "description": "Principals (emails, globs, or role names) who administer this subtree. Root admins are super-admins; deeper entries are subtree admins. Elevation-gated full bypass over scope.",
      "x-zddc-tier": "option"
    },
    "roles": {
      "type": "object",
      "description": "Named principal groups referenced by acl/worm/admins. Membership UNIONS across the cascade. The operator fills the members.",
      "additionalProperties": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "members": {
            "type": "array",
            "items": { "type": "string" },
            "description": "Email patterns (alice@x, *@acme.com, *) in this role."
          },
          "reset": {
            "type": "boolean",
            "description": "Stop the membership union here: ancestor definitions above this level are excluded."
          }
        }
      },
      "x-zddc-tier": "option"
    },
    "acl": {
      "type": "object",
      "description": "Access control for this level. permissions maps a principal (email/glob/role) to a verb string from r w c d a (empty string = explicit deny). inherit:false clamps the ACL level-walk so ancestor levels' grants do not apply.",
      "additionalProperties": false,
      "properties": {
        "inherit": { "type": "boolean", "description": "false = this level's ACL does not inherit ancestor levels." },
        "permissions": {
          "type": "object",
          "patternProperties": {
            "^.+$": { "type": "string", "pattern": "^[rwcda]*$", "description": "Verb subset of r w c d a; empty = explicit deny." }
          },
          "additionalProperties": false
        }
      },
      "x-zddc-tier": "structure"
    },
    "worm": {
      "type": "array",
      "items": { "type": "string" },
      "description": "WORM zone: write/delete/admin stripped for all; create survives only for the listed principals; admins bypass. Unions across the cascade.",
      "x-zddc-tier": "structure"
    },
    "inherit": {
      "type": "boolean",
      "description": "false = stop the cascade here; everything below (ancestors + embedded defaults) is ignored. Makes a subtree a self-contained island.",
      "x-zddc-tier": "structure"
    },
    "default_tool": {
      "type": "string",
      "enum": ["archive", "transmittal", "classifier", "browse", "tables", "landing", "form"],
      "description": "Tool served at <dir> (no trailing slash). Sugar for views.dir.tool.",
      "x-zddc-tier": "structure"
    },
    "dir_tool": {
      "type": "string",
      "enum": ["archive", "transmittal", "classifier", "browse", "tables", "landing", "form"],
      "description": "Tool served at <dir>/ (trailing slash). Sugar for views.dir_slash.tool; defaults to browse.",
      "x-zddc-tier": "structure"
    },
    "views": {
      "type": "object",
      "description": "Per-URL-shape tool + supporting-config mapping.",
      "additionalProperties": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "tool": { "type": "string", "enum": ["archive", "transmittal", "classifier", "browse", "tables", "landing", "form"] },
          "config": { "type": "string", "description": "Supporting-file name resolved under .zddc.d/ (no slashes)." }
        }
      },
      "x-zddc-tier": "structure"
    },
    "available_tools": {
      "type": "array",
      "items": { "type": "string" },
      "description": "Tools the apps subsystem may auto-serve here and below. Concat-dedupe union across the cascade.",
      "x-zddc-tier": "structure"
    },
    "auto_own": {
      "type": "boolean",
      "description": "mkdir here writes a creator-owned .zddc (creator: rwcda).",
      "x-zddc-tier": "structure"
    },
    "auto_own_fenced": {
      "type": "boolean",
      "description": "The auto-own .zddc is written with acl.inherit:false (private to its creator).",
      "x-zddc-tier": "structure"
    },
    "auto_own_roles": {
      "type": "array",
      "items": { "type": "string" },
      "description": "Roles also granted rwcda in the auto-own .zddc, alongside the creator.",
      "x-zddc-tier": "structure"
    },
    "virtual": {
      "type": "boolean",
      "description": "Never materialise on disk; treat requests as virtual routes.",
      "x-zddc-tier": "structure"
    },
    "drop_target": {
      "type": "boolean",
      "description": "This directory accepts drag-drop uploads (browse drop-zone). Leaf-only.",
      "x-zddc-tier": "structure"
    },
    "party_source": {
      "type": "string",
      "description": "A new <party>/ here requires registration in <source>/<party>.yaml (e.g. 'ssr'). Leaf-only.",
      "x-zddc-tier": "structure"
    },
    "history": {
      "type": "boolean",
      "description": "Snapshot text (markdown) edits to .history/ in this subtree with a server-stamped audit line.",
      "x-zddc-tier": "structure"
    },
    "history_globs": {
      "type": "array",
      "items": { "type": "string" },
      "description": "Which basenames get edit history (default [\"*.md\"]).",
      "x-zddc-tier": "structure"
    },
    "convert": {
      "type": "object",
      "description": "Template variables for MD→{docx,html,pdf} conversion. Cascades leaf→root, per-key latest wins.",
      "additionalProperties": false,
      "properties": {
        "client": { "type": "string" },
        "project": { "type": "string" },
        "contractor": { "type": "string" },
        "project_number": { "type": "string" }
      },
      "x-zddc-tier": "option"
    },
    "field_codes": {
      "type": "object",
      "description": "Vocabularies for tracking-number / record field components. Map-merged per code across the cascade.",
      "additionalProperties": { "type": "object" },
      "x-zddc-tier": "option"
    },
    "records": {
      "type": "object",
      "description": "Per-record-type rules keyed by filename pattern (filename_format, field_defaults, locked, row_field, row_scope_fields, folder_fields).",
      "additionalProperties": { "type": "object" },
      "x-zddc-tier": "structure"
    },
    "display": {
      "type": "object",
      "description": "Human labels for child entries (on-disk name → label). Leaf-only.",
      "additionalProperties": { "type": "string" },
      "x-zddc-tier": "option"
    },
    "tables": {
      "type": "object",
      "description": "Legacy directory-of-YAML table views (stem → spec path).",
      "additionalProperties": { "type": "string" },
      "x-zddc-tier": "structure"
    },
    "received_path": {
      "type": "string",
      "description": "Links a workflow folder back to its canonical submittal in received/. Set by Plan Review.",
      "x-zddc-tier": "structure"
    },
    "planned_review_date": {
      "type": "string",
      "description": "Doc-controller's committed review-completion date (YYYY-MM-DD), on the canonical submittal.",
      "x-zddc-tier": "option"
    },
    "planned_response_date": {
      "type": "string",
      "description": "Doc-controller's committed response-issuance date (YYYY-MM-DD), on the canonical submittal.",
      "x-zddc-tier": "option"
    },
    "paths": {
      "type": "object",
      "description": "Virtual sub-directory rules. Each key is a single path segment (literal or '*'); the value is a nested .zddc applied at the matching child directory. Recursive.",
      "additionalProperties": { "$ref": "#" },
      "x-zddc-tier": "structure"
    }
  }
}
