{
  "$comment": "GENERATED — do not edit by hand. Built from guest/agent/routing.go by github.com/manzhikov/tatnet-app-builder//guest/agent/cmd/schemagen; run `go generate ./...` after changing the vercel* input structs, then publish the result to openapi.tatnet.ru (a pure file copy).",
  "$id": "https://openapi.tatnet.ru/tatnet.json",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "additionalProperties": true,
  "definitions": {
    "condition": {
      "additionalProperties": false,
      "description": "An extra match condition. In `has` ALL listed conditions must hold; in `missing` NONE may hold.",
      "properties": {
        "key": {
          "description": "Name of the header / cookie / query parameter. Ignored when `type` is `host`.",
          "type": "string"
        },
        "type": {
          "description": "What to test. `host` ignores `key` (the request Host is matched against `value`).",
          "enum": [
            "header",
            "cookie",
            "query",
            "host"
          ],
          "type": "string"
        },
        "value": {
          "description": "PCRE the value must match. Omit (or leave empty) to assert mere presence of the header/cookie/query/host.",
          "type": "string"
        }
      },
      "required": [
        "type"
      ],
      "type": "object"
    },
    "conditionArray": {
      "items": {
        "$ref": "#/definitions/condition"
      },
      "type": "array"
    },
    "destination": {
      "description": "Same-origin target path (must NOT be an absolute URL in v1 — http://, https://, // are dropped at build). Reference captures from `source` by name (`/new/:slug`) or position (`/new/$1`).",
      "examples": [
        "/new/:slug",
        "/proxy/$1",
        "/index.html"
      ],
      "type": "string"
    },
    "headerRule": {
      "additionalProperties": false,
      "properties": {
        "has": {
          "$ref": "#/definitions/conditionArray"
        },
        "headers": {
          "description": "Headers to set on the response. Applied even on 404 / cold-start responses.",
          "items": {
            "$ref": "#/definitions/keyValue"
          },
          "minItems": 1,
          "type": "array"
        },
        "missing": {
          "$ref": "#/definitions/conditionArray"
        },
        "source": {
          "$ref": "#/definitions/source"
        }
      },
      "required": [
        "source",
        "headers"
      ],
      "type": "object"
    },
    "keyValue": {
      "additionalProperties": false,
      "properties": {
        "key": {
          "description": "Response header name.",
          "minLength": 1,
          "type": "string"
        },
        "value": {
          "description": "Response header value. Supports `:name` / `$1` substitution from `source` captures.",
          "type": "string"
        }
      },
      "required": [
        "key",
        "value"
      ],
      "type": "object"
    },
    "redirectRule": {
      "additionalProperties": false,
      "properties": {
        "destination": {
          "$ref": "#/definitions/destination"
        },
        "has": {
          "$ref": "#/definitions/conditionArray"
        },
        "missing": {
          "$ref": "#/definitions/conditionArray"
        },
        "permanent": {
          "description": "true → 308 (permanent), false → 307 (temporary). Used only when `statusCode` is not set.",
          "type": "boolean"
        },
        "source": {
          "$ref": "#/definitions/source"
        },
        "statusCode": {
          "description": "Explicit redirect status. When set (a 3xx) it takes precedence over `permanent`.",
          "enum": [
            301,
            302,
            303,
            307,
            308
          ],
          "type": "integer"
        }
      },
      "required": [
        "source",
        "destination"
      ],
      "type": "object"
    },
    "rewriteRule": {
      "additionalProperties": false,
      "properties": {
        "destination": {
          "$ref": "#/definitions/destination"
        },
        "has": {
          "$ref": "#/definitions/conditionArray"
        },
        "missing": {
          "$ref": "#/definitions/conditionArray"
        },
        "source": {
          "$ref": "#/definitions/source"
        }
      },
      "required": [
        "source",
        "destination"
      ],
      "type": "object"
    },
    "source": {
      "description": "Path pattern, must start with `/`. path-to-regexp syntax (case-sensitive, anchored to the full path, an optional trailing slash is allowed automatically): literal segments; `:name` (one segment); `:name*` (zero+ segments, greedy), `:name+` (one+), `:name?` (optional segment); `:name(regexp)` custom pattern; a bare `(regexp)` group → positional capture `$1`, `$2`, …; `*` → match the rest. Captured params are usable in `destination` as `:name` or `$1`.",
      "examples": [
        "/blog/:slug",
        "/api/:path*",
        "/old-:id(\\d+)",
        "/(.*)"
      ],
      "pattern": "^/",
      "type": "string"
    }
  },
  "description": "Schema for `tatnet.json` (or `vercel.json`) in the root of a TatNet-hosted app. TatNet reads this at build time, compiles the `headers` / `redirects` / `rewrites` blocks, and applies them at the edge — Vercel-parity. If both files exist, `tatnet.json` fully overrides `vercel.json` (it is NOT merged). Only the three keys below are consumed; any other keys (e.g. a full `vercel.json` build config) are ignored, not an error. A malformed config never fails the build — a bad rule is dropped with a build-log warning and the rest still apply. There is no platform CORS by default: declare any `Access-Control-Allow-Origin` you need via a `headers` rule.",
  "examples": [
    {
      "$schema": "https://openapi.tatnet.ru/tatnet.json",
      "headers": [
        {
          "headers": [
            {
              "key": "Access-Control-Allow-Origin",
              "value": "*"
            },
            {
              "key": "Cache-Control",
              "value": "public, max-age=3600"
            }
          ],
          "source": "/(.*)"
        }
      ],
      "redirects": [
        {
          "destination": "/new/:slug",
          "permanent": true,
          "source": "/old/:slug"
        }
      ],
      "rewrites": [
        {
          "destination": "/proxy/:path*",
          "source": "/api/:path*"
        }
      ]
    }
  ],
  "properties": {
    "$schema": {
      "default": "https://openapi.tatnet.ru/tatnet.json",
      "description": "Optional. Point your editor at this schema for autocomplete & validation.",
      "type": "string"
    },
    "headers": {
      "description": "Response headers to add for requests whose path matches `source`. Every matching rule is applied (Vercel parity); on a key collision the last matching rule wins. Total rules across headers+redirects+rewrites must be at most 256.",
      "items": {
        "$ref": "#/definitions/headerRule"
      },
      "maxItems": 256,
      "type": "array"
    },
    "redirects": {
      "description": "HTTP redirects, evaluated before any content is served. First matching rule wins and terminates the request. Same-origin destinations only — an absolute URL (http://, https://, //) is dropped at build time in v1. Total rules across headers+redirects+rewrites must be at most 256.",
      "items": {
        "$ref": "#/definitions/redirectRule"
      },
      "maxItems": 256,
      "type": "array"
    },
    "rewrites": {
      "description": "Internal path rewrites: the request is served as if it had `destination`'s path, but the browser URL is unchanged. First matching rule wins. Same-origin destinations only — an absolute URL is dropped at build time in v1. Total rules across headers+redirects+rewrites must be at most 256.",
      "items": {
        "$ref": "#/definitions/rewriteRule"
      },
      "maxItems": 256,
      "type": "array"
    }
  },
  "title": "TatNet app routing config",
  "type": "object"
}
