{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://sircypkowskyy.github.io/inwards/schema/tool-inwards.json",
  "title": "[tool.inwards]",
  "description": "Configuration of Inwards, the architecture linter for Python, in pyproject.toml. The schema checks structure, types, enums and syntax; the parser also checks relations between entries (unique names, context ownership) and required-version.",
  "markdownDescription": "Configuration of Inwards, the architecture linter for Python, in pyproject.toml. The schema checks structure, types, enums and syntax; the parser also checks relations between entries (unique names, context ownership) and required-version.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#configuration-reference)",
  "type": "object",
  "additionalProperties": false,
  "required": ["layers"],
  "properties": {
    "root": {
      "description": "Directory, relative to pyproject.toml, that module names are computed from.",
      "markdownDescription": "Directory, relative to pyproject.toml, that module names are computed from.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#root)",
      "type": "string",
      "default": "."
    },
    "layers": {
      "description": "The layers, innermost first. A module may import its own layer and any layer listed before it. A nested array holds independent siblings, which may not import each other.",
      "markdownDescription": "The layers, innermost first. A module may import its own layer and any layer listed before it. A nested array holds independent siblings, which may not import each other.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#layers)",
      "type": "array",
      "minItems": 1,
      "items": {
        "anyOf": [{ "$ref": "#/definitions/layer" }, { "$ref": "#/definitions/siblingLayers" }]
      }
    },
    "required-version": {
      "description": "The oldest Inwards allowed to check this project, as \"MAJOR.MINOR.PATCH\". An older binary fails with a config error.",
      "markdownDescription": "The oldest Inwards allowed to check this project, as \"MAJOR.MINOR.PATCH\". An older binary fails with a config error.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#required-version)",
      "type": "string",
      "pattern": "^\\d+\\.\\d+\\.\\d+$"
    },
    "ignore": {
      "description": "Module names left out of the INW006 unassigned-package warning, matched as whole segments anywhere in a module name, or at its start when the entry begins with /.",
      "markdownDescription": "Module names left out of the INW006 unassigned-package warning, matched as whole segments anywhere in a module name, or at its start when the entry begins with /.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#ignore)",
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1
      }
    },
    "generated": {
      "description": "Modules a build step writes, which INW010 treats as existing: dotted names whose segments may use * and ?. A list, even an empty one, replaces the default.",
      "markdownDescription": "Modules a build step writes, which INW010 treats as existing: dotted names whose segments may use * and ?. A list, even an empty one, replaces the default.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#generated)",
      "type": "array",
      "items": {
        "type": "string",
        "pattern": "^[^.\\s/\\\\\\[\\]-]+(\\.[^.\\s/\\\\\\[\\]-]+)*$",
        "not": {
          "pattern": "^[*?.]+$"
        }
      },
      "default": ["*_pb2", "*_pb2_grpc", "_version"]
    },
    "namespace-packages": {
      "description": "Implicit namespace packages that installed distributions add to, such as acme.platform. INW010 doesn't report a missing module directly inside one; a missing module inside a subpackage that is in the project is still reported.",
      "markdownDescription": "Implicit namespace packages that installed distributions add to, such as acme.platform. INW010 doesn't report a missing module directly inside one; a missing module inside a subpackage that is in the project is still reported.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#namespace-packages)",
      "type": "array",
      "items": {
        "$ref": "#/definitions/dottedName"
      }
    },
    "escalate-after": {
      "description": "How many attempts at the same violation before the hooks stop blocking and tell the agent to ask the user.",
      "markdownDescription": "How many attempts at the same violation before the hooks stop blocking and tell the agent to ask the user.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#escalate-after)",
      "type": "integer",
      "minimum": 1,
      "default": 3
    },
    "run-log": {
      "description": "Write the opt-in run log .inwards/runs.jsonl.",
      "markdownDescription": "Write the opt-in run log .inwards/runs.jsonl.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#run-log)",
      "type": "boolean",
      "default": false
    },
    "stop-gate": {
      "description": "What the Claude Code Stop gate checks: \"changed\" (the files the session changed) or \"project\" (the whole project against its baseline).",
      "markdownDescription": "What the Claude Code Stop gate checks: \"changed\" (the files the session changed) or \"project\" (the whole project against its baseline).\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#stop-gate)",
      "enum": ["changed", "project"],
      "default": "changed"
    },
    "cycles": {
      "description": "Which import cycles INW004 reports: between modules, between bounded contexts, both, or none ([]).",
      "markdownDescription": "Which import cycles INW004 reports: between modules, between bounded contexts, both, or none ([]).\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#cycles)",
      "type": "array",
      "items": {
        "enum": ["modules", "contexts"]
      },
      "uniqueItems": true,
      "default": ["contexts"]
    },
    "diagrams": {
      "description": "Markdown, Mermaid and PlantUML files whose marked diagrams (%% inwards: layers or contexts in Mermaid, ' inwards: layers or contexts in PlantUML) INW017, INW018 and INW019 check against the config and the code: paths relative to the config file, with * and ? in a segment and ** for any number of directories.",
      "markdownDescription": "Markdown, Mermaid and PlantUML files whose marked diagrams (`%% inwards: layers` or `contexts` in Mermaid, `' inwards: layers` or `contexts` in PlantUML) INW017, INW018 and INW019 check against the config and the code: paths relative to the config file, with `*` and `?` in a segment and `**` for any number of directories.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#diagrams)",
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1,
        "pattern": "^(?!/)(?![A-Za-z]:)(?!.*\\\\)(?!(?:.*/)?\\.\\.(?:/|$))(?!.*//)"
      }
    },
    "shape": {
      "description": "Package shapes: which members a package may, must and must not hold (INW007, INW008). The first matching entry wins.",
      "markdownDescription": "Package shapes: which members a package may, must and must not hold (INW007, INW008). The first matching entry wins.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#shape)",
      "type": "array",
      "items": {
        "$ref": "#/definitions/shape"
      }
    },
    "names": {
      "description": "Where a member name may appear (INW007).",
      "markdownDescription": "Where a member name may appear (INW007).\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#shape)",
      "type": "array",
      "items": {
        "$ref": "#/definitions/name"
      }
    },
    "rules": {
      "$ref": "#/definitions/rules"
    },
    "agent-suppressions": {
      "description": "Whether the Claude Code hooks honour an inline suppression the agent added: \"deny\" treats it as absent, \"allow\" honours it.",
      "markdownDescription": "Whether the Claude Code hooks honour an inline suppression the agent added: \"deny\" treats it as absent, \"allow\" honours it.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#agent-suppressions)",
      "enum": ["deny", "allow"],
      "default": "deny"
    },
    "contexts": {
      "description": "Bounded contexts or slices: what each owns, which of its modules others may import, and which contexts it may depend on (INW002, INW003).",
      "markdownDescription": "Bounded contexts or slices: what each owns, which of its modules others may import, and which contexts it may depend on (INW002, INW003).\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#contexts)",
      "type": "array",
      "items": {
        "$ref": "#/definitions/context"
      }
    },
    "templates": {
      "description": "Named templates: roles that expand into layers, shape keys and a context's public modules, used with template = \"<name>\" on layer, shape and context entries.",
      "markdownDescription": "Named templates: roles that expand into layers, shape keys and a context's public modules, used with template = \"<name>\" on layer, shape and context entries.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#templates)",
      "type": "object",
      "propertyNames": { "pattern": "\\S" },
      "additionalProperties": {
        "$ref": "#/definitions/template"
      }
    }
  },
  "definitions": {
    "dottedName": {
      "description": "A dotted Python name such as shop.orders, with no wildcards.",
      "type": "string",
      "pattern": "^[^.\\s*?\\[\\]/\\\\-]+(\\.[^.\\s*?\\[\\]/\\\\-]+)*$"
    },
    "publicEntry": {
      "description": "A public entry: a dotted module prefix such as shop.billing.api, or, with a leading =, that module alone without what lies under it, such as =shop.billing.",
      "type": "string",
      "pattern": "^=?[^.\\s*?\\[\\]/\\\\-]+(\\.[^.\\s*?\\[\\]/\\\\-]+)*$"
    },
    "selector": {
      "description": "A package selector: a.b (exact), a.* (one level) or a.** (any depth).",
      "type": "string",
      "pattern": "^(\\*\\*?|[^.\\s*?\\[\\]/\\\\-]+)(\\.(\\*\\*?|[^.\\s*?\\[\\]/\\\\-]+))*$"
    },
    "layerEntry": {
      "description": "A layer entry: a module prefix such as shop.domain, or, with a *, a selector whose segments are identifiers, * (one segment) or ** (one or more), starting with a package name, such as shop.*.domain. Inwards also checks non-ASCII identifiers exactly.",
      "type": "string",
      "minLength": 1,
      "anyOf": [
        {
          "pattern": "^[^*]+$"
        },
        {
          "pattern": "^[A-Za-z_\\u0080-\\uffff][A-Za-z0-9_\\u0080-\\uffff]*(\\.(\\*\\*?|[A-Za-z_\\u0080-\\uffff][A-Za-z0-9_\\u0080-\\uffff]*))+$"
        }
      ]
    },
    "memberPattern": {
      "description": "A member pattern: a name or fnmatch glob (*, ?, [seq], [!seq]), optionally ending in .py or /. Inwards also rejects a reversed range such as [z-a].",
      "type": "string",
      "pattern": "^(?:\\[(?:!(?:\\][^\\]/.]*|[^\\]/.][^\\]/.]*)|\\][^\\]/.]*|[^\\]/.!][^\\]/.]*)\\]|[^/.\\[])+(\\.py|/)?$"
    },
    "libraryList": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/dottedName"
      }
    },
    "ruleCode": {
      "description": "A rule code this Inwards knows.",
      "enum": [
        "INW000",
        "INW001",
        "INW002",
        "INW003",
        "INW004",
        "INW005",
        "INW006",
        "INW007",
        "INW008",
        "INW009",
        "INW010",
        "INW011",
        "INW012",
        "INW013",
        "INW014",
        "INW015",
        "INW016",
        "INW017",
        "INW018",
        "INW019",
        "INW020",
        "INW021",
        "FAPI001",
        "FAPI002",
        "FAPI003",
        "FAPI005",
        "FAPI006",
        "FAPI007",
        "FAPI008",
        "FAPI009"
      ]
    },
    "layer": {
      "type": "object",
      "additionalProperties": false,
      "required": ["name", "modules"],
      "properties": {
        "name": {
          "description": "The layer's name, unique among layers.",
          "markdownDescription": "The layer's name, unique among layers.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#layers)",
          "type": "string",
          "minLength": 1
        },
        "modules": {
          "description": "Module prefixes and selectors that belong to the layer: shop.domain owns shop.domain.order, shop.*.domain owns shop.orders.domain.order.",
          "markdownDescription": "Module prefixes and selectors that belong to the layer: shop.domain owns shop.domain.order, shop.*.domain owns shop.orders.domain.order.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#layers)",
          "type": "array",
          "items": {
            "$ref": "#/definitions/layerEntry"
          }
        },
        "allow-libraries": {
          "description": "Libraries the layer may import; when set, any other third-party library is denied (INW005).",
          "markdownDescription": "Libraries the layer may import; when set, any other third-party library is denied (INW005).\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#layers)",
          "allOf": [
            {
              "$ref": "#/definitions/libraryList"
            }
          ]
        },
        "deny-libraries": {
          "description": "Libraries the layer may not import, stdlib included (INW005).",
          "markdownDescription": "Libraries the layer may not import, stdlib included (INW005).\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#layers)",
          "allOf": [
            {
              "$ref": "#/definitions/libraryList"
            }
          ]
        },
        "extend-deny-libraries": {
          "description": "Libraries added to the layer's deny list or to the innermost layer's default list (INW005).",
          "markdownDescription": "Libraries added to the layer's deny list or to the innermost layer's default list (INW005).\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#layers)",
          "allOf": [
            {
              "$ref": "#/definitions/libraryList"
            }
          ]
        },
        "template": {
          "description": "A template whose roles expand into one layer each, inside this entry's modules. The entry itself is no layer.",
          "markdownDescription": "A template whose roles expand into one layer each, inside this entry's modules. The entry itself is no layer.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#templates)",
          "$ref": "#/definitions/templateName"
        }
      }
    },
    "siblingLayers": {
      "description": "Two or more independent sibling layers: they share a place in the order and may not import each other.",
      "type": "array",
      "minItems": 2,
      "items": {
        "allOf": [
          { "$ref": "#/definitions/layer" },
          { "type": "object", "properties": { "template": false } }
        ]
      }
    },
    "shape": {
      "type": "object",
      "additionalProperties": false,
      "required": ["packages"],
      "properties": {
        "packages": {
          "description": "Package selectors this shape applies to.",
          "markdownDescription": "Package selectors this shape applies to.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#shape)",
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/definitions/selector"
          }
        },
        "allow": {
          "description": "Members the package may hold; anything else is extra.",
          "markdownDescription": "Members the package may hold; anything else is extra.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#shape)",
          "type": "array",
          "items": {
            "$ref": "#/definitions/memberPattern"
          }
        },
        "require": {
          "description": "Members the package must hold (INW008).",
          "markdownDescription": "Members the package must hold (INW008).\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#shape)",
          "type": "array",
          "items": {
            "$ref": "#/definitions/memberPattern"
          }
        },
        "forbid": {
          "description": "Members the package must not hold.",
          "markdownDescription": "Members the package must not hold.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#shape)",
          "type": "array",
          "items": {
            "$ref": "#/definitions/memberPattern"
          }
        },
        "extra": {
          "description": "How an extra member is reported: \"error\" or \"warning\".",
          "markdownDescription": "How an extra member is reported: \"error\" or \"warning\".\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#shape)",
          "enum": ["error", "warning"],
          "default": "error"
        },
        "hints": {
          "description": "Project advice added to the fix steps of an INW007 finding for this shape.",
          "markdownDescription": "Project advice added to the fix steps of an INW007 finding for this shape.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#shape)",
          "$ref": "#/definitions/hints"
        },
        "template": {
          "description": "A template that supplies allow, require, forbid, extra and hints; keys this entry sets win.",
          "markdownDescription": "A template that supplies allow, require, forbid, extra and hints; keys this entry sets win.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#templates)",
          "$ref": "#/definitions/templateName"
        }
      }
    },
    "name": {
      "type": "object",
      "additionalProperties": false,
      "required": ["pattern", "only-in"],
      "properties": {
        "pattern": {
          "description": "One member pattern, such as test_*.",
          "markdownDescription": "One member pattern, such as test_*.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#shape)",
          "allOf": [
            {
              "$ref": "#/definitions/memberPattern"
            }
          ]
        },
        "only-in": {
          "description": "Package selectors where members matching the pattern may appear.",
          "markdownDescription": "Package selectors where members matching the pattern may appear.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#shape)",
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/definitions/selector"
          }
        }
      }
    },
    "rules": {
      "description": "Which rules report and how loudly. ignore wins over select and extend-select; INW000 can't be ignored or re-levelled. A key named after a rule holds that rule's options.",
      "markdownDescription": "Which rules report and how loudly. ignore wins over select and extend-select; INW000 can't be ignored or re-levelled. A key named after a rule holds that rule's options.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#rules)",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "select": {
          "description": "Only these rules report, opt-in rules included. Must list at least one code.",
          "markdownDescription": "Only these rules report, opt-in rules included. Must list at least one code.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#rules)",
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/definitions/ruleCode"
          }
        },
        "extend-select": {
          "description": "These rules report too, on top of select or the rules that are on by default. Turns opt-in rules on. INW000 can't be listed.",
          "markdownDescription": "These rules report too, on top of select or the rules that are on by default. Turns opt-in rules on. INW000 can't be listed.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#rules)",
          "type": "array",
          "items": {
            "allOf": [
              {
                "$ref": "#/definitions/ruleCode"
              },
              {
                "not": {
                  "const": "INW000"
                }
              }
            ]
          }
        },
        "ignore": {
          "description": "These rules don't report. INW000 can't be listed.",
          "markdownDescription": "These rules don't report. INW000 can't be listed.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#rules)",
          "type": "array",
          "items": {
            "allOf": [
              {
                "$ref": "#/definitions/ruleCode"
              },
              {
                "not": {
                  "const": "INW000"
                }
              }
            ]
          }
        },
        "severity": {
          "description": "Per-rule severity, such as { INW006 = \"warning\" }. INW000 can't be listed.",
          "markdownDescription": "Per-rule severity, such as { INW006 = \"warning\" }. INW000 can't be listed.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#rules)",
          "type": "object",
          "propertyNames": {
            "allOf": [
              {
                "$ref": "#/definitions/ruleCode"
              },
              {
                "not": {
                  "const": "INW000"
                }
              }
            ]
          },
          "additionalProperties": {
            "enum": ["error", "warning"]
          }
        },
        "layer-dependency": {
          "$ref": "#/definitions/ruleOptions"
        },
        "context-independence": {
          "$ref": "#/definitions/ruleOptions"
        },
        "public-api-only": {
          "$ref": "#/definitions/ruleOptions"
        },
        "import-cycles": {
          "$ref": "#/definitions/ruleOptions"
        },
        "pure-domain": {
          "$ref": "#/definitions/pureDomainOptions"
        },
        "unassigned-module": {
          "$ref": "#/definitions/ruleOptions"
        },
        "package-shape": {
          "$ref": "#/definitions/ruleOptions"
        },
        "missing-member": {
          "$ref": "#/definitions/ruleOptions"
        },
        "suppression-comment": {
          "$ref": "#/definitions/ruleOptions"
        },
        "unknown-first-party": {
          "$ref": "#/definitions/ruleOptions"
        },
        "dynamic-import": {
          "$ref": "#/definitions/ruleOptions"
        },
        "thin-endpoint": {
          "$ref": "#/definitions/thinEndpointOptions"
        },
        "async-blocking": {
          "$ref": "#/definitions/asyncBlockingOptions"
        },
        "ports-abstract": {
          "$ref": "#/definitions/portsAbstractOptions"
        },
        "construct-only-in": {
          "$ref": "#/definitions/constructOnlyInOptions"
        },
        "orm-naming": {
          "$ref": "#/definitions/ormNamingOptions"
        },
        "private-module": {
          "$ref": "#/definitions/contentRuleOptions"
        },
        "adapter-conformance": {
          "$ref": "#/definitions/adapterConformanceOptions"
        },
        "diagram-unknown-name": {
          "$ref": "#/definitions/ruleOptions"
        },
        "diagram-forbidden-edge": {
          "$ref": "#/definitions/ruleOptions"
        },
        "diagram-missing-dependency": {
          "$ref": "#/definitions/ruleOptions"
        },
        "endpoint-metadata": {
          "$ref": "#/definitions/endpointMetadataOptions"
        },
        "undocumented-error-response": {
          "$ref": "#/definitions/undocumentedErrorResponseOptions"
        },
        "router-wiring": {
          "$ref": "#/definitions/routerWiringOptions"
        },
        "route-shadowing": {
          "$ref": "#/definitions/contentRuleOptions"
        },
        "lifespan-events": {
          "$ref": "#/definitions/contentRuleOptions"
        },
        "yield-dependency-swallows": {
          "$ref": "#/definitions/contentRuleOptions"
        },
        "duplicate-operation-id": {
          "$ref": "#/definitions/contentRuleOptions"
        },
        "depends-called": {
          "$ref": "#/definitions/contentRuleOptions"
        }
      }
    },
    "ruleOptions": {
      "description": "A rule's options, [tool.inwards.rules.<rule-name>]. They don't turn the rule on: extend-select or select does.",
      "markdownDescription": "A rule's options, [tool.inwards.rules.<rule-name>]. They don't turn the rule on: extend-select or select does.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#rules)",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "modules": {
          "description": "Module prefixes or selectors, as in layers[].modules: the rule reports only in the modules they match.",
          "markdownDescription": "Module prefixes or selectors, as in layers[].modules: the rule reports only in the modules they match.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#rules)",
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/definitions/layerEntry"
          }
        }
      }
    },
    "contentRuleOptions": {
      "description": "A content rule's options, [tool.inwards.rules.<rule-name>]. They don't turn the rule on: extend-select or select does.",
      "markdownDescription": "A content rule's options, [tool.inwards.rules.<rule-name>]. They don't turn the rule on: extend-select or select does.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#rules)",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "modules": {
          "description": "Module prefixes or selectors, as in layers[].modules: the rule reports only in the modules they match.",
          "markdownDescription": "Module prefixes or selectors, as in layers[].modules: the rule reports only in the modules they match.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#rules)",
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/definitions/layerEntry"
          }
        },
        "check-tests": {
          "description": "Whether the rule also reports in test modules: test_*.py, *_test.py, conftest.py, and modules with a tests or test segment. Off by default, so the rule skips them.",
          "markdownDescription": "Whether the rule also reports in test modules: test_*.py, *_test.py, conftest.py, and modules with a tests or test segment. Off by default, so the rule skips them.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/#opt-in-rules)",
          "type": "boolean",
          "default": false
        }
      }
    },
    "pureDomainOptions": {
      "description": "INW005's options, [tool.inwards.rules.pure-domain]: modules, as for every rule, and deny.",
      "markdownDescription": "INW005's options, [tool.inwards.rules.pure-domain]: modules, as for every rule, and deny.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#rules)",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "modules": {
          "$ref": "#/definitions/ruleOptions/properties/modules"
        },
        "deny": {
          "description": "Libraries denied to module prefixes that aren't whole layers, whether or not a layer owns them. The layer's allow-libraries doesn't undo them (INW005).",
          "markdownDescription": "Libraries denied to module prefixes that aren't whole layers, whether or not a layer owns them. The layer's allow-libraries doesn't undo them (INW005).\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#rules)",
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["modules", "libraries"],
            "properties": {
              "modules": {
                "description": "Module prefixes or selectors, as in layers[].modules, that may not import this entry's libraries.",
                "markdownDescription": "Module prefixes or selectors, as in layers[].modules, that may not import this entry's libraries.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#rules)",
                "type": "array",
                "minItems": 1,
                "items": {
                  "$ref": "#/definitions/layerEntry"
                }
              },
              "libraries": {
                "description": "Import names such as django or http.client; each covers its submodules, stdlib included.",
                "markdownDescription": "Import names such as django or http.client; each covers its submodules, stdlib included.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#rules)",
                "type": "array",
                "minItems": 1,
                "items": {
                  "$ref": "#/definitions/dottedName"
                }
              }
            }
          }
        }
      }
    },
    "ormNamingOptions": {
      "description": "INW016 orm-naming's options, [tool.inwards.rules.orm-naming]. They don't turn the rule on: extend-select or select does.",
      "markdownDescription": "INW016 orm-naming's options, [tool.inwards.rules.orm-naming]. They don't turn the rule on: extend-select or select does.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW016/)",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "modules": {
          "$ref": "#/definitions/ruleOptions/properties/modules"
        },
        "check-tests": {
          "description": "Whether the rule also reports in test modules: test_*.py, *_test.py, conftest.py, and modules with a tests or test segment. Off by default, so the rule skips them.",
          "markdownDescription": "Whether the rule also reports in test modules: test_*.py, *_test.py, conftest.py, and modules with a tests or test segment. Off by default, so the rule skips them.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/#opt-in-rules)",
          "type": "boolean",
          "default": false
        },
        "table-name": {
          "description": "How table names are checked: lower_case_snake and singular (\"snake_singular\"), lower_case_snake only (\"snake\"), or not at all (false).",
          "markdownDescription": "How table names are checked: lower_case_snake and singular (\"snake_singular\"), lower_case_snake only (\"snake\"), or not at all (false).\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW016/)",
          "enum": ["snake", "snake_singular", false],
          "default": "snake_singular"
        },
        "datetime-suffix": {
          "description": "The suffix every datetime column name ends with, or false to turn the check off.",
          "markdownDescription": "The suffix every datetime column name ends with, or false to turn the check off.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW016/)",
          "oneOf": [
            {
              "type": "string",
              "pattern": "^[a-z0-9_]+$"
            },
            {
              "const": false
            }
          ],
          "default": "_at"
        },
        "date-suffix": {
          "description": "The suffix every date column name ends with, or false to turn the check off.",
          "markdownDescription": "The suffix every date column name ends with, or false to turn the check off.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW016/)",
          "oneOf": [
            {
              "type": "string",
              "pattern": "^[a-z0-9_]+$"
            },
            {
              "const": false
            }
          ],
          "default": "_date"
        },
        "allow-tables": {
          "description": "Table names INW016 accepts as written, such as a mass noun the singular heuristic reads as a plural (\"news\" is built in).",
          "markdownDescription": "Table names INW016 accepts as written, such as a mass noun the singular heuristic reads as a plural (\"news\" is built in).\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW016/)",
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "\\S"
          },
          "default": []
        },
        "require-naming-convention": {
          "description": "In a whole-project run, report a project with SQLAlchemy or SQLModel tables and no MetaData(naming_convention=...).",
          "markdownDescription": "In a whole-project run, report a project with SQLAlchemy or SQLModel tables and no MetaData(naming_convention=...).\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW016/)",
          "type": "boolean",
          "default": true
        }
      }
    },
    "adapterConformanceOptions": {
      "description": "INW020 adapter-conformance's options, [tool.inwards.rules.adapter-conformance]. They don't turn the rule on: extend-select or select does. Without modules, the rule checks the modules with an adapters segment.",
      "markdownDescription": "INW020 adapter-conformance's options, [tool.inwards.rules.adapter-conformance]. They don't turn the rule on: extend-select or select does. Without modules, the rule checks the modules with an adapters segment.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW020/)",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "modules": {
          "$ref": "#/definitions/ruleOptions/properties/modules"
        },
        "check-tests": {
          "description": "Whether the rule also reports in test modules: test_*.py, *_test.py, conftest.py, and modules with a tests or test segment. Off by default, so the rule skips them.",
          "markdownDescription": "Whether the rule also reports in test modules: test_*.py, *_test.py, conftest.py, and modules with a tests or test segment. Off by default, so the rule skips them.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/#opt-in-rules)",
          "type": "boolean",
          "default": false
        },
        "ports": {
          "description": "The port modules, as module prefixes or selectors as in layers[].modules. A conformance line's annotation must name a class from one of them. Without it, the port in a message is the one class the module imports from a module with a ports segment, and any annotation but Any and object counts.",
          "markdownDescription": "The port modules, as module prefixes or selectors as in layers[].modules. A conformance line's annotation must name a class from one of them. Without it, the port in a message is the one class the module imports from a module with a ports segment, and any annotation but Any and object counts.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW020/)",
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/definitions/layerEntry"
          }
        },
        "allow-bases": {
          "description": "Bases that keep a class in an adapter module out of the check, by qualified name with * and ? wildcards; builtins are spelled bare (Exception). Replaces the default list of exceptions, pydantic.BaseModel, NamedTuple, TypedDict and enums.",
          "markdownDescription": "Bases that keep a class in an adapter module out of the check, by qualified name with * and ? wildcards; builtins are spelled bare (Exception). Replaces the default list of exceptions, pydantic.BaseModel, NamedTuple, TypedDict and enums.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW020/)",
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^[^.\\s\\[\\]/\\\\:-]+(\\.[^.\\s\\[\\]/\\\\:-]+)*$"
          },
          "default": [
            "BaseException",
            "Exception",
            "*Error",
            "*Exception",
            "*Warning",
            "pydantic.BaseModel",
            "typing.NamedTuple",
            "typing.TypedDict",
            "typing_extensions.NamedTuple",
            "typing_extensions.TypedDict",
            "enum.*"
          ]
        },
        "extend-allow-bases": {
          "description": "Bases added to allow-bases (or to its default), by qualified name with * and ? wildcards.",
          "markdownDescription": "Bases added to allow-bases (or to its default), by qualified name with * and ? wildcards.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW020/)",
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^[^.\\s\\[\\]/\\\\:-]+(\\.[^.\\s\\[\\]/\\\\:-]+)*$"
          },
          "default": []
        },
        "allow-decorators": {
          "description": "Class decorators that keep a class in an adapter module out of the check, by qualified name with * and ? wildcards. Replaces the default list of dataclass, pydantic and attrs decorators.",
          "markdownDescription": "Class decorators that keep a class in an adapter module out of the check, by qualified name with * and ? wildcards. Replaces the default list of dataclass, pydantic and attrs decorators.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW020/)",
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^[^.\\s\\[\\]/\\\\:-]+(\\.[^.\\s\\[\\]/\\\\:-]+)*$"
          },
          "default": [
            "dataclasses.dataclass",
            "pydantic.dataclasses.dataclass",
            "attrs.define",
            "attrs.frozen",
            "attrs.mutable",
            "attr.s",
            "attr.attrs",
            "attr.define",
            "attr.frozen"
          ]
        }
      }
    },
    "asyncBlockingOptions": {
      "description": "INW013 async-blocking's options, [tool.inwards.rules.async-blocking]. They don't turn the rule on: extend-select or select does.",
      "markdownDescription": "INW013 async-blocking's options, [tool.inwards.rules.async-blocking]. They don't turn the rule on: extend-select or select does.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW013/)",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "modules": {
          "$ref": "#/definitions/ruleOptions/properties/modules"
        },
        "check-tests": {
          "description": "Whether the rule also reports in test modules: test_*.py, *_test.py, conftest.py, and modules with a tests or test segment. Off by default, so the rule skips them.",
          "markdownDescription": "Whether the rule also reports in test modules: test_*.py, *_test.py, conftest.py, and modules with a tests or test segment. Off by default, so the rule skips them.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/#opt-in-rules)",
          "type": "boolean",
          "default": false
        },
        "extend-blocking-calls": {
          "description": "Calls that block when called inside async def, added to INW013's built-in list (sqlite3.connect, psycopg2.connect and the other DB-API drivers), by qualified name with * and ? wildcards.",
          "markdownDescription": "Calls that block when called inside async def, added to INW013's built-in list (sqlite3.connect, psycopg2.connect and the other DB-API drivers), by qualified name with * and ? wildcards.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW013/)",
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^[^.\\s\\[\\]/\\\\:-]+(\\.[^.\\s\\[\\]/\\\\:-]+)*$"
          },
          "default": []
        },
        "extend-blocking-types": {
          "description": "Types or factories whose every method blocks, added to INW013's built-in list (the sync SQLAlchemy Session and Engine, redis.Redis, boto3 clients, DB-API connections), by qualified name with * and ? wildcards. A parameter annotated with one, or a name bound from a call to one, is a blocking receiver.",
          "markdownDescription": "Types or factories whose every method blocks, added to INW013's built-in list (the sync SQLAlchemy Session and Engine, redis.Redis, boto3 clients, DB-API connections), by qualified name with * and ? wildcards. A parameter annotated with one, or a name bound from a call to one, is a blocking receiver.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW013/)",
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^[^.\\s\\[\\]/\\\\:-]+(\\.[^.\\s\\[\\]/\\\\:-]+)*$"
          },
          "default": []
        },
        "follow-modules": {
          "description": "Module prefixes or selectors, as in layers[].modules, of the first-party modules INW013 follows one hop into from an async def to find a sync helper that blocks; packages above them are read too, for re-exports. Unset follows every first-party module; [] keeps the check to the checked module.",
          "markdownDescription": "Module prefixes or selectors, as in layers[].modules, of the first-party modules INW013 follows one hop into from an async def to find a sync helper that blocks; packages above them are read too, for re-exports. Unset follows every first-party module; [] keeps the check to the checked module.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW013/)",
          "type": "array",
          "items": {
            "$ref": "#/definitions/layerEntry"
          }
        }
      }
    },
    "portsAbstractOptions": {
      "description": "INW014 ports-abstract's options, [tool.inwards.rules.ports-abstract]. They don't turn the rule on: extend-select or select does. Without modules, the rule checks the modules with a ports segment.",
      "markdownDescription": "INW014 ports-abstract's options, [tool.inwards.rules.ports-abstract]. They don't turn the rule on: extend-select or select does. Without modules, the rule checks the modules with a ports segment.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW014/)",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "modules": {
          "$ref": "#/definitions/ruleOptions/properties/modules"
        },
        "check-tests": {
          "description": "Whether the rule also reports in test modules: test_*.py, *_test.py, conftest.py, and modules with a tests or test segment. Off by default, so the rule skips them.",
          "markdownDescription": "Whether the rule also reports in test modules: test_*.py, *_test.py, conftest.py, and modules with a tests or test segment. Off by default, so the rule skips them.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/#opt-in-rules)",
          "type": "boolean",
          "default": false
        },
        "allow-bases": {
          "description": "Bases that keep a class in a port module out of the check, by qualified name with * and ? wildcards; builtins are spelled bare (Exception). Replaces the default list of exceptions, pydantic.BaseModel, NamedTuple, TypedDict and enums.",
          "markdownDescription": "Bases that keep a class in a port module out of the check, by qualified name with * and ? wildcards; builtins are spelled bare (Exception). Replaces the default list of exceptions, pydantic.BaseModel, NamedTuple, TypedDict and enums.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW014/)",
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^[^.\\s\\[\\]/\\\\:-]+(\\.[^.\\s\\[\\]/\\\\:-]+)*$"
          },
          "default": [
            "BaseException",
            "Exception",
            "*Error",
            "*Exception",
            "*Warning",
            "pydantic.BaseModel",
            "typing.NamedTuple",
            "typing.TypedDict",
            "typing_extensions.NamedTuple",
            "typing_extensions.TypedDict",
            "enum.*"
          ]
        },
        "extend-allow-bases": {
          "description": "Bases added to allow-bases (or to its default), by qualified name with * and ? wildcards.",
          "markdownDescription": "Bases added to allow-bases (or to its default), by qualified name with * and ? wildcards.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW014/)",
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^[^.\\s\\[\\]/\\\\:-]+(\\.[^.\\s\\[\\]/\\\\:-]+)*$"
          },
          "default": []
        },
        "allow-decorators": {
          "description": "Class decorators that keep a class in a port module out of the check, by qualified name with * and ? wildcards. Replaces the default list of dataclass, pydantic and attrs decorators.",
          "markdownDescription": "Class decorators that keep a class in a port module out of the check, by qualified name with * and ? wildcards. Replaces the default list of dataclass, pydantic and attrs decorators.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW014/)",
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^[^.\\s\\[\\]/\\\\:-]+(\\.[^.\\s\\[\\]/\\\\:-]+)*$"
          },
          "default": [
            "dataclasses.dataclass",
            "pydantic.dataclasses.dataclass",
            "attrs.define",
            "attrs.frozen",
            "attrs.mutable",
            "attr.s",
            "attr.attrs",
            "attr.define",
            "attr.frozen"
          ]
        },
        "interface": {
          "description": "What a port class must be: \"any\" accepts ABCs and Protocols; \"protocol\" also reports an ABC in a port module, and a port that extends a port without listing Protocol among its own bases.",
          "markdownDescription": "What a port class must be: \"any\" accepts ABCs and Protocols; \"protocol\" also reports an ABC in a port module, and a port that extends a port without listing Protocol among its own bases.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW014/)",
          "enum": ["any", "protocol"],
          "default": "any"
        },
        "allow-subclassing": {
          "description": "Whether a class outside the port modules may list a class from a port module among its bases. false reports each such base: adapters implement ports by their shape, checked with _: Port = Adapter(...) under if TYPE_CHECKING:.",
          "markdownDescription": "Whether a class outside the port modules may list a class from a port module among its bases. false reports each such base: adapters implement ports by their shape, checked with _: Port = Adapter(...) under if TYPE_CHECKING:.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW014/)",
          "type": "boolean",
          "default": true
        }
      }
    },
    "thinEndpointOptions": {
      "description": "INW012 thin-endpoint's options, [tool.inwards.rules.thin-endpoint]. They don't turn the rule on: extend-select or select does.",
      "markdownDescription": "INW012 thin-endpoint's options, [tool.inwards.rules.thin-endpoint]. They don't turn the rule on: extend-select or select does.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW012/)",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "modules": {
          "$ref": "#/definitions/ruleOptions/properties/modules"
        },
        "check-tests": {
          "description": "Whether the rule also reports in test modules: test_*.py, *_test.py, conftest.py, and modules with a tests or test segment. Off by default, so the rule skips them.",
          "markdownDescription": "Whether the rule also reports in test modules: test_*.py, *_test.py, conftest.py, and modules with a tests or test segment. Off by default, so the rule skips them.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/#opt-in-rules)",
          "type": "boolean",
          "default": false
        },
        "max-statements": {
          "description": "The most statements an endpoint's body may hold, nested ones included; guards that raise an HTTP error and the docstring don't count. false turns the check off.",
          "markdownDescription": "The most statements an endpoint's body may hold, nested ones included; guards that raise an HTTP error and the docstring don't count. false turns the check off.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW012/)",
          "oneOf": [
            {
              "type": "integer",
              "minimum": 0,
              "maximum": 1000
            },
            {
              "const": false
            }
          ],
          "default": 10
        },
        "max-branches": {
          "description": "The most if/elif, case and except branches an endpoint may hold, guards left out. false turns the check off.",
          "markdownDescription": "The most if/elif, case and except branches an endpoint may hold, guards left out. false turns the check off.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW012/)",
          "oneOf": [
            {
              "type": "integer",
              "minimum": 0,
              "maximum": 1000
            },
            {
              "const": false
            }
          ],
          "default": 2
        },
        "max-nesting": {
          "description": "How deep compound statements may nest in an endpoint. false turns the check off.",
          "markdownDescription": "How deep compound statements may nest in an endpoint. false turns the check off.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW012/)",
          "oneOf": [
            {
              "type": "integer",
              "minimum": 0,
              "maximum": 1000
            },
            {
              "const": false
            }
          ],
          "default": 2
        },
        "allow-loops": {
          "description": "Whether an endpoint may hold for and while loops.",
          "markdownDescription": "Whether an endpoint may hold for and while loops.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW012/)",
          "type": "boolean",
          "default": false
        },
        "allow-comprehensions": {
          "description": "Whether comprehensions and generator expressions are allowed; false counts them as loops.",
          "markdownDescription": "Whether comprehensions and generator expressions are allowed; false counts them as loops.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW012/)",
          "type": "boolean",
          "default": true
        },
        "deny-calls": {
          "description": "Calls an endpoint may not make, by qualified name with * and ? wildcards. Replaces the default list (requests.*, httpx.*, sqlalchemy.* and others); [] turns the check off.",
          "markdownDescription": "Calls an endpoint may not make, by qualified name with * and ? wildcards. Replaces the default list (requests.*, httpx.*, sqlalchemy.* and others); [] turns the check off.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW012/)",
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^[^.\\s\\[\\]/\\\\:-]+(\\.[^.\\s\\[\\]/\\\\:-]+)*$"
          }
        },
        "extend-deny-calls": {
          "description": "Calls added to deny-calls (or to its default list), by qualified name with * and ? wildcards.",
          "markdownDescription": "Calls added to deny-calls (or to its default list), by qualified name with * and ? wildcards.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW012/)",
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^[^.\\s\\[\\]/\\\\:-]+(\\.[^.\\s\\[\\]/\\\\:-]+)*$"
          }
        },
        "deny-receiver-types": {
          "description": "Parameter types whose method calls are database work (db.execute, session.add), by qualified name. Default: the SQLAlchemy and SQLModel sessions.",
          "markdownDescription": "Parameter types whose method calls are database work (db.execute, session.add), by qualified name. Default: the SQLAlchemy and SQLModel sessions.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW012/)",
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^[^.\\s\\[\\]/\\\\:-]+(\\.[^.\\s\\[\\]/\\\\:-]+)*$"
          }
        },
        "deny-receiver-params": {
          "description": "Parameter names whose method calls count as database work whatever their type, for untyped code, such as db or session.",
          "markdownDescription": "Parameter names whose method calls count as database work whatever their type, for untyped code, such as db or session.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW012/)",
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^[^\\d\\W]\\w*$"
          },
          "default": []
        },
        "delegate-to": {
          "description": "Layer names, module prefixes or selectors the endpoint must call into at least once, such as application or shop.*.service.",
          "markdownDescription": "Layer names, module prefixes or selectors the endpoint must call into at least once, such as application or shop.*.service.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW012/)",
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "string",
            "pattern": "\\S"
          }
        },
        "decorators": {
          "description": "Decorators that mark an endpoint besides the frameworks' own, by qualified name with * and ? wildcards, such as app.http.endpoint.",
          "markdownDescription": "Decorators that mark an endpoint besides the frameworks' own, by qualified name with * and ? wildcards, such as app.http.endpoint.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW012/)",
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^[^.\\s\\[\\]/\\\\:-]+(\\.[^.\\s\\[\\]/\\\\:-]+)*$"
          },
          "default": []
        },
        "frameworks": {
          "description": "The frameworks whose endpoints INW012 recognises: fastapi (with Starlette), flask, litestar and django (with Django REST framework). Default: every framework the file mentions.",
          "markdownDescription": "The frameworks whose endpoints INW012 recognises: fastapi (with Starlette), flask, litestar and django (with Django REST framework). Default: every framework the file mentions.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW012/)",
          "type": "array",
          "uniqueItems": true,
          "items": { "enum": ["fastapi", "flask", "litestar", "django"] }
        },
        "base-classes": {
          "description": "In-house view base classes, by qualified name with * and ? wildcards: methods named after HTTP verbs or ViewSet actions on their subclasses are endpoints.",
          "markdownDescription": "In-house view base classes, by qualified name with * and ? wildcards: methods named after HTTP verbs or ViewSet actions on their subclasses are endpoints.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW012/)",
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^[^.\\s\\[\\]/\\\\:-]+(\\.[^.\\s\\[\\]/\\\\:-]+)*$"
          },
          "default": []
        }
      }
    },
    "constructOnlyInOptions": {
      "description": "INW015 construct-only-in's options, [tool.inwards.rules.construct-only-in]. They don't turn the rule on: extend-select or select does.",
      "markdownDescription": "INW015 construct-only-in's options, [tool.inwards.rules.construct-only-in]. They don't turn the rule on: extend-select or select does.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW015/)",
      "type": "object",
      "additionalProperties": false,
      "required": ["role"],
      "properties": {
        "modules": {
          "$ref": "#/definitions/ruleOptions/properties/modules"
        },
        "check-tests": {
          "description": "Whether the rule also reports in test modules: test_*.py, *_test.py, conftest.py, and modules with a tests or test segment. Off by default, so the rule skips them.",
          "markdownDescription": "Whether the rule also reports in test modules: test_*.py, *_test.py, conftest.py, and modules with a tests or test segment. Off by default, so the rule skips them.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/#opt-in-rules)",
          "type": "boolean",
          "default": false
        },
        "role": {
          "description": "The guarded modules, such as the outbound adapters, as module prefixes or selectors as in layers[].modules. Only the role itself and allowed-in may import them at runtime or build their classes.",
          "markdownDescription": "The guarded modules, such as the outbound adapters, as module prefixes or selectors as in layers[].modules. Only the role itself and allowed-in may import them at runtime or build their classes.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW015/)",
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/definitions/layerEntry"
          }
        },
        "allowed-in": {
          "description": "The composition root: the modules, as prefixes or selectors, that may import the role and build its classes, such as app.di and app.main. Unset means only the role itself may.",
          "markdownDescription": "The composition root: the modules, as prefixes or selectors, that may import the role and build its classes, such as app.di and app.main. Unset means only the role itself may.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/INW015/)",
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/definitions/layerEntry"
          }
        }
      }
    },
    "routerWiringOptions": {
      "description": "FAPI003 router-wiring's options, [tool.inwards.rules.router-wiring]. They don't turn the rule on: extend-select or select does.",
      "markdownDescription": "FAPI003 router-wiring's options, [tool.inwards.rules.router-wiring]. They don't turn the rule on: extend-select or select does.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#rules)",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "modules": {
          "$ref": "#/definitions/ruleOptions/properties/modules"
        },
        "check-tests": {
          "description": "Whether the rule also reports in test modules: test_*.py, *_test.py, conftest.py, and modules with a tests or test segment. Off by default, so the rule skips them.",
          "markdownDescription": "Whether the rule also reports in test modules: test_*.py, *_test.py, conftest.py, and modules with a tests or test segment. Off by default, so the rule skips them.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/#opt-in-rules)",
          "type": "boolean",
          "default": false
        },
        "entrypoints": {
          "description": "The apps unmounted routers are measured from, as module:name, where name is the app's variable or the top-level function that builds it. Default: every FastAPI() in the project.",
          "markdownDescription": "The apps unmounted routers are measured from, as module:name, where name is the app's variable or the top-level function that builds it. Default: every FastAPI() in the project.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#rules)",
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "string",
            "pattern": "^[^.\\s*?\\[\\]/\\\\:-]+(\\.[^.\\s*?\\[\\]/\\\\:-]+)*:[^.\\s*?\\[\\]/\\\\:-]+$"
          }
        },
        "allow-unmounted": {
          "description": "Routers that may stay unmounted, as module prefixes or selectors of their qualified name, such as app.experimental.*.",
          "markdownDescription": "Routers that may stay unmounted, as module prefixes or selectors of their qualified name, such as app.experimental.*.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#rules)",
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/definitions/layerEntry"
          }
        },
        "unresolved-includes": {
          "description": "What an include_router call Inwards can't resolve does to unmounted routers: warn turns them into warnings, silent drops them.",
          "markdownDescription": "What an include_router call Inwards can't resolve does to unmounted routers: warn turns them into warnings, silent drops them.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#rules)",
          "enum": ["warn", "silent"],
          "default": "warn"
        },
        "check-order": {
          "description": "Whether to report an include_router call that runs above the included router's own routes in the same file.",
          "markdownDescription": "Whether to report an include_router call that runs above the included router's own routes in the same file.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#rules)",
          "type": "boolean",
          "default": true
        }
      }
    },
    "context": {
      "type": "object",
      "additionalProperties": false,
      "required": ["name", "modules"],
      "properties": {
        "name": {
          "description": "The context's name: non-blank, case-sensitive, unique among contexts.",
          "markdownDescription": "The context's name: non-blank, case-sensitive, unique among contexts.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#contexts)",
          "type": "string",
          "pattern": "\\S"
        },
        "modules": {
          "description": "Literal module prefixes the context owns, with their descendants. The longest matching prefix decides a module's one owning context.",
          "markdownDescription": "Literal module prefixes the context owns, with their descendants. The longest matching prefix decides a module's one owning context.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#contexts)",
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/definitions/dottedName"
          }
        },
        "public": {
          "description": "Prefixes of this context's own modules that contexts depending on it may import. Absolute names, not relative to the context. Write =name to open that module alone, not what lies under it (a package facade).",
          "markdownDescription": "Prefixes of this context's own modules that contexts depending on it may import. Absolute names, not relative to the context. Write =name to open that module alone, not what lies under it (a package facade).\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#contexts)",
          "type": "array",
          "items": {
            "$ref": "#/definitions/publicEntry"
          },
          "default": []
        },
        "depends-on": {
          "description": "Contexts this one may import from directly: not transitive, not reverse.",
          "markdownDescription": "Contexts this one may import from directly: not transitive, not reverse.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#contexts)",
          "type": "array",
          "uniqueItems": true,
          "items": {
            "type": "string",
            "pattern": "\\S"
          },
          "default": []
        },
        "template": {
          "description": "A template whose public modules, under each of this context's prefixes, join its public list.",
          "markdownDescription": "A template whose public modules, under each of this context's prefixes, join its public list.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#templates)",
          "$ref": "#/definitions/templateName"
        }
      }
    },
    "templateName": {
      "description": "The name of a [tool.inwards.templates.<name>] table.",
      "type": "string",
      "pattern": "\\S"
    },
    "hints": {
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1
      }
    },
    "template": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "roles": {
          "description": "Role modules, innermost first, relative to the layer entry's modules; \"a | b\" makes independent siblings.",
          "markdownDescription": "Role modules, innermost first, relative to the layer entry's modules; \"a | b\" makes independent siblings.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#templates)",
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "string",
            "pattern": "^\\s*[^.\\s*?\\[\\]/\\\\|-]+(\\.[^.\\s*?\\[\\]/\\\\|-]+)*(\\s*\\|\\s*[^.\\s*?\\[\\]/\\\\|-]+(\\.[^.\\s*?\\[\\]/\\\\|-]+)*)*\\s*$"
          }
        },
        "public": {
          "description": "Modules, relative to a context's prefixes, that other contexts may import (INW003).",
          "markdownDescription": "Modules, relative to a context's prefixes, that other contexts may import (INW003).\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#templates)",
          "type": "array",
          "items": {
            "$ref": "#/definitions/dottedName"
          }
        },
        "allow": {
          "description": "Members a shaped package may hold besides require and __init__; the roles are added.",
          "markdownDescription": "Members a shaped package may hold besides require and __init__; the roles are added.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#templates)",
          "type": "array",
          "items": {
            "$ref": "#/definitions/memberPattern"
          }
        },
        "require": {
          "description": "Members a shaped package must hold (INW008).",
          "markdownDescription": "Members a shaped package must hold (INW008).\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#templates)",
          "type": "array",
          "items": {
            "$ref": "#/definitions/memberPattern"
          }
        },
        "forbid": {
          "description": "Members a shaped package must not hold.",
          "markdownDescription": "Members a shaped package must not hold.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#templates)",
          "type": "array",
          "items": {
            "$ref": "#/definitions/memberPattern"
          }
        },
        "extra": {
          "description": "How an extra member is reported: \"error\" or \"warning\".",
          "markdownDescription": "How an extra member is reported: \"error\" or \"warning\".\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#templates)",
          "enum": ["error", "warning"]
        },
        "hints": {
          "description": "Project advice added to the INW007 fix steps.",
          "markdownDescription": "Project advice added to the INW007 fix steps.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#templates)",
          "$ref": "#/definitions/hints"
        },
        "rules": {
          "description": "Opt-in rules each role turns on in its modules, such as { router = { async-blocking = true } }. Expands into [tool.inwards.rules].",
          "markdownDescription": "Opt-in rules each role turns on in its modules, such as { router = { async-blocking = true } }. Expands into [tool.inwards.rules].\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#template-rules)",
          "$ref": "#/definitions/templateRules"
        }
      }
    },
    "templateRules": {
      "description": "Opt-in rules each role of the template turns on in the role's modules, by role: { router = { async-blocking = true } }.",
      "markdownDescription": "Opt-in rules each role of the template turns on in the role's modules, by role: { router = { async-blocking = true } }.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#template-rules)",
      "type": "object",
      "propertyNames": {
        "$ref": "#/definitions/dottedName"
      },
      "additionalProperties": {
        "description": "Opt-in rules this role turns on, by rule name: true, a severity, or the rule's options without modules (the role's modules fill it; INW015's role too).",
        "markdownDescription": "Opt-in rules this role turns on, by rule name: true, a severity, or the rule's options without modules (the role's modules fill it; INW015's role too).\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#template-rules)",
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "thin-endpoint": {
            "anyOf": [
              {
                "const": true
              },
              {
                "enum": ["error", "warning"]
              },
              {
                "allOf": [
                  {
                    "$ref": "#/definitions/thinEndpointOptions"
                  },
                  { "type": "object", "propertyNames": { "not": { "const": "modules" } } }
                ]
              }
            ]
          },
          "async-blocking": {
            "anyOf": [
              {
                "const": true
              },
              {
                "enum": ["error", "warning"]
              },
              {
                "allOf": [
                  {
                    "$ref": "#/definitions/asyncBlockingOptions"
                  },
                  { "type": "object", "propertyNames": { "not": { "const": "modules" } } }
                ]
              }
            ]
          },
          "ports-abstract": {
            "anyOf": [
              {
                "const": true
              },
              {
                "enum": ["error", "warning"]
              },
              {
                "allOf": [
                  {
                    "$ref": "#/definitions/portsAbstractOptions"
                  },
                  { "type": "object", "propertyNames": { "not": { "const": "modules" } } }
                ]
              }
            ]
          },
          "construct-only-in": {
            "anyOf": [
              {
                "const": true
              },
              {
                "enum": ["error", "warning"]
              },
              {
                "$ref": "#/definitions/templateConstructOnlyIn"
              }
            ]
          },
          "orm-naming": {
            "anyOf": [
              {
                "const": true
              },
              {
                "enum": ["error", "warning"]
              },
              {
                "allOf": [
                  {
                    "$ref": "#/definitions/ormNamingOptions"
                  },
                  { "type": "object", "propertyNames": { "not": { "const": "modules" } } }
                ]
              }
            ]
          },
          "adapter-conformance": {
            "anyOf": [
              {
                "const": true
              },
              {
                "enum": ["error", "warning"]
              },
              {
                "allOf": [
                  {
                    "$ref": "#/definitions/adapterConformanceOptions"
                  },
                  { "type": "object", "propertyNames": { "not": { "const": "modules" } } }
                ]
              }
            ]
          },
          "endpoint-metadata": {
            "anyOf": [
              {
                "const": true
              },
              {
                "enum": ["error", "warning"]
              },
              {
                "allOf": [
                  {
                    "$ref": "#/definitions/endpointMetadataOptions"
                  },
                  { "type": "object", "propertyNames": { "not": { "const": "modules" } } }
                ]
              }
            ]
          },
          "undocumented-error-response": {
            "anyOf": [
              {
                "const": true
              },
              {
                "enum": ["error", "warning"]
              },
              {
                "allOf": [
                  {
                    "$ref": "#/definitions/undocumentedErrorResponseOptions"
                  },
                  { "type": "object", "propertyNames": { "not": { "const": "modules" } } }
                ]
              }
            ]
          },
          "router-wiring": {
            "anyOf": [
              {
                "const": true
              },
              {
                "enum": ["error", "warning"]
              },
              {
                "allOf": [
                  {
                    "$ref": "#/definitions/routerWiringOptions"
                  },
                  { "type": "object", "propertyNames": { "not": { "const": "modules" } } }
                ]
              }
            ]
          },
          "private-module": {
            "anyOf": [
              {
                "const": true
              },
              {
                "enum": ["error", "warning"]
              },
              {
                "allOf": [
                  {
                    "$ref": "#/definitions/contentRuleOptions"
                  },
                  { "type": "object", "propertyNames": { "not": { "const": "modules" } } }
                ]
              }
            ]
          },
          "route-shadowing": {
            "anyOf": [
              {
                "const": true
              },
              {
                "enum": ["error", "warning"]
              },
              {
                "allOf": [
                  {
                    "$ref": "#/definitions/contentRuleOptions"
                  },
                  { "type": "object", "propertyNames": { "not": { "const": "modules" } } }
                ]
              }
            ]
          },
          "lifespan-events": {
            "anyOf": [
              {
                "const": true
              },
              {
                "enum": ["error", "warning"]
              },
              {
                "allOf": [
                  {
                    "$ref": "#/definitions/contentRuleOptions"
                  },
                  { "type": "object", "propertyNames": { "not": { "const": "modules" } } }
                ]
              }
            ]
          },
          "yield-dependency-swallows": {
            "anyOf": [
              {
                "const": true
              },
              {
                "enum": ["error", "warning"]
              },
              {
                "allOf": [
                  {
                    "$ref": "#/definitions/contentRuleOptions"
                  },
                  { "type": "object", "propertyNames": { "not": { "const": "modules" } } }
                ]
              }
            ]
          },
          "duplicate-operation-id": {
            "anyOf": [
              {
                "const": true
              },
              {
                "enum": ["error", "warning"]
              },
              {
                "allOf": [
                  {
                    "$ref": "#/definitions/contentRuleOptions"
                  },
                  { "type": "object", "propertyNames": { "not": { "const": "modules" } } }
                ]
              }
            ]
          },
          "diagram-unknown-name": {
            "anyOf": [
              {
                "const": true
              },
              {
                "enum": ["error", "warning"]
              },
              {
                "allOf": [
                  {
                    "$ref": "#/definitions/ruleOptions"
                  },
                  { "type": "object", "propertyNames": { "not": { "const": "modules" } } }
                ]
              }
            ]
          },
          "diagram-forbidden-edge": {
            "anyOf": [
              {
                "const": true
              },
              {
                "enum": ["error", "warning"]
              },
              {
                "allOf": [
                  {
                    "$ref": "#/definitions/ruleOptions"
                  },
                  { "type": "object", "propertyNames": { "not": { "const": "modules" } } }
                ]
              }
            ]
          },
          "diagram-missing-dependency": {
            "anyOf": [
              {
                "const": true
              },
              {
                "enum": ["error", "warning"]
              },
              {
                "allOf": [
                  {
                    "$ref": "#/definitions/ruleOptions"
                  },
                  { "type": "object", "propertyNames": { "not": { "const": "modules" } } }
                ]
              }
            ]
          },
          "depends-called": {
            "anyOf": [
              {
                "const": true
              },
              {
                "enum": ["error", "warning"]
              },
              {
                "allOf": [
                  {
                    "$ref": "#/definitions/contentRuleOptions"
                  },
                  { "type": "object", "propertyNames": { "not": { "const": "modules" } } }
                ]
              }
            ]
          }
        }
      }
    },
    "templateConstructOnlyIn": {
      "description": "INW015's options in a template: allowed-in and check-tests. The template fills role with the role's modules.",
      "markdownDescription": "INW015's options in a template: allowed-in and check-tests. The template fills role with the role's modules.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#template-rules)",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "check-tests": {
          "$ref": "#/definitions/constructOnlyInOptions/properties/check-tests"
        },
        "allowed-in": {
          "$ref": "#/definitions/constructOnlyInOptions/properties/allowed-in"
        }
      }
    },
    "endpointMetadataOptions": {
      "description": "FAPI001 endpoint-metadata's options, [tool.inwards.rules.endpoint-metadata]. They don't turn the rule on: extend-select or select does.",
      "markdownDescription": "FAPI001 endpoint-metadata's options, [tool.inwards.rules.endpoint-metadata]. They don't turn the rule on: extend-select or select does.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/FAPI001/)",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "modules": {
          "description": "Module prefixes or selectors, as in layers[].modules: the rule reports only in the modules they match.",
          "markdownDescription": "Module prefixes or selectors, as in layers[].modules: the rule reports only in the modules they match.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#rules)",
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/definitions/layerEntry"
          }
        },
        "check-tests": {
          "description": "Whether the rule also reports in test modules: test_*.py, *_test.py, conftest.py, and modules with a tests or test segment. Off by default, so the rule skips them.",
          "markdownDescription": "Whether the rule also reports in test modules: test_*.py, *_test.py, conftest.py, and modules with a tests or test segment. Off by default, so the rule skips them.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/#opt-in-rules)",
          "type": "boolean",
          "default": false
        },
        "require-summary": {
          "description": "Require summary= or a docstring (\"summary-or-docstring\"), summary= itself (\"summary\"), or nothing (false).",
          "markdownDescription": "Require summary= or a docstring (\"summary-or-docstring\"), summary= itself (\"summary\"), or nothing (false).\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/FAPI001/)",
          "enum": ["summary-or-docstring", "summary", false],
          "default": "summary-or-docstring"
        },
        "require-response-model": {
          "description": "Require response_model= or a return annotation FastAPI can use; a status_code=204 route is exempt.",
          "markdownDescription": "Require response_model= or a return annotation FastAPI can use; a status_code=204 route is exempt.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/FAPI001/)",
          "type": "boolean",
          "default": true
        },
        "require-status-code": {
          "description": "HTTP methods whose path operations must set status_code= explicitly.",
          "markdownDescription": "HTTP methods whose path operations must set status_code= explicitly.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/FAPI001/)",
          "type": "array",
          "uniqueItems": true,
          "items": {
            "enum": ["get", "post", "put", "delete", "patch", "options", "head", "trace"]
          },
          "default": ["post", "delete"]
        },
        "require-response-fields": {
          "description": "Keys every entry in responses= must have.",
          "markdownDescription": "Keys every entry in responses= must have.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/FAPI001/)",
          "type": "array",
          "uniqueItems": true,
          "items": {
            "enum": ["description", "model", "content"]
          },
          "default": ["description"]
        },
        "require-tags": {
          "description": "Require tags= on the path operation, or on a router or include_router above it.",
          "markdownDescription": "Require tags= on the path operation, or on a router or include_router above it.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/FAPI001/)",
          "type": "boolean",
          "default": false
        },
        "require-operation-id": {
          "description": "Require an explicit operation_id=.",
          "markdownDescription": "Require an explicit operation_id=.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/FAPI001/)",
          "type": "boolean",
          "default": false
        }
      }
    },
    "undocumentedErrorResponseOptions": {
      "description": "FAPI002 undocumented-error-response's options, [tool.inwards.rules.undocumented-error-response]. They don't turn the rule on: extend-select or select does.",
      "markdownDescription": "FAPI002 undocumented-error-response's options, [tool.inwards.rules.undocumented-error-response]. They don't turn the rule on: extend-select or select does.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/FAPI002/)",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "modules": {
          "description": "Module prefixes or selectors, as in layers[].modules: the rule reports only in the modules they match.",
          "markdownDescription": "Module prefixes or selectors, as in layers[].modules: the rule reports only in the modules they match.\n\n[Reference](https://sircypkowskyy.github.io/inwards/guides/configuration/#rules)",
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/definitions/layerEntry"
          }
        },
        "check-tests": {
          "description": "Whether the rule also reports in test modules: test_*.py, *_test.py, conftest.py, and modules with a tests or test segment. Off by default, so the rule skips them.",
          "markdownDescription": "Whether the rule also reports in test modules: test_*.py, *_test.py, conftest.py, and modules with a tests or test segment. Off by default, so the rule skips them.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/#opt-in-rules)",
          "type": "boolean",
          "default": false
        },
        "codes": {
          "description": "Which error codes must be declared: 4xx only, or 4xx and 5xx.",
          "markdownDescription": "Which error codes must be declared: 4xx only, or 4xx and 5xx.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/FAPI002/)",
          "enum": ["4xx", "4xx-5xx"],
          "default": "4xx"
        },
        "max-depth": {
          "description": "How many calls deep FAPI002 follows helpers and dependencies; 0 reads the endpoint's own body only.",
          "markdownDescription": "How many calls deep FAPI002 follows helpers and dependencies; 0 reads the endpoint's own body only.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/FAPI002/)",
          "type": "integer",
          "minimum": 0,
          "maximum": 8,
          "default": 2
        },
        "report-direct-raises": {
          "description": "Report codes raised with HTTPException in the endpoint's own body; false leaves them to Ruff FAST004.",
          "markdownDescription": "Report codes raised with HTTPException in the endpoint's own body; false leaves them to Ruff FAST004.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/FAPI002/)",
          "type": "boolean",
          "default": true
        },
        "handled-counts-as-documented": {
          "description": "Count a code that only comes from a custom exception with a registered handler as documented.",
          "markdownDescription": "Count a code that only comes from a custom exception with a registered handler as documented.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/FAPI002/)",
          "type": "boolean",
          "default": false
        },
        "explicit-422": {
          "description": "\"ignore\": a 422 counts as documented when the operation takes parameters, since FastAPI documents it; \"report\": it must be declared.",
          "markdownDescription": "\"ignore\": a 422 counts as documented when the operation takes parameters, since FastAPI documents it; \"report\": it must be declared.\n\n[Reference](https://sircypkowskyy.github.io/inwards/rules/FAPI002/)",
          "enum": ["ignore", "report"],
          "default": "ignore"
        }
      }
    }
  }
}
