From 59c92f9a83d11380da4e2ad0645f300466245b87 Mon Sep 17 00:00:00 2001 From: Lukas Date: Thu, 30 Apr 2026 21:00:05 +0200 Subject: [PATCH] feat: Implement automated OpenAPI type generation Add automated type synchronization from backend OpenAPI schema to frontend TypeScript types to prevent type drift and ensure runtime safety. Changes: - Add openapi-typescript as dev dependency - Create npm scripts for type generation (generate:types) and validation (validate:types) - Integrate type generation into build pipeline (runs before TypeScript compilation) - Generate frontend/src/types/generated.ts from backend OpenAPI schema - Add frontend/scripts/validate-types.sh for CI/CD validation - Update Web-Development.md with type generation workflow documentation - Update Backend-Development.md with OpenAPI schema sync requirements Workflow: 1. Backend automatically exposes OpenAPI schema at /api/openapi.json (FastAPI built-in) 2. Frontend build runs 'npm run generate:types' to generate types from schema 3. Generated types are committed to version control 4. CI can run 'npm run validate:types' to fail builds if types drift Fixes critical type safety issue where frontend types were manually maintained and could become out of sync with backend Pydantic models. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- Docs/Backend-Development.md | 24 +- Docs/Web-Development.md | 44 + frontend/package-lock.json | 230 + frontend/package.json | 5 +- frontend/scripts/validate-types.sh | 45 + frontend/src/types/generated.ts | 8616 ++++++++++++++++++++++++++++ 6 files changed, 8962 insertions(+), 2 deletions(-) create mode 100644 frontend/scripts/validate-types.sh create mode 100644 frontend/src/types/generated.ts diff --git a/Docs/Backend-Development.md b/Docs/Backend-Development.md index a7f0e46..37aba17 100644 --- a/Docs/Backend-Development.md +++ b/Docs/Backend-Development.md @@ -293,10 +293,31 @@ async def get_jails(state: JailServiceStateDep) -> JailListResponse: # Good — pass db=None on GET so geo_service never commits result = await geo_service.lookup_batch(ips, http_session, db=None) - # Bad — triggers INSERT + COMMIT per IP inside a GET handler + # Bad — triggers INSERT + COMMIT per GET inside a GET handler result = await geo_service.lookup_batch(ips, http_session, db=app_db) ``` +### OpenAPI Schema Synchronization + +**Critical:** The OpenAPI schema is the single source of truth for frontend types. When you add, modify, or remove endpoints or response models: + +1. **FastAPI automatically updates the schema** based on your Pydantic models and endpoint definitions. +2. **The frontend regenerates types** from the schema on every build: `npm run generate:types`. +3. **Ensure your Pydantic models are accurate** — they are directly serialized into the schema and used to generate frontend types. +4. **Test type generation locally** before committing: + ```bash + cd frontend + npm run generate:types # Generates src/types/generated.ts + npm run build # Build should succeed if types match + ``` +5. **The backend must be running** for type generation to work (the tool fetches `/api/openapi.json`). +6. **Commit generated types** alongside backend changes — they must always be in sync. + +**Never:** +- Manually edit `src/types/generated.ts` on the frontend — regenerate from the schema instead. +- Commit backend changes without ensuring the frontend can regenerate types. +- Assume the OpenAPI schema is correct — validate your Pydantic model's `field` descriptions and types are as intended. + ```python from fastapi import APIRouter, Depends, HTTPException, status from app.models.jail import JailResponse, JailListResponse @@ -310,6 +331,7 @@ async def list_jails(service: JailService = Depends()) -> JailListResponse: return JailListResponse(jails=jails) ``` + ### Dependency Layering: Enforcing the Repository Boundary The **repository boundary** separates database-aware code from application logic. This is enforced through dependency injection. diff --git a/Docs/Web-Development.md b/Docs/Web-Development.md index 780faad..0aff173 100644 --- a/Docs/Web-Development.md +++ b/Docs/Web-Development.md @@ -69,6 +69,50 @@ import type { Ban } from "../types/ban"; --- +## 2.5. Generated Types from OpenAPI Schema + +**Critical:** Frontend types are automatically generated from the backend's OpenAPI schema to prevent type drift. This ensures frontend types always match the backend's Pydantic models. + +### Workflow + +1. **Backend exposes OpenAPI schema** at `GET /api/openapi.json` (enabled automatically by FastAPI). +2. **Frontend builds include type generation:** + ```bash + npm run generate:types # Generates src/types/generated.ts + npm run build # Automatically calls generate:types first + ``` +3. **Generated types** (`src/types/generated.ts`) are committed to version control and imported wherever needed. +4. **CI validation** ensures generated types stay in sync with the backend: + ```bash + npm run validate:types # Fails if types differ from backend schema + ``` + +### When Backend Models Change + +1. Modify the Pydantic model in `backend/app/models/` as needed. +2. Ensure the change is reflected in the OpenAPI schema (FastAPI does this automatically). +3. On the next build, `npm run generate:types` regenerates types from the new schema. +4. The build fails if types differ (pre-commit hook can catch this locally). +5. Commit the updated `src/types/generated.ts` alongside your backend changes. + +### CI/CD Integration + +Add `npm run validate:types` to your CI pipeline to catch type drift: + +```yaml +# GitHub Actions example +- name: Validate types + run: npm run validate:types +``` + +The script returns: +- **Exit 0:** Types are in sync +- **Exit 1:** Generated types differ (run `npm run generate:types` to fix) +- **Exit 2:** Backend is not accessible (set `BANGUI_BACKEND_URL` if needed) +- **Exit 3:** Type generation failed + +--- + ## 3. Type Safety in API Calls - Every API call must have a **typed request** and **typed response**. diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 291fafb..9043910 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -38,6 +38,7 @@ "eslint-plugin-react-hooks": "^5.0.0", "jiti": "^2.6.1", "jsdom": "^28.1.0", + "openapi-typescript": "^7.13.0", "prettier": "^3.3.3", "typescript": "^5.6.3", "typescript-eslint": "^8.56.1", @@ -2974,6 +2975,89 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@redocly/ajv": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/@redocly/ajv/-/ajv-8.11.2.tgz", + "integrity": "sha512-io1JpnwtIcvojV7QKDUSIuMN/ikdOUd1ReEnUnMKGfDVridQZ31J0MmIuqwuRjWDZfmvr+Q0MqCcfHM2gTivOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js-replace": "^1.0.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@redocly/ajv/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/@redocly/config": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@redocly/config/-/config-0.22.0.tgz", + "integrity": "sha512-gAy93Ddo01Z3bHuVdPWfCwzgfaYgMdaZPcfL7JZ7hWJoK9V0lXDbigTWkhiPFAaLWzbOJ+kbUQG1+XwIm0KRGQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@redocly/openapi-core": { + "version": "1.34.14", + "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.34.14.tgz", + "integrity": "sha512-y+xFx+Zz54Xhr8jUdnLENYnt7Y7GEDL6Q03ga7rTtX8DVwefX9H+hQEPgJp1nda7vdH+wJ9/HBVvyfBuW9x6rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@redocly/ajv": "8.11.2", + "@redocly/config": "0.22.0", + "colorette": "1.4.0", + "https-proxy-agent": "7.0.6", + "js-levenshtein": "1.1.6", + "js-yaml": "4.1.1", + "minimatch": "5.1.9", + "pluralize": "8.0.0", + "yaml-ast-parser": "0.0.43" + }, + "engines": { + "node": ">=18.17.0", + "npm": ">=9.5.0" + } + }, + "node_modules/@redocly/openapi-core/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@redocly/openapi-core/node_modules/brace-expansion": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", + "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@redocly/openapi-core/node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@reduxjs/toolkit": { "version": "2.11.2", "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.11.2.tgz", @@ -4123,6 +4207,16 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -4548,6 +4642,13 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/change-case": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz", + "integrity": "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==", + "dev": true, + "license": "MIT" + }, "node_modules/clsx": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", @@ -4577,6 +4678,13 @@ "dev": true, "license": "MIT" }, + "node_modules/colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", + "dev": true, + "license": "MIT" + }, "node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -6100,6 +6208,19 @@ "node": ">=8" } }, + "node_modules/index-to-position": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.2.0.tgz", + "integrity": "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/internal-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", @@ -6591,6 +6712,16 @@ "jiti": "lib/jiti-cli.mjs" } }, + "node_modules/js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -7069,6 +7200,40 @@ ], "license": "MIT" }, + "node_modules/openapi-typescript": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/openapi-typescript/-/openapi-typescript-7.13.0.tgz", + "integrity": "sha512-EFP392gcqXS7ntPvbhBzbF8TyBA+baIYEm791Hy5YkjDYKTnk/Tn5OQeKm5BIZvJihpp8Zzr4hzx0Irde1LNGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@redocly/openapi-core": "^1.34.6", + "ansi-colors": "^4.1.3", + "change-case": "^5.4.4", + "parse-json": "^8.3.0", + "supports-color": "^10.2.2", + "yargs-parser": "^21.1.1" + }, + "bin": { + "openapi-typescript": "bin/cli.js" + }, + "peerDependencies": { + "typescript": "^5.x" + } + }, + "node_modules/openapi-typescript/node_modules/supports-color": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -7150,6 +7315,24 @@ "node": ">=6" } }, + "node_modules/parse-json": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", + "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "index-to-position": "^1.1.0", + "type-fest": "^4.39.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parse5": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz", @@ -7217,6 +7400,16 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", @@ -8267,6 +8460,19 @@ "node": ">= 0.8.0" } }, + "node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typed-array-buffer": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", @@ -8460,6 +8666,13 @@ "punycode": "^2.1.0" } }, + "node_modules/uri-js-replace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uri-js-replace/-/uri-js-replace-1.0.1.tgz", + "integrity": "sha512-W+C9NWNLFOoBI2QWDp4UT9pv65r2w5Cx+3sTYFvtMdDBxkKt1syCqsUdSFAChbEe1uK5TfS04wt/nGwmaeIQ0g==", + "dev": true, + "license": "MIT" + }, "node_modules/use-sync-external-store": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", @@ -9425,6 +9638,23 @@ "dev": true, "license": "ISC" }, + "node_modules/yaml-ast-parser": { + "version": "0.0.43", + "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz", + "integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 8995a0f..751dfa6 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -6,7 +6,9 @@ "type": "module", "scripts": { "dev": "vite", - "build": "tsc --noEmit && vite build", + "generate:types": "openapi-typescript http://localhost:8000/api/openapi.json -o src/types/generated.ts", + "validate:types": "bash scripts/validate-types.sh", + "build": "npm run generate:types && tsc --noEmit && vite build", "preview": "vite preview", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "typecheck": "tsc --noEmit", @@ -45,6 +47,7 @@ "eslint-plugin-react-hooks": "^5.0.0", "jiti": "^2.6.1", "jsdom": "^28.1.0", + "openapi-typescript": "^7.13.0", "prettier": "^3.3.3", "typescript": "^5.6.3", "typescript-eslint": "^8.56.1", diff --git a/frontend/scripts/validate-types.sh b/frontend/scripts/validate-types.sh new file mode 100644 index 0000000..4667228 --- /dev/null +++ b/frontend/scripts/validate-types.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# Validate that generated types match the committed types. +# This script is designed to run in CI/CD pipelines to prevent type drift. +# +# Exit codes: +# 0 — types are in sync +# 1 — types are out of sync +# 2 — backend is not accessible +# 3 — generation failed + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +FRONTEND_DIR="$(dirname "$SCRIPT_DIR")" +TYPES_DIR="${FRONTEND_DIR}/src/types" +GENERATED_FILE="${TYPES_DIR}/generated.ts" +TEMP_FILE=$(mktemp) +trap "rm -f $TEMP_FILE" EXIT + +# Check if backend is accessible +BACKEND_URL="${BANGUI_BACKEND_URL:-http://localhost:8000}" +if ! curl -sf "${BACKEND_URL}/api/openapi.json" > /dev/null 2>&1; then + echo "❌ Backend not accessible at ${BACKEND_URL}/api/openapi.json" >&2 + exit 2 +fi + +echo "📋 Validating OpenAPI schema types..." + +# Generate types to a temporary file +if ! npx openapi-typescript "${BACKEND_URL}/api/openapi.json" -o "$TEMP_FILE" 2>&1; then + echo "❌ Failed to generate types from OpenAPI schema" >&2 + exit 3 +fi + +# Compare with committed generated types +if ! diff -u "$GENERATED_FILE" "$TEMP_FILE" > /dev/null 2>&1; then + echo "❌ Generated types differ from committed types" >&2 + echo "" + echo "Run 'npm run generate:types' to update types, then commit the changes:" + diff -u "$GENERATED_FILE" "$TEMP_FILE" || true + exit 1 +fi + +echo "✅ Types are in sync with backend schema" +exit 0 diff --git a/frontend/src/types/generated.ts b/frontend/src/types/generated.ts new file mode 100644 index 0000000..83bdb88 --- /dev/null +++ b/frontend/src/types/generated.ts @@ -0,0 +1,8616 @@ +/** + * This file was auto-generated by openapi-typescript. + * Do not make direct changes to the file. + */ + +export interface paths { + "/api/health": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Application health check + * @description Return 200 with application and fail2ban status. + * + * HTTP 200 is always returned so Docker health checks do not restart the + * backend container when fail2ban is temporarily offline. The + * ``fail2ban`` field in the body indicates the daemon's current state. + * + * Args: + * server_status: Injected cached server status snapshot. + * + * Returns: + * A JSON object with ``{"status": "ok", "fail2ban": "online"|"offline"}``. + */ + get: operations["health_check_api_health_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/setup": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Check whether setup has been completed + * @description Return whether the initial setup wizard has been completed. + * + * Returns: + * :class:`~app.models.setup.SetupStatusResponse` with ``completed`` + * set to ``True`` if setup is done, ``False`` otherwise. + */ + get: operations["get_setup_status_api_setup_get"]; + put?: never; + /** + * Run the initial setup wizard + * @description Persist the initial BanGUI configuration. + * + * Args: + * app: The FastAPI application instance. + * body: Setup request payload validated by Pydantic. + * settings_ctx: Settings service context containing db and repository. + * + * Returns: + * :class:`~app.models.setup.SetupResponse` on success. + * + * Raises: + * SetupAlreadyCompleteError: if setup has already been completed. + */ + post: operations["post_setup_api_setup_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/setup/timezone": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return the configured IANA timezone + * @description Return the IANA timezone configured during the initial setup wizard. + * + * The frontend uses this to convert UTC timestamps to the local time zone + * chosen by the administrator. + * + * Returns: + * :class:`~app.models.setup.SetupTimezoneResponse` with ``timezone`` + * set to the stored IANA identifier (e.g. ``"UTC"`` or + * ``"Europe/Berlin"``), defaulting to ``"UTC"`` if unset. + */ + get: operations["get_timezone_api_setup_timezone_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/auth/login": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Authenticate with the master password + * @description Verify the master password and return a session token. + * + * On success the token is also set as an ``HttpOnly`` ``SameSite=Lax`` + * cookie so the browser SPA benefits from automatic credential handling. + * + * Rate limiting: Exponential backoff on failed attempts. Each wrong password + * incurs an increasing delay (0.5s, 1s, 2s, 4s, 5s max per IP address). + * Requests during the penalty period return ``429 Too Many Requests`` with + * a ``Retry-After`` header. + * + * Args: + * body: Login request validated by Pydantic. + * response: FastAPI response object used to set the cookie. + * request: The incoming HTTP request (used to extract client IP). + * session_ctx: Session service context containing db and repository. + * settings: Application settings (used for session duration and trusted proxies). + * rate_limiter: The login rate limiter (per IP). + * + * Returns: + * :class:`~app.models.auth.LoginResponse` containing the token. + * + * Raises: + * AuthenticationError: if the password is incorrect. + * RateLimitError: if the rate limit is exceeded. + */ + post: operations["login_api_auth_login_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/auth/session": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Validate the current session + * @description Validate the current session. + * + * This endpoint requires a valid session and returns 200 if the session is + * valid and still active. If the session is invalid, expired, or missing, + * FastAPI's ``require_auth`` dependency returns 401 automatically. + * + * The frontend calls this on mount to bootstrap its authentication state + * from the backend rather than relying solely on cached ``sessionStorage``. + * + * Args: + * _: The injected session object (unused, but its presence triggers validation). + * + * Returns: + * A simple JSON object confirming the session is valid. + */ + get: operations["validate_session_api_auth_session_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/auth/logout": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Revoke the current session + * @description Invalidate the active session. + * + * The session token is read from the ``bangui_session`` cookie or the + * ``Authorization: Bearer`` header. If no token is present the request + * is silently treated as a successful logout (idempotent). + * + * Args: + * request: FastAPI request (used to extract the token). + * response: FastAPI response (used to clear the cookie). + * session_ctx: Session service context containing db and repository. + * settings: Application settings (used to unwrap signed tokens). + * session_cache: Session cache for invalidation. + * + * Returns: + * :class:`~app.models.auth.LogoutResponse`. + */ + post: operations["logout_api_auth_logout_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/dashboard/status": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return the cached fail2ban server status + * @description Return the most recent fail2ban health snapshot. + * + * The snapshot is populated by a background task that runs every 30 seconds. + * If the task has not yet executed a placeholder ``online=False`` status is + * returned so the response is always well-formed. + * + * Args: + * server_status: Cached fail2ban server health snapshot (injected). + * _auth: Validated session — enforces authentication on this endpoint. + * + * Returns: + * :class:`~app.models.server.ServerStatusResponse` containing the + * current health snapshot. + */ + get: operations["get_server_status_api_dashboard_status_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/dashboard/bans": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return a paginated list of recent bans + * @description Return a paginated list of bans within the selected time window. + * + * Reads from the fail2ban database and enriches each entry with + * geolocation data (country, ASN, organisation) from the ip-api.com + * free API. Results are sorted newest-first. Geo lookups are served + * from the in-memory cache only; no database writes occur during this + * GET request. + * + * Args: + * _auth: Validated session dependency. + * ban_ctx: Ban service context containing db and repository. + * socket_path: Path to fail2ban Unix domain socket. + * http_session: Shared HTTP session for geolocation. + * geo_cache: Geolocation cache instance. + * range: Time-range preset — ``"24h"``, ``"7d"``, ``"30d"``, or + * ``"365d"``. + * page: 1-based page number. + * page_size: Maximum items per page (1–500). + * origin: Optional filter by ban origin. + * + * Returns: + * :class:`~app.models.ban.DashboardBanListResponse` with paginated + * ban items and the total count for the selected window. + */ + get: operations["get_dashboard_bans_api_dashboard_bans_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/dashboard/bans/by-country": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return ban counts aggregated by country + * @description Return ban counts aggregated by ISO country code. + * + * Uses SQL aggregation (``GROUP BY ip``) and batch geo-resolution to handle + * 10 000+ banned IPs efficiently. Returns a ``{country_code: count}`` map + * and the 200 most recent raw ban rows for the companion access table. Geo + * lookups are served from the in-memory cache only; no database writes occur + * during this GET request. + * + * Args: + * _auth: Validated session dependency. + * ban_ctx: Ban service context containing db and repository. + * socket_path: Path to fail2ban Unix domain socket. + * http_session: Shared HTTP session for geolocation. + * geo_cache: Geolocation cache instance. + * range: Time-range preset. + * origin: Optional filter by ban origin. + * + * Returns: + * :class:`~app.models.ban.BansByCountryResponse` with per-country + * aggregation and the companion ban list. + */ + get: operations["get_bans_by_country_api_dashboard_bans_by_country_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/dashboard/bans/trend": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return ban counts aggregated into time buckets + * @description Return ban counts grouped into equal-width time buckets. + * + * Each bucket represents a contiguous time interval within the selected + * window. All buckets are returned — empty buckets (zero bans) are + * included so the frontend always receives a complete, gap-free series + * suitable for rendering a continuous area or line chart. + * + * Bucket sizes: + * + * * ``24h`` → 1-hour buckets (24 total) + * * ``7d`` → 6-hour buckets (28 total) + * * ``30d`` → 1-day buckets (30 total) + * * ``365d`` → 7-day buckets (~53 total) + * + * Args: + * _auth: Validated session dependency. + * ban_ctx: Ban service context containing db and repository. + * socket_path: Path to fail2ban Unix domain socket. + * range: Time-range preset. + * origin: Optional filter by ban origin. + * + * Returns: + * :class:`~app.models.ban.BanTrendResponse` with the ordered bucket + * list and the bucket-size label. + */ + get: operations["get_ban_trend_api_dashboard_bans_trend_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/dashboard/bans/by-jail": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return ban counts aggregated by jail + * @description Return ban counts grouped by jail name for the selected time window. + * + * Queries the fail2ban database and returns a list of jails sorted by + * ban count descending. This endpoint is intended for the dashboard jail + * distribution bar chart. + * + * Args: + * _auth: Validated session dependency. + * ban_ctx: Ban service context containing db and repository. + * socket_path: Path to fail2ban Unix domain socket. + * range: Time-range preset — ``"24h"``, ``"7d"``, ``"30d"``, or + * ``"365d"``. + * origin: Optional filter by ban origin. + * + * Returns: + * :class:`~app.models.ban.BansByJailResponse` with per-jail counts + * sorted descending and the total for the selected window. + */ + get: operations["get_bans_by_jail_api_dashboard_bans_by_jail_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/jails": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List all active fail2ban jails + * @description Return a summary of every active fail2ban jail. + * + * Includes runtime metrics (currently banned, total bans, failures) and + * key configuration (find time, ban time, max retries, backend, idle state) + * for each jail. + * + * Args: + * _auth: Validated session — enforces authentication. + * socket_path: Path to the fail2ban Unix domain socket. + * state: The jail service state holder. + * + * Returns: + * :class:`~app.models.jail.JailListResponse` with all active jails. + */ + get: operations["get_jails_api_jails_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/jails/{name}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return full detail for a single jail + * @description Return the complete configuration and runtime state for one jail. + * + * Includes log paths, fail regex and ignore regex patterns, date pattern, + * log encoding, attached action names, ban-time settings, and runtime + * counters. + * + * Args: + * _auth: Validated session — enforces authentication. + * name: Jail name. + * + * Returns: + * :class:`~app.models.jail.JailDetailResponse` with the full jail. + * + * Raises: + * HTTPException: 404 when the jail does not exist. + * HTTPException: 502 when fail2ban is unreachable. + */ + get: operations["get_jail_api_jails__name__get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/jails/reload-all": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Reload all fail2ban jails + * @description Reload every fail2ban jail to apply configuration changes. + * + * This command instructs fail2ban to re-read its configuration for all + * jails simultaneously. + * + * Args: + * _auth: Validated session — enforces authentication. + * + * Returns: + * :class:`~app.models.jail.JailCommandResponse` confirming the reload. + * + * Raises: + * HTTPException: 502 when fail2ban is unreachable. + * HTTPException: 409 when fail2ban reports the operation failed. + */ + post: operations["reload_all_jails_api_jails_reload_all_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/jails/{name}/start": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Start a stopped jail + * @description Start a fail2ban jail that is currently stopped. + * + * Args: + * _auth: Validated session — enforces authentication. + * name: Jail name. + * + * Returns: + * :class:`~app.models.jail.JailCommandResponse` confirming the start. + * + * Raises: + * HTTPException: 404 when the jail does not exist. + * HTTPException: 409 when fail2ban reports the operation failed. + * HTTPException: 502 when fail2ban is unreachable. + */ + post: operations["start_jail_api_jails__name__start_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/jails/{name}/stop": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Stop a running jail + * @description Stop a running fail2ban jail. + * + * The jail will no longer monitor logs or issue new bans. Existing bans + * may or may not be removed depending on fail2ban configuration. If the + * jail is already stopped the request succeeds silently (idempotent). + * + * Args: + * _auth: Validated session — enforces authentication. + * name: Jail name. + * + * Returns: + * :class:`~app.models.jail.JailCommandResponse` confirming the stop. + * + * Raises: + * HTTPException: 409 when fail2ban reports the operation failed. + * HTTPException: 502 when fail2ban is unreachable. + */ + post: operations["stop_jail_api_jails__name__stop_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/jails/{name}/idle": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Toggle idle mode for a jail + * @description Enable or disable idle mode for a fail2ban jail. + * + * In idle mode the jail suspends log monitoring without fully stopping, + * preserving all existing bans. + * + * Args: + * _auth: Validated session — enforces authentication. + * name: Jail name. + * on: ``true`` to enable idle, ``false`` to disable. + * + * Returns: + * :class:`~app.models.jail.JailCommandResponse` confirming the change. + * + * Raises: + * HTTPException: 404 when the jail does not exist. + * HTTPException: 409 when fail2ban reports the operation failed. + * HTTPException: 502 when fail2ban is unreachable. + */ + post: operations["toggle_idle_api_jails__name__idle_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/jails/{name}/reload": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Reload a single jail + * @description Reload a single fail2ban jail to pick up configuration changes. + * + * Args: + * _auth: Validated session — enforces authentication. + * name: Jail name. + * + * Returns: + * :class:`~app.models.jail.JailCommandResponse` confirming the reload. + * + * Raises: + * HTTPException: 404 when the jail does not exist. + * HTTPException: 409 when fail2ban reports the operation failed. + * HTTPException: 502 when fail2ban is unreachable. + */ + post: operations["reload_jail_api_jails__name__reload_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/jails/{name}/ignoreip": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List the ignore IPs for a jail + * @description Return the current ignore list (IP whitelist) for a fail2ban jail. + * + * Args: + * _auth: Validated session — enforces authentication. + * name: Jail name. + * + * Returns: + * List of IP addresses and CIDR networks on the ignore list. + * + * Raises: + * HTTPException: 404 when the jail does not exist. + * HTTPException: 502 when fail2ban is unreachable. + */ + get: operations["get_ignore_list_api_jails__name__ignoreip_get"]; + put?: never; + /** + * Add an IP or network to the ignore list + * @description Add an IP address or CIDR network to a jail's ignore list. + * + * IPs on the ignore list are never banned by that jail, even if they + * trigger the configured fail regex. + * + * Args: + * _auth: Validated session — enforces authentication. + * name: Jail name. + * body: Payload containing the IP or CIDR to add. + * + * Returns: + * :class:`~app.models.jail.JailCommandResponse` confirming the addition. + * + * Raises: + * HTTPException: 400 when the IP address or network is invalid. + * HTTPException: 404 when the jail does not exist. + * HTTPException: 409 when fail2ban reports the operation failed. + * HTTPException: 502 when fail2ban is unreachable. + */ + post: operations["add_ignore_ip_api_jails__name__ignoreip_post"]; + /** + * Remove an IP or network from the ignore list + * @description Remove an IP address or CIDR network from a jail's ignore list. + * + * Args: + * _auth: Validated session — enforces authentication. + * name: Jail name. + * body: Payload containing the IP or CIDR to remove. + * + * Returns: + * :class:`~app.models.jail.JailCommandResponse` confirming the removal. + * + * Raises: + * HTTPException: 404 when the jail does not exist. + * HTTPException: 409 when fail2ban reports the operation failed. + * HTTPException: 502 when fail2ban is unreachable. + */ + delete: operations["del_ignore_ip_api_jails__name__ignoreip_delete"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/jails/{name}/ignoreself": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Toggle the ignoreself option for a jail + * @description Toggle the ``ignoreself`` flag for a fail2ban jail. + * + * When ``ignoreself`` is enabled fail2ban automatically adds the server's + * own IP addresses to the ignore list so the host can never ban itself. + * + * Args: + * _auth: Validated session — enforces authentication. + * name: Jail name. + * on: ``true`` to enable, ``false`` to disable. + * + * Returns: + * :class:`~app.models.jail.JailCommandResponse` confirming the change. + * + * Raises: + * HTTPException: 404 when the jail does not exist. + * HTTPException: 409 when fail2ban reports the operation failed. + * HTTPException: 502 when fail2ban is unreachable. + */ + post: operations["toggle_ignore_self_api_jails__name__ignoreself_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/jails/{name}/banned": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return paginated currently-banned IPs for a single jail + * @description Return a paginated list of IPs currently banned by a specific jail. + * + * The full ban list is fetched from the fail2ban socket, filtered by the + * optional *search* substring, sliced to the requested page, and then + * geo-enriched exclusively for that page slice. + * + * Args: + * _auth: Validated session — enforces authentication. + * ban_ctx: Ban service context containing db and repository. + * name: Jail name. + * socket_path: Path to fail2ban Unix domain socket. + * http_session: Shared HTTP session for geolocation. + * geo_cache: Geolocation cache instance. + * page: 1-based page number (default 1, min 1). + * page_size: Items per page (default 25, max 100). + * search: Optional case-insensitive substring filter on the IP address. + * + * Returns: + * :class:`~app.models.ban.JailBannedIpsResponse` with the paginated bans. + * + * Raises: + * HTTPException: 400 when *page* or *page_size* are out of range. + * HTTPException: 404 when the jail does not exist. + * HTTPException: 502 when fail2ban is unreachable. + */ + get: operations["get_jail_banned_ips_api_jails__name__banned_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/bans/active": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List all currently banned IPs across all jails + * @description Return every IP that is currently banned across all fail2ban jails. + * + * Each entry includes the jail name, ban start time, expiry time, and + * enriched geolocation data (country code). + * + * Args: + * request: Incoming request (used to access ``app.state``). + * _auth: Validated session — enforces authentication. + * ban_ctx: Ban service context containing db and repository. + * socket_path: Path to fail2ban Unix domain socket. + * http_session: Shared HTTP session for geolocation. + * geo_cache: Geolocation cache instance. + * + * Returns: + * :class:`~app.models.ban.ActiveBanListResponse` with all active bans. + * + * Raises: + * HTTPException: 502 when fail2ban is unreachable. + */ + get: operations["get_active_bans_api_bans_active_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/bans": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Ban an IP address in a specific jail + * @description Ban an IP address in the specified fail2ban jail. + * + * The IP address is validated before the command is sent. IPv4 and + * IPv6 addresses are both accepted. + * + * Args: + * request: Incoming request (used to access ``app.state``). + * _auth: Validated session — enforces authentication. + * body: Payload containing the IP address and target jail. + * + * Returns: + * :class:`~app.models.jail.JailCommandResponse` confirming the ban. + * + * Raises: + * HTTPException: 400 when the IP address is invalid. + * HTTPException: 404 when the specified jail does not exist. + * HTTPException: 409 when fail2ban reports the ban failed. + * HTTPException: 502 when fail2ban is unreachable. + */ + post: operations["ban_ip_api_bans_post"]; + /** + * Unban an IP address from one or all jails + * @description Unban an IP address from a specific jail or all jails. + * + * When ``unban_all`` is ``true`` the IP is removed from every jail using + * fail2ban's global unban command. When ``jail`` is specified only that + * jail is targeted. If neither ``unban_all`` nor ``jail`` is provided the + * IP is unbanned from all jails (equivalent to ``unban_all=true``). + * + * Args: + * request: Incoming request (used to access ``app.state``). + * _auth: Validated session — enforces authentication. + * body: Payload with the IP address, optional jail, and unban_all flag. + * + * Returns: + * :class:`~app.models.jail.JailCommandResponse` confirming the unban. + * + * Raises: + * HTTPException: 400 when the IP address is invalid. + * HTTPException: 404 when the specified jail does not exist. + * HTTPException: 409 when fail2ban reports the unban failed. + * HTTPException: 502 when fail2ban is unreachable. + */ + delete: operations["unban_ip_api_bans_delete"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/bans/all": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + /** + * Unban every currently banned IP across all jails + * @description Remove all active bans from every fail2ban jail in a single operation. + * + * Uses fail2ban's ``unban --all`` command to atomically clear every active + * ban across all jails. Returns the number of IPs that were unbanned. + * + * Args: + * request: Incoming request (used to access ``app.state``). + * _auth: Validated session — enforces authentication. + * + * Returns: + * :class:`~app.models.ban.UnbanAllResponse` with the count of + * unbanned IPs. + * + * Raises: + * HTTPException: 502 when fail2ban is unreachable. + */ + delete: operations["unban_all_api_bans_all_delete"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/geo/lookup/{ip}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Look up ban status and geo information for an IP + * @description Return current ban status, geo data, and network information for an IP. + * + * Checks every running fail2ban jail to determine whether the IP is + * currently banned, and enriches the result with country, ASN, and + * organisation data from ip-api.com. + * + * Args: + * _auth: Validated session — enforces authentication. + * ip: The IP address to look up. + * + * Returns: + * :class:`~app.models.geo.IpLookupResponse` with ban status and geo data. + * + * Raises: + * HTTPException: 400 when *ip* is not a valid IP address. + * HTTPException: 502 when fail2ban is unreachable. + */ + get: operations["lookup_ip_api_geo_lookup__ip__get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/geo/stats": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Geo cache diagnostic counters + * @description Return diagnostic counters for the geo cache subsystem. + * + * Useful for operators and the UI to gauge geo-resolution health. + * + * Args: + * _auth: Validated session — enforces authentication. + * ban_ctx: Ban service context containing db and repository. + * + * Returns: + * :class:`~app.models.geo.GeoCacheStatsResponse` with current counters. + */ + get: operations["geo_stats_api_geo_stats_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/geo/re-resolve": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Re-resolve all IPs whose country could not be determined + * @description Retry geo resolution for every IP in ``geo_cache`` with a null country. + * + * Clears the in-memory negative cache first so that previously failing IPs + * are immediately eligible for a new API attempt. + * + * Args: + * _auth: Validated session — enforces authentication. + * ban_ctx: Ban service context containing db and repository. + * http_session: Shared HTTP session for geo lookups. + * + * Returns: + * A :class:`~app.models.geo.GeoReResolveResponse` with retry counts. + */ + post: operations["re_resolve_geo_api_geo_re_resolve_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/jails": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List configuration for all active jails + * @description Return editable configuration for every active fail2ban jail. + * + * Fetches ban time, find time, max retries, regex patterns, log paths, + * date pattern, encoding, backend, and attached actions for all jails. + * + * Args: + * request: Incoming request (used to access ``app.state``). + * _auth: Validated session — enforces authentication. + * + * Returns: + * :class:`~app.models.config.JailConfigListResponse`. + */ + get: operations["get_jail_configs_api_config_jails_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/jails/inactive": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List all inactive jails discovered in config files + * @description Return all jails defined in fail2ban config files that are not running. + * + * Parses ``jail.conf``, ``jail.local``, and ``jail.d/`` following the + * fail2ban merge order. Jails that fail2ban currently reports as running + * are excluded; only truly inactive entries are returned. + * + * Args: + * request: FastAPI request object. + * _auth: Validated session — enforces authentication. + * + * Returns: + * :class:`~app.models.config.InactiveJailListResponse`. + */ + get: operations["get_inactive_jails_api_config_jails_inactive_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/jails/pending-recovery": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return active crash-recovery record if one exists + * @description Return the current :class:`~app.models.config.PendingRecovery` record. + * + * A non-null response means fail2ban crashed shortly after a jail activation + * and the user should be offered a rollback option. Returns ``null`` (HTTP + * 200 with ``null`` body) when no recovery is pending. + * + * Args: + * request: FastAPI request object. + * _auth: Validated session. + * + * Returns: + * :class:`~app.models.config.PendingRecovery` or ``None``. + */ + get: operations["get_pending_recovery_api_config_jails_pending_recovery_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/jails/{name}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return configuration for a single jail + * @description Return the full editable configuration for one fail2ban jail. + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * name: Jail name. + * + * Returns: + * :class:`~app.models.config.JailConfigResponse`. + * + * Raises: + * HTTPException: 404 when the jail does not exist. + * HTTPException: 502 when fail2ban is unreachable. + */ + get: operations["get_jail_config_api_config_jails__name__get"]; + /** + * Update jail configuration + * @description Update one or more configuration fields for an active fail2ban jail. + * + * Regex patterns are validated before being sent to fail2ban. An invalid + * pattern returns 422 with the regex error message. + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * name: Jail name. + * body: Partial update — only non-None fields are written. + * + * Raises: + * HTTPException: 404 when the jail does not exist. + * HTTPException: 422 when a regex pattern fails to compile. + * HTTPException: 400 when a set command is rejected. + * HTTPException: 502 when fail2ban is unreachable. + */ + put: operations["update_jail_config_api_config_jails__name__put"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/jails/{name}/logpath": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Add a log file path to an existing jail + * @description Register an additional log file for an existing jail to monitor. + * + * Uses ``set addlogpath `` to add the path + * without requiring a daemon restart. + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * name: Jail name. + * body: Log path and tail/head preference. + * + * Raises: + * HTTPException: 404 when the jail does not exist. + * HTTPException: 400 when the command is rejected or path is invalid. + * HTTPException: 502 when fail2ban is unreachable. + */ + post: operations["add_log_path_api_config_jails__name__logpath_post"]; + /** + * Remove a monitored log path from a jail + * @description Stop a jail from monitoring the specified log file. + * + * Uses ``set dellogpath `` to remove the log path at runtime + * without requiring a daemon restart. + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * name: Jail name. + * log_path: Absolute path to the log file to remove (query parameter). + * + * Raises: + * HTTPException: 422 when the log path is outside allowed directories. + * HTTPException: 404 when the jail does not exist. + * HTTPException: 400 when the command is rejected. + * HTTPException: 502 when fail2ban is unreachable. + */ + delete: operations["delete_log_path_api_config_jails__name__logpath_delete"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/jails/{name}/activate": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Activate an inactive jail + * @description Enable an inactive jail and reload fail2ban. + * + * Writes ``enabled = true`` (plus any override values from the request + * body) to ``jail.d/{name}.local`` and triggers a full fail2ban reload so + * the jail starts immediately. + * + * Args: + * app: FastAPI application instance. + * _auth: Validated session. + * config_dir: Absolute path to the fail2ban configuration directory. + * socket_path: Path to the fail2ban Unix domain socket. + * health_probe: Injectable health probe function for checking fail2ban status. + * name: Name of the jail to activate. + * body: Optional override values (bantime, findtime, maxretry, port, + * logpath). + * + * Returns: + * :class:`~app.models.config.JailActivationResponse`. + * + * Raises: + * HTTPException: 400 if *name* contains invalid characters. + * HTTPException: 404 if *name* is not found in any config file. + * HTTPException: 409 if the jail is already active. + * HTTPException: 502 if fail2ban is unreachable. + */ + post: operations["activate_jail_api_config_jails__name__activate_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/jails/{name}/deactivate": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Deactivate an active jail + * @description Disable an active jail and reload fail2ban. + * + * Writes ``enabled = false`` to ``jail.d/{name}.local`` and triggers a + * full fail2ban reload so the jail stops immediately. + * + * Args: + * _auth: Validated session. + * config_dir: Absolute path to the fail2ban configuration directory. + * socket_path: Path to the fail2ban Unix domain socket. + * health_probe: Injectable health probe function for checking fail2ban status. + * name: Name of the jail to deactivate. + * + * Returns: + * :class:`~app.models.config.JailActivationResponse`. + * + * Raises: + * HTTPException: 400 if *name* contains invalid characters. + * HTTPException: 404 if *name* is not found in any config file. + * HTTPException: 409 if the jail is already inactive. + * HTTPException: 502 if fail2ban is unreachable. + */ + post: operations["deactivate_jail_api_config_jails__name__deactivate_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/jails/{name}/local": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + /** + * Delete the jail.d override file for an inactive jail + * @description Remove the ``jail.d/{name}.local`` override file for an inactive jail. + * + * This endpoint is the clean-up action for inactive jails that still carry + * a ``.local`` override file (e.g. one written with ``enabled = false`` by a + * previous deactivation). The file is deleted without modifying fail2ban's + * running state, since the jail is already inactive. + * + * Args: + * request: FastAPI request object. + * _auth: Validated session. + * name: Name of the jail whose ``.local`` file should be removed. + * + * Raises: + * HTTPException: 400 if *name* contains invalid characters. + * HTTPException: 404 if *name* is not found in any config file. + * HTTPException: 409 if the jail is currently active. + * HTTPException: 500 if the file cannot be deleted. + * HTTPException: 502 if fail2ban is unreachable. + */ + delete: operations["delete_jail_local_override_api_config_jails__name__local_delete"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/jails/{name}/validate": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Validate jail configuration before activation + * @description Run pre-activation validation checks on a jail configuration. + * + * Validates filter and action file existence, regex pattern compilation, and + * log path existence without modifying any files or reloading fail2ban. + * + * Args: + * request: FastAPI request object. + * _auth: Validated session. + * name: Jail name to validate. + * + * Returns: + * :class:`~app.models.config.JailValidationResult` with any issues found. + * + * Raises: + * HTTPException: 400 if *name* contains invalid characters. + * HTTPException: 404 if *name* is not found in any config file. + */ + post: operations["validate_jail_api_config_jails__name__validate_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/jails/{name}/rollback": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Disable a bad jail config and restart fail2ban + * @description Disable the specified jail and attempt to restart fail2ban. + * + * Writes ``enabled = false`` to ``jail.d/{name}.local`` (works even when + * fail2ban is down — no socket is needed), then runs the configured start + * command and waits up to ten seconds for the daemon to come back online. + * + * On success, clears the :class:`~app.models.config.PendingRecovery` record. + * + * Args: + * _auth: Validated session. + * app: FastAPI application instance. + * name: Jail name to disable and roll back. + * + * Returns: + * :class:`~app.models.config.RollbackResponse`. + * + * Raises: + * HTTPException: 400 if *name* contains invalid characters. + * HTTPException: 500 if writing the .local override file fails. + */ + post: operations["rollback_jail_api_config_jails__name__rollback_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/jails/{name}/filter": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Assign a filter to a jail + * @description Write ``filter = {filter_name}`` to the jail's ``.local`` config. + * + * Existing keys in the jail's ``.local`` file are preserved. If the file + * does not exist it is created. + * + * Args: + * request: FastAPI request object. + * _auth: Validated session. + * name: Jail name. + * body: Filter to assign. + * reload: When ``true``, trigger a fail2ban reload after writing. + * + * Raises: + * HTTPException: 400 if *name* or *filter_name* contain invalid characters. + * HTTPException: 404 if the jail or filter does not exist. + * HTTPException: 500 if writing fails. + */ + post: operations["assign_filter_to_jail_api_config_jails__name__filter_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/jails/{name}/action": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Add an action to a jail + * @description Append an action entry to the jail's ``.local`` config. + * + * Existing keys in the jail's ``.local`` file are preserved. If the file + * does not exist it is created. The action is not duplicated if it is + * already present. + * + * Args: + * request: FastAPI request object. + * _auth: Validated session. + * name: Jail name. + * body: Action to add plus optional per-jail parameters. + * reload: When ``true``, trigger a fail2ban reload after writing. + * + * Raises: + * HTTPException: 400 if *name* or *action_name* contain invalid characters. + * HTTPException: 404 if the jail or action does not exist. + * HTTPException: 500 if writing fails. + */ + post: operations["assign_action_to_jail_api_config_jails__name__action_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/jails/{name}/action/{action_name}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + /** + * Remove an action from a jail + * @description Remove an action from the jail's ``.local`` config. + * + * If the jail has no ``.local`` file or the action is not listed there, + * the call is silently idempotent. + * + * Args: + * request: FastAPI request object. + * _auth: Validated session. + * name: Jail name. + * action_name: Base name of the action to remove. + * reload: When ``true``, trigger a fail2ban reload after writing. + * + * Raises: + * HTTPException: 400 if *name* or *action_name* contain invalid characters. + * HTTPException: 404 if the jail is not found in config files. + * HTTPException: 500 if writing fails. + */ + delete: operations["remove_action_from_jail_api_config_jails__name__action__action_name__delete"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/filters": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List all available filters with active/inactive status + * @description Return all filters discovered in ``filter.d/`` with active/inactive status. + * + * Scans ``{config_dir}/filter.d/`` for ``.conf`` files, merges any + * corresponding ``.local`` overrides, and cross-references each filter's + * name against the ``filter`` fields of currently running jails to determine + * whether it is active. + * + * Active filters (those used by at least one running jail) are sorted to the + * top of the list; inactive filters follow. Both groups are sorted + * alphabetically within themselves. + * + * Args: + * request: FastAPI request object. + * _auth: Validated session — enforces authentication. + * + * Returns: + * :class:`~app.models.config.FilterListResponse` with all discovered + * filters. + */ + get: operations["list_filters_api_config_filters_get"]; + put?: never; + /** + * Create a new user-defined filter + * @description Create a new user-defined filter at ``filter.d/{name}.local``. + * + * The filter is created as a ``.local`` file so it can coexist safely with + * shipped ``.conf`` files. Returns 409 if a ``.conf`` or ``.local`` for + * the requested name already exists. + * + * Args: + * request: FastAPI request object. + * _auth: Validated session. + * body: Filter name and ``[Definition]`` fields. + * reload: When ``true``, trigger a fail2ban reload after creating. + * + * Returns: + * :class:`~app.models.config.FilterConfig` for the new filter. + * + * Raises: + * HTTPException: 400 if the name contains invalid characters. + * HTTPException: 409 if the filter already exists. + * HTTPException: 422 if any regex pattern is invalid. + * HTTPException: 500 if writing fails. + */ + post: operations["create_filter_api_config_filters_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/filters/{name}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return full parsed detail for a single filter + * @description Return the full parsed configuration and active/inactive status for one filter. + * + * Reads ``{config_dir}/filter.d/{name}.conf``, merges any corresponding + * ``.local`` override, and annotates the result with ``active``, + * ``used_by_jails``, ``source_file``, and ``has_local_override``. + * + * Args: + * request: FastAPI request object. + * _auth: Validated session — enforces authentication. + * name: Filter base name (with or without ``.conf`` extension). + * + * Returns: + * :class:`~app.models.config.FilterConfig`. + * + * Raises: + * HTTPException: 404 if the filter is not found in ``filter.d/``. + * HTTPException: 502 if fail2ban is unreachable. + */ + get: operations["get_filter_api_config_filters__name__get"]; + /** + * Update a filter's .local override with new regex/pattern values + * @description Update a filter's ``[Definition]`` fields by writing a ``.local`` override. + * + * All regex patterns are validated before writing. The original ``.conf`` + * file is never modified. Fields left as ``null`` in the request body are + * kept at their current values. + * + * Args: + * request: FastAPI request object. + * _auth: Validated session. + * name: Filter base name (with or without ``.conf`` extension). + * body: Partial update — ``failregex``, ``ignoreregex``, ``datepattern``, + * ``journalmatch``. + * reload: When ``true``, trigger a fail2ban reload after writing. + * + * Returns: + * Updated :class:`~app.models.config.FilterConfig`. + * + * Raises: + * HTTPException: 400 if *name* contains invalid characters. + * HTTPException: 404 if the filter does not exist. + * HTTPException: 422 if any regex pattern fails to compile. + * HTTPException: 500 if writing the ``.local`` file fails. + */ + put: operations["update_filter_api_config_filters__name__put"]; + post?: never; + /** + * Delete a user-created filter's .local file + * @description Delete a user-created filter's ``.local`` override file. + * + * Shipped ``.conf``-only filters cannot be deleted (returns 409). When + * both a ``.conf`` and a ``.local`` exist, only the ``.local`` is removed. + * When only a ``.local`` exists (user-created filter), the file is deleted + * entirely. + * + * Args: + * request: FastAPI request object. + * _auth: Validated session. + * name: Filter base name. + * + * Raises: + * HTTPException: 400 if *name* contains invalid characters. + * HTTPException: 404 if the filter does not exist. + * HTTPException: 409 if the filter is a shipped default (conf-only). + * HTTPException: 500 if deletion fails. + */ + delete: operations["delete_filter_api_config_filters__name__delete"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/actions": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List all action definition files + * @description Return a list of every ``.conf`` and ``.local`` file in ``action.d/``. + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * + * Returns: + * :class:`~app.models.file_config.ConfFilesResponse`. + */ + get: operations["list_action_files_api_config_actions_get"]; + put?: never; + /** + * Create a new action definition file + * @description Create a new ``.conf`` file in ``action.d/``. + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * body: Name and initial content for the new file. + * + * Returns: + * The created :class:`~app.models.file_config.ConfFileContent`. + * + * Raises: + * HTTPException: 400 if *name* is invalid or content exceeds limit. + * HTTPException: 409 if a file with that name already exists. + * HTTPException: 503 if the config directory is unavailable. + */ + post: operations["create_action_file_api_config_actions_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/actions/{name}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return full parsed detail for a single action + * @description Return the full parsed configuration and active/inactive status for one action. + * + * Reads ``{config_dir}/action.d/{name}.conf``, merges any corresponding + * ``.local`` override, and annotates the result with ``active``, + * ``used_by_jails``, ``source_file``, and ``has_local_override``. + * + * Args: + * request: FastAPI request object. + * _auth: Validated session — enforces authentication. + * name: Action base name (with or without ``.conf`` extension). + * + * Returns: + * :class:`~app.models.config.ActionConfig`. + * + * Raises: + * HTTPException: 404 if the action is not found in ``action.d/``. + */ + get: operations["get_action_api_config_actions__name__get"]; + /** + * Update an action's .local override with new lifecycle command values + * @description Update an action's ``[Definition]`` fields by writing a ``.local`` override. + * + * Only non-``null`` fields in the request body are written. The original + * ``.conf`` file is never modified. + * + * Args: + * request: FastAPI request object. + * _auth: Validated session. + * name: Action base name (with or without ``.conf`` extension). + * body: Partial update — lifecycle commands and ``[Init]`` parameters. + * reload: When ``true``, trigger a fail2ban reload after writing. + * + * Returns: + * Updated :class:`~app.models.config.ActionConfig`. + * + * Raises: + * HTTPException: 400 if *name* contains invalid characters. + * HTTPException: 404 if the action does not exist. + * HTTPException: 500 if writing the ``.local`` file fails. + */ + put: operations["update_action_api_config_actions__name__put"]; + post?: never; + /** + * Delete a user-created action's .local file + * @description Delete a user-created action's ``.local`` override file. + * + * Shipped ``.conf``-only actions cannot be deleted (returns 409). When + * both a ``.conf`` and a ``.local`` exist, only the ``.local`` is removed. + * + * Args: + * request: FastAPI request object. + * _auth: Validated session. + * name: Action base name. + * + * Raises: + * HTTPException: 400 if *name* contains invalid characters. + * HTTPException: 404 if the action does not exist. + * HTTPException: 409 if the action is a shipped default (conf-only). + * HTTPException: 500 if deletion fails. + */ + delete: operations["delete_action_api_config_actions__name__delete"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/global": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return global fail2ban settings + * @description Return global fail2ban settings. + * + * Includes log level, log target, and database configuration. + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * + * Returns: + * :class:`~app.models.config.GlobalConfigResponse`. + * + * Raises: + * HTTPException: 502 when fail2ban is unreachable. + */ + get: operations["get_global_config_api_config_global_get"]; + /** + * Update global fail2ban settings + * @description Update global fail2ban settings. + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * body: Partial update — only non-None fields are written. + * + * Raises: + * HTTPException: 400 when a set command is rejected or log_target is invalid. + * HTTPException: 502 when fail2ban is unreachable. + */ + put: operations["update_global_config_api_config_global_put"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/reload": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Reload fail2ban to apply configuration changes + * @description Trigger a full fail2ban reload. + * + * All jails are stopped and restarted with the current configuration. + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * + * Raises: + * HTTPException: 409 when fail2ban reports the reload failed. + * HTTPException: 502 when fail2ban is unreachable. + */ + post: operations["reload_fail2ban_api_config_reload_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/restart": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Restart the fail2ban service + * @description Trigger a full fail2ban service restart. + * + * Stops the fail2ban daemon via the Unix domain socket, then starts it + * again using the configured ``fail2ban_start_command``. After starting, + * probes the socket for up to 10 seconds to confirm the daemon came back + * online. + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * + * Raises: + * HTTPException: 409 when fail2ban reports the stop command failed. + * HTTPException: 502 when fail2ban is unreachable for the stop command. + * HTTPException: 503 when fail2ban does not come back online within + * 10 seconds after being started. Check the fail2ban log for + * initialisation errors. Use + * ``POST /api/config/jails/{name}/rollback`` + * if a specific jail is suspect. + */ + post: operations["restart_fail2ban_api_config_restart_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/regex-test": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Test a fail regex pattern against a sample log line + * @description Test whether a regex pattern matches a given log line. + * + * This endpoint is entirely in-process — no fail2ban socket call is made. + * Returns the match result and any captured groups. + * + * Args: + * _auth: Validated session. + * body: Sample log line and regex pattern. + * + * Returns: + * :class:`~app.models.config.RegexTestResponse` with match result and + * groups. + */ + post: operations["regex_test_api_config_regex_test_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/preview-log": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Preview log file lines against a regex pattern + * @description Read the last N lines of a log file and test a regex against each one. + * + * Returns each line with a flag indicating whether the regex matched, and + * the captured groups for matching lines. The log file is read from the + * server's local filesystem. + * + * Args: + * _auth: Validated session. + * body: Log file path, regex pattern, and number of lines to read. + * + * Returns: + * :class:`~app.models.config.LogPreviewResponse` with per-line results. + */ + post: operations["preview_log_api_config_preview_log_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/map-color-thresholds": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get map color threshold configuration + * @description Return the configured map color thresholds. + * + * Args: + * _request: FastAPI request object. + * _auth: Validated session. + * settings_ctx: Settings service context containing db and repository. + * + * Returns: + * :class:`~app.models.config.MapColorThresholdsResponse` with + * current thresholds. + */ + get: operations["get_map_color_thresholds_api_config_map_color_thresholds_get"]; + /** + * Update map color threshold configuration + * @description Update the map color threshold configuration. + * + * Args: + * _request: FastAPI request object. + * _auth: Validated session. + * settings_ctx: Settings service context containing db and repository. + * body: New threshold values. + * + * Returns: + * :class:`~app.models.config.MapColorThresholdsResponse` with + * updated thresholds. + * + * Raises: + * HTTPException: 400 if validation fails (thresholds not + * properly ordered). + */ + put: operations["update_map_color_thresholds_api_config_map_color_thresholds_put"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/fail2ban-log": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Read the tail of the fail2ban daemon log file + * @description Return the tail of the fail2ban daemon log file. + * + * Queries the fail2ban socket for the current log target and log level, + * reads the last *lines* entries from the file, and optionally filters + * them by *filter*. Only file-based log targets are supported. + * + * Args: + * request: Incoming request. + * _auth: Validated session — enforces authentication. + * lines: Number of tail lines to return (1–2000, default 200). + * filter: Optional plain-text substring — only matching lines returned. + * + * Returns: + * :class:`~app.models.config.Fail2BanLogResponse`. + * + * Raises: + * HTTPException: 400 when the log target is not a file or path is outside + * the allowed directory. + * HTTPException: 502 when fail2ban is unreachable. + */ + get: operations["get_fail2ban_log_api_config_fail2ban_log_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/service-status": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return fail2ban service health status with log configuration + * @description Return fail2ban service health and current log configuration. + * + * Probes the fail2ban daemon to determine online/offline state, then + * augments the result with the current log level and log target values. + * + * Args: + * request: Incoming request. + * _auth: Validated session — enforces authentication. + * + * Returns: + * :class:`~app.models.config.ServiceStatusResponse`. + * + * Raises: + * HTTPException: 502 when fail2ban is unreachable (the service itself + * handles this gracefully and returns ``online=False``). + */ + get: operations["get_service_status_api_config_service_status_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/jail-files": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List all jail config files + * @description Return metadata for every ``.conf`` and ``.local`` file in ``jail.d/``. + * + * The ``enabled`` field reflects the value of the ``enabled`` key inside the + * file (defaulting to ``true`` when the key is absent). + * + * Args: + * config_dir: Config directory path injected from application settings. + * _auth: Validated session — enforces authentication. + * + * Returns: + * :class:`~app.models.file_config.JailConfigFilesResponse`. + */ + get: operations["list_jail_config_files_api_config_jail_files_get"]; + put?: never; + /** + * Create a new jail.d config file + * @description Create a new ``.conf`` file in ``jail.d/``. + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * body: :class:`~app.models.file_config.ConfFileCreateRequest` with name and content. + * + * Returns: + * :class:`~app.models.file_config.ConfFileContent` with the created file metadata. + * + * Raises: + * HTTPException: 400 if the name is unsafe or the content exceeds the size limit. + * HTTPException: 409 if a file with that name already exists. + * HTTPException: 503 if the config directory is unavailable. + */ + post: operations["create_jail_config_file_api_config_jail_files_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/jail-files/{filename}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return a single jail config file with its content + * @description Return the metadata and raw content of one jail config file. + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * filename: Filename including extension (e.g. ``sshd.conf``). + * + * Returns: + * :class:`~app.models.file_config.JailConfigFileContent`. + * + * Raises: + * HTTPException: 400 if *filename* is unsafe. + * HTTPException: 404 if the file does not exist. + * HTTPException: 503 if the config directory is unavailable. + */ + get: operations["get_jail_config_file_api_config_jail_files__filename__get"]; + /** + * Overwrite a jail.d config file with new raw content + * @description Overwrite the raw content of an existing jail.d config file. + * + * The change is written directly to disk. You must reload fail2ban + * (``POST /api/config/reload``) separately for the change to take effect. + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * filename: Filename of the jail config file (e.g. ``sshd.conf``). + * body: New raw file content. + * + * Raises: + * HTTPException: 400 if *filename* is unsafe or content is invalid. + * HTTPException: 404 if the file does not exist. + * HTTPException: 503 if the config directory is unavailable. + */ + put: operations["write_jail_config_file_api_config_jail_files__filename__put"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/jail-files/{filename}/enabled": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** + * Enable or disable a jail configuration file + * @description Set the ``enabled = true/false`` key inside a jail config file. + * + * The change modifies the file on disk. You must reload fail2ban + * (``POST /api/config/reload``) separately for the change to take effect. + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * filename: Filename of the jail config file (e.g. ``sshd.conf``). + * body: New enabled state. + * + * Raises: + * HTTPException: 400 if *filename* is unsafe or the operation fails. + * HTTPException: 404 if the file does not exist. + * HTTPException: 503 if the config directory is unavailable. + */ + put: operations["set_jail_config_file_enabled_api_config_jail_files__filename__enabled_put"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/filters/{name}/raw": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return a filter definition file's raw content + * @description Return the raw content of a filter definition file. + * + * This endpoint provides direct access to the file bytes for the raw + * config editor. For structured parsing with active/inactive status use + * ``GET /api/config/filters/{name}`` (served by the config router). + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * name: Base name with or without extension (e.g. ``sshd`` or ``sshd.conf``). + * + * Returns: + * :class:`~app.models.file_config.ConfFileContent`. + * + * Raises: + * HTTPException: 400 if *name* is unsafe. + * HTTPException: 404 if the file does not exist. + * HTTPException: 503 if the config directory is unavailable. + */ + get: operations["get_filter_file_raw_api_config_filters__name__raw_get"]; + /** + * Update a filter definition file (raw content) + * @description Overwrite the content of an existing filter definition file. + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * name: Base name with or without extension. + * body: New file content. + * + * Raises: + * HTTPException: 400 if *name* is unsafe or content exceeds the size limit. + * HTTPException: 404 if the file does not exist. + * HTTPException: 503 if the config directory is unavailable. + */ + put: operations["write_filter_file_api_config_filters__name__raw_put"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/filters/raw": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Create a new filter definition file (raw content) + * @description Create a new ``.conf`` file in ``filter.d/``. + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * body: Name and initial content for the new file. + * + * Returns: + * The created :class:`~app.models.file_config.ConfFileContent`. + * + * Raises: + * HTTPException: 400 if *name* is invalid or content exceeds limit. + * HTTPException: 409 if a file with that name already exists. + * HTTPException: 503 if the config directory is unavailable. + */ + post: operations["create_filter_file_api_config_filters_raw_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/actions/{name}/raw": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return an action definition file with its content + * @description Return the content of an action definition file. + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * name: Base name with or without extension. + * + * Returns: + * :class:`~app.models.file_config.ConfFileContent`. + * + * Raises: + * HTTPException: 400 if *name* is unsafe. + * HTTPException: 404 if the file does not exist. + * HTTPException: 503 if the config directory is unavailable. + */ + get: operations["get_action_file_api_config_actions__name__raw_get"]; + /** + * Update an action definition file + * @description Overwrite the content of an existing action definition file. + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * name: Base name with or without extension. + * body: New file content. + * + * Raises: + * HTTPException: 400 if *name* is unsafe or content exceeds the size limit. + * HTTPException: 404 if the file does not exist. + * HTTPException: 503 if the config directory is unavailable. + */ + put: operations["write_action_file_api_config_actions__name__raw_put"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/filters/{name}/parsed": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return a filter file parsed into a structured model + * @description Parse a filter definition file and return its structured fields. + * + * The file is read from ``filter.d/``, parsed as fail2ban INI format, and + * returned as a :class:`~app.models.config.FilterConfig` JSON object. This + * is the input model for the form-based filter editor (Task 2.3). + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * name: Base name (e.g. ``sshd`` or ``sshd.conf``). + * + * Returns: + * :class:`~app.models.config.FilterConfig`. + * + * Raises: + * HTTPException: 400 if *name* is unsafe. + * HTTPException: 404 if the file does not exist. + * HTTPException: 503 if the config directory is unavailable. + */ + get: operations["get_parsed_filter_api_config_filters__name__parsed_get"]; + /** + * Update a filter file from a structured model + * @description Apply a partial structured update to a filter definition file. + * + * Fields set to ``null`` in the request body are left unchanged. The file is + * re-serialized to fail2ban INI format after merging. + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * name: Base name of the filter to update. + * body: Partial :class:`~app.models.config.FilterConfigUpdate`. + * + * Raises: + * HTTPException: 400 if *name* is unsafe or content exceeds the size limit. + * HTTPException: 404 if the file does not exist. + * HTTPException: 503 if the config directory is unavailable. + */ + put: operations["update_parsed_filter_api_config_filters__name__parsed_put"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/actions/{name}/parsed": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return an action file parsed into a structured model + * @description Parse an action definition file and return its structured fields. + * + * The file is read from ``action.d/``, parsed as fail2ban INI format, and + * returned as a :class:`~app.models.config.ActionConfig` JSON object. This + * is the input model for the form-based action editor (Task 3.3). + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * name: Base name (e.g. ``iptables`` or ``iptables.conf``). + * + * Returns: + * :class:`~app.models.config.ActionConfig`. + * + * Raises: + * HTTPException: 400 if *name* is unsafe. + * HTTPException: 404 if the file does not exist. + * HTTPException: 503 if the config directory is unavailable. + */ + get: operations["get_parsed_action_api_config_actions__name__parsed_get"]; + /** + * Update an action file from a structured model + * @description Apply a partial structured update to an action definition file. + * + * Fields set to ``null`` in the request body are left unchanged. The file is + * re-serialized to fail2ban INI format after merging. + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * name: Base name of the action to update. + * body: Partial :class:`~app.models.config.ActionConfigUpdate`. + * + * Raises: + * HTTPException: 400 if *name* is unsafe or content exceeds the size limit. + * HTTPException: 404 if the file does not exist. + * HTTPException: 503 if the config directory is unavailable. + */ + put: operations["update_parsed_action_api_config_actions__name__parsed_put"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/config/jail-files/{filename}/parsed": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return a jail.d file parsed into a structured model + * @description Parse a jail.d config file and return its structured fields. + * + * The file is read from ``jail.d/``, parsed as fail2ban INI format, and + * returned as a :class:`~app.models.config.JailFileConfig` JSON object. This + * is the input model for the form-based jail file editor (Task 6.2). + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * filename: Filename including extension (e.g. ``sshd.conf``). + * + * Returns: + * :class:`~app.models.config.JailFileConfig`. + * + * Raises: + * HTTPException: 400 if *filename* is unsafe. + * HTTPException: 404 if the file does not exist. + * HTTPException: 503 if the config directory is unavailable. + */ + get: operations["get_parsed_jail_file_api_config_jail_files__filename__parsed_get"]; + /** + * Update a jail.d file from a structured model + * @description Apply a partial structured update to a jail.d config file. + * + * Fields set to ``null`` in the request body are left unchanged. The file is + * re-serialized to fail2ban INI format after merging. + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * filename: Filename including extension (e.g. ``sshd.conf``). + * body: Partial :class:`~app.models.config.JailFileConfigUpdate`. + * + * Raises: + * HTTPException: 400 if *filename* is unsafe or content exceeds size limit. + * HTTPException: 404 if the file does not exist. + * HTTPException: 503 if the config directory is unavailable. + */ + put: operations["update_parsed_jail_file_api_config_jail_files__filename__parsed_put"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/server/settings": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return fail2ban server-level settings + * @description Return the current fail2ban server-level settings. + * + * Includes log level, log target, syslog socket, database file path, + * database purge age, and maximum stored matches per record. + * + * Args: + * request: Incoming request (used to access ``app.state``). + * _auth: Validated session — enforces authentication. + * + * Returns: + * :class:`~app.models.server.ServerSettingsResponse`. + * + * Raises: + * HTTPException: 502 when fail2ban is unreachable. + */ + get: operations["get_server_settings_api_server_settings_get"]; + /** + * Update fail2ban server-level settings + * @description Update fail2ban server-level settings. + * + * Only non-None fields in the request body are written. Changes take + * effect immediately without a daemon restart. + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * body: Partial settings update. + * + * Raises: + * HTTPException: 400 when a set command is rejected by fail2ban. + * HTTPException: 502 when fail2ban is unreachable. + */ + put: operations["update_server_settings_api_server_settings_put"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/server/flush-logs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Flush and re-open fail2ban log files + * @description Flush and re-open fail2ban log files. + * + * Useful after log rotation so the daemon writes to the newly created + * log file rather than continuing to append to the rotated one. + * + * Args: + * request: Incoming request. + * _auth: Validated session. + * + * Returns: + * ``{"message": ""}`` + * + * Raises: + * HTTPException: 400 when the command is rejected. + * HTTPException: 502 when fail2ban is unreachable. + */ + post: operations["flush_logs_api_server_flush_logs_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/history": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return a paginated list of historical bans + * @description Return a paginated list of historical bans with optional filters. + * + * Queries the fail2ban database for all ban records, applying the requested + * filters. Results are ordered newest-first and enriched with geolocation. + * + * Args: + * request: The incoming request (used to access ``app.state``). + * _auth: Validated session — enforces authentication. + * history_ctx: History service context containing db and repositories. + * socket_path: Path to fail2ban Unix domain socket. + * http_session: Shared HTTP session for geolocation. + * fail2ban_metadata_service: Fail2Ban metadata service. + * range: Optional time-range preset. ``None`` means all-time. + * jail: Optional jail name filter (exact match). + * ip: Optional IP prefix filter (prefix match). + * page: 1-based page number. + * page_size: Items per page (1–500). + * + * Returns: + * :class:`~app.models.history.HistoryListResponse` with paginated items + * and the total matching count. + */ + get: operations["get_history_api_history_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/history/archive": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Return a paginated list of archived historical bans */ + get: operations["get_history_archive_api_history_archive_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/history/{ip}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return the full ban history for a single IP address + * @description Return the complete historical record for a single IP address. + * + * Fetches all ban events for the given IP from the fail2ban database and + * aggregates them into a timeline. Returns ``404`` if the IP has no + * recorded history. + * + * Args: + * request: The incoming request. + * _auth: Validated session dependency. + * ip: The IP address to look up. + * + * Returns: + * :class:`~app.models.history.IpDetailResponse` with aggregated totals + * and a full ban timeline. + * + * Raises: + * HTTPException: 404 if the IP has no history in the database. + */ + get: operations["get_ip_history_api_history__ip__get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/blocklists": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List all blocklist sources + * @description Return all configured blocklist source definitions. + * + * Args: + * blocklist_ctx: Blocklist service context containing db and repositories. + * _auth: Validated session — enforces authentication. + * + * Returns: + * :class:`~app.models.blocklist.BlocklistListResponse` with all sources. + */ + get: operations["list_blocklists_api_blocklists_get"]; + put?: never; + /** + * Add a new blocklist source + * @description Create a new blocklist source definition. + * + * Args: + * payload: New source data (name, url, enabled). + * blocklist_ctx: Blocklist service context containing db and repositories. + * _auth: Validated session — enforces authentication. + * + * Returns: + * The newly created :class:`~app.models.blocklist.BlocklistSource`. + * + * Raises: + * HTTPException: 400 if URL validation fails. + */ + post: operations["create_blocklist_api_blocklists_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/blocklists/import": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Trigger a manual blocklist import + * @description Download and apply all enabled blocklist sources immediately. + * + * Args: + * http_session: Shared HTTP session (injected). + * blocklist_ctx: Blocklist service context containing db and repositories. + * _auth: Validated session — enforces authentication. + * socket_path: Path to fail2ban Unix domain socket. + * geo_cache: Geolocation cache instance. + * + * Returns: + * :class:`~app.models.blocklist.ImportRunResult` with per-source + * results and aggregated counters. + */ + post: operations["run_import_now_api_blocklists_import_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/blocklists/schedule": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get the current import schedule + * @description Return the current schedule configuration and runtime metadata. + * + * The ``next_run_at`` field is read from APScheduler if the job is active. + * + * Args: + * blocklist_ctx: Blocklist service context containing db and repositories. + * _auth: Validated session — enforces authentication. + * scheduler: APScheduler instance. + * + * Returns: + * :class:`~app.models.blocklist.ScheduleInfo` with config and run + * times. + */ + get: operations["get_schedule_api_blocklists_schedule_get"]; + /** + * Update the import schedule + * @description Persist a new schedule configuration and reschedule the import job. + * + * Args: + * payload: New :class:`~app.models.blocklist.ScheduleConfig`. + * blocklist_ctx: Blocklist service context containing db and repositories. + * _auth: Validated session — enforces authentication. + * scheduler: Shared APScheduler instance (injected). + * http_session: Shared HTTP session used by the scheduler job. + * settings: Current application settings used by the scheduler job. + * + * Returns: + * Updated :class:`~app.models.blocklist.ScheduleInfo`. + */ + put: operations["update_schedule_api_blocklists_schedule_put"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/blocklists/log": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get the paginated import log + * @description Return a paginated log of all import runs. + * + * Args: + * blocklist_ctx: Blocklist service context containing db and repositories. + * _auth: Validated session — enforces authentication. + * source_id: Optional filter — only show logs for this source. + * page: 1-based page number. + * page_size: Items per page. + * + * Returns: + * :class:`~app.models.blocklist.ImportLogListResponse`. + */ + get: operations["get_import_log_api_blocklists_log_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/blocklists/{source_id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get a single blocklist source + * @description Return a single blocklist source by id. + * + * Args: + * source_id: Primary key of the source. + * blocklist_ctx: Blocklist service context containing db and repositories. + * _auth: Validated session — enforces authentication. + * + * Raises: + * HTTPException: 404 if the source does not exist. + */ + get: operations["get_blocklist_api_blocklists__source_id__get"]; + /** + * Update a blocklist source + * @description Update one or more fields on a blocklist source. + * + * Args: + * source_id: Primary key of the source to update. + * payload: Fields to update (all optional). + * blocklist_ctx: Blocklist service context containing db and repositories. + * _auth: Validated session — enforces authentication. + * + * Raises: + * HTTPException: 400 if URL validation fails. + * HTTPException: 404 if the source does not exist. + */ + put: operations["update_blocklist_api_blocklists__source_id__put"]; + post?: never; + /** + * Delete a blocklist source + * @description Delete a blocklist source by id. + * + * Args: + * source_id: Primary key of the source to remove. + * blocklist_ctx: Blocklist service context containing db and repositories. + * _auth: Validated session — enforces authentication. + * + * Raises: + * HTTPException: 404 if the source does not exist. + */ + delete: operations["delete_blocklist_api_blocklists__source_id__delete"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/blocklists/{source_id}/preview": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Preview the contents of a blocklist source + * @description Download and preview a sample of a blocklist source. + * + * Returns the first :data:`~app.services.blocklist_service._PREVIEW_LINES` + * valid IP entries together with validation statistics. + * + * Args: + * source_id: Primary key of the source to preview. + * http_session: Shared HTTP session for downloading. + * blocklist_ctx: Blocklist service context containing db and repositories. + * _auth: Validated session — enforces authentication. + * + * Raises: + * HTTPException: 404 if the source does not exist. + * HTTPException: 502 if the URL cannot be reached. + */ + get: operations["preview_blocklist_api_blocklists__source_id__preview_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; +} +export type webhooks = Record; +export interface components { + schemas: { + /** + * ActionConfig + * @description Structured representation of an ``action.d/*.conf`` file. + */ + ActionConfig: { + /** + * Name + * @description Action base name, e.g. ``iptables``. + */ + name: string; + /** + * Filename + * @description Actual filename, e.g. ``iptables.conf``. + */ + filename: string; + /** Before */ + before?: string | null; + /** After */ + after?: string | null; + /** + * Actionstart + * @description Executed at jail start or first ban. + */ + actionstart?: string | null; + /** + * Actionstop + * @description Executed at jail stop. + */ + actionstop?: string | null; + /** + * Actioncheck + * @description Executed before each ban. + */ + actioncheck?: string | null; + /** + * Actionban + * @description Executed to ban an IP. Tags: ````, ````, ````. + */ + actionban?: string | null; + /** + * Actionunban + * @description Executed to unban an IP. + */ + actionunban?: string | null; + /** + * Actionflush + * @description Executed to flush all bans on shutdown. + */ + actionflush?: string | null; + /** + * Definition Vars + * @description Additional ``[Definition]`` variables. + */ + definition_vars?: { + [key: string]: string; + }; + /** + * Init Vars + * @description Runtime parameters that can be overridden per jail. + */ + init_vars?: { + [key: string]: string; + }; + /** + * Active + * @description ``True`` when this action is referenced by at least one currently enabled (running) jail. + * @default false + */ + active: boolean; + /** + * Used By Jails + * @description Names of currently enabled jails that reference this action. Empty when ``active`` is ``False``. + */ + used_by_jails?: string[]; + /** + * Source File + * @description Absolute path to the ``.conf`` source file for this action. + * @default + */ + source_file: string; + /** + * Has Local Override + * @description ``True`` when a ``.local`` override file exists alongside the base ``.conf`` file. + * @default false + */ + has_local_override: boolean; + }; + /** + * ActionConfigUpdate + * @description Partial update payload for a parsed action file. + */ + ActionConfigUpdate: { + /** Before */ + before?: string | null; + /** After */ + after?: string | null; + /** Actionstart */ + actionstart?: string | null; + /** Actionstop */ + actionstop?: string | null; + /** Actioncheck */ + actioncheck?: string | null; + /** Actionban */ + actionban?: string | null; + /** Actionunban */ + actionunban?: string | null; + /** Actionflush */ + actionflush?: string | null; + /** Definition Vars */ + definition_vars?: { + [key: string]: string; + } | null; + /** Init Vars */ + init_vars?: { + [key: string]: string; + } | null; + }; + /** + * ActionCreateRequest + * @description Payload for ``POST /api/config/actions``. + * + * Creates a new user-defined action at ``action.d/{name}.local``. + */ + ActionCreateRequest: { + /** + * Name + * @description Action base name (e.g. ``my-custom-action``). Must not already exist. + */ + name: string; + /** + * Actionstart + * @description Command to execute at jail start. + */ + actionstart?: string | null; + /** + * Actionstop + * @description Command to execute at jail stop. + */ + actionstop?: string | null; + /** + * Actioncheck + * @description Command to execute before each ban. + */ + actioncheck?: string | null; + /** + * Actionban + * @description Command to execute to ban an IP. + */ + actionban?: string | null; + /** + * Actionunban + * @description Command to execute to unban an IP. + */ + actionunban?: string | null; + /** + * Actionflush + * @description Command to flush all bans on shutdown. + */ + actionflush?: string | null; + /** + * Definition Vars + * @description Additional ``[Definition]`` variables. + */ + definition_vars?: { + [key: string]: string; + }; + /** + * Init Vars + * @description ``[Init]`` runtime parameters. + */ + init_vars?: { + [key: string]: string; + }; + }; + /** + * ActionListResponse + * @description Response for ``GET /api/config/actions``. + */ + ActionListResponse: { + /** + * Actions + * @description All discovered actions, each annotated with active/inactive status and the jails that reference them. + */ + actions?: components["schemas"]["ActionConfig"][]; + /** + * Total + * @description Total number of actions found. + */ + total: number; + }; + /** + * ActionUpdateRequest + * @description Payload for ``PUT /api/config/actions/{name}``. + * + * Accepts only the user-editable ``[Definition]`` lifecycle fields and + * ``[Init]`` parameters. Fields left as ``None`` are not changed. + */ + ActionUpdateRequest: { + /** + * Actionstart + * @description Updated ``actionstart`` command. ``None`` = keep existing. + */ + actionstart?: string | null; + /** + * Actionstop + * @description Updated ``actionstop`` command. ``None`` = keep existing. + */ + actionstop?: string | null; + /** + * Actioncheck + * @description Updated ``actioncheck`` command. ``None`` = keep existing. + */ + actioncheck?: string | null; + /** + * Actionban + * @description Updated ``actionban`` command. ``None`` = keep existing. + */ + actionban?: string | null; + /** + * Actionunban + * @description Updated ``actionunban`` command. ``None`` = keep existing. + */ + actionunban?: string | null; + /** + * Actionflush + * @description Updated ``actionflush`` command. ``None`` = keep existing. + */ + actionflush?: string | null; + /** + * Definition Vars + * @description Additional ``[Definition]`` variables to set. ``None`` = keep existing. + */ + definition_vars?: { + [key: string]: string; + } | null; + /** + * Init Vars + * @description ``[Init]`` parameters to set. ``None`` = keep existing. + */ + init_vars?: { + [key: string]: string; + } | null; + }; + /** + * ActivateJailRequest + * @description Optional override values when activating an inactive jail. + * + * All fields are optional. Omitted fields are not written to the + * ``.local`` override file so that fail2ban falls back to its default + * values. + */ + ActivateJailRequest: { + /** + * Bantime + * @description Override ban duration, e.g. ``1h`` or ``3600``. + */ + bantime?: string | null; + /** + * Findtime + * @description Override failure-counting window, e.g. ``10m``. + */ + findtime?: string | null; + /** + * Maxretry + * @description Override maximum failures before a ban. + */ + maxretry?: number | null; + /** + * Port + * @description Override port(s) to monitor. + */ + port?: string | null; + /** + * Logpath + * @description Override log file paths. + */ + logpath?: string[] | null; + }; + /** + * ActiveBan + * @description A currently active ban entry returned by ``GET /api/bans/active``. + */ + ActiveBan: { + /** + * Ip + * @description Banned IP address. + */ + ip: string; + /** + * Jail + * @description Jail holding the ban. + */ + jail: string; + /** + * Banned At + * @description ISO 8601 UTC start of the ban. + */ + banned_at?: string | null; + /** + * Expires At + * @description ISO 8601 UTC expiry, or ``null`` if permanent. + */ + expires_at?: string | null; + /** + * Ban Count + * @description Running ban count for this IP. + * @default 1 + */ + ban_count: number; + /** + * Country + * @description ISO 3166-1 alpha-2 country code. + */ + country?: string | null; + }; + /** + * ActiveBanListResponse + * @description List of all currently active bans across all jails. + * + * Request: `GET /api/bans/active` with optional filter parameters. + * Response: Non-paginated collection of currently active bans with total count. + * + * Note: This endpoint does not support pagination. All matching bans are returned. + * For paginated results, use individual jail endpoints or the dashboard ban-list view. + */ + ActiveBanListResponse: { + /** + * Items + * @description Collection items. + */ + items?: components["schemas"]["ActiveBan"][]; + /** + * Total + * @description Total number of items. + */ + total: number; + }; + /** + * AddLogPathRequest + * @description Payload for ``POST /api/config/jails/{name}/logpath``. + */ + AddLogPathRequest: { + /** + * Log Path + * @description Absolute path to the log file to monitor. + */ + log_path: string; + /** + * Tail + * @description If true, monitor from current end of file (tail). If false, read from the beginning. + * @default true + */ + tail: boolean; + }; + /** + * AssignActionRequest + * @description Payload for ``POST /api/config/jails/{jail_name}/action``. + */ + AssignActionRequest: { + /** + * Action Name + * @description Action base name to add to the jail (e.g. ``iptables-multiport``). + */ + action_name: string; + /** + * Params + * @description Optional per-jail action parameters written as ``action_name[key=value, ...]`` in the jail config. + */ + params?: { + [key: string]: string; + }; + }; + /** + * AssignFilterRequest + * @description Payload for ``POST /api/config/jails/{jail_name}/filter``. + */ + AssignFilterRequest: { + /** + * Filter Name + * @description Filter base name to assign to the jail (e.g. ``sshd``). + */ + filter_name: string; + }; + /** + * BanRequest + * @description Payload for ``POST /api/bans`` (ban an IP). + */ + BanRequest: { + /** + * Ip + * @description IP address to ban. + */ + ip: string; + /** + * Jail + * @description Jail in which to apply the ban. + */ + jail: string; + }; + /** + * BanTrendBucket + * @description A single time bucket in the ban trend series. + */ + BanTrendBucket: { + /** + * Timestamp + * @description ISO 8601 UTC start of the bucket. + */ + timestamp: string; + /** + * Count + * @description Number of bans that started in this bucket. + */ + count: number; + }; + /** + * BanTrendResponse + * @description Response for the ``GET /api/dashboard/bans/trend`` endpoint. + */ + BanTrendResponse: { + /** + * Buckets + * @description Time-ordered list of ban-count buckets covering the full window. + */ + buckets?: components["schemas"]["BanTrendBucket"][]; + /** + * Bucket Size + * @description Human-readable bucket size label (e.g. '1h', '6h', '1d', '7d'). + */ + bucket_size: string; + }; + /** + * BansByCountryResponse + * @description Response for the bans-by-country aggregation endpoint. + * + * Contains a per-country ban count, a human-readable country name map, and + * the full (un-paginated) ban list for the selected time window so the + * frontend can render both the world map and its companion table from a + * single request. + */ + BansByCountryResponse: { + /** + * Countries + * @description ISO 3166-1 alpha-2 country code → ban count. + */ + countries?: { + [key: string]: number; + }; + /** + * Country Names + * @description ISO 3166-1 alpha-2 country code → human-readable country name. + */ + country_names?: { + [key: string]: string; + }; + /** + * Bans + * @description All bans in the selected time window (up to the server limit). + */ + bans?: components["schemas"]["DashboardBanItem"][]; + /** + * Total + * @description Total ban count in the window. + */ + total: number; + }; + /** + * BansByJailResponse + * @description Response for the ``GET /api/dashboard/bans/by-jail`` endpoint. + */ + BansByJailResponse: { + /** + * Jails + * @description Jails ordered by ban count descending. + */ + jails?: components["schemas"]["JailBanCount"][]; + /** + * Total + * @description Total ban count in the selected window. + */ + total: number; + }; + /** + * BantimeEscalation + * @description Incremental ban-time escalation configuration for a jail. + */ + BantimeEscalation: { + /** + * Increment + * @description Whether incremental banning is enabled. + * @default false + */ + increment: boolean; + /** + * Factor + * @description Multiplier applied to the base ban time on each repeat offence. + */ + factor?: number | null; + /** + * Formula + * @description Python expression evaluated to compute the escalated ban time. + */ + formula?: string | null; + /** + * Multipliers + * @description Space-separated integers used as per-offence multipliers. + */ + multipliers?: string | null; + /** + * Max Time + * @description Maximum ban duration in seconds when escalation is active. + */ + max_time?: number | null; + /** + * Rnd Time + * @description Random jitter (seconds) added to each escalated ban time. + */ + rnd_time?: number | null; + /** + * Overall Jails + * @description Count repeat offences across all jails, not just the current one. + * @default false + */ + overall_jails: boolean; + }; + /** + * BantimeEscalationUpdate + * @description Partial update payload for ban-time escalation settings. + */ + BantimeEscalationUpdate: { + /** Increment */ + increment?: boolean | null; + /** Factor */ + factor?: number | null; + /** Formula */ + formula?: string | null; + /** Multipliers */ + multipliers?: string | null; + /** Max Time */ + max_time?: number | null; + /** Rnd Time */ + rnd_time?: number | null; + /** Overall Jails */ + overall_jails?: boolean | null; + }; + /** + * BlocklistListResponse + * @description Response for ``GET /api/blocklists``. + */ + BlocklistListResponse: { + /** Sources */ + sources?: components["schemas"]["BlocklistSource"][]; + }; + /** + * BlocklistSource + * @description Domain model for a blocklist source definition. + */ + BlocklistSource: { + /** Id */ + id: number; + /** Name */ + name: string; + /** Url */ + url: string; + /** Enabled */ + enabled: boolean; + /** Created At */ + created_at: string; + /** Updated At */ + updated_at: string; + }; + /** + * BlocklistSourceCreate + * @description Payload for ``POST /api/blocklists``. + * + * URL must use http/https scheme. The hostname must resolve to a public IP + * (not private, loopback, link-local, or reserved). Validation happens + * asynchronously in the service layer. + */ + BlocklistSourceCreate: { + /** + * Name + * @description Human-readable source name. + */ + name: string; + /** + * Url + * Format: uri + * @description URL of the blocklist file (http/https only). + */ + url: string; + /** + * Enabled + * @default true + */ + enabled: boolean; + }; + /** + * BlocklistSourceUpdate + * @description Payload for ``PUT /api/blocklists/{id}``. All fields are optional. + * + * If URL is provided, it must use http/https scheme. + */ + BlocklistSourceUpdate: { + /** Name */ + name?: string | null; + /** Url */ + url?: string | null; + /** Enabled */ + enabled?: boolean | null; + }; + /** + * ConfFileContent + * @description A conf file with its raw text content. + */ + ConfFileContent: { + /** + * Name + * @description Base name without extension. + */ + name: string; + /** + * Filename + * @description Actual filename. + */ + filename: string; + /** + * Content + * @description Raw file content. + */ + content: string; + }; + /** + * ConfFileCreateRequest + * @description Payload for ``POST /api/config/filters`` and ``POST /api/config/actions``. + */ + ConfFileCreateRequest: { + /** + * Name + * @description New file base name (without extension). Must contain only alphanumeric characters, hyphens, underscores, and dots. + */ + name: string; + /** + * Content + * @description Initial raw file content (must not exceed 512 KB). + */ + content: string; + }; + /** + * ConfFileEntry + * @description Metadata for a single ``.conf`` or ``.local`` file. + */ + ConfFileEntry: { + /** + * Name + * @description Base name without extension (e.g. ``sshd``). + */ + name: string; + /** + * Filename + * @description Actual filename (e.g. ``sshd.conf``). + */ + filename: string; + }; + /** + * ConfFileUpdateRequest + * @description Payload for ``PUT /api/config/filters/{name}`` and ``PUT /api/config/actions/{name}``. + */ + ConfFileUpdateRequest: { + /** + * Content + * @description New raw file content (must not exceed 512 KB). + */ + content: string; + }; + /** + * ConfFilesResponse + * @description Response for list endpoints (``GET /api/config/filters`` and ``GET /api/config/actions``). + */ + ConfFilesResponse: { + /** Files */ + files?: components["schemas"]["ConfFileEntry"][]; + /** Total */ + total: number; + }; + /** + * DashboardBanItem + * @description A single row in the dashboard ban-list table. + * + * Populated from the fail2ban database and enriched with geo data. + */ + DashboardBanItem: { + /** + * Ip + * @description Banned IP address. + */ + ip: string; + /** + * Jail + * @description Jail that issued the ban. + */ + jail: string; + /** + * Banned At + * @description ISO 8601 UTC timestamp of the ban. + */ + banned_at: string; + /** + * Service + * @description First matched log line — used as context for the ban. + */ + service?: string | null; + /** + * Country Code + * @description ISO 3166-1 alpha-2 country code, or ``null`` if unknown. + */ + country_code?: string | null; + /** + * Country Name + * @description Human-readable country name, or ``null`` if unknown. + */ + country_name?: string | null; + /** + * Asn + * @description Autonomous System Number string (e.g. ``'AS3320'``). + */ + asn?: string | null; + /** + * Org + * @description Organisation name associated with the IP. + */ + org?: string | null; + /** + * Ban Count + * @description How many times this IP was banned. + */ + ban_count: number; + /** + * Origin + * @description Whether this ban came from a blocklist import or fail2ban itself. + * @enum {string} + */ + origin: "blocklist" | "selfblock"; + }; + /** + * DashboardBanListResponse + * @description Paginated dashboard ban-list response. + * + * Request: `GET /api/dashboard/bans` with time range, page, and filter parameters. + * Response: Paginated collection of dashboard ban items with geo-enrichment. + */ + DashboardBanListResponse: { + /** + * Items + * @description Data items for the current page. + */ + items?: components["schemas"]["DashboardBanItem"][]; + /** + * Total + * @description Total number of items matching the query. + */ + total: number; + /** + * Page + * @description Current page number (1-based). + */ + page: number; + /** + * Page Size + * @description Number of items per page. + */ + page_size: number; + }; + /** + * Fail2BanLogResponse + * @description Response for ``GET /api/config/fail2ban-log``. + */ + Fail2BanLogResponse: { + /** + * Log Path + * @description Resolved absolute path of the log file being read. + */ + log_path: string; + /** + * Lines + * @description Log lines returned (tail, optionally filtered). + */ + lines?: string[]; + /** + * Total Lines + * @description Total number of lines in the file before filtering. + */ + total_lines: number; + /** + * Log Level + * @description Current fail2ban log level. + */ + log_level: string; + /** + * Log Target + * @description Current fail2ban log target (file path or special value). + */ + log_target: string; + }; + /** + * FilterConfig + * @description Structured representation of a ``filter.d/*.conf`` file. + * + * The ``active``, ``used_by_jails``, ``source_file``, and + * ``has_local_override`` fields are populated by + * :func:`~app.services.filter_config_service.list_filters` and + * :func:`~app.services.filter_config_service.get_filter`. When the model is + * returned from the raw file-based endpoints (``/filters/{name}/parsed``), + * these fields carry their default values. + */ + FilterConfig: { + /** + * Name + * @description Filter base name, e.g. ``sshd``. + */ + name: string; + /** + * Filename + * @description Actual filename, e.g. ``sshd.conf``. + */ + filename: string; + /** + * Before + * @description Included file read before this one. + */ + before?: string | null; + /** + * After + * @description Included file read after this one. + */ + after?: string | null; + /** + * Variables + * @description Free-form ``[DEFAULT]`` section variables. + */ + variables?: { + [key: string]: string; + }; + /** + * Prefregex + * @description Prefix regex prepended to every failregex. + */ + prefregex?: string | null; + /** + * Failregex + * @description Failure detection regex patterns (one per list entry). + */ + failregex?: string[]; + /** + * Ignoreregex + * @description Regex patterns that bypass ban logic. + */ + ignoreregex?: string[]; + /** + * Maxlines + * @description Maximum number of log lines accumulated for a single match attempt. + */ + maxlines?: number | null; + /** + * Datepattern + * @description Custom date-parsing pattern, or ``None`` for auto-detect. + */ + datepattern?: string | null; + /** + * Journalmatch + * @description Systemd journal match expression. + */ + journalmatch?: string | null; + /** + * Active + * @description ``True`` when this filter is referenced by at least one currently enabled (running) jail. + * @default false + */ + active: boolean; + /** + * Used By Jails + * @description Names of currently enabled jails that reference this filter. Empty when ``active`` is ``False``. + */ + used_by_jails?: string[]; + /** + * Source File + * @description Absolute path to the ``.conf`` source file for this filter. + * @default + */ + source_file: string; + /** + * Has Local Override + * @description ``True`` when a ``.local`` override file exists alongside the base ``.conf`` file. + * @default false + */ + has_local_override: boolean; + }; + /** + * FilterConfigUpdate + * @description Partial update payload for a parsed filter file. + * + * Only explicitly set (non-``None``) fields are written back. + */ + FilterConfigUpdate: { + /** Before */ + before?: string | null; + /** After */ + after?: string | null; + /** Variables */ + variables?: { + [key: string]: string; + } | null; + /** Prefregex */ + prefregex?: string | null; + /** Failregex */ + failregex?: string[] | null; + /** Ignoreregex */ + ignoreregex?: string[] | null; + /** Maxlines */ + maxlines?: number | null; + /** Datepattern */ + datepattern?: string | null; + /** Journalmatch */ + journalmatch?: string | null; + }; + /** + * FilterCreateRequest + * @description Payload for ``POST /api/config/filters``. + * + * Creates a new user-defined filter at ``filter.d/{name}.local``. + */ + FilterCreateRequest: { + /** + * Name + * @description Filter base name (e.g. ``my-custom-filter``). Must not already exist in ``filter.d/``. + */ + name: string; + /** + * Failregex + * @description Failure-detection regex patterns. + */ + failregex?: string[]; + /** + * Ignoreregex + * @description Regex patterns that bypass ban logic. + */ + ignoreregex?: string[]; + /** + * Prefregex + * @description Prefix regex prepended to every failregex. + */ + prefregex?: string | null; + /** + * Datepattern + * @description Custom date-parsing pattern. + */ + datepattern?: string | null; + /** + * Journalmatch + * @description Systemd journal match expression. + */ + journalmatch?: string | null; + }; + /** + * FilterListResponse + * @description Response for ``GET /api/config/filters``. + */ + FilterListResponse: { + /** + * Filters + * @description All discovered filters, each annotated with active/inactive status and the jails that reference them. + */ + filters?: components["schemas"]["FilterConfig"][]; + /** + * Total + * @description Total number of filters found. + */ + total: number; + }; + /** + * FilterUpdateRequest + * @description Payload for ``PUT /api/config/filters/{name}``. + * + * Accepts only the user-editable ``[Definition]`` fields. Fields left as + * ``None`` are not changed; the existing value from the merged conf/local is + * preserved. + */ + FilterUpdateRequest: { + /** + * Failregex + * @description Updated failure-detection regex patterns. ``None`` = keep existing. + */ + failregex?: string[] | null; + /** + * Ignoreregex + * @description Updated bypass-ban regex patterns. ``None`` = keep existing. + */ + ignoreregex?: string[] | null; + /** + * Datepattern + * @description Custom date-parsing pattern. ``None`` = keep existing. + */ + datepattern?: string | null; + /** + * Journalmatch + * @description Systemd journal match expression. ``None`` = keep existing. + */ + journalmatch?: string | null; + }; + /** + * GeoCacheStatsResponse + * @description Response for ``GET /api/geo/stats``. + * + * Exposes diagnostic counters of the geo cache subsystem so operators + * can assess resolution health from the UI or CLI. + */ + GeoCacheStatsResponse: { + /** + * Cache Size + * @description Number of positive entries in the in-memory cache. + */ + cache_size: number; + /** + * Unresolved + * @description Number of geo_cache rows with country_code IS NULL. + */ + unresolved: number; + /** + * Neg Cache Size + * @description Number of entries in the in-memory negative cache. + */ + neg_cache_size: number; + /** + * Dirty Size + * @description Number of newly resolved entries not yet flushed to disk. + */ + dirty_size: number; + }; + /** + * GeoDetail + * @description Enriched geolocation data for an IP address. + * + * Populated from the ip-api.com free API. + */ + GeoDetail: { + /** + * Country Code + * @description ISO 3166-1 alpha-2 country code. + */ + country_code?: string | null; + /** + * Country Name + * @description Human-readable country name. + */ + country_name?: string | null; + /** + * Asn + * @description Autonomous System Number (e.g. ``'AS3320'``). + */ + asn?: string | null; + /** + * Org + * @description Organisation associated with the ASN. + */ + org?: string | null; + }; + /** + * GeoReResolveResponse + * @description Response for ``POST /api/geo/re-resolve``. + * + * Reports how many previously unresolved IPs were retried and how many + * gained a resolved country code after the re-resolve operation. + */ + GeoReResolveResponse: { + /** + * Resolved + * @description Number of IPs successfully resolved. + */ + resolved: number; + /** + * Total + * @description Number of IPs retried. + */ + total: number; + }; + /** + * GlobalConfigResponse + * @description Response for ``GET /api/config/global``. + */ + GlobalConfigResponse: { + /** + * Log Level + * @enum {string} + */ + log_level: "CRITICAL" | "ERROR" | "WARNING" | "NOTICE" | "INFO" | "DEBUG"; + /** + * Log Target + * @description Log target: STDOUT, STDERR, SYSLOG, or a validated file path. + */ + log_target: string; + /** + * Db Purge Age + * @description Seconds after which ban records are purged from the fail2ban DB. + */ + db_purge_age: number; + /** + * Db Max Matches + * @description Maximum stored log-line matches per ban record. + */ + db_max_matches: number; + }; + /** + * GlobalConfigUpdate + * @description Payload for ``PUT /api/config/global``. + */ + GlobalConfigUpdate: { + /** + * Log Level + * @description Log level: CRITICAL, ERROR, WARNING, NOTICE, INFO, or DEBUG. + */ + log_level?: ("CRITICAL" | "ERROR" | "WARNING" | "NOTICE" | "INFO" | "DEBUG") | null; + /** + * Log Target + * @description Log target: STDOUT, STDERR, SYSLOG, or a validated file path. + */ + log_target?: string | null; + /** Db Purge Age */ + db_purge_age?: number | null; + /** Db Max Matches */ + db_max_matches?: number | null; + }; + /** HTTPValidationError */ + HTTPValidationError: { + /** Detail */ + detail?: components["schemas"]["ValidationError"][]; + }; + /** + * HistoryBanItem + * @description A single row in the history ban-list table. + * + * Populated from the fail2ban database and optionally enriched with + * geolocation data. + */ + HistoryBanItem: { + /** + * Ip + * @description Banned IP address. + */ + ip: string; + /** + * Jail + * @description Jail that issued the ban. + */ + jail: string; + /** + * Banned At + * @description ISO 8601 UTC timestamp of the ban. + */ + banned_at: string; + /** + * Ban Count + * @description How many times this IP was banned. + */ + ban_count: number; + /** + * Failures + * @description Total failure count extracted from the ``data`` column. + * @default 0 + */ + failures: number; + /** + * Matches + * @description Matched log lines stored in the ``data`` column. + */ + matches?: string[]; + /** + * Country Code + * @description ISO 3166-1 alpha-2 country code, or ``null`` if unknown. + */ + country_code?: string | null; + /** + * Country Name + * @description Human-readable country name, or ``null`` if unknown. + */ + country_name?: string | null; + /** + * Asn + * @description Autonomous System Number string (e.g. ``'AS3320'``). + */ + asn?: string | null; + /** + * Org + * @description Organisation name associated with the IP. + */ + org?: string | null; + }; + /** + * HistoryListResponse + * @description Paginated history ban-list response. + * + * Request: ``GET /api/history`` with optional time-range, jail, IP, and + * origin filters plus pagination parameters. + * Response: Paginated collection of historical ban records with geolocation. + */ + HistoryListResponse: { + /** + * Items + * @description Data items for the current page. + */ + items?: components["schemas"]["HistoryBanItem"][]; + /** + * Total + * @description Total number of items matching the query. + */ + total: number; + /** + * Page + * @description Current page number (1-based). + */ + page: number; + /** + * Page Size + * @description Number of items per page. + */ + page_size: number; + }; + /** + * IgnoreIpRequest + * @description Payload for adding an IP or network to a jail's ignore list. + */ + IgnoreIpRequest: { + /** + * Ip + * @description IP address or CIDR network to ignore. + */ + ip: string; + }; + /** + * IgnoreListResponse + * @description Response for ``GET /api/jails/{name}/ignoreip``. + * + * Returns the jailed ignore list as a standard collection response. + */ + IgnoreListResponse: { + /** + * Items + * @description Collection items. + */ + items?: string[]; + /** + * Total + * @description Total number of items. + */ + total: number; + }; + /** + * ImportLogEntry + * @description A single blocklist import run record. + */ + ImportLogEntry: { + /** Id */ + id: number; + /** Source Id */ + source_id: number | null; + /** Source Url */ + source_url: string; + /** Timestamp */ + timestamp: string; + /** Ips Imported */ + ips_imported: number; + /** Ips Skipped */ + ips_skipped: number; + /** Errors */ + errors: string | null; + }; + /** + * ImportLogListResponse + * @description Response for ``GET /api/blocklists/log``. + * + * Paginated list of all blocklist import runs with timestamps, source info, + * and per-source import/skip counts. + */ + ImportLogListResponse: { + /** + * Items + * @description Data items for the current page. + */ + items?: components["schemas"]["ImportLogEntry"][]; + /** + * Total + * @description Total number of items matching the query. + */ + total: number; + /** + * Page + * @description Current page number (1-based). + */ + page: number; + /** + * Page Size + * @description Number of items per page. + */ + page_size: number; + }; + /** + * ImportRunResult + * @description Aggregated result from a full import run across all enabled sources. + */ + ImportRunResult: { + /** Results */ + results?: components["schemas"]["ImportSourceResult"][]; + /** Total Imported */ + total_imported: number; + /** Total Skipped */ + total_skipped: number; + /** Errors Count */ + errors_count: number; + }; + /** + * ImportSourceResult + * @description Result of importing a single blocklist source. + */ + ImportSourceResult: { + /** Source Id */ + source_id: number | null; + /** Source Url */ + source_url: string; + /** Ips Imported */ + ips_imported: number; + /** Ips Skipped */ + ips_skipped: number; + /** Error */ + error: string | null; + }; + /** + * InactiveJail + * @description A jail defined in fail2ban config files that is not currently active. + * + * A jail is considered inactive when its ``enabled`` key is ``false`` (or + * absent from the config, since fail2ban defaults to disabled) **or** when it + * is explicitly enabled in config but fail2ban is not reporting it as + * running. + */ + InactiveJail: { + /** + * Name + * @description Jail name from the config section header. + */ + name: string; + /** + * Filter + * @description Filter name used by this jail. May include fail2ban mode suffix, e.g. ``sshd[mode=normal]``. + */ + filter: string; + /** + * Actions + * @description Action references listed in the config (raw strings). + */ + actions?: string[]; + /** + * Port + * @description Port(s) to monitor, e.g. ``ssh`` or ``22,2222``. + */ + port?: string | null; + /** + * Logpath + * @description Log file paths to monitor. + */ + logpath?: string[]; + /** + * Bantime + * @description Ban duration as a raw config string, e.g. ``10m`` or ``-1``. + */ + bantime?: string | null; + /** + * Findtime + * @description Failure-counting window as a raw config string, e.g. ``10m``. + */ + findtime?: string | null; + /** + * Maxretry + * @description Number of failures before a ban is issued. + */ + maxretry?: number | null; + /** + * Ban Time Seconds + * @description Ban duration in seconds, parsed from bantime string. + * @default 600 + */ + ban_time_seconds: number; + /** + * Find Time Seconds + * @description Failure-counting window in seconds, parsed from findtime string. + * @default 600 + */ + find_time_seconds: number; + /** + * Log Encoding + * @description Log encoding, e.g. ``utf-8`` or ``auto``. + * @default auto + * @enum {string} + */ + log_encoding: "auto" | "ascii" | "utf-8" | "UTF-8" | "latin-1"; + /** + * Backend + * @description Log-monitoring backend, e.g. ``auto``, ``pyinotify``, ``polling``. + * @default auto + * @enum {string} + */ + backend: "auto" | "polling" | "pyinotify" | "systemd" | "gamin"; + /** + * Date Pattern + * @description Date pattern for log parsing, or None for auto-detect. + */ + date_pattern?: string | null; + /** + * Use Dns + * @description DNS resolution mode: ``yes``, ``warn``, ``no``, or ``raw``. + * @default warn + * @enum {string} + */ + use_dns: "yes" | "warn" | "no" | "raw"; + /** + * Prefregex + * @description Prefix regex prepended to every failregex. + * @default + */ + prefregex: string; + /** + * Fail Regex + * @description List of failure regex patterns. + */ + fail_regex?: string[]; + /** + * Ignore Regex + * @description List of ignore regex patterns. + */ + ignore_regex?: string[]; + /** @description Ban-time escalation configuration, if enabled. */ + bantime_escalation?: components["schemas"]["BantimeEscalation"] | null; + /** + * Source File + * @description Absolute path to the config file where this jail is defined. + */ + source_file: string; + /** + * Enabled + * @description Effective ``enabled`` value from the merged config. ``False`` for inactive jails that appear in this list. + */ + enabled: boolean; + /** + * Has Local Override + * @description ``True`` when a ``jail.d/{name}.local`` file exists for this jail. Only meaningful for inactive jails; indicates that a cleanup action is available. + * @default false + */ + has_local_override: boolean; + }; + /** + * InactiveJailListResponse + * @description Response for ``GET /api/config/jails/inactive``. + * + * Returns a non-paginated collection of inactive jail configurations. + */ + InactiveJailListResponse: { + /** + * Items + * @description Collection items. + */ + items?: components["schemas"]["InactiveJail"][]; + /** + * Total + * @description Total number of items. + */ + total: number; + }; + /** + * IpDetailResponse + * @description Full historical record for a single IP address. + * + * Contains aggregated totals and a chronological timeline of all ban events + * recorded in the fail2ban database for the given IP. + */ + IpDetailResponse: { + /** + * Ip + * @description The IP address. + */ + ip: string; + /** + * Total Bans + * @description Total number of ban records. + */ + total_bans: number; + /** + * Total Failures + * @description Sum of all failure counts across all ban events. + */ + total_failures: number; + /** + * Last Ban At + * @description ISO 8601 UTC timestamp of the most recent ban, or ``null``. + */ + last_ban_at?: string | null; + /** + * Country Code + * @description ISO 3166-1 alpha-2 country code, or ``null`` if unknown. + */ + country_code?: string | null; + /** + * Country Name + * @description Human-readable country name, or ``null`` if unknown. + */ + country_name?: string | null; + /** + * Asn + * @description Autonomous System Number string. + */ + asn?: string | null; + /** + * Org + * @description Organisation name associated with the IP. + */ + org?: string | null; + /** + * Timeline + * @description All ban events for this IP, ordered newest-first. + */ + timeline?: components["schemas"]["IpTimelineEvent"][]; + }; + /** + * IpLookupResponse + * @description Response for ``GET /api/geo/lookup/{ip}``. + * + * Aggregates current ban status and geographical information for an IP. + */ + IpLookupResponse: { + /** + * Ip + * @description The queried IP address. + */ + ip: string; + /** + * Currently Banned In + * @description Names of jails where this IP is currently banned. + */ + currently_banned_in?: string[]; + /** @description Enriched geographical and network information. */ + geo?: components["schemas"]["GeoDetail"] | null; + }; + /** + * IpTimelineEvent + * @description A single ban event in a per-IP timeline. + * + * Represents one row from the fail2ban ``bans`` table for a specific IP. + */ + IpTimelineEvent: { + /** + * Jail + * @description Jail that triggered this ban. + */ + jail: string; + /** + * Banned At + * @description ISO 8601 UTC timestamp of the ban. + */ + banned_at: string; + /** + * Ban Count + * @description Running ban counter for this IP at the time of this event. + */ + ban_count: number; + /** + * Failures + * @description Failure count at the time of the ban. + * @default 0 + */ + failures: number; + /** + * Matches + * @description Matched log lines that triggered the ban. + */ + matches?: string[]; + }; + /** + * Jail + * @description Domain model for a single fail2ban jail with its full configuration. + */ + Jail: { + /** + * Name + * @description Jail name as configured in fail2ban. + */ + name: string; + /** + * Enabled + * @description Whether the jail is currently active. + */ + enabled: boolean; + /** + * Running + * @description Whether the jail backend is running. + */ + running: boolean; + /** + * Idle + * @description Whether the jail is in idle mode. + * @default false + */ + idle: boolean; + /** + * Backend + * @description Log monitoring backend (e.g. polling, systemd). + */ + backend: string; + /** + * Log Paths + * @description Monitored log files. + */ + log_paths?: string[]; + /** + * Fail Regex + * @description Failure detection regex patterns. + */ + fail_regex?: string[]; + /** + * Ignore Regex + * @description Regex patterns that bypass the ban logic. + */ + ignore_regex?: string[]; + /** + * Ignore Ips + * @description IP addresses or CIDRs on the ignore list. + */ + ignore_ips?: string[]; + /** + * Date Pattern + * @description Custom date pattern for log parsing. + */ + date_pattern?: string | null; + /** + * Log Encoding + * @description Log file encoding. + * @default UTF-8 + */ + log_encoding: string; + /** + * Find Time + * @description Time window (seconds) for counting failures. + */ + find_time: number; + /** + * Ban Time + * @description Duration (seconds) of a ban. -1 means permanent. + */ + ban_time: number; + /** + * Max Retry + * @description Number of failures before a ban is issued. + */ + max_retry: number; + /** + * Actions + * @description Names of actions attached to this jail. + */ + actions?: string[]; + /** @description Incremental ban-time escalation settings, or None if not configured. */ + bantime_escalation?: components["schemas"]["BantimeEscalation"] | null; + /** @description Runtime counters. */ + status?: components["schemas"]["JailStatus"] | null; + }; + /** + * JailActivationResponse + * @description Response for jail activation and deactivation endpoints. + */ + JailActivationResponse: { + /** + * Name + * @description Name of the affected jail. + */ + name: string; + /** + * Active + * @description New activation state: ``True`` after activate, ``False`` after deactivate. + */ + active: boolean; + /** + * Message + * @description Human-readable result message. + */ + message: string; + /** + * Fail2Ban Running + * @description Whether the fail2ban daemon is still running after the activation and reload. ``False`` signals that the daemon may have crashed. + * @default true + */ + fail2ban_running: boolean; + /** + * Validation Warnings + * @description Non-fatal warnings from the pre-activation validation step. + */ + validation_warnings?: string[]; + /** + * Recovered + * @description Set when activation failed after writing the config file. ``True`` means the system automatically rolled back the change and restarted fail2ban. ``False`` means the rollback itself also failed and manual intervention is required. ``None`` when activation succeeded or failed before the file was written. + */ + recovered?: boolean | null; + }; + /** + * JailBanCount + * @description A single jail entry in the bans-by-jail aggregation. + */ + JailBanCount: { + /** + * Jail + * @description Jail name. + */ + jail: string; + /** + * Count + * @description Number of bans recorded in this jail. + */ + count: number; + }; + /** + * JailBannedIpsResponse + * @description Paginated response for ``GET /api/jails/{name}/banned``. + * + * Contains only the current page of active ban entries for a single jail, + * geo-enriched exclusively for the page slice to avoid rate-limit issues. + * + * Request: `GET /api/jails/{name}/banned` with page and page_size parameters. + * Response: Paginated collection of active bans for the specified jail. + */ + JailBannedIpsResponse: { + /** + * Items + * @description Data items for the current page. + */ + items?: components["schemas"]["ActiveBan"][]; + /** + * Total + * @description Total number of items matching the query. + */ + total: number; + /** + * Page + * @description Current page number (1-based). + */ + page: number; + /** + * Page Size + * @description Number of items per page. + */ + page_size: number; + }; + /** + * JailCommandResponse + * @description Generic response for jail control commands (start, stop, reload, idle). + * + * Extends the base CommandResponse with a jail field to identify the target. + */ + JailCommandResponse: { + /** + * Message + * @description Human-readable result or error message. + */ + message: string; + /** + * Success + * @description Whether the command succeeded (false for errors in non-exception handlers). + * @default true + */ + success: boolean; + /** + * Jail + * @description Target jail name, or '*' for operations on all jails. + */ + jail: string; + }; + /** + * JailConfig + * @description Configuration snapshot of a single jail (editable fields). + */ + JailConfig: { + /** + * Name + * @description Jail name as configured in fail2ban. + */ + name: string; + /** + * Ban Time + * @description Ban duration in seconds. -1 for permanent. + */ + ban_time: number; + /** + * Max Retry + * @description Number of failures before a ban is issued. + */ + max_retry: number; + /** + * Find Time + * @description Time window (seconds) for counting failures. + */ + find_time: number; + /** + * Fail Regex + * @description Failure detection regex patterns. + */ + fail_regex?: string[]; + /** + * Ignore Regex + * @description Regex patterns that bypass the ban logic. + */ + ignore_regex?: string[]; + /** + * Log Paths + * @description Monitored log files. + */ + log_paths?: string[]; + /** + * Date Pattern + * @description Custom date pattern for log parsing. + */ + date_pattern?: string | null; + /** + * Log Encoding + * @description Log file encoding. + * @default UTF-8 + * @enum {string} + */ + log_encoding: "auto" | "ascii" | "utf-8" | "UTF-8" | "latin-1"; + /** + * Backend + * @description Log monitoring backend. + * @default polling + * @enum {string} + */ + backend: "auto" | "polling" | "pyinotify" | "systemd" | "gamin"; + /** + * Use Dns + * @description DNS lookup mode: yes | warn | no | raw. + * @default warn + * @enum {string} + */ + use_dns: "yes" | "warn" | "no" | "raw"; + /** + * Prefregex + * @description Prefix regex prepended to every failregex; empty means disabled. + * @default + */ + prefregex: string; + /** + * Actions + * @description Names of actions attached to this jail. + */ + actions?: string[]; + /** @description Incremental ban-time escalation settings, or None if not configured. */ + bantime_escalation?: components["schemas"]["BantimeEscalation"] | null; + }; + /** + * JailConfigFile + * @description Metadata for a single jail configuration file in ``jail.d/``. + */ + JailConfigFile: { + /** + * Name + * @description Jail name (file stem, e.g. ``sshd``). + */ + name: string; + /** + * Filename + * @description Actual filename (e.g. ``sshd.conf``). + */ + filename: string; + /** + * Enabled + * @description Whether the jail is enabled. Derived from the ``enabled`` key inside the file; defaults to ``true`` when the key is absent. + */ + enabled: boolean; + }; + /** + * JailConfigFileContent + * @description Single jail config file with its raw content. + */ + JailConfigFileContent: { + /** + * Name + * @description Jail name (file stem). + */ + name: string; + /** + * Filename + * @description Actual filename. + */ + filename: string; + /** + * Enabled + * @description Whether the jail is enabled. + */ + enabled: boolean; + /** + * Content + * @description Raw file content. + */ + content: string; + }; + /** + * JailConfigFileEnabledUpdate + * @description Payload for ``PUT /api/config/jail-files/{filename}/enabled``. + */ + JailConfigFileEnabledUpdate: { + /** + * Enabled + * @description New enabled state for this jail. + */ + enabled: boolean; + }; + /** + * JailConfigFilesResponse + * @description Response for ``GET /api/config/jail-files``. + */ + JailConfigFilesResponse: { + /** Files */ + files?: components["schemas"]["JailConfigFile"][]; + /** Total */ + total: number; + }; + /** + * JailConfigListResponse + * @description Response for ``GET /api/config/jails``. + * + * Returns a non-paginated collection of jail configurations. + */ + JailConfigListResponse: { + /** + * Items + * @description Collection items. + */ + items?: components["schemas"]["JailConfig"][]; + /** + * Total + * @description Total number of items. + */ + total: number; + }; + /** + * JailConfigResponse + * @description Response for ``GET /api/config/jails/{name}``. + */ + JailConfigResponse: { + jail: components["schemas"]["JailConfig"]; + }; + /** + * JailConfigUpdate + * @description Payload for ``PUT /api/config/jails/{name}``. + */ + JailConfigUpdate: { + /** + * Ban Time + * @description Ban duration in seconds. -1 for permanent. + */ + ban_time?: number | null; + /** Max Retry */ + max_retry?: number | null; + /** Find Time */ + find_time?: number | null; + /** + * Fail Regex + * @description Failure detection regex patterns. + */ + fail_regex?: string[] | null; + /** Ignore Regex */ + ignore_regex?: string[] | null; + /** + * Prefregex + * @description Prefix regex; None = skip, '' = clear, non-empty = set. + */ + prefregex?: string | null; + /** Date Pattern */ + date_pattern?: string | null; + /** + * Dns Mode + * @description DNS lookup mode: yes | warn | no | raw. + */ + dns_mode?: ("yes" | "warn" | "no" | "raw") | null; + /** + * Backend + * @description Log monitoring backend. + */ + backend?: ("auto" | "polling" | "pyinotify" | "systemd" | "gamin") | null; + /** + * Log Encoding + * @description Log file encoding. + */ + log_encoding?: ("auto" | "ascii" | "utf-8" | "UTF-8" | "latin-1") | null; + /** Enabled */ + enabled?: boolean | null; + /** @description Incremental ban-time escalation settings to update. */ + bantime_escalation?: components["schemas"]["BantimeEscalationUpdate"] | null; + }; + /** + * JailDetailResponse + * @description Response for ``GET /api/jails/{name}``. + * + * Includes the primary jail object together with supplemental metadata + * required by the UI. + */ + JailDetailResponse: { + jail: components["schemas"]["Jail"]; + /** + * Ignore List + * @description List of IP addresses and networks currently ignored by the jail. + */ + ignore_list?: string[]; + /** + * Ignore Self + * @description Whether the jail ignores the server's own IP addresses. + * @default false + */ + ignore_self: boolean; + }; + /** + * JailFileConfig + * @description Structured representation of a jail.d/*.conf file. + */ + JailFileConfig: { + /** + * Filename + * @description Filename including extension (e.g. 'sshd.conf'). + */ + filename: string; + /** + * Jails + * @description Mapping of jail name → settings for each [section] in the file. + */ + jails?: { + [key: string]: components["schemas"]["JailSectionConfig"]; + }; + }; + /** + * JailFileConfigUpdate + * @description Partial update payload for a jail.d file. + */ + JailFileConfigUpdate: { + /** + * Jails + * @description Jail section updates. Only jails present in this dict are updated. + */ + jails?: { + [key: string]: components["schemas"]["JailSectionConfig"]; + } | null; + }; + /** + * JailListResponse + * @description Response for ``GET /api/jails``. + * + * Returns a non-paginated collection of jail summaries with their current status. + */ + JailListResponse: { + /** + * Items + * @description Collection items. + */ + items?: components["schemas"]["JailSummary"][]; + /** + * Total + * @description Total number of items. + */ + total: number; + }; + /** + * JailSectionConfig + * @description Settings within a single [jailname] section of a jail.d file. + */ + JailSectionConfig: { + /** + * Enabled + * @description Whether this jail is enabled. + */ + enabled?: boolean | null; + /** + * Port + * @description Port(s) to monitor (e.g. 'ssh' or '22,2222'). + */ + port?: string | null; + /** + * Filter + * @description Filter name to use (e.g. 'sshd'). + */ + filter?: string | null; + /** + * Logpath + * @description Log file paths to monitor. + */ + logpath?: string[]; + /** + * Maxretry + * @description Failures before banning. + */ + maxretry?: number | null; + /** + * Findtime + * @description Time window in seconds for counting failures. + */ + findtime?: number | null; + /** + * Bantime + * @description Ban duration in seconds. -1 for permanent. + */ + bantime?: number | null; + /** + * Action + * @description Action references. + */ + action?: string[]; + /** + * Backend + * @description Log monitoring backend. + */ + backend?: ("auto" | "polling" | "pyinotify" | "systemd" | "gamin") | null; + /** + * Extra + * @description Additional settings not captured by named fields. + */ + extra?: { + [key: string]: string; + }; + }; + /** + * JailStatus + * @description Runtime metrics for a single jail. + */ + JailStatus: { + /** Currently Banned */ + currently_banned: number; + /** Total Banned */ + total_banned: number; + /** Currently Failed */ + currently_failed: number; + /** Total Failed */ + total_failed: number; + }; + /** + * JailSummary + * @description Lightweight jail entry for the overview list. + */ + JailSummary: { + /** Name */ + name: string; + /** Enabled */ + enabled: boolean; + /** Running */ + running: boolean; + /** Idle */ + idle: boolean; + /** Backend */ + backend: string; + /** Find Time */ + find_time: number; + /** Ban Time */ + ban_time: number; + /** Max Retry */ + max_retry: number; + status?: components["schemas"]["JailStatus"] | null; + }; + /** + * JailValidationIssue + * @description A single issue found during pre-activation validation of a jail config. + */ + JailValidationIssue: { + /** + * Field + * @description Config field associated with this issue, e.g. 'filter', 'failregex', 'logpath'. + */ + field: string; + /** + * Message + * @description Human-readable description of the issue. + */ + message: string; + }; + /** + * JailValidationResult + * @description Result of pre-activation validation of a single jail configuration. + */ + JailValidationResult: { + /** + * Jail Name + * @description Name of the validated jail. + */ + jail_name: string; + /** + * Valid + * @description True when no issues were found. + */ + valid: boolean; + /** + * Issues + * @description Validation issues found. Empty when valid=True. + */ + issues?: components["schemas"]["JailValidationIssue"][]; + }; + /** + * LogPreviewLine + * @description A single log line with match information. + */ + LogPreviewLine: { + /** Line */ + line: string; + /** Matched */ + matched: boolean; + /** Groups */ + groups?: string[]; + }; + /** + * LogPreviewRequest + * @description Payload for ``POST /api/config/preview-log``. + */ + LogPreviewRequest: { + /** + * Log Path + * @description Absolute path to the log file to preview. + */ + log_path: string; + /** + * Fail Regex + * @description Regex pattern to test against log lines. + */ + fail_regex: string; + /** + * Num Lines + * @description Number of lines to read from the end of the file. + * @default 200 + */ + num_lines: number; + }; + /** + * LogPreviewResponse + * @description Response for ``POST /api/config/preview-log``. + */ + LogPreviewResponse: { + /** Lines */ + lines?: components["schemas"]["LogPreviewLine"][]; + /** Total Lines */ + total_lines: number; + /** Matched Count */ + matched_count: number; + /** + * Regex Error + * @description Set if the regex failed to compile. + */ + regex_error?: string | null; + }; + /** + * LoginRequest + * @description Payload for ``POST /api/auth/login``. + */ + LoginRequest: { + /** + * Password + * @description Master password to authenticate with (max 72 bytes due to bcrypt truncation). + */ + password: string; + }; + /** + * LoginResponse + * @description Successful login response. + * + * The session token is set as an ``HttpOnly`` ``SameSite=Lax`` cookie by the + * router, protecting it from JavaScript access. The JSON body contains only + * the expiry timestamp, allowing the frontend to know when to prompt for + * re-authentication. + * + * For programmatic API clients that require a token in the response body, + * use ``POST /api/auth/token`` instead, which does not set a cookie. + */ + LoginResponse: { + /** + * Expires At + * @description ISO 8601 UTC expiry timestamp. + */ + expires_at: string; + }; + /** + * LogoutResponse + * @description Response body for ``POST /api/auth/logout``. + */ + LogoutResponse: { + /** + * Message + * @default Logged out successfully. + */ + message: string; + }; + /** + * MapColorThresholdsResponse + * @description Response for ``GET /api/config/map-thresholds``. + */ + MapColorThresholdsResponse: { + /** + * Threshold High + * @description Ban count for red coloring. + */ + threshold_high: number; + /** + * Threshold Medium + * @description Ban count for yellow coloring. + */ + threshold_medium: number; + /** + * Threshold Low + * @description Ban count for green coloring. + */ + threshold_low: number; + }; + /** + * MapColorThresholdsUpdate + * @description Payload for ``PUT /api/config/map-thresholds``. + */ + MapColorThresholdsUpdate: { + /** + * Threshold High + * @description Ban count for red. + */ + threshold_high: number; + /** + * Threshold Medium + * @description Ban count for yellow. + */ + threshold_medium: number; + /** + * Threshold Low + * @description Ban count for green. + */ + threshold_low: number; + }; + /** + * PendingRecovery + * @description Records a probable activation-caused fail2ban crash pending user action. + */ + PendingRecovery: { + /** + * Jail Name + * @description Name of the jail whose activation likely caused the crash. + */ + jail_name: string; + /** + * Activated At + * Format: date-time + * @description ISO-8601 UTC timestamp of when the jail was activated. + */ + activated_at: string; + /** + * Detected At + * Format: date-time + * @description ISO-8601 UTC timestamp of when the crash was detected. + */ + detected_at: string; + /** + * Recovered + * @description Whether fail2ban has been successfully restarted. + * @default false + */ + recovered: boolean; + }; + /** + * PreviewResponse + * @description Response for ``GET /api/blocklists/{id}/preview``. + */ + PreviewResponse: { + /** + * Entries + * @description Sample of valid IP entries + */ + entries?: string[]; + /** Total Lines */ + total_lines: number; + /** Valid Count */ + valid_count: number; + /** Skipped Count */ + skipped_count: number; + }; + /** + * RegexTestRequest + * @description Payload for ``POST /api/config/regex-test``. + */ + RegexTestRequest: { + /** + * Log Line + * @description Sample log line to test against. + */ + log_line: string; + /** + * Fail Regex + * @description Regex pattern to match. + */ + fail_regex: string; + }; + /** + * RegexTestResponse + * @description Result of a regex test. + */ + RegexTestResponse: { + /** + * Matched + * @description Whether the pattern matched the log line. + */ + matched: boolean; + /** + * Groups + * @description Named groups captured by a successful match. + */ + groups?: string[]; + /** + * Error + * @description Compilation error message if the regex is invalid. + */ + error?: string | null; + }; + /** + * RollbackResponse + * @description Response for ``POST /api/config/jails/{name}/rollback``. + */ + RollbackResponse: { + /** + * Jail Name + * @description Name of the jail that was disabled. + */ + jail_name: string; + /** + * Disabled + * @description Whether the jail's .local override was successfully written with enabled=false. + */ + disabled: boolean; + /** + * Fail2Ban Running + * @description Whether fail2ban is online after the rollback attempt. + */ + fail2ban_running: boolean; + /** + * Active Jails + * @description Number of currently active jails after a successful restart. + * @default 0 + */ + active_jails: number; + /** + * Message + * @description Human-readable result message. + */ + message: string; + }; + /** + * ScheduleConfig + * @description Import schedule configuration. + * + * The interpretation of fields depends on *frequency*: + * + * - ``hourly``: ``interval_hours`` controls how often (every N hours). + * - ``daily``: ``hour`` and ``minute`` specify the daily run time (UTC). + * - ``weekly``: additionally uses ``day_of_week`` (0=Monday … 6=Sunday). + */ + ScheduleConfig: { + /** @default daily */ + frequency: components["schemas"]["ScheduleFrequency"]; + /** + * Interval Hours + * @description Used when frequency=hourly + * @default 24 + */ + interval_hours: number; + /** + * Hour + * @description UTC hour for daily/weekly runs + * @default 3 + */ + hour: number; + /** + * Minute + * @description Minute for daily/weekly runs + * @default 0 + */ + minute: number; + /** + * Day Of Week + * @description Day of week for weekly runs (0=Monday … 6=Sunday) + * @default 0 + */ + day_of_week: number; + }; + /** + * ScheduleFrequency + * @description Available import schedule frequency presets. + * @enum {string} + */ + ScheduleFrequency: "hourly" | "daily" | "weekly"; + /** + * ScheduleInfo + * @description Current schedule configuration together with runtime metadata. + */ + ScheduleInfo: { + config: components["schemas"]["ScheduleConfig"]; + /** Next Run At */ + next_run_at: string | null; + /** Last Run At */ + last_run_at: string | null; + /** Last Run Errors */ + last_run_errors?: boolean | null; + }; + /** + * ServerSettings + * @description Domain model for fail2ban server-level settings. + */ + ServerSettings: { + /** + * Log Level + * @description fail2ban daemon log level. + */ + log_level: string; + /** + * Log Target + * @description Log destination: STDOUT, STDERR, SYSLOG, or a file path. + */ + log_target: string; + /** Syslog Socket */ + syslog_socket?: string | null; + /** + * Db Path + * @description Path to the fail2ban ban history database. + */ + db_path: string; + /** + * Db Purge Age + * @description Seconds before old records are purged. + */ + db_purge_age: number; + /** + * Db Max Matches + * @description Maximum stored matches per ban record. + */ + db_max_matches: number; + }; + /** + * ServerSettingsResponse + * @description Response for ``GET /api/server/settings``. + */ + ServerSettingsResponse: { + settings: components["schemas"]["ServerSettings"]; + /** + * Warnings + * @description Warnings highlighting potentially unsafe settings. + */ + warnings?: { + [key: string]: boolean; + }; + }; + /** + * ServerSettingsUpdate + * @description Payload for ``PUT /api/server/settings``. + */ + ServerSettingsUpdate: { + /** Log Level */ + log_level?: string | null; + /** Log Target */ + log_target?: string | null; + /** Db Purge Age */ + db_purge_age?: number | null; + /** Db Max Matches */ + db_max_matches?: number | null; + }; + /** + * ServerStatus + * @description Cached fail2ban server health snapshot. + */ + ServerStatus: { + /** + * Online + * @description Whether fail2ban is reachable via its socket. + */ + online: boolean; + /** + * Version + * @description fail2ban version string. + */ + version?: string | null; + /** + * Active Jails + * @description Number of currently active jails. + * @default 0 + */ + active_jails: number; + /** + * Total Bans + * @description Aggregated current ban count across all jails. + * @default 0 + */ + total_bans: number; + /** + * Total Failures + * @description Aggregated current failure count across all jails. + * @default 0 + */ + total_failures: number; + }; + /** + * ServerStatusResponse + * @description Response for ``GET /api/dashboard/status``. + */ + ServerStatusResponse: { + status: components["schemas"]["ServerStatus"]; + }; + /** + * ServiceStatusResponse + * @description Response for ``GET /api/config/service-status``. + */ + ServiceStatusResponse: { + /** + * Online + * @description Whether fail2ban is reachable via its socket. + */ + online: boolean; + /** + * Version + * @description BanGUI application version (or None when offline). + */ + version?: string | null; + /** + * Jail Count + * @description Number of currently active jails. + * @default 0 + */ + jail_count: number; + /** + * Total Bans + * @description Aggregated current ban count across all jails. + * @default 0 + */ + total_bans: number; + /** + * Total Failures + * @description Aggregated current failure count across all jails. + * @default 0 + */ + total_failures: number; + /** + * Log Level + * @description Current fail2ban log level. + * @default UNKNOWN + */ + log_level: string; + /** + * Log Target + * @description Current fail2ban log target. + * @default UNKNOWN + */ + log_target: string; + }; + /** + * SetupRequest + * @description Payload for ``POST /api/setup``. + */ + SetupRequest: { + /** + * Master Password + * @description Master password that protects the BanGUI interface (max 72 bytes due to bcrypt truncation). + */ + master_password: string; + /** + * Database Path + * @description Filesystem path to the BanGUI SQLite application database. + * @default bangui.db + */ + database_path: string; + /** + * Fail2Ban Socket + * @description Path to the fail2ban Unix domain socket. + * @default /var/run/fail2ban/fail2ban.sock + */ + fail2ban_socket: string; + /** + * Timezone + * @description IANA timezone name used when displaying timestamps. + * @default UTC + */ + timezone: string; + /** + * Session Duration Minutes + * @description Number of minutes a user session remains valid. + * @default 60 + */ + session_duration_minutes: number; + }; + /** + * SetupResponse + * @description Response returned after a successful initial setup. + */ + SetupResponse: { + /** + * Message + * @default Setup completed successfully. Please log in. + */ + message: string; + }; + /** + * SetupStatusResponse + * @description Response indicating whether setup has been completed. + */ + SetupStatusResponse: { + /** + * Completed + * @description ``True`` if the initial setup has already been performed. + */ + completed: boolean; + }; + /** + * SetupTimezoneResponse + * @description Response for ``GET /api/setup/timezone``. + */ + SetupTimezoneResponse: { + /** + * Timezone + * @description Configured IANA timezone identifier. + */ + timezone: string; + }; + /** + * UnbanAllResponse + * @description Response for ``DELETE /api/bans/all``. + */ + UnbanAllResponse: { + /** + * Message + * @description Human-readable summary of the operation. + */ + message: string; + /** + * Count + * @description Number of IPs that were unbanned. + */ + count: number; + }; + /** + * UnbanRequest + * @description Payload for ``DELETE /api/bans`` (unban an IP). + */ + UnbanRequest: { + /** + * Ip + * @description IP address to unban. + */ + ip: string; + /** + * Jail + * @description Jail to remove the ban from. ``null`` means all jails. + */ + jail?: string | null; + /** + * Unban All + * @description When ``true`` the IP is unbanned from every jail. + * @default false + */ + unban_all: boolean; + }; + /** ValidationError */ + ValidationError: { + /** Location */ + loc: (string | number)[]; + /** Message */ + msg: string; + /** Error Type */ + type: string; + /** Input */ + input?: unknown; + /** Context */ + ctx?: Record; + }; + }; + responses: never; + parameters: never; + requestBodies: never; + headers: never; + pathItems: never; +} +export type $defs = Record; +export interface operations { + health_check_api_health_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": unknown; + }; + }; + }; + }; + get_setup_status_api_setup_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["SetupStatusResponse"]; + }; + }; + }; + }; + post_setup_api_setup_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["SetupRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["SetupResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_timezone_api_setup_timezone_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["SetupTimezoneResponse"]; + }; + }; + }; + }; + login_api_auth_login_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["LoginRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["LoginResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + validate_session_api_auth_session_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + [key: string]: boolean; + }; + }; + }; + }; + }; + logout_api_auth_logout_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["LogoutResponse"]; + }; + }; + }; + }; + get_server_status_api_dashboard_status_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ServerStatusResponse"]; + }; + }; + }; + }; + get_dashboard_bans_api_dashboard_bans_get: { + parameters: { + query?: { + /** @description Time-range preset. */ + range?: "24h" | "7d" | "30d" | "365d"; + /** @description Data source: 'fail2ban' or 'archive'. */ + source?: "fail2ban" | "archive"; + /** @description 1-based page number. */ + page?: number; + /** @description Items per page. */ + page_size?: number; + /** @description Filter by ban origin: 'blocklist' or 'selfblock'. Omit for all. */ + origin?: ("blocklist" | "selfblock") | null; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DashboardBanListResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_bans_by_country_api_dashboard_bans_by_country_get: { + parameters: { + query?: { + /** @description Time-range preset. */ + range?: "24h" | "7d" | "30d" | "365d"; + /** @description Data source: 'fail2ban' or 'archive'. */ + source?: "fail2ban" | "archive"; + /** @description Filter by ban origin: 'blocklist' or 'selfblock'. Omit for all. */ + origin?: ("blocklist" | "selfblock") | null; + /** @description ISO alpha-2 country code to filter companion rows. */ + country_code?: string | null; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["BansByCountryResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_ban_trend_api_dashboard_bans_trend_get: { + parameters: { + query?: { + /** @description Time-range preset. */ + range?: "24h" | "7d" | "30d" | "365d"; + /** @description Data source: 'fail2ban' or 'archive'. */ + source?: "fail2ban" | "archive"; + /** @description Filter by ban origin: 'blocklist' or 'selfblock'. Omit for all. */ + origin?: ("blocklist" | "selfblock") | null; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["BanTrendResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_bans_by_jail_api_dashboard_bans_by_jail_get: { + parameters: { + query?: { + /** @description Time-range preset. */ + range?: "24h" | "7d" | "30d" | "365d"; + /** @description Data source: 'fail2ban' or 'archive'. */ + source?: "fail2ban" | "archive"; + /** @description Filter by ban origin: 'blocklist' or 'selfblock'. Omit for all. */ + origin?: ("blocklist" | "selfblock") | null; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["BansByJailResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_jails_api_jails_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["JailListResponse"]; + }; + }; + }; + }; + get_jail_api_jails__name__get: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Jail name as configured in fail2ban. */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["JailDetailResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + reload_all_jails_api_jails_reload_all_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["JailCommandResponse"]; + }; + }; + }; + }; + start_jail_api_jails__name__start_post: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Jail name as configured in fail2ban. */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["JailCommandResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + stop_jail_api_jails__name__stop_post: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Jail name as configured in fail2ban. */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["JailCommandResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + toggle_idle_api_jails__name__idle_post: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Jail name as configured in fail2ban. */ + name: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": boolean; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["JailCommandResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + reload_jail_api_jails__name__reload_post: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Jail name as configured in fail2ban. */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["JailCommandResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_ignore_list_api_jails__name__ignoreip_get: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Jail name as configured in fail2ban. */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["IgnoreListResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + add_ignore_ip_api_jails__name__ignoreip_post: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Jail name as configured in fail2ban. */ + name: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["IgnoreIpRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["JailCommandResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + del_ignore_ip_api_jails__name__ignoreip_delete: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Jail name as configured in fail2ban. */ + name: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["IgnoreIpRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["JailCommandResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + toggle_ignore_self_api_jails__name__ignoreself_post: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Jail name as configured in fail2ban. */ + name: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": boolean; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["JailCommandResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_jail_banned_ips_api_jails__name__banned_get: { + parameters: { + query?: { + page?: number; + page_size?: number; + search?: string | null; + }; + header?: never; + path: { + /** @description Jail name as configured in fail2ban. */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["JailBannedIpsResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_active_bans_api_bans_active_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ActiveBanListResponse"]; + }; + }; + }; + }; + ban_ip_api_bans_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["BanRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["JailCommandResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + unban_ip_api_bans_delete: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UnbanRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["JailCommandResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + unban_all_api_bans_all_delete: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["UnbanAllResponse"]; + }; + }; + }; + }; + lookup_ip_api_geo_lookup__ip__get: { + parameters: { + query?: never; + header?: never; + path: { + /** @description IPv4 or IPv6 address to look up. */ + ip: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["IpLookupResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + geo_stats_api_geo_stats_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["GeoCacheStatsResponse"]; + }; + }; + }; + }; + re_resolve_geo_api_geo_re_resolve_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["GeoReResolveResponse"]; + }; + }; + }; + }; + get_jail_configs_api_config_jails_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["JailConfigListResponse"]; + }; + }; + }; + }; + get_inactive_jails_api_config_jails_inactive_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["InactiveJailListResponse"]; + }; + }; + }; + }; + get_pending_recovery_api_config_jails_pending_recovery_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PendingRecovery"] | null; + }; + }; + }; + }; + get_jail_config_api_config_jails__name__get: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Jail name as configured in fail2ban. */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["JailConfigResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + update_jail_config_api_config_jails__name__put: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Jail name as configured in fail2ban. */ + name: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["JailConfigUpdate"]; + }; + }; + responses: { + /** @description Successful Response */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + add_log_path_api_config_jails__name__logpath_post: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Jail name as configured in fail2ban. */ + name: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["AddLogPathRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + delete_log_path_api_config_jails__name__logpath_delete: { + parameters: { + query: { + /** @description Absolute path of the log file to stop monitoring. */ + log_path: string; + }; + header?: never; + path: { + /** @description Jail name as configured in fail2ban. */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + activate_jail_api_config_jails__name__activate_post: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Jail name as configured in fail2ban. */ + name: string; + }; + cookie?: never; + }; + requestBody?: { + content: { + "application/json": components["schemas"]["ActivateJailRequest"] | null; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["JailActivationResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + deactivate_jail_api_config_jails__name__deactivate_post: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Jail name as configured in fail2ban. */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["JailActivationResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + delete_jail_local_override_api_config_jails__name__local_delete: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Jail name as configured in fail2ban. */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + validate_jail_api_config_jails__name__validate_post: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Jail name as configured in fail2ban. */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["JailValidationResult"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + rollback_jail_api_config_jails__name__rollback_post: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Jail name as configured in fail2ban. */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["RollbackResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + assign_filter_to_jail_api_config_jails__name__filter_post: { + parameters: { + query?: { + /** @description Reload fail2ban after assigning. */ + reload?: boolean; + }; + header?: never; + path: { + /** @description Jail name as configured in fail2ban. */ + name: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["AssignFilterRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + assign_action_to_jail_api_config_jails__name__action_post: { + parameters: { + query?: { + /** @description Reload fail2ban after assigning. */ + reload?: boolean; + }; + header?: never; + path: { + /** @description Jail name as configured in fail2ban. */ + name: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["AssignActionRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + remove_action_from_jail_api_config_jails__name__action__action_name__delete: { + parameters: { + query?: { + /** @description Reload fail2ban after removing. */ + reload?: boolean; + }; + header?: never; + path: { + /** @description Jail name as configured in fail2ban. */ + name: string; + /** @description Action base name to remove. */ + action_name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + list_filters_api_config_filters_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["FilterListResponse"]; + }; + }; + }; + }; + create_filter_api_config_filters_post: { + parameters: { + query?: { + /** @description Reload fail2ban after creating. */ + reload?: boolean; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["FilterCreateRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["FilterConfig"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_filter_api_config_filters__name__get: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Filter base name, e.g. ``sshd`` or ``sshd.conf``. */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["FilterConfig"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + update_filter_api_config_filters__name__put: { + parameters: { + query?: { + /** @description Reload fail2ban after writing. */ + reload?: boolean; + }; + header?: never; + path: { + /** @description Filter base name, e.g. ``sshd`` or ``sshd.conf``. */ + name: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["FilterUpdateRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["FilterConfig"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + delete_filter_api_config_filters__name__delete: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Filter base name, e.g. ``sshd`` or ``sshd.conf``. */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + list_action_files_api_config_actions_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ConfFilesResponse"]; + }; + }; + }; + }; + create_action_file_api_config_actions_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ConfFileCreateRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ConfFileContent"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_action_api_config_actions__name__get: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Action base name, e.g. ``iptables`` or ``iptables.conf``. */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ActionConfig"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + update_action_api_config_actions__name__put: { + parameters: { + query?: { + /** @description Reload fail2ban after writing. */ + reload?: boolean; + }; + header?: never; + path: { + /** @description Action base name, e.g. ``iptables`` or ``iptables.conf``. */ + name: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ActionUpdateRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ActionConfig"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + delete_action_api_config_actions__name__delete: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Action base name, e.g. ``iptables`` or ``iptables.conf``. */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_global_config_api_config_global_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["GlobalConfigResponse"]; + }; + }; + }; + }; + update_global_config_api_config_global_put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["GlobalConfigUpdate"]; + }; + }; + responses: { + /** @description Successful Response */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + reload_fail2ban_api_config_reload_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + restart_fail2ban_api_config_restart_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + regex_test_api_config_regex_test_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["RegexTestRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["RegexTestResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + preview_log_api_config_preview_log_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["LogPreviewRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["LogPreviewResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_map_color_thresholds_api_config_map_color_thresholds_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["MapColorThresholdsResponse"]; + }; + }; + }; + }; + update_map_color_thresholds_api_config_map_color_thresholds_put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["MapColorThresholdsUpdate"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["MapColorThresholdsResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_fail2ban_log_api_config_fail2ban_log_get: { + parameters: { + query?: { + /** @description Number of lines to return from the tail. */ + lines?: number; + /** @description Plain-text substring filter; only matching lines are returned. */ + filter?: string | null; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Fail2BanLogResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_service_status_api_config_service_status_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ServiceStatusResponse"]; + }; + }; + }; + }; + list_jail_config_files_api_config_jail_files_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["JailConfigFilesResponse"]; + }; + }; + }; + }; + create_jail_config_file_api_config_jail_files_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ConfFileCreateRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ConfFileContent"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_jail_config_file_api_config_jail_files__filename__get: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Config filename including extension (e.g. ``sshd.conf``). */ + filename: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["JailConfigFileContent"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + write_jail_config_file_api_config_jail_files__filename__put: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Config filename including extension (e.g. ``sshd.conf``). */ + filename: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ConfFileUpdateRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + set_jail_config_file_enabled_api_config_jail_files__filename__enabled_put: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Config filename including extension (e.g. ``sshd.conf``). */ + filename: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["JailConfigFileEnabledUpdate"]; + }; + }; + responses: { + /** @description Successful Response */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_filter_file_raw_api_config_filters__name__raw_get: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Base name with or without extension (e.g. ``sshd`` or ``sshd.conf``). */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ConfFileContent"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + write_filter_file_api_config_filters__name__raw_put: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Base name with or without extension (e.g. ``sshd`` or ``sshd.conf``). */ + name: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ConfFileUpdateRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + create_filter_file_api_config_filters_raw_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ConfFileCreateRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ConfFileContent"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_action_file_api_config_actions__name__raw_get: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Base name with or without extension (e.g. ``sshd`` or ``sshd.conf``). */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ConfFileContent"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + write_action_file_api_config_actions__name__raw_put: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Base name with or without extension (e.g. ``sshd`` or ``sshd.conf``). */ + name: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ConfFileUpdateRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_parsed_filter_api_config_filters__name__parsed_get: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Base name with or without extension (e.g. ``sshd`` or ``sshd.conf``). */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["FilterConfig"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + update_parsed_filter_api_config_filters__name__parsed_put: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Base name with or without extension (e.g. ``sshd`` or ``sshd.conf``). */ + name: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["FilterConfigUpdate"]; + }; + }; + responses: { + /** @description Successful Response */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_parsed_action_api_config_actions__name__parsed_get: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Base name with or without extension (e.g. ``sshd`` or ``sshd.conf``). */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ActionConfig"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + update_parsed_action_api_config_actions__name__parsed_put: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Base name with or without extension (e.g. ``sshd`` or ``sshd.conf``). */ + name: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ActionConfigUpdate"]; + }; + }; + responses: { + /** @description Successful Response */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_parsed_jail_file_api_config_jail_files__filename__parsed_get: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Base name with or without extension (e.g. ``sshd`` or ``sshd.conf``). */ + filename: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["JailFileConfig"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + update_parsed_jail_file_api_config_jail_files__filename__parsed_put: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Base name with or without extension (e.g. ``sshd`` or ``sshd.conf``). */ + filename: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["JailFileConfigUpdate"]; + }; + }; + responses: { + /** @description Successful Response */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_server_settings_api_server_settings_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ServerSettingsResponse"]; + }; + }; + }; + }; + update_server_settings_api_server_settings_put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ServerSettingsUpdate"]; + }; + }; + responses: { + /** @description Successful Response */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + flush_logs_api_server_flush_logs_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + [key: string]: string; + }; + }; + }; + }; + }; + get_history_api_history_get: { + parameters: { + query?: { + /** @description Optional time-range filter. Omit for all-time. */ + range?: ("24h" | "7d" | "30d" | "365d") | null; + /** @description Restrict results to this jail name. */ + jail?: string | null; + /** @description Restrict results to IPs matching this prefix. */ + ip?: string | null; + /** @description Filter by ban origin: 'blocklist' or 'selfblock'. Omit for all. */ + origin?: ("blocklist" | "selfblock") | null; + /** @description Data source: 'fail2ban' or 'archive'. */ + source?: "fail2ban" | "archive"; + /** @description 1-based page number. */ + page?: number; + /** @description Items per page (max 500). */ + page_size?: number; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HistoryListResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_history_archive_api_history_archive_get: { + parameters: { + query?: { + /** @description Optional time-range filter. Omit for all-time. */ + range?: ("24h" | "7d" | "30d" | "365d") | null; + /** @description Restrict results to this jail name. */ + jail?: string | null; + /** @description Restrict results to IPs matching this prefix. */ + ip?: string | null; + /** @description 1-based page number. */ + page?: number; + /** @description Items per page (max 500). */ + page_size?: number; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HistoryListResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_ip_history_api_history__ip__get: { + parameters: { + query?: never; + header?: never; + path: { + ip: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["IpDetailResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + list_blocklists_api_blocklists_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["BlocklistListResponse"]; + }; + }; + }; + }; + create_blocklist_api_blocklists_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["BlocklistSourceCreate"]; + }; + }; + responses: { + /** @description Successful Response */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["BlocklistSource"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + run_import_now_api_blocklists_import_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ImportRunResult"]; + }; + }; + }; + }; + get_schedule_api_blocklists_schedule_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ScheduleInfo"]; + }; + }; + }; + }; + update_schedule_api_blocklists_schedule_put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ScheduleConfig"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ScheduleInfo"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_import_log_api_blocklists_log_get: { + parameters: { + query?: { + /** @description Filter by source id */ + source_id?: number | null; + /** @description 1-based page number. */ + page?: number; + /** @description Items per page (max 500). */ + page_size?: number; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ImportLogListResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_blocklist_api_blocklists__source_id__get: { + parameters: { + query?: never; + header?: never; + path: { + source_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["BlocklistSource"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + update_blocklist_api_blocklists__source_id__put: { + parameters: { + query?: never; + header?: never; + path: { + source_id: number; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["BlocklistSourceUpdate"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["BlocklistSource"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + delete_blocklist_api_blocklists__source_id__delete: { + parameters: { + query?: never; + header?: never; + path: { + source_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + preview_blocklist_api_blocklists__source_id__preview_get: { + parameters: { + query?: never; + header?: never; + path: { + source_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PreviewResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; +}