From 3320ef94fc2727d8d3cc19cbabcbf2ad86510b1b Mon Sep 17 00:00:00 2001 From: Sharang Parnerkar <30073382+mighty840@users.noreply.github.com> Date: Tue, 7 Apr 2026 13:18:29 +0200 Subject: [PATCH] refactor: phase 0 guardrails + phase 1 step 2 (models.py split) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Squash of branch refactor/phase0-guardrails-and-models-split — 4 commits, 81 files, 173/173 pytest green, OpenAPI contract preserved (360 paths / 484 operations). ## Phase 0 — Architecture guardrails Three defense-in-depth layers to keep the architecture rules enforced regardless of who opens Claude Code in this repo: 1. .claude/settings.json PreToolUse hook on Write/Edit blocks any file that would exceed the 500-line hard cap. Auto-loads in every Claude session in this repo. 2. scripts/githooks/pre-commit (install via scripts/install-hooks.sh) enforces the LOC cap locally, freezes migrations/ without [migration-approved], and protects guardrail files without [guardrail-change]. 3. .gitea/workflows/ci.yaml gains loc-budget + guardrail-integrity + sbom-scan (syft+grype) jobs, adds mypy --strict for the new Python packages (compliance/{services,repositories,domain,schemas}), and tsc --noEmit for admin-compliance + developer-portal. Per-language conventions documented in AGENTS.python.md, AGENTS.go.md, AGENTS.typescript.md at the repo root — layering, tooling, and explicit "what you may NOT do" lists. Root CLAUDE.md is prepended with the six non-negotiable rules. Each of the 10 services gets a README.md. scripts/check-loc.sh enforces soft 300 / hard 500 and surfaces the current baseline of 205 hard + 161 soft violations so Phases 1-4 can drain it incrementally. CI gates only CHANGED files in PRs so the legacy baseline does not block unrelated work. ## Deprecation sweep 47 files. Pydantic V1 regex= -> pattern= (2 sites), class Config -> ConfigDict in source_policy_router.py (schemas.py intentionally skipped; it is the Phase 1 Step 3 split target). datetime.utcnow() -> datetime.now(timezone.utc) everywhere including SQLAlchemy default= callables. All DB columns already declare timezone=True, so this is a latent-bug fix at the Python side, not a schema change. DeprecationWarning count dropped from 158 to 35. ## Phase 1 Step 1 — Contract test harness tests/contracts/test_openapi_baseline.py diffs the live FastAPI /openapi.json against tests/contracts/openapi.baseline.json on every test run. Fails on removed paths, removed status codes, or new required request body fields. Regenerate only via tests/contracts/regenerate_baseline.py after a consumer-updated contract change. This is the safety harness for all subsequent refactor commits. ## Phase 1 Step 2 — models.py split (1466 -> 85 LOC shim) compliance/db/models.py is decomposed into seven sibling aggregate modules following the existing repo pattern (dsr_models.py, vvt_models.py, ...): regulation_models.py (134) — Regulation, Requirement control_models.py (279) — Control, Mapping, Evidence, Risk ai_system_models.py (141) — AISystem, AuditExport service_module_models.py (176) — ServiceModule, ModuleRegulation, ModuleRisk audit_session_models.py (177) — AuditSession, AuditSignOff isms_governance_models.py (323) — ISMSScope, Context, Policy, Objective, SoA isms_audit_models.py (468) — Finding, CAPA, MgmtReview, InternalAudit, AuditTrail, Readiness models.py becomes an 85-line re-export shim in dependency order so existing imports continue to work unchanged. Schema is byte-identical: __tablename__, column definitions, relationship strings, back_populates, cascade directives all preserved. All new sibling files are under the 500-line hard cap; largest is isms_audit_models.py at 468. No file in compliance/db/ now exceeds the hard cap. ## Phase 1 Step 3 — infrastructure only backend-compliance/compliance/{schemas,domain,repositories}/ packages are created as landing zones with docstrings. compliance/domain/ exports DomainError / NotFoundError / ConflictError / ValidationError / PermissionError — the base classes services will use to raise domain-level errors instead of HTTPException. PHASE1_RUNBOOK.md at backend-compliance/PHASE1_RUNBOOK.md documents the nine-step execution plan for Phase 1: snapshot baseline, characterization tests, split models.py (this commit), split schemas.py (next), extract services, extract repositories, mypy --strict, coverage. ## Verification backend-compliance/.venv-phase1: uv python install 3.12 + pip -r requirements.txt PYTHONPATH=. pytest compliance/tests/ tests/contracts/ -> 173 passed, 0 failed, 35 warnings, OpenAPI 360/484 unchanged Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/CLAUDE.md | 12 + .claude/rules/architecture.md | 43 + .claude/rules/loc-exceptions.txt | 8 + .claude/settings.json | 28 + .gitea/workflows/ci.yaml | 115 +- AGENTS.go.md | 126 + AGENTS.python.md | 94 + AGENTS.typescript.md | 85 + admin-compliance/README.md | 51 + ai-compliance-sdk/README.md | 55 + backend-compliance/PHASE1_RUNBOOK.md | 181 + backend-compliance/README.md | 55 + .../compliance/api/ai_routes.py | 4 +- .../compliance/api/audit_routes.py | 16 +- .../compliance/api/banner_routes.py | 10 +- .../compliance/api/consent_template_routes.py | 4 +- .../api/control_generator_routes.py | 2 +- .../compliance/api/crud_factory.py | 4 +- .../compliance/api/dashboard_routes.py | 12 +- .../compliance/api/dsfa_routes.py | 6 +- .../compliance/api/dsr_routes.py | 40 +- .../compliance/api/einwilligungen_routes.py | 12 +- .../compliance/api/email_template_routes.py | 8 +- .../compliance/api/escalation_routes.py | 8 +- .../compliance/api/evidence_routes.py | 10 +- .../compliance/api/extraction_routes.py | 4 +- .../compliance/api/isms_routes.py | 24 +- .../compliance/api/legal_document_routes.py | 12 +- .../compliance/api/legal_template_routes.py | 4 +- .../compliance/api/loeschfristen_routes.py | 6 +- .../compliance/api/notfallplan_routes.py | 10 +- .../compliance/api/obligation_routes.py | 6 +- .../compliance/api/quality_routes.py | 10 +- backend-compliance/compliance/api/routes.py | 6 +- .../compliance/api/security_backlog_routes.py | 4 +- .../compliance/api/source_policy_router.py | 11 +- .../api/vendor_compliance_routes.py | 24 +- .../compliance/api/vvt_routes.py | 8 +- .../compliance/db/ai_system_models.py | 141 + .../compliance/db/audit_session_models.py | 177 + .../compliance/db/control_models.py | 279 + .../compliance/db/isms_audit_models.py | 468 + .../compliance/db/isms_governance_models.py | 323 + .../compliance/db/isms_repository.py | 16 +- backend-compliance/compliance/db/models.py | 1539 +- .../compliance/db/regulation_models.py | 134 + .../compliance/db/repository.py | 40 +- .../compliance/db/service_module_models.py | 176 + .../compliance/domain/__init__.py | 30 + .../compliance/repositories/__init__.py | 10 + .../compliance/schemas/__init__.py | 11 + .../services/audit_pdf_generator.py | 6 +- .../compliance/services/auto_risk_updater.py | 12 +- .../compliance/services/export_generator.py | 4 +- .../compliance/services/regulation_scraper.py | 4 +- .../compliance/services/report_generator.py | 6 +- .../compliance/tests/test_audit_routes.py | 18 +- .../tests/test_auto_risk_updater.py | 12 +- .../tests/test_compliance_routes.py | 22 +- .../compliance/tests/test_isms_routes.py | 30 +- backend-compliance/consent_client.py | 6 +- .../tests/contracts/__init__.py | 0 .../tests/contracts/openapi.baseline.json | 49377 ++++++++++++++++ .../tests/contracts/regenerate_baseline.py | 25 + .../tests/contracts/test_openapi_baseline.py | 102 + backend-compliance/tests/test_dsfa_routes.py | 4 +- backend-compliance/tests/test_dsr_routes.py | 16 +- .../tests/test_einwilligungen_routes.py | 26 +- backend-compliance/tests/test_isms_routes.py | 4 +- .../tests/test_legal_document_routes.py | 12 +- .../test_legal_document_routes_extended.py | 4 +- .../tests/test_vendor_compliance_routes.py | 4 +- backend-compliance/tests/test_vvt_routes.py | 4 +- .../tests/test_vvt_tenant_isolation.py | 6 +- breakpilot-compliance-sdk/README.md | 37 + compliance-tts-service/README.md | 30 + developer-portal/README.md | 26 + docs-src/README.md | 19 + document-crawler/README.md | 28 + dsms-gateway/README.md | 55 + dsms-node/README.md | 15 + scripts/check-loc.sh | 123 + scripts/githooks/pre-commit | 55 + scripts/install-hooks.sh | 26 + 84 files changed, 52849 insertions(+), 1731 deletions(-) create mode 100644 .claude/rules/architecture.md create mode 100644 .claude/rules/loc-exceptions.txt create mode 100644 .claude/settings.json create mode 100644 AGENTS.go.md create mode 100644 AGENTS.python.md create mode 100644 AGENTS.typescript.md create mode 100644 admin-compliance/README.md create mode 100644 ai-compliance-sdk/README.md create mode 100644 backend-compliance/PHASE1_RUNBOOK.md create mode 100644 backend-compliance/README.md create mode 100644 backend-compliance/compliance/db/ai_system_models.py create mode 100644 backend-compliance/compliance/db/audit_session_models.py create mode 100644 backend-compliance/compliance/db/control_models.py create mode 100644 backend-compliance/compliance/db/isms_audit_models.py create mode 100644 backend-compliance/compliance/db/isms_governance_models.py create mode 100644 backend-compliance/compliance/db/regulation_models.py create mode 100644 backend-compliance/compliance/db/service_module_models.py create mode 100644 backend-compliance/compliance/domain/__init__.py create mode 100644 backend-compliance/compliance/repositories/__init__.py create mode 100644 backend-compliance/compliance/schemas/__init__.py create mode 100644 backend-compliance/tests/contracts/__init__.py create mode 100644 backend-compliance/tests/contracts/openapi.baseline.json create mode 100644 backend-compliance/tests/contracts/regenerate_baseline.py create mode 100644 backend-compliance/tests/contracts/test_openapi_baseline.py create mode 100644 breakpilot-compliance-sdk/README.md create mode 100644 compliance-tts-service/README.md create mode 100644 developer-portal/README.md create mode 100644 docs-src/README.md create mode 100644 document-crawler/README.md create mode 100644 dsms-gateway/README.md create mode 100644 dsms-node/README.md create mode 100755 scripts/check-loc.sh create mode 100755 scripts/githooks/pre-commit create mode 100755 scripts/install-hooks.sh diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 228f6b8..664642d 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -1,5 +1,17 @@ # BreakPilot Compliance - DSGVO/AI-Act SDK Platform +> **NON-NEGOTIABLE STRUCTURE RULES** (enforced by `.claude/settings.json` hook, git pre-commit, and CI): +> 1. **File-size budget:** soft target **300** lines, **hard cap 500** lines for any non-test, non-generated source file. Anything larger → split it. Exceptions are listed in `.claude/rules/loc-exceptions.txt` and require a written rationale. +> 2. **Clean architecture per service.** Routers/handlers stay thin (≤30 lines per handler) and delegate to services; services use repositories; repositories own DB I/O. See `AGENTS.python.md` / `AGENTS.go.md` / `AGENTS.typescript.md`. +> 3. **Do not touch the database schema.** No new Alembic migrations, no `ALTER TABLE`, no model field renames without an explicit migration plan reviewed by the DB owner. SQLAlchemy `__tablename__` and column names are frozen. +> 4. **Public endpoints are a contract.** Any change to a path, method, status code, request schema, or response schema in `backend-compliance/`, `ai-compliance-sdk/`, `dsms-gateway/`, `document-crawler/`, or `compliance-tts-service/` must be accompanied by a matching update in **every** consumer (`admin-compliance/`, `developer-portal/`, `breakpilot-compliance-sdk/`, `consent-sdk/`). Use the OpenAPI snapshot tests in `tests/contracts/` as the gate. +> 5. **Tests are not optional.** New code without tests fails CI. Refactors must preserve coverage and add a characterization test before splitting an oversized file. +> 6. **Do not bypass the guardrails.** Do not edit `.claude/settings.json`, `scripts/check-loc.sh`, or the loc-exceptions list to silence violations. If a rule is wrong, raise it in a PR description. +> +> These rules apply to **every** Claude Code session opened inside this repository, regardless of who launched it. They are loaded automatically via this `CLAUDE.md`. + + + ## Entwicklungsumgebung (WICHTIG - IMMER ZUERST LESEN) ### Zwei-Rechner-Setup + Hetzner diff --git a/.claude/rules/architecture.md b/.claude/rules/architecture.md new file mode 100644 index 0000000..26c6c36 --- /dev/null +++ b/.claude/rules/architecture.md @@ -0,0 +1,43 @@ +# Architecture Rules (auto-loaded) + +These rules apply to **every** Claude Code session in this repository, regardless of who launched it. They are non-negotiable. + +## File-size budget + +- **Soft target:** 300 lines per non-test, non-generated source file. +- **Hard cap:** 500 lines. The PreToolUse hook in `.claude/settings.json` blocks Write/Edit operations that would create or push a file past 500. The git pre-commit hook re-checks. CI is the final gate. +- Exceptions live in `.claude/rules/loc-exceptions.txt` and require a written rationale plus `[guardrail-change]` in the commit message. The exceptions list should shrink over time, not grow. + +## Clean architecture + +- Python (FastAPI): see `AGENTS.python.md`. Layering: `api → services → repositories → db.models`. Routers ≤30 LOC per handler. Schemas split per domain. +- Go (Gin): see `AGENTS.go.md`. Standard Go Project Layout + hexagonal. `cmd/` thin, wiring in `internal/app`. +- TypeScript (Next.js): see `AGENTS.typescript.md`. Server-by-default, push the client boundary deep, colocate `_components/` and `_hooks/` per route. + +## Database is frozen + +- No new Alembic migrations. No `ALTER TABLE`. No `__tablename__` or column renames. +- The pre-commit hook blocks any change under `migrations/` or `alembic/versions/` unless the commit message contains `[migration-approved]`. + +## Public endpoints are a contract + +- Any change to a path/method/status/request schema/response schema in a backend service must update every consumer in the same change set. +- Each backend service has an OpenAPI baseline at `tests/contracts/openapi.baseline.json`. Contract tests fail on drift. + +## Tests + +- New code without tests fails CI. +- Refactors must preserve coverage. Before splitting an oversized file, add a characterization test that pins current behavior. +- Layout: `tests/unit/`, `tests/integration/`, `tests/contracts/`, `tests/e2e/`. + +## Guardrails are themselves protected + +- Edits to `.claude/settings.json`, `scripts/check-loc.sh`, `scripts/githooks/pre-commit`, `.claude/rules/loc-exceptions.txt`, or any `AGENTS.*.md` require `[guardrail-change]` in the commit message. The pre-commit hook enforces this. +- If you (Claude) think a rule is wrong, surface it to the user. Do not silently weaken it. + +## Tooling baseline + +- Python: `ruff`, `mypy --strict` on new modules, `pytest --cov`. +- Go: `golangci-lint` strict config, `go vet`, table-driven tests. +- TS: `tsc --noEmit` strict, ESLint type-aware, Vitest, Playwright. +- All three: dependency caching in CI, license/SBOM scan via `syft`+`grype`. diff --git a/.claude/rules/loc-exceptions.txt b/.claude/rules/loc-exceptions.txt new file mode 100644 index 0000000..b2ccc89 --- /dev/null +++ b/.claude/rules/loc-exceptions.txt @@ -0,0 +1,8 @@ +# loc-exceptions.txt — files allowed to exceed the 500-line hard cap. +# +# Format: one repo-relative path per line. Comments start with '#' and are ignored. +# Each exception MUST be preceded by a comment explaining why splitting is not viable. +# +# Phase 0 baseline: this list is initially empty. Phases 1-4 will add grandfathered +# entries as we encounter legitimate exceptions (e.g. large generated data tables). +# The goal is for this list to SHRINK over time, never grow. diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..0d899bc --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,28 @@ +{ + "hooks": { + "PreToolUse": [ + { + "matcher": "Write", + "hooks": [ + { + "type": "command", + "command": "f=$(jq -r '.tool_input.file_path // empty'); [ -z \"$f\" ] && exit 0; lines=$(printf '%s' \"$(jq -r '.tool_input.content // empty')\" | awk 'END{print NR}'); if [ \"${lines:-0}\" -gt 500 ]; then echo '{\"decision\":\"block\",\"reason\":\"breakpilot guardrail: file exceeds the 500-line hard cap. Split it into smaller modules per the layering rules in AGENTS..md. If this is generated/data code, add an entry to .claude/rules/loc-exceptions.txt with rationale and reference [guardrail-change].\"}'; exit 0; fi", + "shell": "bash", + "timeout": 5 + } + ] + }, + { + "matcher": "Edit", + "hooks": [ + { + "type": "command", + "command": "f=$(jq -r '.tool_input.file_path // empty'); [ -z \"$f\" ] || [ ! -f \"$f\" ] && exit 0; case \"$f\" in *.md|*.json|*.yaml|*.yml|*test*|*tests/*|*node_modules/*|*.next/*|*migrations/*) exit 0 ;; esac; new_str=$(jq -r '.tool_input.new_string // empty'); old_str=$(jq -r '.tool_input.old_string // empty'); old_lines=$(printf '%s' \"$old_str\" | awk 'END{print NR}'); new_lines=$(printf '%s' \"$new_str\" | awk 'END{print NR}'); cur=$(wc -l < \"$f\" | tr -d ' '); proj=$((cur - old_lines + new_lines)); if [ \"$proj\" -gt 500 ]; then echo \"{\\\"decision\\\":\\\"block\\\",\\\"reason\\\":\\\"breakpilot guardrail: this edit would push $f to ~$proj lines (hard cap is 500). Split the file before continuing. See AGENTS..md for the layering rules.\\\"}\"; fi; exit 0", + "shell": "bash", + "timeout": 5 + } + ] + } + ] + } +} diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml index d706806..fd10d5d 100644 --- a/.gitea/workflows/ci.yaml +++ b/.gitea/workflows/ci.yaml @@ -19,6 +19,55 @@ on: branches: [main, develop] jobs: + # ======================================== + # Guardrails — LOC budget + architecture gates + # Runs on every push/PR. Fails fast and cheap. + # ======================================== + + loc-budget: + runs-on: docker + container: alpine:3.20 + steps: + - name: Checkout + run: | + apk add --no-cache git bash + git clone --depth 50 --branch ${GITHUB_REF_NAME} ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git . + - name: Enforce 500-line hard cap on changed files + run: | + chmod +x scripts/check-loc.sh + if [ "${GITHUB_EVENT_NAME}" = "pull_request" ]; then + git fetch origin ${GITHUB_BASE_REF}:base + mapfile -t changed < <(git diff --name-only --diff-filter=ACM base...HEAD) + [ ${#changed[@]} -eq 0 ] && { echo "No changed files."; exit 0; } + scripts/check-loc.sh "${changed[@]}" + else + # Push to main: only warn on whole-repo state; blocking gate is on PRs. + scripts/check-loc.sh || true + fi + # Phase 0 intentionally gates only changed files so the 205-file legacy + # baseline doesn't block every PR. Phases 1-4 drain the baseline; Phase 5 + # flips this to a whole-repo blocking gate. + + guardrail-integrity: + runs-on: docker + container: alpine:3.20 + if: github.event_name == 'pull_request' + steps: + - name: Checkout + run: | + apk add --no-cache git bash + git clone --depth 20 --branch ${GITHUB_REF_NAME} ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git . + git fetch origin ${GITHUB_BASE_REF}:base + - name: Require [guardrail-change] label in PR commits touching guardrails + run: | + changed=$(git diff --name-only base...HEAD) + echo "$changed" | grep -E '^(\.claude/settings\.json|\.claude/rules/loc-exceptions\.txt|scripts/check-loc\.sh|scripts/githooks/pre-commit|AGENTS\.(python|go|typescript)\.md)$' || exit 0 + if ! git log base..HEAD --format=%B | grep -q '\[guardrail-change\]'; then + echo "::error:: Guardrail files were modified but no commit in this PR carries [guardrail-change]." + echo "If intentional, amend one commit message with [guardrail-change] and explain why in the body." + exit 1 + fi + # ======================================== # Lint (nur bei PRs) # ======================================== @@ -47,13 +96,29 @@ jobs: run: | apt-get update -qq && apt-get install -y -qq git > /dev/null 2>&1 git clone --depth 1 --branch ${GITHUB_REF_NAME} ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git . - - name: Lint Python services + - name: Lint Python services (ruff) run: | pip install --quiet ruff - for svc in backend-compliance document-crawler dsms-gateway; do + fail=0 + for svc in backend-compliance document-crawler dsms-gateway compliance-tts-service; do if [ -d "$svc" ]; then - echo "=== Linting $svc ===" - ruff check "$svc/" --output-format=github || true + echo "=== ruff: $svc ===" + ruff check "$svc/" --output-format=github || fail=1 + fi + done + exit $fail + - name: Type-check new modules (mypy --strict) + # Scoped to the layered packages we own. Expand this list as Phase 1+ refactors land. + run: | + pip install --quiet mypy + for pkg in \ + backend-compliance/compliance/services \ + backend-compliance/compliance/repositories \ + backend-compliance/compliance/domain \ + backend-compliance/compliance/schemas; do + if [ -d "$pkg" ]; then + echo "=== mypy --strict: $pkg ===" + mypy --strict --ignore-missing-imports "$pkg" || exit 1 fi done @@ -66,17 +131,20 @@ jobs: run: | apk add --no-cache git git clone --depth 1 --branch ${GITHUB_REF_NAME} ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git . - - name: Lint Node.js services + - name: Lint + type-check Node.js services run: | + fail=0 for svc in admin-compliance developer-portal; do if [ -d "$svc" ]; then - echo "=== Linting $svc ===" - cd "$svc" - npm ci --silent 2>/dev/null || npm install --silent - npx next lint || true - cd .. + echo "=== $svc: install ===" + (cd "$svc" && (npm ci --silent 2>/dev/null || npm install --silent)) + echo "=== $svc: next lint ===" + (cd "$svc" && npx next lint) || fail=1 + echo "=== $svc: tsc --noEmit ===" + (cd "$svc" && npx tsc --noEmit) || fail=1 fi done + exit $fail # ======================================== # Unit Tests @@ -169,6 +237,32 @@ jobs: pip install --quiet --no-cache-dir pytest pytest-asyncio python -m pytest test_main.py -v --tb=short + # ======================================== + # SBOM + license scan (compliance product → we eat our own dog food) + # ======================================== + + sbom-scan: + runs-on: docker + if: github.event_name == 'pull_request' + container: alpine:3.20 + steps: + - name: Checkout + run: | + apk add --no-cache git curl bash + git clone --depth 1 --branch ${GITHUB_REF_NAME} ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git . + - name: Install syft + grype + run: | + curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin + curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin + - name: Generate SBOM + run: | + mkdir -p sbom-out + syft dir:. -o cyclonedx-json=sbom-out/sbom.cdx.json -q + - name: Vulnerability scan (fail on high+) + run: | + grype sbom:sbom-out/sbom.cdx.json --fail-on high -q || true + # Initially non-blocking ('|| true'). Flip to blocking after baseline is clean. + # ======================================== # Validate Canonical Controls # ======================================== @@ -194,6 +288,7 @@ jobs: runs-on: docker if: github.event_name == 'push' && github.ref == 'refs/heads/main' needs: + - loc-budget - test-go-ai-compliance - test-python-backend-compliance - test-python-document-crawler diff --git a/AGENTS.go.md b/AGENTS.go.md new file mode 100644 index 0000000..3c234b9 --- /dev/null +++ b/AGENTS.go.md @@ -0,0 +1,126 @@ +# AGENTS.go.md — Go Service Conventions + +Applies to: `ai-compliance-sdk/`. + +## Layered architecture (Gin) + +Follows [Standard Go Project Layout](https://github.com/golang-standards/project-layout) + hexagonal/clean-arch. + +``` +ai-compliance-sdk/ +├── cmd/server/main.go # Thin: parse flags → app.New → app.Run. <50 LOC. +├── internal/ +│ ├── app/ # Wiring: config + DI graph + lifecycle. +│ ├── domain/ # Pure types, interfaces, errors. No I/O imports. +│ │ └── / +│ ├── service/ # Business logic. Depends on domain interfaces only. +│ │ └── / +│ ├── repository/postgres/ # Concrete repo implementations. +│ │ └── / +│ ├── transport/http/ # Gin handlers. Thin. One handler per file group. +│ │ ├── handler// +│ │ ├── middleware/ +│ │ └── router.go +│ └── platform/ # DB pool, logger, config, tracing. +└── pkg/ # Importable by other repos. Empty unless needed. +``` + +**Dependency direction:** `transport → service → domain ← repository`. `domain` imports nothing from siblings. + +## Handlers + +- One handler = one Gin function. ≤40 LOC. +- Bind → call service → map domain error to HTTP via `httperr.Write(c, err)` → respond. +- Return early on errors. No business logic, no SQL. + +```go +func (h *IACEHandler) Create(c *gin.Context) { + var req CreateIACERequest + if err := c.ShouldBindJSON(&req); err != nil { + httperr.Write(c, httperr.BadRequest(err)) + return + } + out, err := h.svc.Create(c.Request.Context(), req.ToInput()) + if err != nil { + httperr.Write(c, err) + return + } + c.JSON(http.StatusCreated, out) +} +``` + +## Services + +- Struct + constructor + interface methods. No package-level state. +- Take `context.Context` as first arg always. Propagate to repos. +- Return `(value, error)`. Wrap with `fmt.Errorf("create iace: %w", err)`. +- Domain errors implemented as sentinel vars or typed errors; matched with `errors.Is` / `errors.As`. + +## Repositories + +- Interface lives in `domain//repository.go`. Implementation in `repository/postgres//`. +- One file per query group; no file >500 LOC. +- Use `pgx`/`sqlc` over hand-rolled string SQL when feasible. No ORM globals. +- All queries take `ctx`. No background goroutines without explicit lifecycle. + +## Errors + +Single `internal/platform/httperr` package maps `error` → HTTP status: + +```go +switch { +case errors.Is(err, domain.ErrNotFound): return 404 +case errors.Is(err, domain.ErrConflict): return 409 +case errors.As(err, &validationErr): return 422 +default: return 500 +} +``` + +Never `panic` in request handling. `recover` middleware logs and returns 500. + +## Tests + +- Co-located `*_test.go`. +- **Table-driven** tests for service logic; use `t.Run(tt.name, ...)`. +- Handlers tested with `httptest.NewRecorder`. +- Repos tested with `testcontainers-go` (or the existing compose Postgres) — never mocks at the SQL boundary. +- Coverage target: 80% on `service/`. CI fails on regression. + +```go +func TestIACEService_Create(t *testing.T) { + tests := []struct { + name string + input service.CreateInput + setup func(*mockRepo) + wantErr error + }{ + {"happy path", validInput(), func(r *mockRepo) { r.createReturns(nil) }, nil}, + {"conflict", validInput(), func(r *mockRepo) { r.createReturns(domain.ErrConflict) }, domain.ErrConflict}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { /* ... */ }) + } +} +``` + +## Tooling + +- `golangci-lint` with: `errcheck, govet, staticcheck, revive, gosec, gocyclo (max 15), gocognit (max 20), unused, ineffassign, errorlint, nilerr, nolintlint, contextcheck`. +- `gofumpt` formatting. +- `go vet ./...` clean. +- `go mod tidy` clean — no unused deps. + +## Concurrency + +- Goroutines must have a clear lifecycle owner (struct method that started them must stop them). +- Pass `ctx` everywhere. Cancellation respected. +- No global mutexes for request data. Use per-request context. + +## What you may NOT do + +- Touch DB schema/migrations. +- Add a new top-level package directly under `internal/` without architectural review. +- `import "C"`, unsafe, reflection-heavy code. +- Use `init()` for non-trivial setup. Wire it in `internal/app`. +- Create a file >500 lines. +- Change a public route's contract without updating consumers. diff --git a/AGENTS.python.md b/AGENTS.python.md new file mode 100644 index 0000000..bc24bab --- /dev/null +++ b/AGENTS.python.md @@ -0,0 +1,94 @@ +# AGENTS.python.md — Python Service Conventions + +Applies to: `backend-compliance/`, `document-crawler/`, `dsms-gateway/`, `compliance-tts-service/`. + +## Layered architecture (FastAPI) + +``` +compliance/ +├── api/ # HTTP layer — routers only. Thin (≤30 LOC per handler). +│ └── _routes.py +├── services/ # Business logic. Pure-ish; no FastAPI imports. +│ └── _service.py +├── repositories/ # DB access. Owns SQLAlchemy session usage. +│ └── _repository.py +├── domain/ # Value objects, enums, domain exceptions. +├── schemas/ # Pydantic models, split per domain. NEVER one giant schemas.py. +│ └── .py +└── db/ + └── models/ # SQLAlchemy ORM, one module per aggregate. __tablename__ frozen. +``` + +**Dependency direction:** `api → services → repositories → db.models`. Lower layers must not import upper layers. + +## Routers + +- One `APIRouter` per domain file. +- Handlers do exactly: parse request → call service → map domain errors to HTTPException → return response model. +- Inject services via `Depends`. No globals. +- Tag routes; document with summary + response_model. + +```python +@router.post("/dsr/requests", response_model=DSRRequestRead, status_code=201) +async def create_dsr_request( + payload: DSRRequestCreate, + service: DSRService = Depends(get_dsr_service), + tenant_id: UUID = Depends(get_tenant_id), +) -> DSRRequestRead: + try: + return await service.create(tenant_id, payload) + except DSRConflict as exc: + raise HTTPException(409, str(exc)) from exc +``` + +## Services + +- Constructor takes the repository (interface, not concrete). +- No `Request`, `Response`, or HTTP knowledge. +- Raise domain exceptions (e.g. `DSRConflict`, `DSRNotFound`), never `HTTPException`. +- Return domain objects or Pydantic schemas — pick one and stay consistent inside a service. + +## Repositories + +- Methods are intent-named (`get_pending_for_tenant`), not CRUD-named (`select_where`). +- Sessions injected, not constructed inside. +- No business logic. No cross-aggregate joins for unrelated workflows — that belongs in a service. +- Return ORM models or domain VOs; never `Row`. + +## Schemas (Pydantic v2) + +- One module per domain. Module ≤300 lines. +- Use `model_config = ConfigDict(from_attributes=True, frozen=True)` for read models. +- Separate `*Create`, `*Update`, `*Read`. No giant union schemas. + +## Tests (`pytest`) + +- Layout: `tests/unit/`, `tests/integration/`, `tests/contracts/`. +- Unit tests mock the repository. Use `pytest.fixture` + `unittest.mock.AsyncMock`. +- Integration tests run against the real Postgres from `docker-compose.yml` via a transactional fixture (rollback after each test). +- Contract tests diff `/openapi.json` against `tests/contracts/openapi.baseline.json`. +- Naming: `test___.py::TestClass::test_method`. +- `pytest-asyncio` mode = `auto`. Mark slow tests with `@pytest.mark.slow`. +- Coverage target: 80% for new code; never decrease the service baseline. + +## Tooling + +- `ruff check` + `ruff format` (line length 100). +- `mypy --strict` on `services/`, `repositories/`, `domain/`. Expand outward. +- `pip-audit` in CI. +- Async-first: prefer `httpx.AsyncClient`, `asyncpg`/`SQLAlchemy 2.x async`. + +## Errors & logging + +- Domain errors inherit from a single `DomainError` base per service. +- Log via `structlog` with bound context (`tenant_id`, `request_id`). Never log secrets, PII, or full request bodies. +- Audit-relevant actions go through the audit logger, not the application logger. + +## What you may NOT do + +- Add a new Alembic migration. +- Rename a `__tablename__`, column, or enum value. +- Change a public route's path/method/status/schema without simultaneous dashboard fix. +- Catch `Exception` broadly — catch the specific domain or library error. +- Put business logic in a router or in a Pydantic validator. +- Create a new file >500 lines. Period. diff --git a/AGENTS.typescript.md b/AGENTS.typescript.md new file mode 100644 index 0000000..6359199 --- /dev/null +++ b/AGENTS.typescript.md @@ -0,0 +1,85 @@ +# AGENTS.typescript.md — TypeScript / Next.js Conventions + +Applies to: `admin-compliance/`, `developer-portal/`, `breakpilot-compliance-sdk/`, `consent-sdk/`, `dsms-node/` (where applicable). + +## Layered architecture (Next.js 15 App Router) + +``` +app/ +├── / +│ ├── page.tsx # Server Component by default. ≤200 LOC. +│ ├── layout.tsx +│ ├── _components/ # Private folder; not routable. Colocated UI. +│ │ └── .tsx # Each file ≤300 LOC. +│ ├── _hooks/ # Client hooks for this route. +│ ├── _server/ # Server actions, data loaders for this route. +│ └── loading.tsx / error.tsx +├── api/ +│ └── /route.ts # Thin handler. Delegates to lib/server//. +lib/ +├── / # Pure helpers, types, schemas (zod). Reusable. +└── server// # Server-only logic; uses "server-only" import. +components/ # Truly shared, app-wide components. +``` + +**Server vs Client:** Default is Server Component. Add `"use client"` only when you need state, effects, or browser APIs. Push the boundary as deep as possible. + +## API routes (route.ts) + +- One handler per HTTP method, ≤40 LOC. +- Validate input with `zod`. Reject invalid → 400. +- Delegate to `lib/server//`. No business logic in `route.ts`. +- Always return `NextResponse.json(..., { status })`. Never throw to the framework. + +```ts +export async function POST(req: Request) { + const parsed = CreateDSRSchema.safeParse(await req.json()); + if (!parsed.success) return NextResponse.json({ error: parsed.error.flatten() }, { status: 400 }); + const result = await dsrService.create(parsed.data); + return NextResponse.json(result, { status: 201 }); +} +``` + +## Page components + +- Pages >300 lines must be split into colocated `_components/`. +- Server Components fetch data; pass plain objects to Client Components. +- No data fetching in `useEffect` for server-renderable data. +- State management: prefer URL state (`searchParams`) and Server Components over global stores. + +## Types + +- `lib/sdk/types.ts` is being split into `lib/sdk/types/.ts`. Mirror backend domain boundaries. +- All API DTOs are zod schemas; infer types via `z.infer`. +- No `any`. No `as unknown as`. If you reach for it, the type is wrong. + +## Tests + +- Unit: **Vitest** (`*.test.ts`/`*.test.tsx`), colocated. +- Hooks: `@testing-library/react` `renderHook`. +- E2E: **Playwright** (`tests/e2e/`), one spec per top-level page, smoke happy path minimum. +- Snapshot tests sparingly — only for stable output (CSV, JSON-LD). +- Coverage target: 70% on `lib/`, smoke coverage on `app/`. + +## Tooling + +- `tsc --noEmit` clean (strict mode, `noUncheckedIndexedAccess: true`). +- ESLint with `@typescript-eslint`, `eslint-config-next`, type-aware rules on. +- `prettier`. +- `next build` clean. No `// @ts-ignore`. `// @ts-expect-error` only with a comment explaining why. + +## Performance + +- Use `next/dynamic` for heavy client-only components. +- Image: `next/image` with explicit width/height. +- Avoid waterfalls — `Promise.all` for parallel data fetches in Server Components. + +## What you may NOT do + +- Put business logic in a `page.tsx` or `route.ts`. +- Reach across module boundaries (e.g. `admin-compliance` importing from `developer-portal`). +- Use `dangerouslySetInnerHTML` without explicit sanitization. +- Call backend APIs directly from Client Components when a Server Component or Server Action would do. +- Change a public API route's path/method/schema without updating SDK consumers in the same change. +- Create a file >500 lines. +- Disable a lint or type rule globally to silence a finding — fix the root cause. diff --git a/admin-compliance/README.md b/admin-compliance/README.md new file mode 100644 index 0000000..57f43f6 --- /dev/null +++ b/admin-compliance/README.md @@ -0,0 +1,51 @@ +# admin-compliance + +Next.js 15 dashboard for BreakPilot Compliance — SDK module UI, company profile, DSR, DSFA, VVT, TOM, consent, AI Act, training, audit, change requests, etc. Also hosts 96+ API routes that proxy/orchestrate backend services. + +**Port:** `3007` (container: `bp-compliance-admin`) +**Stack:** Next.js 15 App Router, React 18, TailwindCSS, TypeScript strict. + +## Architecture (target — Phase 3) + +``` +app/ +├── / +│ ├── page.tsx # Server Component (≤200 LOC) +│ ├── _components/ # Colocated UI, each ≤300 LOC +│ ├── _hooks/ # Client hooks +│ └── _server/ # Server actions +├── api//route.ts # Thin handlers → lib/server// +lib/ +├── / # Pure helpers, zod schemas +└── server// # "server-only" logic +components/ # App-wide shared UI +``` + +See `../AGENTS.typescript.md`. + +## Run locally + +```bash +cd admin-compliance +npm install +npm run dev # http://localhost:3007 +``` + +## Tests + +```bash +npm test # Vitest unit + component tests +npx playwright test # E2E +npx tsc --noEmit # Type-check +npx next lint +``` + +## Known debt (Phase 3 targets) + +- `app/sdk/company-profile/page.tsx` (3017 LOC), `tom-generator/controls/loader.ts` (2521), `lib/sdk/types.ts` (2511), `app/sdk/loeschfristen/page.tsx` (2322), `app/sdk/dsb-portal/page.tsx` (2068) — all must be split. +- 0 test files for 182 monolithic pages. Phase 3 adds Playwright smoke + Vitest unit coverage. + +## Don't touch + +- Backend API paths without updating `backend-compliance/` in the same change. +- `lib/sdk/types.ts` in large contiguous chunks — it's being domain-split. diff --git a/ai-compliance-sdk/README.md b/ai-compliance-sdk/README.md new file mode 100644 index 0000000..57be8ed --- /dev/null +++ b/ai-compliance-sdk/README.md @@ -0,0 +1,55 @@ +# ai-compliance-sdk + +Go/Gin service providing AI-Act compliance analysis: iACE impact assessments, UCCA rules engine, hazard library, training/academy, audit, escalation, portfolio, RBAC, RAG, whistleblower, workshop. + +**Port:** `8090` → exposed `8093` (container: `bp-compliance-ai-sdk`) +**Stack:** Go 1.24, Gin, pgx, Postgres. + +## Architecture (target — Phase 2) + +``` +cmd/server/main.go # Thin entrypoint (<50 LOC) +internal/ +├── app/ # Wiring + lifecycle +├── domain// # Types, interfaces, errors +├── service// # Business logic +├── repository/postgres/ # Repo implementations +├── transport/http/ # Gin handlers + middleware + router +└── platform/ # DB pool, logger, config, httperr +``` + +See `../AGENTS.go.md` for the full convention. + +## Run locally + +```bash +cd ai-compliance-sdk +go mod download +export COMPLIANCE_DATABASE_URL=... +go run ./cmd/server +``` + +## Tests + +```bash +go test -race -cover ./... +golangci-lint run --timeout 5m ./... +``` + +Co-located `*_test.go`, table-driven. Repo layer uses testcontainers-go (or the compose Postgres) — no SQL mocks. + +## Public API surface + +Handlers under `internal/api/handlers/` (Phase 2 moves to `internal/transport/http/handler/`). Health at `GET /health`. iACE, UCCA, training, academy, portfolio, escalation, audit, rag, whistleblower, workshop subresources. Every route is a contract. + +## Environment + +| Var | Purpose | +|-----|---------| +| `COMPLIANCE_DATABASE_URL` | Postgres DSN | +| `LLM_GATEWAY_URL` | LLM router for rag/iACE | +| `QDRANT_URL` | Vector search | + +## Don't touch + +DB schema. Hand-rolled migrations elsewhere own it. diff --git a/backend-compliance/PHASE1_RUNBOOK.md b/backend-compliance/PHASE1_RUNBOOK.md new file mode 100644 index 0000000..77b20e8 --- /dev/null +++ b/backend-compliance/PHASE1_RUNBOOK.md @@ -0,0 +1,181 @@ +# Phase 1 Runbook — backend-compliance refactor + +This document is the step-by-step execution guide for Phase 1 of the repo refactor plan at `~/.claude/plans/vectorized-purring-barto.md`. It exists because the refactor must be driven from a session that can actually run `pytest` against the service, and every step must be verified green before moving to the next. + +## Prerequisites + +- Python 3.12 venv with `backend-compliance/requirements.txt` installed. +- Local Postgres reachable via `COMPLIANCE_DATABASE_URL` (use the compose db). +- Existing 48 pytest test files pass from a clean checkout: `pytest compliance/tests/ -v` → all green. **Do not proceed until this is true.** + +## Step 0 — Record the baseline + +```bash +cd backend-compliance +pytest compliance/tests/ -v --tb=short | tee /tmp/baseline.txt +pytest --cov=compliance --cov-report=term | tee /tmp/baseline-coverage.txt +python tests/contracts/regenerate_baseline.py # creates openapi.baseline.json +git add tests/contracts/openapi.baseline.json +git commit -m "phase1: pin OpenAPI baseline before refactor" +``` + +The baseline file is the contract. From this point forward, `pytest tests/contracts/` MUST stay green. + +## Step 1 — Characterization tests (before any code move) + +For each oversized route file we will refactor, add a happy-path + 1-error-path test **before** touching the source. These are called "characterization tests" and their purpose is to freeze current observable behavior so the refactor cannot change it silently. + +Oversized route files to cover (ordered by size): + +| File | LOC | Endpoints to cover | +|---|---:|---| +| `compliance/api/isms_routes.py` | 1676 | one happy + one 4xx per route | +| `compliance/api/dsr_routes.py` | 1176 | same | +| `compliance/api/vvt_routes.py` | *N* | same | +| `compliance/api/dsfa_routes.py` | *N* | same | +| `compliance/api/tom_routes.py` | *N* | same | +| `compliance/api/schemas.py` | 1899 | N/A (covered transitively) | +| `compliance/db/models.py` | 1466 | N/A (covered by existing + route tests) | +| `compliance/db/repository.py` | 1547 | add unit tests per repo class as they are extracted | + +Use `httpx.AsyncClient` + factory fixtures; see `AGENTS.python.md`. Place under `tests/integration/test__contract.py`. + +Commit: `phase1: characterization tests for routes`. + +## Step 2 — Split `compliance/db/models.py` (1466 → <500 per file) + +⚠️ **Atomic step.** A `compliance/db/models/` package CANNOT coexist with the existing `compliance/db/models.py` module — Python's import system shadows the module with the package, breaking every `from compliance.db.models import X` call. The directory skeleton was intentionally NOT pre-created for this reason. Do the following in **one commit**: + +1. Create `compliance/db/models/` directory with `__init__.py` (re-export shim — see template below). +2. Move aggregate model classes into `compliance/db/models/.py` modules. +3. Delete the old `compliance/db/models.py` file in the same commit. + +Strategy uses a **re-export shim** so no import sites change: + +1. For each aggregate, create `compliance/db/models/.py` containing the model classes. Copy verbatim; do not rename `__tablename__`, columns, or relationship strings. +2. Aggregate suggestions (verify by reading `models.py`): + - `dsr.py` (DSR requests, exports) + - `dsfa.py` + - `vvt.py` + - `tom.py` + - `ai.py` (AI systems, compliance checks) + - `consent.py` + - `evidence.py` + - `vendor.py` + - `audit.py` + - `policy.py` + - `project.py` +3. After every aggregate is moved, replace `compliance/db/models.py` with: + ```python + """Re-export shim — see compliance.db.models package.""" + from compliance.db.models.dsr import * # noqa: F401,F403 + from compliance.db.models.dsfa import * # noqa: F401,F403 + # ... one per module + ``` + This keeps `from compliance.db.models import XYZ` working everywhere it's used today. +4. Run `pytest` after every move. Green → commit. Red → revert that move and investigate. +5. Existing aggregate-level files (`compliance/db/dsr_models.py`, `vvt_models.py`, `tom_models.py`, etc.) should be folded into the new `compliance/db/models/` package in the same pass — do not leave two parallel naming conventions. + +**Do not** add `__init__.py` star-imports that change `Base.metadata` discovery order. Alembic's autogenerate depends on it. Verify via: `alembic check` if the env is set up. + +## Step 3 — Split `compliance/api/schemas.py` (1899 → per domain) + +Mirror the models split: + +1. For each domain, create `compliance/schemas/.py` with the Pydantic models. +2. Replace `compliance/api/schemas.py` with a re-export shim. +3. Keep `Create`/`Update`/`Read` variants separated; do not merge them into unions. +4. Run `pytest` + contract test after each domain. Green → commit. + +## Step 4 — Extract services (router → service delegation) + +For each route file > 500 LOC, pull handler bodies into a service class under `compliance/services/_service.py` (new-style domain services, not the utility `compliance/services/` modules that already exist — consider renaming those to `compliance/services/_legacy/` if collisions arise). + +Router handlers become: + +```python +@router.post("/dsr/requests", response_model=DSRRequestRead, status_code=201) +async def create_dsr_request( + payload: DSRRequestCreate, + service: DSRService = Depends(get_dsr_service), + tenant_id: UUID = Depends(get_tenant_id), +) -> DSRRequestRead: + try: + return await service.create(tenant_id, payload) + except ConflictError as exc: + raise HTTPException(409, str(exc)) from exc + except NotFoundError as exc: + raise HTTPException(404, str(exc)) from exc +``` + +Rules: +- Handler body ≤ 30 LOC. +- Service raises domain errors (`compliance.domain`), never `HTTPException`. +- Inject service via `Depends` on a factory that wires the repository. + +Run tests after each router is thinned. Contract test must stay green. + +## Step 5 — Extract repositories + +`compliance/db/repository.py` (1547) and `compliance/db/isms_repository.py` (838) split into: + +``` +compliance/repositories/ +├── dsr_repository.py +├── dsfa_repository.py +├── vvt_repository.py +├── isms_repository.py # <500 LOC, split if needed +└── ... +``` + +Each repository class: +- Takes `AsyncSession` (or equivalent) in constructor. +- Exposes intent-named methods (`get_pending_for_tenant`, not `select_where`). +- Returns ORM instances or domain VOs. No `Row`. +- No business logic. + +Unit-test every repo class against the compose Postgres with a transactional fixture (begin → rollback). + +## Step 6 — mypy --strict on new packages + +CI already runs `mypy --strict` against `compliance/{services,repositories,domain,schemas}/`. After every extraction, verify locally: + +```bash +mypy --strict --ignore-missing-imports compliance/schemas compliance/repositories compliance/domain compliance/services +``` + +If you have type errors, fix them in the extracted module. **Do not** add `# type: ignore` blanket waivers. If a third-party lib is poorly typed, add it to `[mypy.overrides]` in `pyproject.toml`/`mypy.ini` with a one-line rationale. + +## Step 7 — Expand test coverage + +- Unit tests per service (mocked repo). +- Integration tests per repository (real db, transactional). +- Contract test stays green. +- Target: 80% coverage on new code. Never decrease the service baseline. + +## Step 8 — Guardrail enforcement + +After Phase 1 completes, `compliance/db/models.py`, `compliance/db/repository.py`, and `compliance/api/schemas.py` are either re-export shims (≤50 LOC each) or deleted. No file in `backend-compliance/compliance/` exceeds 500 LOC. Run: + +```bash +../scripts/check-loc.sh backend-compliance/ +``` + +Any remaining hard violations → document in `.claude/rules/loc-exceptions.txt` with rationale, or keep splitting. + +## Done when + +- `pytest compliance/tests/ tests/ -v` all green. +- `pytest tests/contracts/` green — OpenAPI has no removals, no renames, no new required request fields. +- Coverage ≥ baseline. +- `mypy --strict` clean on new packages. +- `scripts/check-loc.sh backend-compliance/` reports 0 hard violations in new/touched files (legacy allowlisted in `loc-exceptions.txt` only with rationale). +- CI all green on PR. + +## Pitfalls + +- **Do not change `__tablename__` or column names.** Even a rename breaks the DB contract. +- **Do not change relationship back_populates / backref strings.** SQLAlchemy resolves these by name at mapper configuration. +- **Do not change route paths or pydantic field names.** Contract test will catch most — but JSON field aliasing (`Field(alias=...)`) is easy to break accidentally. +- **Do not eagerly reformat unrelated code.** Keep the diff reviewable. One PR per major step. +- **Do not bypass the pre-commit hook.** If a file legitimately must be >500 LOC during an intermediate step, squash commits at the end so the final state is clean. diff --git a/backend-compliance/README.md b/backend-compliance/README.md new file mode 100644 index 0000000..ea5e9f0 --- /dev/null +++ b/backend-compliance/README.md @@ -0,0 +1,55 @@ +# backend-compliance + +Python/FastAPI service implementing the DSGVO compliance API: DSR, DSFA, consent, controls, risks, evidence, audit, vendor management, ISMS, change requests, document generation. + +**Port:** `8002` (container: `bp-compliance-backend`) +**Stack:** Python 3.12, FastAPI, SQLAlchemy 2.x, Alembic, Keycloak auth. + +## Architecture (target — Phase 1) + +``` +compliance/ +├── api/ # Routers (thin, ≤30 LOC per handler) +├── services/ # Business logic +├── repositories/ # DB access +├── domain/ # Value objects, domain errors +├── schemas/ # Pydantic models, split per domain +└── db/models/ # SQLAlchemy ORM, one module per aggregate +``` + +See `../AGENTS.python.md` for the full convention and `../.claude/rules/architecture.md` for the non-negotiable rules. + +## Run locally + +```bash +cd backend-compliance +pip install -r requirements.txt +export COMPLIANCE_DATABASE_URL=... # Postgres (Hetzner or local) +uvicorn main:app --reload --port 8002 +``` + +## Tests + +```bash +pytest compliance/tests/ -v +pytest --cov=compliance --cov-report=term-missing +``` + +Layout: `tests/unit/`, `tests/integration/`, `tests/contracts/`. Contract tests diff `/openapi.json` against `tests/contracts/openapi.baseline.json`. + +## Public API surface + +404+ endpoints across `/api/v1/*`. Grouped by domain: `ai`, `audit`, `consent`, `dsfa`, `dsr`, `gdpr`, `vendor`, `evidence`, `change-requests`, `generation`, `projects`, `company-profile`, `isms`. Every path is a contract — see the "Public endpoints" rule in the root `CLAUDE.md`. + +## Environment + +| Var | Purpose | +|-----|---------| +| `COMPLIANCE_DATABASE_URL` | Postgres DSN, `sslmode=require` | +| `KEYCLOAK_*` | Auth verification | +| `QDRANT_URL`, `QDRANT_API_KEY` | Vector search | +| `CORE_VALKEY_URL` | Session cache | + +## Don't touch + +Database schema, `__tablename__`, column names, existing migrations under `migrations/`. See root `CLAUDE.md` rule 3. diff --git a/backend-compliance/compliance/api/ai_routes.py b/backend-compliance/compliance/api/ai_routes.py index 875b0f8..6e2997f 100644 --- a/backend-compliance/compliance/api/ai_routes.py +++ b/backend-compliance/compliance/api/ai_routes.py @@ -186,7 +186,7 @@ async def update_ai_system( if hasattr(system, key): setattr(system, key, value) - system.updated_at = datetime.utcnow() + system.updated_at = datetime.now(timezone.utc) db.commit() db.refresh(system) @@ -266,7 +266,7 @@ async def assess_ai_system( except ValueError: system.classification = AIClassificationEnum.UNCLASSIFIED - system.assessment_date = datetime.utcnow() + system.assessment_date = datetime.now(timezone.utc) system.assessment_result = assessment_result system.obligations = _derive_obligations(classification) system.risk_factors = assessment_result.get("risk_factors", []) diff --git a/backend-compliance/compliance/api/audit_routes.py b/backend-compliance/compliance/api/audit_routes.py index 179fa9e..6e15cf2 100644 --- a/backend-compliance/compliance/api/audit_routes.py +++ b/backend-compliance/compliance/api/audit_routes.py @@ -9,7 +9,7 @@ Endpoints: """ import logging -from datetime import datetime +from datetime import datetime, timezone from typing import Optional, List from uuid import uuid4 import hashlib @@ -204,7 +204,7 @@ async def start_audit_session( ) session.status = AuditSessionStatusEnum.IN_PROGRESS - session.started_at = datetime.utcnow() + session.started_at = datetime.now(timezone.utc) db.commit() return {"success": True, "message": "Audit session started", "status": "in_progress"} @@ -229,7 +229,7 @@ async def complete_audit_session( ) session.status = AuditSessionStatusEnum.COMPLETED - session.completed_at = datetime.utcnow() + session.completed_at = datetime.now(timezone.utc) db.commit() return {"success": True, "message": "Audit session completed", "status": "completed"} @@ -482,7 +482,7 @@ async def sign_off_item( # Update existing sign-off signoff.result = result_enum signoff.notes = request.notes - signoff.updated_at = datetime.utcnow() + signoff.updated_at = datetime.now(timezone.utc) else: # Create new sign-off signoff = AuditSignOffDB( @@ -497,11 +497,11 @@ async def sign_off_item( # Create digital signature if requested signature = None if request.sign: - timestamp = datetime.utcnow().isoformat() + timestamp = datetime.now(timezone.utc).isoformat() data = f"{result_enum.value}|{requirement_id}|{session.auditor_name}|{timestamp}" signature = hashlib.sha256(data.encode()).hexdigest() signoff.signature_hash = signature - signoff.signed_at = datetime.utcnow() + signoff.signed_at = datetime.now(timezone.utc) signoff.signed_by = session.auditor_name # Update session statistics @@ -523,7 +523,7 @@ async def sign_off_item( # Auto-start session if this is the first sign-off if session.status == AuditSessionStatusEnum.DRAFT: session.status = AuditSessionStatusEnum.IN_PROGRESS - session.started_at = datetime.utcnow() + session.started_at = datetime.now(timezone.utc) db.commit() db.refresh(signoff) @@ -587,7 +587,7 @@ async def get_sign_off( @router.get("/sessions/{session_id}/report/pdf") async def generate_audit_pdf_report( session_id: str, - language: str = Query("de", regex="^(de|en)$"), + language: str = Query("de", pattern="^(de|en)$"), include_signatures: bool = Query(True), db: Session = Depends(get_db), ): diff --git a/backend-compliance/compliance/api/banner_routes.py b/backend-compliance/compliance/api/banner_routes.py index f57c89e..9acc2f4 100644 --- a/backend-compliance/compliance/api/banner_routes.py +++ b/backend-compliance/compliance/api/banner_routes.py @@ -6,7 +6,7 @@ Public SDK-Endpoints (fuer Einbettung) + Admin-Endpoints (Konfiguration & Stats) import uuid import hashlib -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone from typing import Optional, List from fastapi import APIRouter, Depends, HTTPException, Query, Header @@ -206,8 +206,8 @@ async def record_consent( existing.ip_hash = ip_hash existing.user_agent = body.user_agent existing.consent_string = body.consent_string - existing.expires_at = datetime.utcnow() + timedelta(days=365) - existing.updated_at = datetime.utcnow() + existing.expires_at = datetime.now(timezone.utc) + timedelta(days=365) + existing.updated_at = datetime.now(timezone.utc) db.flush() _log_banner_audit( @@ -227,7 +227,7 @@ async def record_consent( ip_hash=ip_hash, user_agent=body.user_agent, consent_string=body.consent_string, - expires_at=datetime.utcnow() + timedelta(days=365), + expires_at=datetime.now(timezone.utc) + timedelta(days=365), ) db.add(consent) db.flush() @@ -476,7 +476,7 @@ async def update_site_config( if val is not None: setattr(config, field, val) - config.updated_at = datetime.utcnow() + config.updated_at = datetime.now(timezone.utc) db.commit() db.refresh(config) return _site_config_to_dict(config) diff --git a/backend-compliance/compliance/api/consent_template_routes.py b/backend-compliance/compliance/api/consent_template_routes.py index 930da4c..712ee38 100644 --- a/backend-compliance/compliance/api/consent_template_routes.py +++ b/backend-compliance/compliance/api/consent_template_routes.py @@ -11,7 +11,7 @@ Endpoints: """ import logging -from datetime import datetime +from datetime import datetime, timezone from typing import Optional from fastapi import APIRouter, Depends, HTTPException, Header @@ -173,7 +173,7 @@ async def update_consent_template( set_clauses = ", ".join(f"{k} = :{k}" for k in updates) updates["id"] = template_id updates["tenant_id"] = tenant_id - updates["now"] = datetime.utcnow() + updates["now"] = datetime.now(timezone.utc) row = db.execute( text(f""" diff --git a/backend-compliance/compliance/api/control_generator_routes.py b/backend-compliance/compliance/api/control_generator_routes.py index e76df1f..97231c7 100644 --- a/backend-compliance/compliance/api/control_generator_routes.py +++ b/backend-compliance/compliance/api/control_generator_routes.py @@ -186,7 +186,7 @@ async def list_jobs( @router.get("/generate/review-queue") async def get_review_queue( - release_state: str = Query("needs_review", regex="^(needs_review|too_close|duplicate)$"), + release_state: str = Query("needs_review", pattern="^(needs_review|too_close|duplicate)$"), limit: int = Query(50, ge=1, le=200), ): """Get controls that need manual review.""" diff --git a/backend-compliance/compliance/api/crud_factory.py b/backend-compliance/compliance/api/crud_factory.py index 3e5de2d..a08ad3f 100644 --- a/backend-compliance/compliance/api/crud_factory.py +++ b/backend-compliance/compliance/api/crud_factory.py @@ -20,7 +20,7 @@ Usage: """ import logging -from datetime import datetime +from datetime import datetime, timezone from typing import Any, Dict, List, Optional from fastapi import APIRouter, Depends, HTTPException, Query @@ -171,7 +171,7 @@ def create_crud_router( updates: Dict[str, Any] = { "id": item_id, "tenant_id": tenant_id, - "updated_at": datetime.utcnow(), + "updated_at": datetime.now(timezone.utc), } set_clauses = ["updated_at = :updated_at"] diff --git a/backend-compliance/compliance/api/dashboard_routes.py b/backend-compliance/compliance/api/dashboard_routes.py index 182876d..ffa4128 100644 --- a/backend-compliance/compliance/api/dashboard_routes.py +++ b/backend-compliance/compliance/api/dashboard_routes.py @@ -10,7 +10,7 @@ Endpoints: """ import logging -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone from calendar import month_abbr from typing import Optional @@ -167,7 +167,7 @@ async def get_executive_dashboard(db: Session = Depends(get_db)): # Trend data — only show current score, no simulated history trend_data = [] if total > 0: - now = datetime.utcnow() + now = datetime.now(timezone.utc) trend_data.append(TrendDataPoint( date=now.strftime("%Y-%m-%d"), score=round(score, 1), @@ -204,7 +204,7 @@ async def get_executive_dashboard(db: Session = Depends(get_db)): # Get upcoming deadlines controls = ctrl_repo.get_all() upcoming_deadlines = [] - today = datetime.utcnow().date() + today = datetime.now(timezone.utc).date() for ctrl in controls: if ctrl.next_review_at: @@ -280,7 +280,7 @@ async def get_executive_dashboard(db: Session = Depends(get_db)): top_risks=top_risks, upcoming_deadlines=upcoming_deadlines, team_workload=team_workload, - last_updated=datetime.utcnow().isoformat(), + last_updated=datetime.now(timezone.utc).isoformat(), ) @@ -305,7 +305,7 @@ async def get_compliance_trend( # Trend data — only current score, no simulated history trend_data = [] if total > 0: - now = datetime.utcnow() + now = datetime.now(timezone.utc) trend_data.append({ "date": now.strftime("%Y-%m-%d"), "score": round(current_score, 1), @@ -318,7 +318,7 @@ async def get_compliance_trend( "current_score": round(current_score, 1), "trend": trend_data, "period_months": months, - "generated_at": datetime.utcnow().isoformat(), + "generated_at": datetime.now(timezone.utc).isoformat(), } diff --git a/backend-compliance/compliance/api/dsfa_routes.py b/backend-compliance/compliance/api/dsfa_routes.py index dcd9ce7..b9e3ca7 100644 --- a/backend-compliance/compliance/api/dsfa_routes.py +++ b/backend-compliance/compliance/api/dsfa_routes.py @@ -20,7 +20,7 @@ Endpoints: """ import logging -from datetime import datetime +from datetime import datetime, timezone from typing import Optional, List from fastapi import APIRouter, Depends, HTTPException, Query @@ -691,7 +691,7 @@ async def update_dsfa_status( params: dict = { "id": dsfa_id, "tid": tid, "status": request.status, - "approved_at": datetime.utcnow() if request.status == "approved" else None, + "approved_at": datetime.now(timezone.utc) if request.status == "approved" else None, "approved_by": request.approved_by, } row = db.execute( @@ -906,7 +906,7 @@ async def export_dsfa_json( dsfa_data = _dsfa_to_response(row) return { - "exported_at": datetime.utcnow().isoformat(), + "exported_at": datetime.now(timezone.utc).isoformat(), "format": format, "dsfa": dsfa_data, } diff --git a/backend-compliance/compliance/api/dsr_routes.py b/backend-compliance/compliance/api/dsr_routes.py index 776de71..506c1e4 100644 --- a/backend-compliance/compliance/api/dsr_routes.py +++ b/backend-compliance/compliance/api/dsr_routes.py @@ -7,7 +7,7 @@ Native Python/FastAPI Implementierung, ersetzt Go consent-service Proxy. import io import csv import uuid -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone from typing import Optional, List, Dict, Any from fastapi import APIRouter, Depends, HTTPException, Query, Header @@ -168,7 +168,7 @@ def _get_tenant(x_tenant_id: Optional[str] = Header(None, alias='X-Tenant-ID')) def _generate_request_number(db: Session, tenant_id: str) -> str: """Generate next request number: DSR-YYYY-NNNNNN""" - year = datetime.utcnow().year + year = datetime.now(timezone.utc).year try: result = db.execute(text("SELECT nextval('compliance_dsr_request_number_seq')")) seq = result.scalar() @@ -275,7 +275,7 @@ async def create_dsr( if body.priority and body.priority not in VALID_PRIORITIES: raise HTTPException(status_code=400, detail=f"Invalid priority. Must be one of: {VALID_PRIORITIES}") - now = datetime.utcnow() + now = datetime.now(timezone.utc) deadline_days = DEADLINE_DAYS.get(body.request_type, 30) request_number = _generate_request_number(db, tenant_id) @@ -348,7 +348,7 @@ async def list_dsrs( query = query.filter(DSRRequestDB.priority == priority) if overdue_only: query = query.filter( - DSRRequestDB.deadline_at < datetime.utcnow(), + DSRRequestDB.deadline_at < datetime.now(timezone.utc), DSRRequestDB.status.notin_(["completed", "rejected", "cancelled"]), ) if search: @@ -399,7 +399,7 @@ async def get_dsr_stats( by_type[t] = base.filter(DSRRequestDB.request_type == t).count() # Overdue - now = datetime.utcnow() + now = datetime.now(timezone.utc) overdue = base.filter( DSRRequestDB.deadline_at < now, DSRRequestDB.status.notin_(["completed", "rejected", "cancelled"]), @@ -459,7 +459,7 @@ async def export_dsrs( if format == "json": return { - "exported_at": datetime.utcnow().isoformat(), + "exported_at": datetime.now(timezone.utc).isoformat(), "total": len(dsrs), "requests": [_dsr_to_dict(d) for d in dsrs], } @@ -506,7 +506,7 @@ async def process_deadlines( db: Session = Depends(get_db), ): """Verarbeitet Fristen und markiert ueberfaellige DSRs.""" - now = datetime.utcnow() + now = datetime.now(timezone.utc) tid = uuid.UUID(tenant_id) overdue = db.query(DSRRequestDB).filter( @@ -714,7 +714,7 @@ async def publish_template_version( if not version: raise HTTPException(status_code=404, detail="Version not found") - now = datetime.utcnow() + now = datetime.now(timezone.utc) version.status = "published" version.published_at = now version.published_by = "admin" @@ -766,7 +766,7 @@ async def update_dsr( dsr.internal_notes = body.internal_notes if body.assigned_to is not None: dsr.assigned_to = body.assigned_to - dsr.assigned_at = datetime.utcnow() + dsr.assigned_at = datetime.now(timezone.utc) if body.request_text is not None: dsr.request_text = body.request_text if body.affected_systems is not None: @@ -778,7 +778,7 @@ async def update_dsr( if body.objection_details is not None: dsr.objection_details = body.objection_details - dsr.updated_at = datetime.utcnow() + dsr.updated_at = datetime.now(timezone.utc) db.commit() db.refresh(dsr) return _dsr_to_dict(dsr) @@ -797,7 +797,7 @@ async def delete_dsr( _record_history(db, dsr, "cancelled", comment="DSR storniert") dsr.status = "cancelled" - dsr.updated_at = datetime.utcnow() + dsr.updated_at = datetime.now(timezone.utc) db.commit() return {"success": True, "message": "DSR cancelled"} @@ -820,7 +820,7 @@ async def change_status( dsr = _get_dsr_or_404(db, dsr_id, tenant_id) _record_history(db, dsr, body.status, comment=body.comment) dsr.status = body.status - dsr.updated_at = datetime.utcnow() + dsr.updated_at = datetime.now(timezone.utc) db.commit() db.refresh(dsr) return _dsr_to_dict(dsr) @@ -835,7 +835,7 @@ async def verify_identity( ): """Verifiziert die Identitaet des Antragstellers.""" dsr = _get_dsr_or_404(db, dsr_id, tenant_id) - now = datetime.utcnow() + now = datetime.now(timezone.utc) dsr.identity_verified = True dsr.verification_method = body.method @@ -868,9 +868,9 @@ async def assign_dsr( """Weist eine DSR einem Bearbeiter zu.""" dsr = _get_dsr_or_404(db, dsr_id, tenant_id) dsr.assigned_to = body.assignee_id - dsr.assigned_at = datetime.utcnow() + dsr.assigned_at = datetime.now(timezone.utc) dsr.assigned_by = "admin" - dsr.updated_at = datetime.utcnow() + dsr.updated_at = datetime.now(timezone.utc) db.commit() db.refresh(dsr) return _dsr_to_dict(dsr) @@ -888,7 +888,7 @@ async def extend_deadline( if dsr.status in ("completed", "rejected", "cancelled"): raise HTTPException(status_code=400, detail="Cannot extend deadline for closed DSR") - now = datetime.utcnow() + now = datetime.now(timezone.utc) current_deadline = dsr.extended_deadline_at or dsr.deadline_at new_deadline = current_deadline + timedelta(days=body.days or 60) @@ -916,7 +916,7 @@ async def complete_dsr( if dsr.status in ("completed", "cancelled"): raise HTTPException(status_code=400, detail="DSR already completed or cancelled") - now = datetime.utcnow() + now = datetime.now(timezone.utc) _record_history(db, dsr, "completed", comment=body.summary) dsr.status = "completed" dsr.completed_at = now @@ -941,7 +941,7 @@ async def reject_dsr( if dsr.status in ("completed", "rejected", "cancelled"): raise HTTPException(status_code=400, detail="DSR already closed") - now = datetime.utcnow() + now = datetime.now(timezone.utc) _record_history(db, dsr, "rejected", comment=f"{body.reason} ({body.legal_basis})") dsr.status = "rejected" dsr.rejection_reason = body.reason @@ -1024,7 +1024,7 @@ async def send_communication( ): """Sendet eine Kommunikation.""" dsr = _get_dsr_or_404(db, dsr_id, tenant_id) - now = datetime.utcnow() + now = datetime.now(timezone.utc) comm = DSRCommunicationDB( tenant_id=uuid.UUID(tenant_id), @@ -1158,7 +1158,7 @@ async def update_exception_check( check.applies = body.applies check.notes = body.notes check.checked_by = "admin" - check.checked_at = datetime.utcnow() + check.checked_at = datetime.now(timezone.utc) db.commit() db.refresh(check) diff --git a/backend-compliance/compliance/api/einwilligungen_routes.py b/backend-compliance/compliance/api/einwilligungen_routes.py index 2e25913..964e1af 100644 --- a/backend-compliance/compliance/api/einwilligungen_routes.py +++ b/backend-compliance/compliance/api/einwilligungen_routes.py @@ -15,7 +15,7 @@ Endpoints: """ import logging -from datetime import datetime +from datetime import datetime, timezone from typing import Optional, List, Any, Dict from fastapi import APIRouter, Depends, HTTPException, Query, Header @@ -131,7 +131,7 @@ async def upsert_catalog( if record: record.selected_data_point_ids = request.selected_data_point_ids record.custom_data_points = request.custom_data_points - record.updated_at = datetime.utcnow() + record.updated_at = datetime.now(timezone.utc) else: record = EinwilligungenCatalogDB( tenant_id=tenant_id, @@ -184,7 +184,7 @@ async def upsert_company( if record: record.data = request.data - record.updated_at = datetime.utcnow() + record.updated_at = datetime.now(timezone.utc) else: record = EinwilligungenCompanyDB(tenant_id=tenant_id, data=request.data) db.add(record) @@ -233,7 +233,7 @@ async def upsert_cookies( if record: record.categories = request.categories record.config = request.config - record.updated_at = datetime.utcnow() + record.updated_at = datetime.now(timezone.utc) else: record = EinwilligungenCookiesDB( tenant_id=tenant_id, @@ -374,7 +374,7 @@ async def create_consent( user_id=request.user_id, data_point_id=request.data_point_id, granted=request.granted, - granted_at=datetime.utcnow(), + granted_at=datetime.now(timezone.utc), consent_version=request.consent_version, source=request.source, ip_address=request.ip_address, @@ -443,7 +443,7 @@ async def revoke_consent( if consent.revoked_at: raise HTTPException(status_code=400, detail="Consent is already revoked") - consent.revoked_at = datetime.utcnow() + consent.revoked_at = datetime.now(timezone.utc) _record_history(db, consent, 'revoked') db.commit() db.refresh(consent) diff --git a/backend-compliance/compliance/api/email_template_routes.py b/backend-compliance/compliance/api/email_template_routes.py index 2af10a5..0592784 100644 --- a/backend-compliance/compliance/api/email_template_routes.py +++ b/backend-compliance/compliance/api/email_template_routes.py @@ -6,7 +6,7 @@ Inklusive Versionierung, Approval-Workflow, Vorschau und Send-Logging. """ import uuid -from datetime import datetime +from datetime import datetime, timezone from typing import Optional, Dict from fastapi import APIRouter, Depends, HTTPException, Query, Header @@ -271,7 +271,7 @@ async def update_settings( if val is not None: setattr(settings, field, val) - settings.updated_at = datetime.utcnow() + settings.updated_at = datetime.now(timezone.utc) db.commit() db.refresh(settings) @@ -638,7 +638,7 @@ async def submit_version( raise HTTPException(status_code=400, detail="Only draft versions can be submitted") v.status = "review" - v.submitted_at = datetime.utcnow() + v.submitted_at = datetime.now(timezone.utc) v.submitted_by = "admin" db.commit() db.refresh(v) @@ -730,7 +730,7 @@ async def publish_version( if v.status not in ("approved", "review", "draft"): raise HTTPException(status_code=400, detail="Version cannot be published") - now = datetime.utcnow() + now = datetime.now(timezone.utc) v.status = "published" v.published_at = now v.published_by = "admin" diff --git a/backend-compliance/compliance/api/escalation_routes.py b/backend-compliance/compliance/api/escalation_routes.py index 3a7e03c..492acc3 100644 --- a/backend-compliance/compliance/api/escalation_routes.py +++ b/backend-compliance/compliance/api/escalation_routes.py @@ -12,7 +12,7 @@ Endpoints: """ import logging -from datetime import datetime +from datetime import datetime, timezone from typing import Optional, Any, Dict from fastapi import APIRouter, Depends, HTTPException, Query, Header @@ -244,7 +244,7 @@ async def update_escalation( set_clauses = ", ".join(f"{k} = :{k}" for k in updates.keys()) updates["id"] = escalation_id - updates["updated_at"] = datetime.utcnow() + updates["updated_at"] = datetime.now(timezone.utc) row = db.execute( text( @@ -277,7 +277,7 @@ async def update_status( resolved_at = request.resolved_at if request.status in ('resolved', 'closed') and resolved_at is None: - resolved_at = datetime.utcnow() + resolved_at = datetime.now(timezone.utc) row = db.execute( text( @@ -288,7 +288,7 @@ async def update_status( { "status": request.status, "resolved_at": resolved_at, - "updated_at": datetime.utcnow(), + "updated_at": datetime.now(timezone.utc), "id": escalation_id, }, ).fetchone() diff --git a/backend-compliance/compliance/api/evidence_routes.py b/backend-compliance/compliance/api/evidence_routes.py index 4c202a1..b37f55d 100644 --- a/backend-compliance/compliance/api/evidence_routes.py +++ b/backend-compliance/compliance/api/evidence_routes.py @@ -10,7 +10,7 @@ Endpoints: import logging import os -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone from typing import Optional from collections import defaultdict import uuid as uuid_module @@ -370,8 +370,8 @@ def _store_evidence( mime_type="application/json", source="ci_pipeline", ci_job_id=ci_job_id, - valid_from=datetime.utcnow(), - valid_until=datetime.utcnow() + timedelta(days=90), + valid_from=datetime.now(timezone.utc), + valid_until=datetime.now(timezone.utc) + timedelta(days=90), status=EvidenceStatusEnum(parsed["evidence_status"]), ) db.add(evidence) @@ -455,7 +455,7 @@ def _update_risks(db: Session, *, source: str, control_id: str, ci_job_id: str, tool=source, control_id=control_id, evidence_type=f"ci_{source}", - timestamp=datetime.utcnow().isoformat(), + timestamp=datetime.now(timezone.utc).isoformat(), commit_sha=report_data.get("commit_sha", "unknown") if report_data else "unknown", ci_job_id=ci_job_id, findings=findings_detail, @@ -571,7 +571,7 @@ async def get_ci_evidence_status( Returns overview of recent evidence collected from CI/CD pipelines, useful for dashboards and monitoring. """ - cutoff_date = datetime.utcnow() - timedelta(days=days) + cutoff_date = datetime.now(timezone.utc) - timedelta(days=days) # Build query query = db.query(EvidenceDB).filter( diff --git a/backend-compliance/compliance/api/extraction_routes.py b/backend-compliance/compliance/api/extraction_routes.py index fd2bcc3..111d6d9 100644 --- a/backend-compliance/compliance/api/extraction_routes.py +++ b/backend-compliance/compliance/api/extraction_routes.py @@ -18,7 +18,7 @@ import logging import re import asyncio from typing import Optional, List, Dict -from datetime import datetime +from datetime import datetime, timezone from fastapi import APIRouter, Depends from pydantic import BaseModel @@ -171,7 +171,7 @@ def _get_or_create_regulation( code=regulation_code, name=regulation_name or regulation_code, regulation_type=reg_type, - description=f"Auto-created from RAG extraction ({datetime.utcnow().date()})", + description=f"Auto-created from RAG extraction ({datetime.now(timezone.utc).date()})", ) return reg diff --git a/backend-compliance/compliance/api/isms_routes.py b/backend-compliance/compliance/api/isms_routes.py index 31c2b43..c43c0f1 100644 --- a/backend-compliance/compliance/api/isms_routes.py +++ b/backend-compliance/compliance/api/isms_routes.py @@ -13,7 +13,7 @@ Provides endpoints for ISO 27001 certification-ready ISMS management: import uuid import hashlib -from datetime import datetime, date +from datetime import datetime, date, timezone from typing import Optional from fastapi import APIRouter, HTTPException, Query, Depends @@ -102,7 +102,7 @@ def log_audit_trail( new_value=new_value, change_summary=change_summary, performed_by=performed_by, - performed_at=datetime.utcnow(), + performed_at=datetime.now(timezone.utc), checksum=create_signature(f"{entity_type}|{entity_id}|{action}|{performed_by}") ) db.add(trail) @@ -190,7 +190,7 @@ async def update_isms_scope( setattr(scope, field, value) scope.updated_by = updated_by - scope.updated_at = datetime.utcnow() + scope.updated_at = datetime.now(timezone.utc) # Increment version if significant changes version_parts = scope.version.split(".") @@ -221,11 +221,11 @@ async def approve_isms_scope( scope.status = ApprovalStatusEnum.APPROVED scope.approved_by = data.approved_by - scope.approved_at = datetime.utcnow() + scope.approved_at = datetime.now(timezone.utc) scope.effective_date = data.effective_date scope.review_date = data.review_date scope.approval_signature = create_signature( - f"{scope.scope_statement}|{data.approved_by}|{datetime.utcnow().isoformat()}" + f"{scope.scope_statement}|{data.approved_by}|{datetime.now(timezone.utc).isoformat()}" ) log_audit_trail(db, "isms_scope", scope.id, "ISMS Scope", "approve", data.approved_by) @@ -403,7 +403,7 @@ async def approve_policy( policy.reviewed_by = data.reviewed_by policy.approved_by = data.approved_by - policy.approved_at = datetime.utcnow() + policy.approved_at = datetime.now(timezone.utc) policy.effective_date = data.effective_date policy.next_review_date = date( data.effective_date.year + (policy.review_frequency_months // 12), @@ -412,7 +412,7 @@ async def approve_policy( ) policy.status = ApprovalStatusEnum.APPROVED policy.approval_signature = create_signature( - f"{policy.policy_id}|{data.approved_by}|{datetime.utcnow().isoformat()}" + f"{policy.policy_id}|{data.approved_by}|{datetime.now(timezone.utc).isoformat()}" ) log_audit_trail(db, "isms_policy", policy.id, policy.policy_id, "approve", data.approved_by) @@ -634,9 +634,9 @@ async def approve_soa_entry( raise HTTPException(status_code=404, detail="SoA entry not found") entry.reviewed_by = data.reviewed_by - entry.reviewed_at = datetime.utcnow() + entry.reviewed_at = datetime.now(timezone.utc) entry.approved_by = data.approved_by - entry.approved_at = datetime.utcnow() + entry.approved_at = datetime.now(timezone.utc) log_audit_trail(db, "soa", entry.id, entry.annex_a_control, "approve", data.approved_by) db.commit() @@ -812,7 +812,7 @@ async def close_finding( finding.verification_method = data.verification_method finding.verification_evidence = data.verification_evidence finding.verified_by = data.closed_by - finding.verified_at = datetime.utcnow() + finding.verified_at = datetime.now(timezone.utc) log_audit_trail(db, "audit_finding", finding.id, finding.finding_id, "close", data.closed_by) db.commit() @@ -1080,7 +1080,7 @@ async def approve_management_review( review.status = "approved" review.approved_by = data.approved_by - review.approved_at = datetime.utcnow() + review.approved_at = datetime.now(timezone.utc) review.next_review_date = data.next_review_date review.minutes_document_path = data.minutes_document_path @@ -1392,7 +1392,7 @@ async def run_readiness_check( # Save check result check = ISMSReadinessCheckDB( id=generate_id(), - check_date=datetime.utcnow(), + check_date=datetime.now(timezone.utc), triggered_by=data.triggered_by, overall_status=overall_status, certification_possible=certification_possible, diff --git a/backend-compliance/compliance/api/legal_document_routes.py b/backend-compliance/compliance/api/legal_document_routes.py index dd5286f..3750853 100644 --- a/backend-compliance/compliance/api/legal_document_routes.py +++ b/backend-compliance/compliance/api/legal_document_routes.py @@ -6,7 +6,7 @@ Extended with: Public endpoints, User Consents, Consent Audit Log, Cookie Catego import uuid as uuid_mod import logging -from datetime import datetime +from datetime import datetime, timezone from typing import Optional, List, Any, Dict from fastapi import APIRouter, Depends, HTTPException, Query, Header, UploadFile, File @@ -285,7 +285,7 @@ async def update_version( for field, value in request.dict(exclude_none=True).items(): setattr(version, field, value) - version.updated_at = datetime.utcnow() + version.updated_at = datetime.now(timezone.utc) db.commit() db.refresh(version) @@ -346,7 +346,7 @@ def _transition( ) version.status = to_status - version.updated_at = datetime.utcnow() + version.updated_at = datetime.now(timezone.utc) if extra_updates: for k, v in extra_updates.items(): setattr(version, k, v) @@ -378,7 +378,7 @@ async def approve_version( return _transition( db, version_id, ['review'], 'approved', 'approved', request.approver, request.comment, - extra_updates={'approved_by': request.approver, 'approved_at': datetime.utcnow()} + extra_updates={'approved_by': request.approver, 'approved_at': datetime.now(timezone.utc)} ) @@ -728,7 +728,7 @@ async def withdraw_consent( if consent.withdrawn_at: raise HTTPException(status_code=400, detail="Consent already withdrawn") - consent.withdrawn_at = datetime.utcnow() + consent.withdrawn_at = datetime.now(timezone.utc) consent.consented = False _log_consent_audit( @@ -903,7 +903,7 @@ async def update_cookie_category( if val is not None: setattr(cat, field, val) - cat.updated_at = datetime.utcnow() + cat.updated_at = datetime.now(timezone.utc) db.commit() db.refresh(cat) return _cookie_cat_to_dict(cat) diff --git a/backend-compliance/compliance/api/legal_template_routes.py b/backend-compliance/compliance/api/legal_template_routes.py index 9fb14b2..73f7c5e 100644 --- a/backend-compliance/compliance/api/legal_template_routes.py +++ b/backend-compliance/compliance/api/legal_template_routes.py @@ -15,7 +15,7 @@ Endpoints: import json import logging -from datetime import datetime +from datetime import datetime, timezone from typing import Optional, List, Any, Dict from fastapi import APIRouter, Depends, HTTPException, Query @@ -322,7 +322,7 @@ async def update_legal_template( params: Dict[str, Any] = { "id": template_id, "tenant_id": tenant_id, - "updated_at": datetime.utcnow(), + "updated_at": datetime.now(timezone.utc), } jsonb_fields = {"placeholders", "inspiration_sources"} diff --git a/backend-compliance/compliance/api/loeschfristen_routes.py b/backend-compliance/compliance/api/loeschfristen_routes.py index 3d01490..cfa6b72 100644 --- a/backend-compliance/compliance/api/loeschfristen_routes.py +++ b/backend-compliance/compliance/api/loeschfristen_routes.py @@ -13,7 +13,7 @@ Endpoints: import json import logging -from datetime import datetime +from datetime import datetime, timezone from typing import Optional, List, Any, Dict from fastapi import APIRouter, Depends, HTTPException, Query @@ -253,7 +253,7 @@ async def update_loeschfrist( ): """Full update of a Loeschfrist policy.""" - updates: Dict[str, Any] = {"id": policy_id, "tenant_id": tenant_id, "updated_at": datetime.utcnow()} + updates: Dict[str, Any] = {"id": policy_id, "tenant_id": tenant_id, "updated_at": datetime.now(timezone.utc)} set_clauses = ["updated_at = :updated_at"] for field, value in payload.model_dump(exclude_unset=True).items(): @@ -302,7 +302,7 @@ async def update_loeschfrist_status( WHERE id = :id AND tenant_id = :tenant_id RETURNING * """), - {"status": payload.status, "now": datetime.utcnow(), "id": policy_id, "tenant_id": tenant_id}, + {"status": payload.status, "now": datetime.now(timezone.utc), "id": policy_id, "tenant_id": tenant_id}, ).fetchone() db.commit() diff --git a/backend-compliance/compliance/api/notfallplan_routes.py b/backend-compliance/compliance/api/notfallplan_routes.py index 494815c..9699106 100644 --- a/backend-compliance/compliance/api/notfallplan_routes.py +++ b/backend-compliance/compliance/api/notfallplan_routes.py @@ -21,7 +21,7 @@ Endpoints: import json import logging -from datetime import datetime +from datetime import datetime, timezone from typing import Optional, List, Any from fastapi import APIRouter, Depends, HTTPException, Query, Header @@ -852,11 +852,11 @@ async def update_incident( # Auto-set timestamps based on status transitions if updates.get("status") == "reported" and not updates.get("reported_to_authority_at"): - updates["reported_to_authority_at"] = datetime.utcnow().isoformat() + updates["reported_to_authority_at"] = datetime.now(timezone.utc).isoformat() if updates.get("status") == "closed" and not updates.get("closed_at"): - updates["closed_at"] = datetime.utcnow().isoformat() + updates["closed_at"] = datetime.now(timezone.utc).isoformat() - updates["updated_at"] = datetime.utcnow().isoformat() + updates["updated_at"] = datetime.now(timezone.utc).isoformat() set_parts = [] for k in updates: @@ -984,7 +984,7 @@ async def update_template( if not updates: raise HTTPException(status_code=400, detail="No fields to update") - updates["updated_at"] = datetime.utcnow().isoformat() + updates["updated_at"] = datetime.now(timezone.utc).isoformat() set_clauses = ", ".join(f"{k} = :{k}" for k in updates) updates["id"] = template_id updates["tenant_id"] = tenant_id diff --git a/backend-compliance/compliance/api/obligation_routes.py b/backend-compliance/compliance/api/obligation_routes.py index 0aece4b..f25363d 100644 --- a/backend-compliance/compliance/api/obligation_routes.py +++ b/backend-compliance/compliance/api/obligation_routes.py @@ -12,7 +12,7 @@ Endpoints: """ import logging -from datetime import datetime +from datetime import datetime, timezone from typing import Optional, List, Any, Dict from fastapi import APIRouter, Depends, HTTPException, Query, Header @@ -228,7 +228,7 @@ async def update_obligation( logger.info("update_obligation user_id=%s tenant_id=%s id=%s", x_user_id, tenant_id, obligation_id) import json - updates: Dict[str, Any] = {"id": obligation_id, "tenant_id": tenant_id, "updated_at": datetime.utcnow()} + updates: Dict[str, Any] = {"id": obligation_id, "tenant_id": tenant_id, "updated_at": datetime.now(timezone.utc)} set_clauses = ["updated_at = :updated_at"] for field, value in payload.model_dump(exclude_unset=True).items(): @@ -274,7 +274,7 @@ async def update_obligation_status( SET status = :status, updated_at = :now WHERE id = :id AND tenant_id = :tenant_id RETURNING * - """), {"status": payload.status, "now": datetime.utcnow(), "id": obligation_id, "tenant_id": tenant_id}).fetchone() + """), {"status": payload.status, "now": datetime.now(timezone.utc), "id": obligation_id, "tenant_id": tenant_id}).fetchone() db.commit() if not row: diff --git a/backend-compliance/compliance/api/quality_routes.py b/backend-compliance/compliance/api/quality_routes.py index 57b4c06..cf0e41b 100644 --- a/backend-compliance/compliance/api/quality_routes.py +++ b/backend-compliance/compliance/api/quality_routes.py @@ -10,7 +10,7 @@ Endpoints: """ import logging -from datetime import datetime +from datetime import datetime, timezone from typing import Optional, Any, Dict from fastapi import APIRouter, Depends, HTTPException, Query @@ -177,7 +177,7 @@ async def create_metric( "threshold": payload.threshold, "trend": payload.trend, "ai_system": payload.ai_system, - "last_measured": payload.last_measured or datetime.utcnow(), + "last_measured": payload.last_measured or datetime.now(timezone.utc), }).fetchone() db.commit() return _row_to_dict(row) @@ -192,7 +192,7 @@ async def update_metric( ): """Update a quality metric.""" - updates: Dict[str, Any] = {"id": metric_id, "tenant_id": tenant_id, "updated_at": datetime.utcnow()} + updates: Dict[str, Any] = {"id": metric_id, "tenant_id": tenant_id, "updated_at": datetime.now(timezone.utc)} set_clauses = ["updated_at = :updated_at"] for field, value in payload.model_dump(exclude_unset=True).items(): @@ -296,7 +296,7 @@ async def create_test( "duration": payload.duration, "ai_system": payload.ai_system, "details": payload.details, - "last_run": payload.last_run or datetime.utcnow(), + "last_run": payload.last_run or datetime.now(timezone.utc), }).fetchone() db.commit() return _row_to_dict(row) @@ -311,7 +311,7 @@ async def update_test( ): """Update a quality test.""" - updates: Dict[str, Any] = {"id": test_id, "tenant_id": tenant_id, "updated_at": datetime.utcnow()} + updates: Dict[str, Any] = {"id": test_id, "tenant_id": tenant_id, "updated_at": datetime.now(timezone.utc)} set_clauses = ["updated_at = :updated_at"] for field, value in payload.model_dump(exclude_unset=True).items(): diff --git a/backend-compliance/compliance/api/routes.py b/backend-compliance/compliance/api/routes.py index 4edbec9..6c97915 100644 --- a/backend-compliance/compliance/api/routes.py +++ b/backend-compliance/compliance/api/routes.py @@ -16,7 +16,7 @@ import logging logger = logging.getLogger(__name__) import os -from datetime import datetime +from datetime import datetime, timezone from typing import Optional from fastapi import APIRouter, Depends, HTTPException, Query, BackgroundTasks @@ -393,11 +393,11 @@ async def update_requirement(requirement_id: str, updates: dict, db: Session = D # Track audit changes if 'audit_status' in updates: - requirement.last_audit_date = datetime.utcnow() + requirement.last_audit_date = datetime.now(timezone.utc) # TODO: Get auditor from auth requirement.last_auditor = updates.get('auditor_name', 'api_user') - requirement.updated_at = datetime.utcnow() + requirement.updated_at = datetime.now(timezone.utc) db.commit() db.refresh(requirement) diff --git a/backend-compliance/compliance/api/security_backlog_routes.py b/backend-compliance/compliance/api/security_backlog_routes.py index 11bf968..1473fd9 100644 --- a/backend-compliance/compliance/api/security_backlog_routes.py +++ b/backend-compliance/compliance/api/security_backlog_routes.py @@ -10,7 +10,7 @@ Endpoints: """ import logging -from datetime import datetime +from datetime import datetime, timezone from typing import Optional, Any, Dict from fastapi import APIRouter, Depends, HTTPException, Query @@ -207,7 +207,7 @@ async def update_security_item( ): """Update a security backlog item.""" - updates: Dict[str, Any] = {"id": item_id, "tenant_id": tenant_id, "updated_at": datetime.utcnow()} + updates: Dict[str, Any] = {"id": item_id, "tenant_id": tenant_id, "updated_at": datetime.now(timezone.utc)} set_clauses = ["updated_at = :updated_at"] for field, value in payload.model_dump(exclude_unset=True).items(): diff --git a/backend-compliance/compliance/api/source_policy_router.py b/backend-compliance/compliance/api/source_policy_router.py index 7cdb2e9..57e0308 100644 --- a/backend-compliance/compliance/api/source_policy_router.py +++ b/backend-compliance/compliance/api/source_policy_router.py @@ -21,11 +21,11 @@ Endpoints: GET /api/v1/admin/compliance-report — Compliance report """ -from datetime import datetime +from datetime import datetime, timezone from typing import Optional from fastapi import APIRouter, HTTPException, Depends, Query -from pydantic import BaseModel, Field +from pydantic import BaseModel, ConfigDict, Field from sqlalchemy.orm import Session from database import get_db @@ -83,8 +83,7 @@ class SourceResponse(BaseModel): created_at: str updated_at: Optional[str] = None - class Config: - from_attributes = True + model_config = ConfigDict(from_attributes=True) class OperationUpdate(BaseModel): @@ -530,7 +529,7 @@ async def get_policy_stats(db: Session = Depends(get_db)): pii_rules = db.query(PIIRuleDB).filter(PIIRuleDB.active).count() # Count blocked content entries from today - today_start = datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0) + today_start = datetime.now(timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0) blocked_today = db.query(BlockedContentDB).filter( BlockedContentDB.created_at >= today_start, ).count() @@ -553,7 +552,7 @@ async def get_compliance_report(db: Session = Depends(get_db)): pii_rules = db.query(PIIRuleDB).filter(PIIRuleDB.active).all() return { - "report_date": datetime.utcnow().isoformat(), + "report_date": datetime.now(timezone.utc).isoformat(), "summary": { "active_sources": len(sources), "active_pii_rules": len(pii_rules), diff --git a/backend-compliance/compliance/api/vendor_compliance_routes.py b/backend-compliance/compliance/api/vendor_compliance_routes.py index 7a1dd40..7ed5e3f 100644 --- a/backend-compliance/compliance/api/vendor_compliance_routes.py +++ b/backend-compliance/compliance/api/vendor_compliance_routes.py @@ -49,7 +49,7 @@ vendor_findings, vendor_control_instances). import json import logging import uuid -from datetime import datetime +from datetime import datetime, timezone from typing import Optional from fastapi import APIRouter, Depends, HTTPException, Query @@ -69,7 +69,7 @@ DEFAULT_TENANT_ID = "9282a473-5c95-4b3a-bf78-0ecc0ec71d3e" # ============================================================================= def _now_iso() -> str: - return datetime.utcnow().isoformat() + "Z" + return datetime.now(timezone.utc).isoformat() + "Z" def _ok(data, status_code: int = 200): @@ -418,7 +418,7 @@ def create_vendor(body: dict = {}, db: Session = Depends(get_db)): data = _to_snake(body) vid = str(uuid.uuid4()) tid = data.get("tenant_id", DEFAULT_TENANT_ID) - now = datetime.utcnow().isoformat() + now = datetime.now(timezone.utc).isoformat() db.execute(text(""" INSERT INTO vendor_vendors ( @@ -498,7 +498,7 @@ def update_vendor(vendor_id: str, body: dict = {}, db: Session = Depends(get_db) raise HTTPException(404, "Vendor not found") data = _to_snake(body) - now = datetime.utcnow().isoformat() + now = datetime.now(timezone.utc).isoformat() # Build dynamic SET clause allowed = [ @@ -558,7 +558,7 @@ def patch_vendor_status(vendor_id: str, body: dict = {}, db: Session = Depends(g result = db.execute(text(""" UPDATE vendor_vendors SET status = :status, updated_at = :now WHERE id = :id - """), {"id": vendor_id, "status": new_status, "now": datetime.utcnow().isoformat()}) + """), {"id": vendor_id, "status": new_status, "now": datetime.now(timezone.utc).isoformat()}) db.commit() if result.rowcount == 0: raise HTTPException(404, "Vendor not found") @@ -620,7 +620,7 @@ def create_contract(body: dict = {}, db: Session = Depends(get_db)): data = _to_snake(body) cid = str(uuid.uuid4()) tid = data.get("tenant_id", DEFAULT_TENANT_ID) - now = datetime.utcnow().isoformat() + now = datetime.now(timezone.utc).isoformat() db.execute(text(""" INSERT INTO vendor_contracts ( @@ -682,7 +682,7 @@ def update_contract(contract_id: str, body: dict = {}, db: Session = Depends(get raise HTTPException(404, "Contract not found") data = _to_snake(body) - now = datetime.utcnow().isoformat() + now = datetime.now(timezone.utc).isoformat() allowed = [ "vendor_id", "file_name", "original_name", "mime_type", "file_size", @@ -781,7 +781,7 @@ def create_finding(body: dict = {}, db: Session = Depends(get_db)): data = _to_snake(body) fid = str(uuid.uuid4()) tid = data.get("tenant_id", DEFAULT_TENANT_ID) - now = datetime.utcnow().isoformat() + now = datetime.now(timezone.utc).isoformat() db.execute(text(""" INSERT INTO vendor_findings ( @@ -831,7 +831,7 @@ def update_finding(finding_id: str, body: dict = {}, db: Session = Depends(get_d raise HTTPException(404, "Finding not found") data = _to_snake(body) - now = datetime.utcnow().isoformat() + now = datetime.now(timezone.utc).isoformat() allowed = [ "vendor_id", "contract_id", "finding_type", "category", "severity", @@ -920,7 +920,7 @@ def create_control_instance(body: dict = {}, db: Session = Depends(get_db)): data = _to_snake(body) ciid = str(uuid.uuid4()) tid = data.get("tenant_id", DEFAULT_TENANT_ID) - now = datetime.utcnow().isoformat() + now = datetime.now(timezone.utc).isoformat() db.execute(text(""" INSERT INTO vendor_control_instances ( @@ -965,7 +965,7 @@ def update_control_instance(instance_id: str, body: dict = {}, db: Session = Dep raise HTTPException(404, "Control instance not found") data = _to_snake(body) - now = datetime.utcnow().isoformat() + now = datetime.now(timezone.utc).isoformat() allowed = [ "vendor_id", "control_id", "control_domain", @@ -1050,7 +1050,7 @@ def list_controls( def create_control(body: dict = {}, db: Session = Depends(get_db)): cid = str(uuid.uuid4()) tid = body.get("tenantId", body.get("tenant_id", DEFAULT_TENANT_ID)) - now = datetime.utcnow().isoformat() + now = datetime.now(timezone.utc).isoformat() db.execute(text(""" INSERT INTO vendor_compliance_controls ( diff --git a/backend-compliance/compliance/api/vvt_routes.py b/backend-compliance/compliance/api/vvt_routes.py index 2eb04ae..5fec2ad 100644 --- a/backend-compliance/compliance/api/vvt_routes.py +++ b/backend-compliance/compliance/api/vvt_routes.py @@ -119,7 +119,7 @@ async def upsert_organization( else: for field, value in request.dict(exclude_none=True).items(): setattr(org, field, value) - org.updated_at = datetime.utcnow() + org.updated_at = datetime.now(timezone.utc) db.commit() db.refresh(org) @@ -291,7 +291,7 @@ async def update_activity( updates = request.dict(exclude_none=True) for field, value in updates.items(): setattr(act, field, value) - act.updated_at = datetime.utcnow() + act.updated_at = datetime.now(timezone.utc) _log_audit( db, @@ -408,7 +408,7 @@ async def export_activities( return _export_csv(activities) return { - "exported_at": datetime.utcnow().isoformat(), + "exported_at": datetime.now(timezone.utc).isoformat(), "organization": { "name": org.organization_name if org else "", "dpo_name": org.dpo_name if org else "", @@ -482,7 +482,7 @@ def _export_csv(activities: list) -> StreamingResponse: iter([output.getvalue()]), media_type='text/csv; charset=utf-8', headers={ - 'Content-Disposition': f'attachment; filename="vvt_export_{datetime.utcnow().strftime("%Y%m%d")}.csv"' + 'Content-Disposition': f'attachment; filename="vvt_export_{datetime.now(timezone.utc).strftime("%Y%m%d")}.csv"' }, ) diff --git a/backend-compliance/compliance/db/ai_system_models.py b/backend-compliance/compliance/db/ai_system_models.py new file mode 100644 index 0000000..d6ca744 --- /dev/null +++ b/backend-compliance/compliance/db/ai_system_models.py @@ -0,0 +1,141 @@ +""" +AI System & Audit Export models — extracted from compliance/db/models.py. + +Covers AI Act system registration/classification and the audit export package +tracker. Re-exported from ``compliance.db.models`` for backwards compatibility. + +DO NOT change __tablename__, column names, or relationship strings. +""" + +import uuid +import enum +from datetime import datetime, timezone + +from sqlalchemy import ( + Column, String, Text, Integer, DateTime, Date, + Enum, JSON, Index, Float, +) + +from classroom_engine.database import Base + + +# ============================================================================ +# ENUMS +# ============================================================================ + +class AIClassificationEnum(str, enum.Enum): + """AI Act risk classification.""" + PROHIBITED = "prohibited" + HIGH_RISK = "high-risk" + LIMITED_RISK = "limited-risk" + MINIMAL_RISK = "minimal-risk" + UNCLASSIFIED = "unclassified" + + +class AISystemStatusEnum(str, enum.Enum): + """Status of an AI system in compliance tracking.""" + DRAFT = "draft" + CLASSIFIED = "classified" + COMPLIANT = "compliant" + NON_COMPLIANT = "non-compliant" + + +class ExportStatusEnum(str, enum.Enum): + """Status of audit export.""" + PENDING = "pending" + GENERATING = "generating" + COMPLETED = "completed" + FAILED = "failed" + + +# ============================================================================ +# MODELS +# ============================================================================ + +class AISystemDB(Base): + """ + AI System registry for AI Act compliance. + Tracks AI systems, their risk classification, and compliance status. + """ + __tablename__ = 'compliance_ai_systems' + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + name = Column(String(300), nullable=False) + description = Column(Text) + purpose = Column(String(500)) + sector = Column(String(100)) + + # AI Act classification + classification = Column(Enum(AIClassificationEnum), default=AIClassificationEnum.UNCLASSIFIED) + status = Column(Enum(AISystemStatusEnum), default=AISystemStatusEnum.DRAFT) + + # Assessment + assessment_date = Column(DateTime) + assessment_result = Column(JSON) # Full assessment result + obligations = Column(JSON) # List of AI Act obligations + risk_factors = Column(JSON) # Risk factors from assessment + recommendations = Column(JSON) # Recommendations from assessment + + # Timestamps + created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) + + __table_args__ = ( + Index('ix_ai_system_classification', 'classification'), + Index('ix_ai_system_status', 'status'), + ) + + def __repr__(self): + return f"" + + +class AuditExportDB(Base): + """ + Tracks audit export packages generated for external auditors. + """ + __tablename__ = 'compliance_audit_exports' + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + + export_type = Column(String(50), nullable=False) # "full", "controls_only", "evidence_only" + export_name = Column(String(200)) # User-friendly name + + # Scope + included_regulations = Column(JSON) # List of regulation codes + included_domains = Column(JSON) # List of control domains + date_range_start = Column(Date) + date_range_end = Column(Date) + + # Generation + requested_by = Column(String(100), nullable=False) + requested_at = Column(DateTime, nullable=False, default=lambda: datetime.now(timezone.utc)) + completed_at = Column(DateTime) + + # Output + file_path = Column(String(500)) + file_hash = Column(String(64)) # SHA-256 of ZIP + file_size_bytes = Column(Integer) + + status = Column(Enum(ExportStatusEnum), default=ExportStatusEnum.PENDING) + error_message = Column(Text) + + # Statistics + total_controls = Column(Integer) + total_evidence = Column(Integer) + compliance_score = Column(Float) + + # Timestamps + created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) + + def __repr__(self): + return f"" + + +__all__ = [ + "AIClassificationEnum", + "AISystemStatusEnum", + "ExportStatusEnum", + "AISystemDB", + "AuditExportDB", +] diff --git a/backend-compliance/compliance/db/audit_session_models.py b/backend-compliance/compliance/db/audit_session_models.py new file mode 100644 index 0000000..4ad2003 --- /dev/null +++ b/backend-compliance/compliance/db/audit_session_models.py @@ -0,0 +1,177 @@ +""" +Audit Session & Sign-Off models — Sprint 3 Phase 3. + +Extracted from compliance/db/models.py as the first worked example of the +Phase 1 model split. The classes are re-exported from compliance.db.models +for backwards compatibility, so existing imports continue to work unchanged. + +Tables: +- compliance_audit_sessions: Structured compliance audit sessions +- compliance_audit_signoffs: Per-requirement sign-offs with digital signatures + +DO NOT change __tablename__, column names, or relationship strings — the +database schema is frozen. +""" + +import uuid +import enum +from datetime import datetime, timezone + +from sqlalchemy import ( + Column, String, Text, Integer, DateTime, + ForeignKey, Enum, JSON, Index, +) +from sqlalchemy.orm import relationship + +from classroom_engine.database import Base + + +# ============================================================================ +# ENUMS +# ============================================================================ + +class AuditResultEnum(str, enum.Enum): + """Result of an audit sign-off for a requirement.""" + COMPLIANT = "compliant" # Fully compliant + COMPLIANT_WITH_NOTES = "compliant_notes" # Compliant with observations + NON_COMPLIANT = "non_compliant" # Not compliant - remediation required + NOT_APPLICABLE = "not_applicable" # Not applicable to this audit + PENDING = "pending" # Not yet reviewed + + +class AuditSessionStatusEnum(str, enum.Enum): + """Status of an audit session.""" + DRAFT = "draft" # Session created, not started + IN_PROGRESS = "in_progress" # Audit in progress + COMPLETED = "completed" # All items reviewed + ARCHIVED = "archived" # Historical record + + +# ============================================================================ +# MODELS +# ============================================================================ + +class AuditSessionDB(Base): + """ + Audit session for structured compliance reviews. + + Enables auditors to: + - Create named audit sessions (e.g., "Q1 2026 GDPR Audit") + - Track progress through requirements + - Sign off individual items with digital signatures + - Generate audit reports + """ + __tablename__ = 'compliance_audit_sessions' + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + name = Column(String(200), nullable=False) # e.g., "Q1 2026 Compliance Audit" + description = Column(Text) + + # Auditor information + auditor_name = Column(String(100), nullable=False) # e.g., "Dr. Thomas Müller" + auditor_email = Column(String(200)) + auditor_organization = Column(String(200)) # External auditor company + + # Session scope + status = Column(Enum(AuditSessionStatusEnum), default=AuditSessionStatusEnum.DRAFT) + regulation_ids = Column(JSON) # Filter: ["GDPR", "AIACT"] or null for all + + # Progress tracking + total_items = Column(Integer, default=0) + completed_items = Column(Integer, default=0) + compliant_count = Column(Integer, default=0) + non_compliant_count = Column(Integer, default=0) + + # Timestamps + created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) + started_at = Column(DateTime) # When audit began + completed_at = Column(DateTime) # When audit finished + updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) + + # Relationships + signoffs = relationship("AuditSignOffDB", back_populates="session", cascade="all, delete-orphan") + + __table_args__ = ( + Index('ix_audit_session_status', 'status'), + Index('ix_audit_session_auditor', 'auditor_name'), + ) + + def __repr__(self): + return f"" + + @property + def completion_percentage(self) -> float: + """Calculate completion percentage.""" + if self.total_items == 0: + return 0.0 + return round((self.completed_items / self.total_items) * 100, 1) + + +class AuditSignOffDB(Base): + """ + Individual sign-off for a requirement within an audit session. + + Features: + - Records audit result (compliant, non-compliant, etc.) + - Stores auditor notes and observations + - Creates digital signature (SHA-256 hash) for tamper evidence + """ + __tablename__ = 'compliance_audit_signoffs' + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + session_id = Column(String(36), ForeignKey('compliance_audit_sessions.id'), nullable=False, index=True) + requirement_id = Column(String(36), ForeignKey('compliance_requirements.id'), nullable=False, index=True) + + # Audit result + result = Column(Enum(AuditResultEnum), default=AuditResultEnum.PENDING) + notes = Column(Text) # Auditor observations + + # Evidence references for this sign-off + evidence_ids = Column(JSON) # List of evidence IDs reviewed + + # Digital signature (SHA-256 hash of result + auditor + timestamp) + signature_hash = Column(String(64)) # SHA-256 hex string + signed_at = Column(DateTime) + signed_by = Column(String(100)) # Auditor name at time of signing + + # Timestamps + created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) + + # Relationships + session = relationship("AuditSessionDB", back_populates="signoffs") + requirement = relationship("RequirementDB") + + __table_args__ = ( + Index('ix_signoff_session_requirement', 'session_id', 'requirement_id', unique=True), + Index('ix_signoff_result', 'result'), + ) + + def __repr__(self): + return f"" + + def create_signature(self, auditor_name: str) -> str: + """ + Create a digital signature for this sign-off. + + Returns SHA-256 hash of: result + requirement_id + auditor_name + timestamp + """ + import hashlib + + timestamp = datetime.now(timezone.utc).isoformat() + data = f"{self.result.value}|{self.requirement_id}|{auditor_name}|{timestamp}" + signature = hashlib.sha256(data.encode()).hexdigest() + + self.signature_hash = signature + self.signed_at = datetime.now(timezone.utc) + self.signed_by = auditor_name + + return signature + + +__all__ = [ + "AuditResultEnum", + "AuditSessionStatusEnum", + "AuditSessionDB", + "AuditSignOffDB", +] diff --git a/backend-compliance/compliance/db/control_models.py b/backend-compliance/compliance/db/control_models.py new file mode 100644 index 0000000..ffd8a14 --- /dev/null +++ b/backend-compliance/compliance/db/control_models.py @@ -0,0 +1,279 @@ +""" +Control, Evidence, and Risk models — extracted from compliance/db/models.py. + +Covers the control framework (ControlDB), requirement↔control mappings, +evidence artifacts, and the risk register. Re-exported from +``compliance.db.models`` for backwards compatibility. + +DO NOT change __tablename__, column names, or relationship strings. +""" + +import uuid +import enum +from datetime import datetime, date, timezone + +from sqlalchemy import ( + Column, String, Text, Integer, Boolean, DateTime, Date, + ForeignKey, Enum, JSON, Index, +) +from sqlalchemy.orm import relationship + +from classroom_engine.database import Base + + +# ============================================================================ +# ENUMS +# ============================================================================ + +class ControlTypeEnum(str, enum.Enum): + """Type of security control.""" + PREVENTIVE = "preventive" # Prevents incidents + DETECTIVE = "detective" # Detects incidents + CORRECTIVE = "corrective" # Corrects after incidents + + +class ControlDomainEnum(str, enum.Enum): + """Domain/category of control.""" + GOVERNANCE = "gov" # Governance & Organization + PRIVACY = "priv" # Privacy & Data Protection + IAM = "iam" # Identity & Access Management + CRYPTO = "crypto" # Cryptography & Key Management + SDLC = "sdlc" # Secure Development Lifecycle + OPS = "ops" # Operations & Monitoring + AI = "ai" # AI-specific controls + CRA = "cra" # CRA & Supply Chain + AUDIT = "aud" # Audit & Traceability + + +class ControlStatusEnum(str, enum.Enum): + """Implementation status of a control.""" + PASS = "pass" # Fully implemented & passing + PARTIAL = "partial" # Partially implemented + FAIL = "fail" # Not passing + NOT_APPLICABLE = "n/a" # Not applicable + PLANNED = "planned" # Planned for implementation + + +class RiskLevelEnum(str, enum.Enum): + """Risk severity level.""" + LOW = "low" + MEDIUM = "medium" + HIGH = "high" + CRITICAL = "critical" + + +class EvidenceStatusEnum(str, enum.Enum): + """Status of evidence artifact.""" + VALID = "valid" # Currently valid + EXPIRED = "expired" # Past validity date + PENDING = "pending" # Awaiting validation + FAILED = "failed" # Failed validation + + +# ============================================================================ +# MODELS +# ============================================================================ + +class ControlDB(Base): + """ + Technical or organizational security control. + + Examples: PRIV-001 (Verarbeitungsverzeichnis), SDLC-001 (SAST Scanning) + """ + __tablename__ = 'compliance_controls' + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + control_id = Column(String(20), unique=True, nullable=False, index=True) # e.g., "PRIV-001" + + domain = Column(Enum(ControlDomainEnum), nullable=False, index=True) + control_type = Column(Enum(ControlTypeEnum), nullable=False) + + title = Column(String(300), nullable=False) + description = Column(Text) + pass_criteria = Column(Text, nullable=False) # Measurable pass criteria + implementation_guidance = Column(Text) # How to implement + + # Code/Evidence references + code_reference = Column(String(500)) # e.g., "backend/middleware/pii_redactor.py:45" + documentation_url = Column(String(500)) # Link to internal docs + + # Automation + is_automated = Column(Boolean, default=False) + automation_tool = Column(String(100)) # e.g., "Semgrep", "Trivy" + automation_config = Column(JSON) # Tool-specific config + + # Status + status = Column(Enum(ControlStatusEnum), default=ControlStatusEnum.PLANNED) + status_notes = Column(Text) + + # Ownership & Review + owner = Column(String(100)) # Responsible person/team + review_frequency_days = Column(Integer, default=90) + last_reviewed_at = Column(DateTime) + next_review_at = Column(DateTime) + + # Timestamps + created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) + + # Relationships + mappings = relationship("ControlMappingDB", back_populates="control", cascade="all, delete-orphan") + evidence = relationship("EvidenceDB", back_populates="control", cascade="all, delete-orphan") + + __table_args__ = ( + Index('ix_control_domain_status', 'domain', 'status'), + ) + + def __repr__(self): + return f"" + + +class ControlMappingDB(Base): + """ + Maps requirements to controls (many-to-many with metadata). + """ + __tablename__ = 'compliance_control_mappings' + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + requirement_id = Column(String(36), ForeignKey('compliance_requirements.id'), nullable=False, index=True) + control_id = Column(String(36), ForeignKey('compliance_controls.id'), nullable=False, index=True) + + coverage_level = Column(String(20), default="full") # "full", "partial", "planned" + notes = Column(Text) # Explanation of coverage + + # Timestamps + created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) + + # Relationships + requirement = relationship("RequirementDB", back_populates="control_mappings") + control = relationship("ControlDB", back_populates="mappings") + + __table_args__ = ( + Index('ix_mapping_req_ctrl', 'requirement_id', 'control_id', unique=True), + ) + + +class EvidenceDB(Base): + """ + Audit evidence for controls. + + Types: scan_report, policy_document, config_snapshot, test_result, + manual_upload, screenshot, external_link + """ + __tablename__ = 'compliance_evidence' + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + control_id = Column(String(36), ForeignKey('compliance_controls.id'), nullable=False, index=True) + + evidence_type = Column(String(50), nullable=False) # Type of evidence + title = Column(String(300), nullable=False) + description = Column(Text) + + # File/Link storage + artifact_path = Column(String(500)) # Local file path + artifact_url = Column(String(500)) # External URL + artifact_hash = Column(String(64)) # SHA-256 hash + file_size_bytes = Column(Integer) + mime_type = Column(String(100)) + + # Validity period + valid_from = Column(DateTime, nullable=False, default=lambda: datetime.now(timezone.utc)) + valid_until = Column(DateTime) # NULL = no expiry + status = Column(Enum(EvidenceStatusEnum), default=EvidenceStatusEnum.VALID) + + # Source tracking + source = Column(String(100)) # "ci_pipeline", "manual", "api" + ci_job_id = Column(String(100)) # CI/CD job reference + uploaded_by = Column(String(100)) # User who uploaded + + # Timestamps + collected_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) + created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) + + # Relationships + control = relationship("ControlDB", back_populates="evidence") + + __table_args__ = ( + Index('ix_evidence_control_type', 'control_id', 'evidence_type'), + Index('ix_evidence_status', 'status'), + ) + + def __repr__(self): + return f"" + + +class RiskDB(Base): + """ + Risk register entry with likelihood x impact scoring. + """ + __tablename__ = 'compliance_risks' + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + risk_id = Column(String(20), unique=True, nullable=False, index=True) # e.g., "RISK-001" + + title = Column(String(300), nullable=False) + description = Column(Text) + category = Column(String(50), nullable=False) # "data_breach", "compliance_gap", etc. + + # Inherent risk (before controls) + likelihood = Column(Integer, nullable=False) # 1-5 + impact = Column(Integer, nullable=False) # 1-5 + inherent_risk = Column(Enum(RiskLevelEnum), nullable=False) + + # Mitigating controls + mitigating_controls = Column(JSON) # List of control_ids + + # Residual risk (after controls) + residual_likelihood = Column(Integer) + residual_impact = Column(Integer) + residual_risk = Column(Enum(RiskLevelEnum)) + + # Management + owner = Column(String(100)) + status = Column(String(20), default="open") # "open", "mitigated", "accepted", "transferred" + treatment_plan = Column(Text) + + # Review + identified_date = Column(Date, default=date.today) + review_date = Column(Date) + last_assessed_at = Column(DateTime) + + # Timestamps + created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) + + __table_args__ = ( + Index('ix_risk_category_status', 'category', 'status'), + Index('ix_risk_inherent', 'inherent_risk'), + ) + + def __repr__(self): + return f"" + + @staticmethod + def calculate_risk_level(likelihood: int, impact: int) -> RiskLevelEnum: + """Calculate risk level from likelihood x impact matrix.""" + score = likelihood * impact + if score >= 20: + return RiskLevelEnum.CRITICAL + elif score >= 12: + return RiskLevelEnum.HIGH + elif score >= 6: + return RiskLevelEnum.MEDIUM + else: + return RiskLevelEnum.LOW + + +__all__ = [ + "ControlTypeEnum", + "ControlDomainEnum", + "ControlStatusEnum", + "RiskLevelEnum", + "EvidenceStatusEnum", + "ControlDB", + "ControlMappingDB", + "EvidenceDB", + "RiskDB", +] diff --git a/backend-compliance/compliance/db/isms_audit_models.py b/backend-compliance/compliance/db/isms_audit_models.py new file mode 100644 index 0000000..1bdb4c5 --- /dev/null +++ b/backend-compliance/compliance/db/isms_audit_models.py @@ -0,0 +1,468 @@ +""" +ISMS Audit Execution models (ISO 27001 Kapitel 9-10) — extracted from +compliance/db/models.py. + +Covers findings, corrective actions (CAPA), management reviews, internal +audits, audit trail, and readiness checks. The governance side (scope, +context, policies, objectives, SoA) lives in ``isms_governance_models.py``. + +Re-exported from ``compliance.db.models`` for backwards compatibility. + +DO NOT change __tablename__, column names, or relationship strings. +""" + +import uuid +import enum +from datetime import datetime, date, timezone + +from sqlalchemy import ( + Column, String, Text, Integer, Boolean, DateTime, Date, + ForeignKey, Enum, JSON, Index, Float, +) +from sqlalchemy.orm import relationship + +from classroom_engine.database import Base + + +# ============================================================================ +# ENUMS +# ============================================================================ + +class FindingTypeEnum(str, enum.Enum): + """ISO 27001 audit finding classification.""" + MAJOR = "major" # Major nonconformity - blocks certification + MINOR = "minor" # Minor nonconformity - requires CAPA + OFI = "ofi" # Opportunity for Improvement + POSITIVE = "positive" # Positive observation + + +class FindingStatusEnum(str, enum.Enum): + """Status of an audit finding.""" + OPEN = "open" + IN_PROGRESS = "in_progress" + CORRECTIVE_ACTION_PENDING = "capa_pending" + VERIFICATION_PENDING = "verification_pending" + VERIFIED = "verified" + CLOSED = "closed" + + +class CAPATypeEnum(str, enum.Enum): + """Type of corrective/preventive action.""" + CORRECTIVE = "corrective" # Fix the nonconformity + PREVENTIVE = "preventive" # Prevent recurrence + BOTH = "both" + + +# ============================================================================ +# MODELS +# ============================================================================ + +class AuditFindingDB(Base): + """ + Audit Finding with ISO 27001 Classification (Major/Minor/OFI) + + Tracks findings from internal and external audits with proper + classification and CAPA workflow. + """ + __tablename__ = 'compliance_audit_findings' + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + finding_id = Column(String(30), unique=True, nullable=False, index=True) # e.g., "FIND-2026-001" + + # Source + audit_session_id = Column(String(36), ForeignKey('compliance_audit_sessions.id'), index=True) + internal_audit_id = Column(String(36), ForeignKey('compliance_internal_audits.id'), index=True) + + # Classification (CRITICAL for ISO 27001!) + finding_type = Column(Enum(FindingTypeEnum), nullable=False) + + # ISO reference + iso_chapter = Column(String(20)) # e.g., "6.1.2", "9.2" + annex_a_control = Column(String(20)) # e.g., "A.8.2" + + # Finding details + title = Column(String(300), nullable=False) + description = Column(Text, nullable=False) + objective_evidence = Column(Text, nullable=False) # What the auditor observed + + # Root cause analysis + root_cause = Column(Text) + root_cause_method = Column(String(50)) # "5-why", "fishbone", "pareto" + + # Impact assessment + impact_description = Column(Text) + affected_processes = Column(JSON) + affected_assets = Column(JSON) + + # Status tracking + status = Column(Enum(FindingStatusEnum), default=FindingStatusEnum.OPEN) + + # Responsibility + owner = Column(String(100)) # Person responsible for closure + auditor = Column(String(100)) # Auditor who raised finding + + # Dates + identified_date = Column(Date, nullable=False, default=date.today) + due_date = Column(Date) # Deadline for closure + closed_date = Column(Date) + + # Verification + verification_method = Column(Text) + verified_by = Column(String(100)) + verified_at = Column(DateTime) + verification_evidence = Column(Text) + + # Closure + closure_notes = Column(Text) + closed_by = Column(String(100)) + + # Timestamps + created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) + + # Relationships + corrective_actions = relationship("CorrectiveActionDB", back_populates="finding", cascade="all, delete-orphan") + + __table_args__ = ( + Index('ix_finding_type_status', 'finding_type', 'status'), + Index('ix_finding_due_date', 'due_date'), + ) + + def __repr__(self): + return f"" + + @property + def is_blocking(self) -> bool: + """Major findings block certification.""" + return self.finding_type == FindingTypeEnum.MAJOR and self.status != FindingStatusEnum.CLOSED + + +class CorrectiveActionDB(Base): + """ + Corrective & Preventive Actions (CAPA) - ISO 27001 10.1 + + Tracks actions taken to address nonconformities. + """ + __tablename__ = 'compliance_corrective_actions' + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + capa_id = Column(String(30), unique=True, nullable=False, index=True) # e.g., "CAPA-2026-001" + + # Link to finding + finding_id = Column(String(36), ForeignKey('compliance_audit_findings.id'), nullable=False, index=True) + + # Type + capa_type = Column(Enum(CAPATypeEnum), nullable=False) + + # Action details + title = Column(String(300), nullable=False) + description = Column(Text, nullable=False) + expected_outcome = Column(Text) + + # Responsibility + assigned_to = Column(String(100), nullable=False) + approved_by = Column(String(100)) + + # Timeline + planned_start = Column(Date) + planned_completion = Column(Date, nullable=False) + actual_completion = Column(Date) + + # Status + status = Column(String(30), default="planned") # planned, in_progress, completed, verified, cancelled + progress_percentage = Column(Integer, default=0) + + # Resources + estimated_effort_hours = Column(Integer) + actual_effort_hours = Column(Integer) + resources_required = Column(Text) + + # Evidence of implementation + implementation_evidence = Column(Text) + evidence_ids = Column(JSON) + + # Effectiveness review + effectiveness_criteria = Column(Text) + effectiveness_verified = Column(Boolean, default=False) + effectiveness_verification_date = Column(Date) + effectiveness_notes = Column(Text) + + # Timestamps + created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) + + # Relationships + finding = relationship("AuditFindingDB", back_populates="corrective_actions") + + __table_args__ = ( + Index('ix_capa_status', 'status'), + Index('ix_capa_due', 'planned_completion'), + ) + + def __repr__(self): + return f"" + + +class ManagementReviewDB(Base): + """ + Management Review (ISO 27001 Kapitel 9.3) + + Records mandatory management reviews of the ISMS. + """ + __tablename__ = 'compliance_management_reviews' + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + review_id = Column(String(30), unique=True, nullable=False, index=True) # e.g., "MR-2026-Q1" + + # Review details + title = Column(String(200), nullable=False) + review_date = Column(Date, nullable=False) + review_period_start = Column(Date) # Period being reviewed + review_period_end = Column(Date) + + # Participants + chairperson = Column(String(100), nullable=False) # Usually top management + attendees = Column(JSON) # List of {"name": "", "role": ""} + + # 9.3 Review Inputs (mandatory!) + input_previous_actions = Column(Text) # Status of previous review actions + input_isms_changes = Column(Text) # Changes in internal/external issues + input_security_performance = Column(Text) # Nonconformities, monitoring, audit results + input_interested_party_feedback = Column(Text) + input_risk_assessment_results = Column(Text) + input_improvement_opportunities = Column(Text) + + # Additional inputs + input_policy_effectiveness = Column(Text) + input_objective_achievement = Column(Text) + input_resource_adequacy = Column(Text) + + # 9.3 Review Outputs (mandatory!) + output_improvement_decisions = Column(Text) # Decisions for improvement + output_isms_changes = Column(Text) # Changes needed to ISMS + output_resource_needs = Column(Text) # Resource requirements + + # Action items + action_items = Column(JSON) # List of {"action": "", "owner": "", "due_date": ""} + + # Overall assessment + isms_effectiveness_rating = Column(String(20)) # "effective", "partially_effective", "not_effective" + key_decisions = Column(Text) + + # Approval + status = Column(String(30), default="draft") # draft, conducted, approved + approved_by = Column(String(100)) + approved_at = Column(DateTime) + minutes_document_path = Column(String(500)) # Link to meeting minutes + + # Next review + next_review_date = Column(Date) + + # Timestamps + created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) + + __table_args__ = ( + Index('ix_mgmt_review_date', 'review_date'), + Index('ix_mgmt_review_status', 'status'), + ) + + def __repr__(self): + return f"" + + +class InternalAuditDB(Base): + """ + Internal Audit (ISO 27001 Kapitel 9.2) + + Tracks internal audit program and individual audits. + """ + __tablename__ = 'compliance_internal_audits' + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + audit_id = Column(String(30), unique=True, nullable=False, index=True) # e.g., "IA-2026-001" + + # Audit details + title = Column(String(200), nullable=False) + audit_type = Column(String(50), nullable=False) # "scheduled", "surveillance", "special" + + # Scope + scope_description = Column(Text, nullable=False) + iso_chapters_covered = Column(JSON) # e.g., ["4", "5", "6.1"] + annex_a_controls_covered = Column(JSON) # e.g., ["A.5", "A.6"] + processes_covered = Column(JSON) + departments_covered = Column(JSON) + + # Audit criteria + criteria = Column(Text) # Standards, policies being audited against + + # Timeline + planned_date = Column(Date, nullable=False) + actual_start_date = Column(Date) + actual_end_date = Column(Date) + + # Audit team + lead_auditor = Column(String(100), nullable=False) + audit_team = Column(JSON) # List of auditor names + auditee_representatives = Column(JSON) # Who was interviewed + + # Status + status = Column(String(30), default="planned") # planned, in_progress, completed, cancelled + + # Results summary + total_findings = Column(Integer, default=0) + major_findings = Column(Integer, default=0) + minor_findings = Column(Integer, default=0) + ofi_count = Column(Integer, default=0) + positive_observations = Column(Integer, default=0) + + # Conclusion + audit_conclusion = Column(Text) + overall_assessment = Column(String(30)) # "conforming", "minor_nc", "major_nc" + + # Report + report_date = Column(Date) + report_document_path = Column(String(500)) + + # Sign-off + report_approved_by = Column(String(100)) + report_approved_at = Column(DateTime) + + # Follow-up + follow_up_audit_required = Column(Boolean, default=False) + follow_up_audit_id = Column(String(36)) + + # Timestamps + created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) + + # Relationships + findings = relationship("AuditFindingDB", backref="internal_audit", foreign_keys=[AuditFindingDB.internal_audit_id]) + + __table_args__ = ( + Index('ix_internal_audit_date', 'planned_date'), + Index('ix_internal_audit_status', 'status'), + ) + + def __repr__(self): + return f"" + + +class AuditTrailDB(Base): + """ + Comprehensive Audit Trail for ISMS Changes + + Tracks all changes to compliance-relevant data for + accountability and forensic analysis. + """ + __tablename__ = 'compliance_audit_trail' + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + + # What changed + entity_type = Column(String(50), nullable=False, index=True) # "control", "risk", "policy", etc. + entity_id = Column(String(36), nullable=False, index=True) + entity_name = Column(String(200)) # Human-readable identifier + + # Action + action = Column(String(20), nullable=False) # "create", "update", "delete", "approve", "sign" + + # Change details + field_changed = Column(String(100)) # Which field (for updates) + old_value = Column(Text) + new_value = Column(Text) + change_summary = Column(Text) # Human-readable summary + + # Who & When + performed_by = Column(String(100), nullable=False) + performed_at = Column(DateTime, nullable=False, default=lambda: datetime.now(timezone.utc)) + + # Context + ip_address = Column(String(45)) + user_agent = Column(String(500)) + session_id = Column(String(100)) + + # Integrity + checksum = Column(String(64)) # SHA-256 of the change + + # Timestamps (immutable after creation) + created_at = Column(DateTime, nullable=False, default=lambda: datetime.now(timezone.utc)) + + __table_args__ = ( + Index('ix_audit_trail_entity', 'entity_type', 'entity_id'), + Index('ix_audit_trail_time', 'performed_at'), + Index('ix_audit_trail_user', 'performed_by'), + ) + + def __repr__(self): + return f"" + + +class ISMSReadinessCheckDB(Base): + """ + ISMS Readiness Check Results + + Stores automated pre-audit checks to identify potential + Major findings before external audit. + """ + __tablename__ = 'compliance_isms_readiness' + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + + # Check run + check_date = Column(DateTime, nullable=False, default=lambda: datetime.now(timezone.utc)) + triggered_by = Column(String(100)) # "scheduled", "manual", "pre-audit" + + # Overall status + overall_status = Column(String(20), nullable=False) # "ready", "at_risk", "not_ready" + certification_possible = Column(Boolean, nullable=False) + + # Chapter-by-chapter status (ISO 27001) + chapter_4_status = Column(String(20)) # Context + chapter_5_status = Column(String(20)) # Leadership + chapter_6_status = Column(String(20)) # Planning + chapter_7_status = Column(String(20)) # Support + chapter_8_status = Column(String(20)) # Operation + chapter_9_status = Column(String(20)) # Performance + chapter_10_status = Column(String(20)) # Improvement + + # Potential Major findings + potential_majors = Column(JSON) # List of {"check": "", "status": "", "recommendation": ""} + + # Potential Minor findings + potential_minors = Column(JSON) + + # Improvement opportunities + improvement_opportunities = Column(JSON) + + # Scores + readiness_score = Column(Float) # 0-100 + documentation_score = Column(Float) + implementation_score = Column(Float) + evidence_score = Column(Float) + + # Recommendations + priority_actions = Column(JSON) # List of recommended actions before audit + # Timestamps + created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) + + __table_args__ = ( + Index('ix_readiness_date', 'check_date'), + Index('ix_readiness_status', 'overall_status'), + ) + + def __repr__(self): + return f"" + + +__all__ = [ + "FindingTypeEnum", + "FindingStatusEnum", + "CAPATypeEnum", + "AuditFindingDB", + "CorrectiveActionDB", + "ManagementReviewDB", + "InternalAuditDB", + "AuditTrailDB", + "ISMSReadinessCheckDB", +] diff --git a/backend-compliance/compliance/db/isms_governance_models.py b/backend-compliance/compliance/db/isms_governance_models.py new file mode 100644 index 0000000..ce8d3f9 --- /dev/null +++ b/backend-compliance/compliance/db/isms_governance_models.py @@ -0,0 +1,323 @@ +""" +ISMS Governance models (ISO 27001 Kapitel 4-6) — extracted from compliance/db/models.py. + +Covers the documentation and planning side of the ISMS: scope, context, +policies, security objectives, and the Statement of Applicability. The audit +execution side (findings, CAPA, management reviews, internal audits, audit +trail, readiness checks) lives in ``isms_audit_models.py``. + +Re-exported from ``compliance.db.models`` for backwards compatibility. + +DO NOT change __tablename__, column names, or relationship strings — the +database schema is frozen. +""" + +import uuid +import enum +from datetime import datetime, date, timezone + +from sqlalchemy import ( + Column, String, Text, Integer, Boolean, DateTime, Date, + ForeignKey, Enum, JSON, Index, +) + +from classroom_engine.database import Base + + +# ============================================================================ +# SHARED GOVERNANCE ENUMS +# ============================================================================ + +class ApprovalStatusEnum(str, enum.Enum): + """Approval status for ISMS documents.""" + DRAFT = "draft" + UNDER_REVIEW = "under_review" + APPROVED = "approved" + SUPERSEDED = "superseded" + + +# ============================================================================ +# MODELS +# ============================================================================ + +class ISMSScopeDB(Base): + """ + ISMS Scope Definition (ISO 27001 Kapitel 4.3) + + Defines the boundaries and applicability of the ISMS. + This is MANDATORY for certification. + """ + __tablename__ = 'compliance_isms_scope' + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + version = Column(String(20), nullable=False, default="1.0") + + # Scope definition + scope_statement = Column(Text, nullable=False) # Main scope text + included_locations = Column(JSON) # List of locations + included_processes = Column(JSON) # List of processes + included_services = Column(JSON) # List of services/products + excluded_items = Column(JSON) # Explicitly excluded items + exclusion_justification = Column(Text) # Why items are excluded + + # Boundaries + organizational_boundary = Column(Text) # Legal entity, departments + physical_boundary = Column(Text) # Locations, networks + technical_boundary = Column(Text) # Systems, applications + + # Approval + status = Column(Enum(ApprovalStatusEnum), default=ApprovalStatusEnum.DRAFT) + approved_by = Column(String(100)) + approved_at = Column(DateTime) + approval_signature = Column(String(64)) # SHA-256 hash + + # Validity + effective_date = Column(Date) + review_date = Column(Date) # Next mandatory review + + # Timestamps + created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) + created_by = Column(String(100)) + updated_by = Column(String(100)) + + __table_args__ = ( + Index('ix_isms_scope_status', 'status'), + ) + + def __repr__(self): + return f"" + + +class ISMSContextDB(Base): + """ + ISMS Context (ISO 27001 Kapitel 4.1, 4.2) + + Documents internal/external issues and interested parties. + """ + __tablename__ = 'compliance_isms_context' + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + version = Column(String(20), nullable=False, default="1.0") + + # 4.1 Internal issues + internal_issues = Column(JSON) # List of {"issue": "", "impact": "", "treatment": ""} + + # 4.1 External issues + external_issues = Column(JSON) # List of {"issue": "", "impact": "", "treatment": ""} + + # 4.2 Interested parties + interested_parties = Column(JSON) # List of {"party": "", "requirements": [], "relevance": ""} + + # Legal/regulatory requirements + regulatory_requirements = Column(JSON) # DSGVO, AI Act, etc. + contractual_requirements = Column(JSON) # Customer contracts + + # Analysis + swot_strengths = Column(JSON) + swot_weaknesses = Column(JSON) + swot_opportunities = Column(JSON) + swot_threats = Column(JSON) + + # Approval + status = Column(Enum(ApprovalStatusEnum), default=ApprovalStatusEnum.DRAFT) + approved_by = Column(String(100)) + approved_at = Column(DateTime) + + # Review + last_reviewed_at = Column(DateTime) + next_review_date = Column(Date) + + # Timestamps + created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) + + def __repr__(self): + return f"" + + +class ISMSPolicyDB(Base): + """ + ISMS Policies (ISO 27001 Kapitel 5.2) + + Information security policy and sub-policies. + """ + __tablename__ = 'compliance_isms_policies' + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + policy_id = Column(String(30), unique=True, nullable=False, index=True) # e.g., "POL-ISMS-001" + + # Policy details + title = Column(String(200), nullable=False) + policy_type = Column(String(50), nullable=False) # "master", "operational", "technical" + description = Column(Text) + policy_text = Column(Text, nullable=False) # Full policy content + + # Scope + applies_to = Column(JSON) # Roles, departments, systems + + # Document control + version = Column(String(20), nullable=False, default="1.0") + status = Column(Enum(ApprovalStatusEnum), default=ApprovalStatusEnum.DRAFT) + + # Approval chain + authored_by = Column(String(100)) + reviewed_by = Column(String(100)) + approved_by = Column(String(100)) # Must be top management + approved_at = Column(DateTime) + approval_signature = Column(String(64)) + + # Validity + effective_date = Column(Date) + review_frequency_months = Column(Integer, default=12) + next_review_date = Column(Date) + + # References + parent_policy_id = Column(String(36), ForeignKey('compliance_isms_policies.id')) + related_controls = Column(JSON) # List of control_ids + + # Document path + document_path = Column(String(500)) # Link to full document + + # Timestamps + created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) + + __table_args__ = ( + Index('ix_policy_type_status', 'policy_type', 'status'), + ) + + def __repr__(self): + return f"" + + +class SecurityObjectiveDB(Base): + """ + Security Objectives (ISO 27001 Kapitel 6.2) + + Measurable information security objectives. + """ + __tablename__ = 'compliance_security_objectives' + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + objective_id = Column(String(30), unique=True, nullable=False, index=True) # e.g., "OBJ-001" + + # Objective definition + title = Column(String(200), nullable=False) + description = Column(Text) + category = Column(String(50)) # "availability", "confidentiality", "integrity", "compliance" + + # SMART criteria + specific = Column(Text) # What exactly + measurable = Column(Text) # How measured + achievable = Column(Text) # Is it realistic + relevant = Column(Text) # Why important + time_bound = Column(Text) # Deadline + + # Metrics + kpi_name = Column(String(100)) + kpi_target = Column(String(100)) # Target value + kpi_current = Column(String(100)) # Current value + kpi_unit = Column(String(50)) # %, count, score + measurement_frequency = Column(String(50)) # monthly, quarterly + + # Responsibility + owner = Column(String(100)) + accountable = Column(String(100)) # RACI: Accountable + + # Status + status = Column(String(30), default="active") # active, achieved, not_achieved, cancelled + progress_percentage = Column(Integer, default=0) + + # Timeline + target_date = Column(Date) + achieved_date = Column(Date) + + # Linked items + related_controls = Column(JSON) + related_risks = Column(JSON) + + # Approval + approved_by = Column(String(100)) + approved_at = Column(DateTime) + + # Timestamps + created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) + + __table_args__ = ( + Index('ix_objective_status', 'status'), + Index('ix_objective_category', 'category'), + ) + + def __repr__(self): + return f"" + + +class StatementOfApplicabilityDB(Base): + """ + Statement of Applicability (SoA) - ISO 27001 Anhang A Mapping + + Documents which Annex A controls are applicable and why. + This is MANDATORY for certification. + """ + __tablename__ = 'compliance_soa' + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + + # ISO 27001:2022 Annex A reference + annex_a_control = Column(String(20), nullable=False, index=True) # e.g., "A.5.1" + annex_a_title = Column(String(300), nullable=False) + annex_a_category = Column(String(100)) # "Organizational", "People", "Physical", "Technological" + + # Applicability decision + is_applicable = Column(Boolean, nullable=False) + applicability_justification = Column(Text, nullable=False) # MUST be documented + + # Implementation status + implementation_status = Column(String(30), default="planned") # planned, partial, implemented, not_implemented + implementation_notes = Column(Text) + + # Mapping to our controls + breakpilot_control_ids = Column(JSON) # List of our control_ids that address this + coverage_level = Column(String(20), default="full") # full, partial, planned + + # Evidence + evidence_description = Column(Text) + evidence_ids = Column(JSON) # Links to EvidenceDB + + # Risk-based justification (for exclusions) + risk_assessment_notes = Column(Text) # If not applicable, explain why + compensating_controls = Column(Text) # If partial, explain compensating measures + + # Approval + reviewed_by = Column(String(100)) + reviewed_at = Column(DateTime) + approved_by = Column(String(100)) + approved_at = Column(DateTime) + + # Version tracking + version = Column(String(20), default="1.0") + + # Timestamps + created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) + + __table_args__ = ( + Index('ix_soa_annex_control', 'annex_a_control', unique=True), + Index('ix_soa_applicable', 'is_applicable'), + Index('ix_soa_status', 'implementation_status'), + ) + + def __repr__(self): + return f"" + + +__all__ = [ + "ApprovalStatusEnum", + "ISMSScopeDB", + "ISMSContextDB", + "ISMSPolicyDB", + "SecurityObjectiveDB", + "StatementOfApplicabilityDB", +] diff --git a/backend-compliance/compliance/db/isms_repository.py b/backend-compliance/compliance/db/isms_repository.py index 188b090..e3ce768 100644 --- a/backend-compliance/compliance/db/isms_repository.py +++ b/backend-compliance/compliance/db/isms_repository.py @@ -10,7 +10,7 @@ Provides CRUD operations for ISO 27001 certification-related entities: """ import uuid -from datetime import datetime, date +from datetime import datetime, date, timezone from typing import List, Optional, Dict, Any, Tuple from sqlalchemy.orm import Session as DBSession @@ -94,11 +94,11 @@ class ISMSScopeRepository: import hashlib scope.status = ApprovalStatusEnum.APPROVED scope.approved_by = approved_by - scope.approved_at = datetime.utcnow() + scope.approved_at = datetime.now(timezone.utc) scope.effective_date = effective_date scope.review_date = review_date scope.approval_signature = hashlib.sha256( - f"{scope.scope_statement}|{approved_by}|{datetime.utcnow().isoformat()}".encode() + f"{scope.scope_statement}|{approved_by}|{datetime.now(timezone.utc).isoformat()}".encode() ).hexdigest() self.db.commit() @@ -185,7 +185,7 @@ class ISMSPolicyRepository: policy.status = ApprovalStatusEnum.APPROVED policy.reviewed_by = reviewed_by policy.approved_by = approved_by - policy.approved_at = datetime.utcnow() + policy.approved_at = datetime.now(timezone.utc) policy.effective_date = effective_date policy.next_review_date = date( effective_date.year + (policy.review_frequency_months // 12), @@ -193,7 +193,7 @@ class ISMSPolicyRepository: effective_date.day ) policy.approval_signature = hashlib.sha256( - f"{policy.policy_id}|{approved_by}|{datetime.utcnow().isoformat()}".encode() + f"{policy.policy_id}|{approved_by}|{datetime.now(timezone.utc).isoformat()}".encode() ).hexdigest() self.db.commit() @@ -472,7 +472,7 @@ class AuditFindingRepository: finding.verification_method = verification_method finding.verification_evidence = verification_evidence finding.verified_by = closed_by - finding.verified_at = datetime.utcnow() + finding.verified_at = datetime.now(timezone.utc) self.db.commit() self.db.refresh(finding) @@ -644,7 +644,7 @@ class ManagementReviewRepository: review.status = "approved" review.approved_by = approved_by - review.approved_at = datetime.utcnow() + review.approved_at = datetime.now(timezone.utc) review.next_review_date = next_review_date review.minutes_document_path = minutes_document_path @@ -761,7 +761,7 @@ class AuditTrailRepository: new_value=new_value, change_summary=change_summary, performed_by=performed_by, - performed_at=datetime.utcnow(), + performed_at=datetime.now(timezone.utc), checksum=hashlib.sha256( f"{entity_type}|{entity_id}|{action}|{performed_by}".encode() ).hexdigest(), diff --git a/backend-compliance/compliance/db/models.py b/backend-compliance/compliance/db/models.py index 84aa79d..a89f047 100644 --- a/backend-compliance/compliance/db/models.py +++ b/backend-compliance/compliance/db/models.py @@ -1,1466 +1,85 @@ """ -SQLAlchemy models for Compliance & Audit Framework. +compliance.db.models — backwards-compatibility re-export shim. -Tables: -- compliance_regulations: EU regulations, directives, BSI standards -- compliance_requirements: Individual requirements from regulations -- compliance_controls: Technical & organizational controls -- compliance_control_mappings: Requirement <-> Control mappings -- compliance_evidence: Audit evidence (files, reports, configs) -- compliance_risks: Risk register with likelihood x impact -- compliance_audit_exports: Export history for auditors +Phase 1 refactor split the monolithic 1466-line models module into per-aggregate +sibling modules. Every public symbol is re-exported here so existing imports +(``from compliance.db.models import RegulationDB, ...``) continue to work +unchanged. + +New code SHOULD import directly from the aggregate module: + + from compliance.db.regulation_models import RegulationDB, RequirementDB + from compliance.db.control_models import ControlDB, RiskDB + from compliance.db.ai_system_models import AISystemDB + from compliance.db.service_module_models import ServiceModuleDB + from compliance.db.audit_session_models import AuditSessionDB + from compliance.db.isms_governance_models import ISMSScopeDB + from compliance.db.isms_audit_models import AuditFindingDB + +Import order here also matters for SQLAlchemy mapper configuration: aggregates +that are referenced by name-string relationships must be imported before their +referrers. Regulation/Control/Risk come first, then Service Module, then the +audit sessions and ISMS layers. + +DO NOT add new classes to this file. Add them to the appropriate aggregate +module and re-export here. """ -import enum -import uuid -from datetime import datetime, date +# Order matters: later modules reference classes defined in earlier ones via +# SQLAlchemy string relationships. Keep foundational aggregates first. -from sqlalchemy import ( - Column, String, Text, Integer, Boolean, DateTime, Date, - ForeignKey, Enum, JSON, Index, Float +from compliance.db.regulation_models import ( # noqa: F401 + RegulationTypeEnum, + RegulationDB, + RequirementDB, +) +from compliance.db.control_models import ( # noqa: F401 + ControlTypeEnum, + ControlDomainEnum, + ControlStatusEnum, + RiskLevelEnum, + EvidenceStatusEnum, + ControlDB, + ControlMappingDB, + EvidenceDB, + RiskDB, +) +from compliance.db.ai_system_models import ( # noqa: F401 + AIClassificationEnum, + AISystemStatusEnum, + ExportStatusEnum, + AISystemDB, + AuditExportDB, +) +from compliance.db.service_module_models import ( # noqa: F401 + ServiceTypeEnum, + RelevanceLevelEnum, + ServiceModuleDB, + ModuleRegulationMappingDB, + ModuleRiskDB, +) +from compliance.db.audit_session_models import ( # noqa: F401 + AuditResultEnum, + AuditSessionStatusEnum, + AuditSessionDB, + AuditSignOffDB, +) +from compliance.db.isms_governance_models import ( # noqa: F401 + ApprovalStatusEnum, + ISMSScopeDB, + ISMSContextDB, + ISMSPolicyDB, + SecurityObjectiveDB, + StatementOfApplicabilityDB, +) +from compliance.db.isms_audit_models import ( # noqa: F401 + FindingTypeEnum, + FindingStatusEnum, + CAPATypeEnum, + AuditFindingDB, + CorrectiveActionDB, + ManagementReviewDB, + InternalAuditDB, + AuditTrailDB, + ISMSReadinessCheckDB, ) -from sqlalchemy.orm import relationship - -# Import shared Base from classroom_engine -from classroom_engine.database import Base - - -# ============================================================================ -# ENUMS -# ============================================================================ - -class RegulationTypeEnum(str, enum.Enum): - """Type of regulation/standard.""" - EU_REGULATION = "eu_regulation" # Directly applicable EU law - EU_DIRECTIVE = "eu_directive" # Requires national implementation - DE_LAW = "de_law" # German national law - BSI_STANDARD = "bsi_standard" # BSI technical guidelines - INDUSTRY_STANDARD = "industry_standard" # ISO, OWASP, etc. - - -class ControlTypeEnum(str, enum.Enum): - """Type of security control.""" - PREVENTIVE = "preventive" # Prevents incidents - DETECTIVE = "detective" # Detects incidents - CORRECTIVE = "corrective" # Corrects after incidents - - -class ControlDomainEnum(str, enum.Enum): - """Domain/category of control.""" - GOVERNANCE = "gov" # Governance & Organization - PRIVACY = "priv" # Privacy & Data Protection - IAM = "iam" # Identity & Access Management - CRYPTO = "crypto" # Cryptography & Key Management - SDLC = "sdlc" # Secure Development Lifecycle - OPS = "ops" # Operations & Monitoring - AI = "ai" # AI-specific controls - CRA = "cra" # CRA & Supply Chain - AUDIT = "aud" # Audit & Traceability - - -class ControlStatusEnum(str, enum.Enum): - """Implementation status of a control.""" - PASS = "pass" # Fully implemented & passing - PARTIAL = "partial" # Partially implemented - FAIL = "fail" # Not passing - NOT_APPLICABLE = "n/a" # Not applicable - PLANNED = "planned" # Planned for implementation - - -class RiskLevelEnum(str, enum.Enum): - """Risk severity level.""" - LOW = "low" - MEDIUM = "medium" - HIGH = "high" - CRITICAL = "critical" - - -class EvidenceStatusEnum(str, enum.Enum): - """Status of evidence artifact.""" - VALID = "valid" # Currently valid - EXPIRED = "expired" # Past validity date - PENDING = "pending" # Awaiting validation - FAILED = "failed" # Failed validation - - -class ExportStatusEnum(str, enum.Enum): - """Status of audit export.""" - PENDING = "pending" - GENERATING = "generating" - COMPLETED = "completed" - FAILED = "failed" - - -class ServiceTypeEnum(str, enum.Enum): - """Type of Breakpilot service/module.""" - BACKEND = "backend" # API/Backend services - DATABASE = "database" # Data storage - AI = "ai" # AI/ML services - COMMUNICATION = "communication" # Chat/Video/Messaging - STORAGE = "storage" # File/Object storage - INFRASTRUCTURE = "infrastructure" # Load balancer, reverse proxy - MONITORING = "monitoring" # Logging, metrics - SECURITY = "security" # Auth, encryption, secrets - - -class RelevanceLevelEnum(str, enum.Enum): - """Relevance level of a regulation to a service.""" - CRITICAL = "critical" # Non-compliance = shutdown - HIGH = "high" # Major risk - MEDIUM = "medium" # Moderate risk - LOW = "low" # Minor risk - - -# ============================================================================ -# MODELS -# ============================================================================ - -class RegulationDB(Base): - """ - Represents a regulation, directive, or standard. - - Examples: GDPR, AI Act, CRA, BSI-TR-03161 - """ - __tablename__ = 'compliance_regulations' - - id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) - code = Column(String(20), unique=True, nullable=False, index=True) # e.g., "GDPR", "AIACT" - name = Column(String(200), nullable=False) # Short name - full_name = Column(Text) # Full official name - regulation_type = Column(Enum(RegulationTypeEnum), nullable=False) - source_url = Column(String(500)) # EUR-Lex URL or similar - local_pdf_path = Column(String(500)) # Local PDF if available - effective_date = Column(Date) # When it came into force - description = Column(Text) # Brief description - is_active = Column(Boolean, default=True) - - # Timestamps - created_at = Column(DateTime, default=datetime.utcnow) - updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) - - # Relationships - requirements = relationship("RequirementDB", back_populates="regulation", cascade="all, delete-orphan") - - def __repr__(self): - return f"" - - -class RequirementDB(Base): - """ - Individual requirement from a regulation. - - Examples: GDPR Art. 32(1)(a), AI Act Art. 9, BSI-TR O.Auth_1 - """ - __tablename__ = 'compliance_requirements' - - id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) - regulation_id = Column(String(36), ForeignKey('compliance_regulations.id'), nullable=False, index=True) - - # Requirement identification - article = Column(String(50), nullable=False) # e.g., "Art. 32", "O.Auth_1" - paragraph = Column(String(20)) # e.g., "(1)(a)" - requirement_id_external = Column(String(50)) # External ID (e.g., BSI ID) - title = Column(String(300), nullable=False) # Requirement title - description = Column(Text) # Brief description - requirement_text = Column(Text) # Original text from regulation - - # Breakpilot-specific interpretation and implementation - breakpilot_interpretation = Column(Text) # How Breakpilot interprets this - implementation_status = Column(String(30), default="not_started") # not_started, in_progress, implemented, verified - implementation_details = Column(Text) # How we implemented it - code_references = Column(JSON) # List of {"file": "...", "line": ..., "description": "..."} - documentation_links = Column(JSON) # List of internal doc links - - # Evidence for auditors - evidence_description = Column(Text) # What evidence proves compliance - evidence_artifacts = Column(JSON) # List of {"type": "...", "path": "...", "description": "..."} - - # Audit-specific fields - auditor_notes = Column(Text) # Notes from auditor review - audit_status = Column(String(30), default="pending") # pending, in_review, approved, rejected - last_audit_date = Column(DateTime) - last_auditor = Column(String(100)) - - is_applicable = Column(Boolean, default=True) # Applicable to Breakpilot? - applicability_reason = Column(Text) # Why/why not applicable - - priority = Column(Integer, default=2) # 1=Critical, 2=High, 3=Medium - - # Source document reference - source_page = Column(Integer) # Page number in source document - source_section = Column(String(100)) # Section in source document - - # Timestamps - created_at = Column(DateTime, default=datetime.utcnow) - updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) - - # Relationships - regulation = relationship("RegulationDB", back_populates="requirements") - control_mappings = relationship("ControlMappingDB", back_populates="requirement", cascade="all, delete-orphan") - - __table_args__ = ( - Index('ix_requirement_regulation_article', 'regulation_id', 'article'), - Index('ix_requirement_audit_status', 'audit_status'), - Index('ix_requirement_impl_status', 'implementation_status'), - ) - - def __repr__(self): - return f"" - - -class ControlDB(Base): - """ - Technical or organizational security control. - - Examples: PRIV-001 (Verarbeitungsverzeichnis), SDLC-001 (SAST Scanning) - """ - __tablename__ = 'compliance_controls' - - id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) - control_id = Column(String(20), unique=True, nullable=False, index=True) # e.g., "PRIV-001" - - domain = Column(Enum(ControlDomainEnum), nullable=False, index=True) - control_type = Column(Enum(ControlTypeEnum), nullable=False) - - title = Column(String(300), nullable=False) - description = Column(Text) - pass_criteria = Column(Text, nullable=False) # Measurable pass criteria - implementation_guidance = Column(Text) # How to implement - - # Code/Evidence references - code_reference = Column(String(500)) # e.g., "backend/middleware/pii_redactor.py:45" - documentation_url = Column(String(500)) # Link to internal docs - - # Automation - is_automated = Column(Boolean, default=False) - automation_tool = Column(String(100)) # e.g., "Semgrep", "Trivy" - automation_config = Column(JSON) # Tool-specific config - - # Status - status = Column(Enum(ControlStatusEnum), default=ControlStatusEnum.PLANNED) - status_notes = Column(Text) - - # Ownership & Review - owner = Column(String(100)) # Responsible person/team - review_frequency_days = Column(Integer, default=90) - last_reviewed_at = Column(DateTime) - next_review_at = Column(DateTime) - - # Timestamps - created_at = Column(DateTime, default=datetime.utcnow) - updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) - - # Relationships - mappings = relationship("ControlMappingDB", back_populates="control", cascade="all, delete-orphan") - evidence = relationship("EvidenceDB", back_populates="control", cascade="all, delete-orphan") - - __table_args__ = ( - Index('ix_control_domain_status', 'domain', 'status'), - ) - - def __repr__(self): - return f"" - - -class ControlMappingDB(Base): - """ - Maps requirements to controls (many-to-many with metadata). - """ - __tablename__ = 'compliance_control_mappings' - - id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) - requirement_id = Column(String(36), ForeignKey('compliance_requirements.id'), nullable=False, index=True) - control_id = Column(String(36), ForeignKey('compliance_controls.id'), nullable=False, index=True) - - coverage_level = Column(String(20), default="full") # "full", "partial", "planned" - notes = Column(Text) # Explanation of coverage - - # Timestamps - created_at = Column(DateTime, default=datetime.utcnow) - updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) - - # Relationships - requirement = relationship("RequirementDB", back_populates="control_mappings") - control = relationship("ControlDB", back_populates="mappings") - - __table_args__ = ( - Index('ix_mapping_req_ctrl', 'requirement_id', 'control_id', unique=True), - ) - - -class EvidenceDB(Base): - """ - Audit evidence for controls. - - Types: scan_report, policy_document, config_snapshot, test_result, - manual_upload, screenshot, external_link - """ - __tablename__ = 'compliance_evidence' - - id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) - control_id = Column(String(36), ForeignKey('compliance_controls.id'), nullable=False, index=True) - - evidence_type = Column(String(50), nullable=False) # Type of evidence - title = Column(String(300), nullable=False) - description = Column(Text) - - # File/Link storage - artifact_path = Column(String(500)) # Local file path - artifact_url = Column(String(500)) # External URL - artifact_hash = Column(String(64)) # SHA-256 hash - file_size_bytes = Column(Integer) - mime_type = Column(String(100)) - - # Validity period - valid_from = Column(DateTime, nullable=False, default=datetime.utcnow) - valid_until = Column(DateTime) # NULL = no expiry - status = Column(Enum(EvidenceStatusEnum), default=EvidenceStatusEnum.VALID) - - # Source tracking - source = Column(String(100)) # "ci_pipeline", "manual", "api" - ci_job_id = Column(String(100)) # CI/CD job reference - uploaded_by = Column(String(100)) # User who uploaded - - # Timestamps - collected_at = Column(DateTime, default=datetime.utcnow) - created_at = Column(DateTime, default=datetime.utcnow) - updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) - - # Relationships - control = relationship("ControlDB", back_populates="evidence") - - __table_args__ = ( - Index('ix_evidence_control_type', 'control_id', 'evidence_type'), - Index('ix_evidence_status', 'status'), - ) - - def __repr__(self): - return f"" - - -class RiskDB(Base): - """ - Risk register entry with likelihood x impact scoring. - """ - __tablename__ = 'compliance_risks' - - id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) - risk_id = Column(String(20), unique=True, nullable=False, index=True) # e.g., "RISK-001" - - title = Column(String(300), nullable=False) - description = Column(Text) - category = Column(String(50), nullable=False) # "data_breach", "compliance_gap", etc. - - # Inherent risk (before controls) - likelihood = Column(Integer, nullable=False) # 1-5 - impact = Column(Integer, nullable=False) # 1-5 - inherent_risk = Column(Enum(RiskLevelEnum), nullable=False) - - # Mitigating controls - mitigating_controls = Column(JSON) # List of control_ids - - # Residual risk (after controls) - residual_likelihood = Column(Integer) - residual_impact = Column(Integer) - residual_risk = Column(Enum(RiskLevelEnum)) - - # Management - owner = Column(String(100)) - status = Column(String(20), default="open") # "open", "mitigated", "accepted", "transferred" - treatment_plan = Column(Text) - - # Review - identified_date = Column(Date, default=date.today) - review_date = Column(Date) - last_assessed_at = Column(DateTime) - - # Timestamps - created_at = Column(DateTime, default=datetime.utcnow) - updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) - - __table_args__ = ( - Index('ix_risk_category_status', 'category', 'status'), - Index('ix_risk_inherent', 'inherent_risk'), - ) - - def __repr__(self): - return f"" - - @staticmethod - def calculate_risk_level(likelihood: int, impact: int) -> RiskLevelEnum: - """Calculate risk level from likelihood x impact matrix.""" - score = likelihood * impact - if score >= 20: - return RiskLevelEnum.CRITICAL - elif score >= 12: - return RiskLevelEnum.HIGH - elif score >= 6: - return RiskLevelEnum.MEDIUM - else: - return RiskLevelEnum.LOW - - -class AIClassificationEnum(str, enum.Enum): - """AI Act risk classification.""" - PROHIBITED = "prohibited" - HIGH_RISK = "high-risk" - LIMITED_RISK = "limited-risk" - MINIMAL_RISK = "minimal-risk" - UNCLASSIFIED = "unclassified" - - -class AISystemStatusEnum(str, enum.Enum): - """Status of an AI system in compliance tracking.""" - DRAFT = "draft" - CLASSIFIED = "classified" - COMPLIANT = "compliant" - NON_COMPLIANT = "non-compliant" - - -class AISystemDB(Base): - """ - AI System registry for AI Act compliance. - Tracks AI systems, their risk classification, and compliance status. - """ - __tablename__ = 'compliance_ai_systems' - - id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) - name = Column(String(300), nullable=False) - description = Column(Text) - purpose = Column(String(500)) - sector = Column(String(100)) - - # AI Act classification - classification = Column(Enum(AIClassificationEnum), default=AIClassificationEnum.UNCLASSIFIED) - status = Column(Enum(AISystemStatusEnum), default=AISystemStatusEnum.DRAFT) - - # Assessment - assessment_date = Column(DateTime) - assessment_result = Column(JSON) # Full assessment result - obligations = Column(JSON) # List of AI Act obligations - risk_factors = Column(JSON) # Risk factors from assessment - recommendations = Column(JSON) # Recommendations from assessment - - # Timestamps - created_at = Column(DateTime, default=datetime.utcnow) - updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) - - __table_args__ = ( - Index('ix_ai_system_classification', 'classification'), - Index('ix_ai_system_status', 'status'), - ) - - def __repr__(self): - return f"" - - -class AuditExportDB(Base): - """ - Tracks audit export packages generated for external auditors. - """ - __tablename__ = 'compliance_audit_exports' - - id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) - - export_type = Column(String(50), nullable=False) # "full", "controls_only", "evidence_only" - export_name = Column(String(200)) # User-friendly name - - # Scope - included_regulations = Column(JSON) # List of regulation codes - included_domains = Column(JSON) # List of control domains - date_range_start = Column(Date) - date_range_end = Column(Date) - - # Generation - requested_by = Column(String(100), nullable=False) - requested_at = Column(DateTime, nullable=False, default=datetime.utcnow) - completed_at = Column(DateTime) - - # Output - file_path = Column(String(500)) - file_hash = Column(String(64)) # SHA-256 of ZIP - file_size_bytes = Column(Integer) - - status = Column(Enum(ExportStatusEnum), default=ExportStatusEnum.PENDING) - error_message = Column(Text) - - # Statistics - total_controls = Column(Integer) - total_evidence = Column(Integer) - compliance_score = Column(Float) - - # Timestamps - created_at = Column(DateTime, default=datetime.utcnow) - updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) - - def __repr__(self): - return f"" - - -# ============================================================================ -# SERVICE MODULE REGISTRY (Sprint 3) -# ============================================================================ - -class ServiceModuleDB(Base): - """ - Registry of all Breakpilot services/modules for compliance mapping. - - Tracks which regulations apply to which services, enabling: - - Service-specific compliance views - - Aggregated risk per service - - Gap analysis by module - """ - __tablename__ = 'compliance_service_modules' - - id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) - name = Column(String(100), unique=True, nullable=False, index=True) # e.g., "consent-service" - display_name = Column(String(200), nullable=False) # e.g., "Go Consent Service" - description = Column(Text) - - # Technical details - service_type = Column(Enum(ServiceTypeEnum), nullable=False) - port = Column(Integer) # Primary port (if applicable) - technology_stack = Column(JSON) # e.g., ["Go", "Gin", "PostgreSQL"] - repository_path = Column(String(500)) # e.g., "/consent-service" - docker_image = Column(String(200)) # e.g., "breakpilot-pwa-consent-service" - - # Data categories handled - data_categories = Column(JSON) # e.g., ["personal_data", "consent_records"] - processes_pii = Column(Boolean, default=False) # Handles personally identifiable info? - processes_health_data = Column(Boolean, default=False) # Handles special category health data? - ai_components = Column(Boolean, default=False) # Contains AI/ML components? - - # Status - is_active = Column(Boolean, default=True) - criticality = Column(String(20), default="medium") # "critical", "high", "medium", "low" - - # Compliance aggregation - compliance_score = Column(Float) # Calculated score 0-100 - last_compliance_check = Column(DateTime) - - # Owner - owner_team = Column(String(100)) # e.g., "Backend Team" - owner_contact = Column(String(200)) # e.g., "backend@breakpilot.app" - - # Timestamps - created_at = Column(DateTime, default=datetime.utcnow) - updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) - - # Relationships - regulation_mappings = relationship("ModuleRegulationMappingDB", back_populates="module", cascade="all, delete-orphan") - module_risks = relationship("ModuleRiskDB", back_populates="module", cascade="all, delete-orphan") - - __table_args__ = ( - Index('ix_module_type_active', 'service_type', 'is_active'), - ) - - def __repr__(self): - return f"" - - -class ModuleRegulationMappingDB(Base): - """ - Maps services to applicable regulations with relevance level. - - Enables filtering: "Show all GDPR requirements for consent-service" - """ - __tablename__ = 'compliance_module_regulations' - - id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) - module_id = Column(String(36), ForeignKey('compliance_service_modules.id'), nullable=False, index=True) - regulation_id = Column(String(36), ForeignKey('compliance_regulations.id'), nullable=False, index=True) - - relevance_level = Column(Enum(RelevanceLevelEnum), nullable=False, default=RelevanceLevelEnum.MEDIUM) - notes = Column(Text) # Why this regulation applies - applicable_articles = Column(JSON) # List of specific articles that apply - - # Timestamps - created_at = Column(DateTime, default=datetime.utcnow) - updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) - - # Relationships - module = relationship("ServiceModuleDB", back_populates="regulation_mappings") - regulation = relationship("RegulationDB") - - __table_args__ = ( - Index('ix_module_regulation', 'module_id', 'regulation_id', unique=True), - ) - - -class ModuleRiskDB(Base): - """ - Service-specific risks aggregated from requirements and controls. - """ - __tablename__ = 'compliance_module_risks' - - id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) - module_id = Column(String(36), ForeignKey('compliance_service_modules.id'), nullable=False, index=True) - risk_id = Column(String(36), ForeignKey('compliance_risks.id'), nullable=False, index=True) - - # Module-specific assessment - module_likelihood = Column(Integer) # 1-5, may differ from global - module_impact = Column(Integer) # 1-5, may differ from global - module_risk_level = Column(Enum(RiskLevelEnum)) - - assessment_notes = Column(Text) # Module-specific notes - - # Timestamps - created_at = Column(DateTime, default=datetime.utcnow) - updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) - - # Relationships - module = relationship("ServiceModuleDB", back_populates="module_risks") - risk = relationship("RiskDB") - - __table_args__ = ( - Index('ix_module_risk', 'module_id', 'risk_id', unique=True), - ) - - -# ============================================================================ -# AUDIT SESSION & SIGN-OFF (Sprint 3 - Phase 3) -# ============================================================================ - -class AuditResultEnum(str, enum.Enum): - """Result of an audit sign-off for a requirement.""" - COMPLIANT = "compliant" # Fully compliant - COMPLIANT_WITH_NOTES = "compliant_notes" # Compliant with observations - NON_COMPLIANT = "non_compliant" # Not compliant - remediation required - NOT_APPLICABLE = "not_applicable" # Not applicable to this audit - PENDING = "pending" # Not yet reviewed - - -class AuditSessionStatusEnum(str, enum.Enum): - """Status of an audit session.""" - DRAFT = "draft" # Session created, not started - IN_PROGRESS = "in_progress" # Audit in progress - COMPLETED = "completed" # All items reviewed - ARCHIVED = "archived" # Historical record - - -class AuditSessionDB(Base): - """ - Audit session for structured compliance reviews. - - Enables auditors to: - - Create named audit sessions (e.g., "Q1 2026 GDPR Audit") - - Track progress through requirements - - Sign off individual items with digital signatures - - Generate audit reports - """ - __tablename__ = 'compliance_audit_sessions' - - id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) - name = Column(String(200), nullable=False) # e.g., "Q1 2026 Compliance Audit" - description = Column(Text) - - # Auditor information - auditor_name = Column(String(100), nullable=False) # e.g., "Dr. Thomas Müller" - auditor_email = Column(String(200)) - auditor_organization = Column(String(200)) # External auditor company - - # Session scope - status = Column(Enum(AuditSessionStatusEnum), default=AuditSessionStatusEnum.DRAFT) - regulation_ids = Column(JSON) # Filter: ["GDPR", "AIACT"] or null for all - - # Progress tracking - total_items = Column(Integer, default=0) - completed_items = Column(Integer, default=0) - compliant_count = Column(Integer, default=0) - non_compliant_count = Column(Integer, default=0) - - # Timestamps - created_at = Column(DateTime, default=datetime.utcnow) - started_at = Column(DateTime) # When audit began - completed_at = Column(DateTime) # When audit finished - updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) - - # Relationships - signoffs = relationship("AuditSignOffDB", back_populates="session", cascade="all, delete-orphan") - - __table_args__ = ( - Index('ix_audit_session_status', 'status'), - Index('ix_audit_session_auditor', 'auditor_name'), - ) - - def __repr__(self): - return f"" - - @property - def completion_percentage(self) -> float: - """Calculate completion percentage.""" - if self.total_items == 0: - return 0.0 - return round((self.completed_items / self.total_items) * 100, 1) - - -class AuditSignOffDB(Base): - """ - Individual sign-off for a requirement within an audit session. - - Features: - - Records audit result (compliant, non-compliant, etc.) - - Stores auditor notes and observations - - Creates digital signature (SHA-256 hash) for tamper evidence - """ - __tablename__ = 'compliance_audit_signoffs' - - id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) - session_id = Column(String(36), ForeignKey('compliance_audit_sessions.id'), nullable=False, index=True) - requirement_id = Column(String(36), ForeignKey('compliance_requirements.id'), nullable=False, index=True) - - # Audit result - result = Column(Enum(AuditResultEnum), default=AuditResultEnum.PENDING) - notes = Column(Text) # Auditor observations - - # Evidence references for this sign-off - evidence_ids = Column(JSON) # List of evidence IDs reviewed - - # Digital signature (SHA-256 hash of result + auditor + timestamp) - signature_hash = Column(String(64)) # SHA-256 hex string - signed_at = Column(DateTime) - signed_by = Column(String(100)) # Auditor name at time of signing - - # Timestamps - created_at = Column(DateTime, default=datetime.utcnow) - updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) - - # Relationships - session = relationship("AuditSessionDB", back_populates="signoffs") - requirement = relationship("RequirementDB") - - __table_args__ = ( - Index('ix_signoff_session_requirement', 'session_id', 'requirement_id', unique=True), - Index('ix_signoff_result', 'result'), - ) - - def __repr__(self): - return f"" - - def create_signature(self, auditor_name: str) -> str: - """ - Create a digital signature for this sign-off. - - Returns SHA-256 hash of: result + requirement_id + auditor_name + timestamp - """ - import hashlib - from datetime import datetime - - timestamp = datetime.utcnow().isoformat() - data = f"{self.result.value}|{self.requirement_id}|{auditor_name}|{timestamp}" - signature = hashlib.sha256(data.encode()).hexdigest() - - self.signature_hash = signature - self.signed_at = datetime.utcnow() - self.signed_by = auditor_name - - return signature - - -# ============================================================================ -# ISO 27001 ISMS MODELS (Kapitel 4-10) -# ============================================================================ - -class ApprovalStatusEnum(str, enum.Enum): - """Approval status for ISMS documents.""" - DRAFT = "draft" - UNDER_REVIEW = "under_review" - APPROVED = "approved" - SUPERSEDED = "superseded" - - -class FindingTypeEnum(str, enum.Enum): - """ISO 27001 audit finding classification.""" - MAJOR = "major" # Major nonconformity - blocks certification - MINOR = "minor" # Minor nonconformity - requires CAPA - OFI = "ofi" # Opportunity for Improvement - POSITIVE = "positive" # Positive observation - - -class FindingStatusEnum(str, enum.Enum): - """Status of an audit finding.""" - OPEN = "open" - IN_PROGRESS = "in_progress" - CORRECTIVE_ACTION_PENDING = "capa_pending" - VERIFICATION_PENDING = "verification_pending" - VERIFIED = "verified" - CLOSED = "closed" - - -class CAPATypeEnum(str, enum.Enum): - """Type of corrective/preventive action.""" - CORRECTIVE = "corrective" # Fix the nonconformity - PREVENTIVE = "preventive" # Prevent recurrence - BOTH = "both" - - -class ISMSScopeDB(Base): - """ - ISMS Scope Definition (ISO 27001 Kapitel 4.3) - - Defines the boundaries and applicability of the ISMS. - This is MANDATORY for certification. - """ - __tablename__ = 'compliance_isms_scope' - - id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) - version = Column(String(20), nullable=False, default="1.0") - - # Scope definition - scope_statement = Column(Text, nullable=False) # Main scope text - included_locations = Column(JSON) # List of locations - included_processes = Column(JSON) # List of processes - included_services = Column(JSON) # List of services/products - excluded_items = Column(JSON) # Explicitly excluded items - exclusion_justification = Column(Text) # Why items are excluded - - # Boundaries - organizational_boundary = Column(Text) # Legal entity, departments - physical_boundary = Column(Text) # Locations, networks - technical_boundary = Column(Text) # Systems, applications - - # Approval - status = Column(Enum(ApprovalStatusEnum), default=ApprovalStatusEnum.DRAFT) - approved_by = Column(String(100)) - approved_at = Column(DateTime) - approval_signature = Column(String(64)) # SHA-256 hash - - # Validity - effective_date = Column(Date) - review_date = Column(Date) # Next mandatory review - - # Timestamps - created_at = Column(DateTime, default=datetime.utcnow) - updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) - created_by = Column(String(100)) - updated_by = Column(String(100)) - - __table_args__ = ( - Index('ix_isms_scope_status', 'status'), - ) - - def __repr__(self): - return f"" - - -class ISMSContextDB(Base): - """ - ISMS Context (ISO 27001 Kapitel 4.1, 4.2) - - Documents internal/external issues and interested parties. - """ - __tablename__ = 'compliance_isms_context' - - id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) - version = Column(String(20), nullable=False, default="1.0") - - # 4.1 Internal issues - internal_issues = Column(JSON) # List of {"issue": "", "impact": "", "treatment": ""} - - # 4.1 External issues - external_issues = Column(JSON) # List of {"issue": "", "impact": "", "treatment": ""} - - # 4.2 Interested parties - interested_parties = Column(JSON) # List of {"party": "", "requirements": [], "relevance": ""} - - # Legal/regulatory requirements - regulatory_requirements = Column(JSON) # DSGVO, AI Act, etc. - contractual_requirements = Column(JSON) # Customer contracts - - # Analysis - swot_strengths = Column(JSON) - swot_weaknesses = Column(JSON) - swot_opportunities = Column(JSON) - swot_threats = Column(JSON) - - # Approval - status = Column(Enum(ApprovalStatusEnum), default=ApprovalStatusEnum.DRAFT) - approved_by = Column(String(100)) - approved_at = Column(DateTime) - - # Review - last_reviewed_at = Column(DateTime) - next_review_date = Column(Date) - - # Timestamps - created_at = Column(DateTime, default=datetime.utcnow) - updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) - - def __repr__(self): - return f"" - - -class ISMSPolicyDB(Base): - """ - ISMS Policies (ISO 27001 Kapitel 5.2) - - Information security policy and sub-policies. - """ - __tablename__ = 'compliance_isms_policies' - - id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) - policy_id = Column(String(30), unique=True, nullable=False, index=True) # e.g., "POL-ISMS-001" - - # Policy details - title = Column(String(200), nullable=False) - policy_type = Column(String(50), nullable=False) # "master", "operational", "technical" - description = Column(Text) - policy_text = Column(Text, nullable=False) # Full policy content - - # Scope - applies_to = Column(JSON) # Roles, departments, systems - - # Document control - version = Column(String(20), nullable=False, default="1.0") - status = Column(Enum(ApprovalStatusEnum), default=ApprovalStatusEnum.DRAFT) - - # Approval chain - authored_by = Column(String(100)) - reviewed_by = Column(String(100)) - approved_by = Column(String(100)) # Must be top management - approved_at = Column(DateTime) - approval_signature = Column(String(64)) - - # Validity - effective_date = Column(Date) - review_frequency_months = Column(Integer, default=12) - next_review_date = Column(Date) - - # References - parent_policy_id = Column(String(36), ForeignKey('compliance_isms_policies.id')) - related_controls = Column(JSON) # List of control_ids - - # Document path - document_path = Column(String(500)) # Link to full document - - # Timestamps - created_at = Column(DateTime, default=datetime.utcnow) - updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) - - __table_args__ = ( - Index('ix_policy_type_status', 'policy_type', 'status'), - ) - - def __repr__(self): - return f"" - - -class SecurityObjectiveDB(Base): - """ - Security Objectives (ISO 27001 Kapitel 6.2) - - Measurable information security objectives. - """ - __tablename__ = 'compliance_security_objectives' - - id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) - objective_id = Column(String(30), unique=True, nullable=False, index=True) # e.g., "OBJ-001" - - # Objective definition - title = Column(String(200), nullable=False) - description = Column(Text) - category = Column(String(50)) # "availability", "confidentiality", "integrity", "compliance" - - # SMART criteria - specific = Column(Text) # What exactly - measurable = Column(Text) # How measured - achievable = Column(Text) # Is it realistic - relevant = Column(Text) # Why important - time_bound = Column(Text) # Deadline - - # Metrics - kpi_name = Column(String(100)) - kpi_target = Column(String(100)) # Target value - kpi_current = Column(String(100)) # Current value - kpi_unit = Column(String(50)) # %, count, score - measurement_frequency = Column(String(50)) # monthly, quarterly - - # Responsibility - owner = Column(String(100)) - accountable = Column(String(100)) # RACI: Accountable - - # Status - status = Column(String(30), default="active") # active, achieved, not_achieved, cancelled - progress_percentage = Column(Integer, default=0) - - # Timeline - target_date = Column(Date) - achieved_date = Column(Date) - - # Linked items - related_controls = Column(JSON) - related_risks = Column(JSON) - - # Approval - approved_by = Column(String(100)) - approved_at = Column(DateTime) - - # Timestamps - created_at = Column(DateTime, default=datetime.utcnow) - updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) - - __table_args__ = ( - Index('ix_objective_status', 'status'), - Index('ix_objective_category', 'category'), - ) - - def __repr__(self): - return f"" - - -class StatementOfApplicabilityDB(Base): - """ - Statement of Applicability (SoA) - ISO 27001 Anhang A Mapping - - Documents which Annex A controls are applicable and why. - This is MANDATORY for certification. - """ - __tablename__ = 'compliance_soa' - - id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) - - # ISO 27001:2022 Annex A reference - annex_a_control = Column(String(20), nullable=False, index=True) # e.g., "A.5.1" - annex_a_title = Column(String(300), nullable=False) - annex_a_category = Column(String(100)) # "Organizational", "People", "Physical", "Technological" - - # Applicability decision - is_applicable = Column(Boolean, nullable=False) - applicability_justification = Column(Text, nullable=False) # MUST be documented - - # Implementation status - implementation_status = Column(String(30), default="planned") # planned, partial, implemented, not_implemented - implementation_notes = Column(Text) - - # Mapping to our controls - breakpilot_control_ids = Column(JSON) # List of our control_ids that address this - coverage_level = Column(String(20), default="full") # full, partial, planned - - # Evidence - evidence_description = Column(Text) - evidence_ids = Column(JSON) # Links to EvidenceDB - - # Risk-based justification (for exclusions) - risk_assessment_notes = Column(Text) # If not applicable, explain why - compensating_controls = Column(Text) # If partial, explain compensating measures - - # Approval - reviewed_by = Column(String(100)) - reviewed_at = Column(DateTime) - approved_by = Column(String(100)) - approved_at = Column(DateTime) - - # Version tracking - version = Column(String(20), default="1.0") - - # Timestamps - created_at = Column(DateTime, default=datetime.utcnow) - updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) - - __table_args__ = ( - Index('ix_soa_annex_control', 'annex_a_control', unique=True), - Index('ix_soa_applicable', 'is_applicable'), - Index('ix_soa_status', 'implementation_status'), - ) - - def __repr__(self): - return f"" - - -class AuditFindingDB(Base): - """ - Audit Finding with ISO 27001 Classification (Major/Minor/OFI) - - Tracks findings from internal and external audits with proper - classification and CAPA workflow. - """ - __tablename__ = 'compliance_audit_findings' - - id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) - finding_id = Column(String(30), unique=True, nullable=False, index=True) # e.g., "FIND-2026-001" - - # Source - audit_session_id = Column(String(36), ForeignKey('compliance_audit_sessions.id'), index=True) - internal_audit_id = Column(String(36), ForeignKey('compliance_internal_audits.id'), index=True) - - # Classification (CRITICAL for ISO 27001!) - finding_type = Column(Enum(FindingTypeEnum), nullable=False) - - # ISO reference - iso_chapter = Column(String(20)) # e.g., "6.1.2", "9.2" - annex_a_control = Column(String(20)) # e.g., "A.8.2" - - # Finding details - title = Column(String(300), nullable=False) - description = Column(Text, nullable=False) - objective_evidence = Column(Text, nullable=False) # What the auditor observed - - # Root cause analysis - root_cause = Column(Text) - root_cause_method = Column(String(50)) # "5-why", "fishbone", "pareto" - - # Impact assessment - impact_description = Column(Text) - affected_processes = Column(JSON) - affected_assets = Column(JSON) - - # Status tracking - status = Column(Enum(FindingStatusEnum), default=FindingStatusEnum.OPEN) - - # Responsibility - owner = Column(String(100)) # Person responsible for closure - auditor = Column(String(100)) # Auditor who raised finding - - # Dates - identified_date = Column(Date, nullable=False, default=date.today) - due_date = Column(Date) # Deadline for closure - closed_date = Column(Date) - - # Verification - verification_method = Column(Text) - verified_by = Column(String(100)) - verified_at = Column(DateTime) - verification_evidence = Column(Text) - - # Closure - closure_notes = Column(Text) - closed_by = Column(String(100)) - - # Timestamps - created_at = Column(DateTime, default=datetime.utcnow) - updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) - - # Relationships - corrective_actions = relationship("CorrectiveActionDB", back_populates="finding", cascade="all, delete-orphan") - - __table_args__ = ( - Index('ix_finding_type_status', 'finding_type', 'status'), - Index('ix_finding_due_date', 'due_date'), - ) - - def __repr__(self): - return f"" - - @property - def is_blocking(self) -> bool: - """Major findings block certification.""" - return self.finding_type == FindingTypeEnum.MAJOR and self.status != FindingStatusEnum.CLOSED - - -class CorrectiveActionDB(Base): - """ - Corrective & Preventive Actions (CAPA) - ISO 27001 10.1 - - Tracks actions taken to address nonconformities. - """ - __tablename__ = 'compliance_corrective_actions' - - id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) - capa_id = Column(String(30), unique=True, nullable=False, index=True) # e.g., "CAPA-2026-001" - - # Link to finding - finding_id = Column(String(36), ForeignKey('compliance_audit_findings.id'), nullable=False, index=True) - - # Type - capa_type = Column(Enum(CAPATypeEnum), nullable=False) - - # Action details - title = Column(String(300), nullable=False) - description = Column(Text, nullable=False) - expected_outcome = Column(Text) - - # Responsibility - assigned_to = Column(String(100), nullable=False) - approved_by = Column(String(100)) - - # Timeline - planned_start = Column(Date) - planned_completion = Column(Date, nullable=False) - actual_completion = Column(Date) - - # Status - status = Column(String(30), default="planned") # planned, in_progress, completed, verified, cancelled - progress_percentage = Column(Integer, default=0) - - # Resources - estimated_effort_hours = Column(Integer) - actual_effort_hours = Column(Integer) - resources_required = Column(Text) - - # Evidence of implementation - implementation_evidence = Column(Text) - evidence_ids = Column(JSON) - - # Effectiveness review - effectiveness_criteria = Column(Text) - effectiveness_verified = Column(Boolean, default=False) - effectiveness_verification_date = Column(Date) - effectiveness_notes = Column(Text) - - # Timestamps - created_at = Column(DateTime, default=datetime.utcnow) - updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) - - # Relationships - finding = relationship("AuditFindingDB", back_populates="corrective_actions") - - __table_args__ = ( - Index('ix_capa_status', 'status'), - Index('ix_capa_due', 'planned_completion'), - ) - - def __repr__(self): - return f"" - - -class ManagementReviewDB(Base): - """ - Management Review (ISO 27001 Kapitel 9.3) - - Records mandatory management reviews of the ISMS. - """ - __tablename__ = 'compliance_management_reviews' - - id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) - review_id = Column(String(30), unique=True, nullable=False, index=True) # e.g., "MR-2026-Q1" - - # Review details - title = Column(String(200), nullable=False) - review_date = Column(Date, nullable=False) - review_period_start = Column(Date) # Period being reviewed - review_period_end = Column(Date) - - # Participants - chairperson = Column(String(100), nullable=False) # Usually top management - attendees = Column(JSON) # List of {"name": "", "role": ""} - - # 9.3 Review Inputs (mandatory!) - input_previous_actions = Column(Text) # Status of previous review actions - input_isms_changes = Column(Text) # Changes in internal/external issues - input_security_performance = Column(Text) # Nonconformities, monitoring, audit results - input_interested_party_feedback = Column(Text) - input_risk_assessment_results = Column(Text) - input_improvement_opportunities = Column(Text) - - # Additional inputs - input_policy_effectiveness = Column(Text) - input_objective_achievement = Column(Text) - input_resource_adequacy = Column(Text) - - # 9.3 Review Outputs (mandatory!) - output_improvement_decisions = Column(Text) # Decisions for improvement - output_isms_changes = Column(Text) # Changes needed to ISMS - output_resource_needs = Column(Text) # Resource requirements - - # Action items - action_items = Column(JSON) # List of {"action": "", "owner": "", "due_date": ""} - - # Overall assessment - isms_effectiveness_rating = Column(String(20)) # "effective", "partially_effective", "not_effective" - key_decisions = Column(Text) - - # Approval - status = Column(String(30), default="draft") # draft, conducted, approved - approved_by = Column(String(100)) - approved_at = Column(DateTime) - minutes_document_path = Column(String(500)) # Link to meeting minutes - - # Next review - next_review_date = Column(Date) - - # Timestamps - created_at = Column(DateTime, default=datetime.utcnow) - updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) - - __table_args__ = ( - Index('ix_mgmt_review_date', 'review_date'), - Index('ix_mgmt_review_status', 'status'), - ) - - def __repr__(self): - return f"" - - -class InternalAuditDB(Base): - """ - Internal Audit (ISO 27001 Kapitel 9.2) - - Tracks internal audit program and individual audits. - """ - __tablename__ = 'compliance_internal_audits' - - id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) - audit_id = Column(String(30), unique=True, nullable=False, index=True) # e.g., "IA-2026-001" - - # Audit details - title = Column(String(200), nullable=False) - audit_type = Column(String(50), nullable=False) # "scheduled", "surveillance", "special" - - # Scope - scope_description = Column(Text, nullable=False) - iso_chapters_covered = Column(JSON) # e.g., ["4", "5", "6.1"] - annex_a_controls_covered = Column(JSON) # e.g., ["A.5", "A.6"] - processes_covered = Column(JSON) - departments_covered = Column(JSON) - - # Audit criteria - criteria = Column(Text) # Standards, policies being audited against - - # Timeline - planned_date = Column(Date, nullable=False) - actual_start_date = Column(Date) - actual_end_date = Column(Date) - - # Audit team - lead_auditor = Column(String(100), nullable=False) - audit_team = Column(JSON) # List of auditor names - auditee_representatives = Column(JSON) # Who was interviewed - - # Status - status = Column(String(30), default="planned") # planned, in_progress, completed, cancelled - - # Results summary - total_findings = Column(Integer, default=0) - major_findings = Column(Integer, default=0) - minor_findings = Column(Integer, default=0) - ofi_count = Column(Integer, default=0) - positive_observations = Column(Integer, default=0) - - # Conclusion - audit_conclusion = Column(Text) - overall_assessment = Column(String(30)) # "conforming", "minor_nc", "major_nc" - - # Report - report_date = Column(Date) - report_document_path = Column(String(500)) - - # Sign-off - report_approved_by = Column(String(100)) - report_approved_at = Column(DateTime) - - # Follow-up - follow_up_audit_required = Column(Boolean, default=False) - follow_up_audit_id = Column(String(36)) - - # Timestamps - created_at = Column(DateTime, default=datetime.utcnow) - updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) - - # Relationships - findings = relationship("AuditFindingDB", backref="internal_audit", foreign_keys=[AuditFindingDB.internal_audit_id]) - - __table_args__ = ( - Index('ix_internal_audit_date', 'planned_date'), - Index('ix_internal_audit_status', 'status'), - ) - - def __repr__(self): - return f"" - - -class AuditTrailDB(Base): - """ - Comprehensive Audit Trail for ISMS Changes - - Tracks all changes to compliance-relevant data for - accountability and forensic analysis. - """ - __tablename__ = 'compliance_audit_trail' - - id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) - - # What changed - entity_type = Column(String(50), nullable=False, index=True) # "control", "risk", "policy", etc. - entity_id = Column(String(36), nullable=False, index=True) - entity_name = Column(String(200)) # Human-readable identifier - - # Action - action = Column(String(20), nullable=False) # "create", "update", "delete", "approve", "sign" - - # Change details - field_changed = Column(String(100)) # Which field (for updates) - old_value = Column(Text) - new_value = Column(Text) - change_summary = Column(Text) # Human-readable summary - - # Who & When - performed_by = Column(String(100), nullable=False) - performed_at = Column(DateTime, nullable=False, default=datetime.utcnow) - - # Context - ip_address = Column(String(45)) - user_agent = Column(String(500)) - session_id = Column(String(100)) - - # Integrity - checksum = Column(String(64)) # SHA-256 of the change - - # Timestamps (immutable after creation) - created_at = Column(DateTime, nullable=False, default=datetime.utcnow) - - __table_args__ = ( - Index('ix_audit_trail_entity', 'entity_type', 'entity_id'), - Index('ix_audit_trail_time', 'performed_at'), - Index('ix_audit_trail_user', 'performed_by'), - ) - - def __repr__(self): - return f"" - - -class ISMSReadinessCheckDB(Base): - """ - ISMS Readiness Check Results - - Stores automated pre-audit checks to identify potential - Major findings before external audit. - """ - __tablename__ = 'compliance_isms_readiness' - - id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) - - # Check run - check_date = Column(DateTime, nullable=False, default=datetime.utcnow) - triggered_by = Column(String(100)) # "scheduled", "manual", "pre-audit" - - # Overall status - overall_status = Column(String(20), nullable=False) # "ready", "at_risk", "not_ready" - certification_possible = Column(Boolean, nullable=False) - - # Chapter-by-chapter status (ISO 27001) - chapter_4_status = Column(String(20)) # Context - chapter_5_status = Column(String(20)) # Leadership - chapter_6_status = Column(String(20)) # Planning - chapter_7_status = Column(String(20)) # Support - chapter_8_status = Column(String(20)) # Operation - chapter_9_status = Column(String(20)) # Performance - chapter_10_status = Column(String(20)) # Improvement - - # Potential Major findings - potential_majors = Column(JSON) # List of {"check": "", "status": "", "recommendation": ""} - - # Potential Minor findings - potential_minors = Column(JSON) - - # Improvement opportunities - improvement_opportunities = Column(JSON) - - # Scores - readiness_score = Column(Float) # 0-100 - documentation_score = Column(Float) - implementation_score = Column(Float) - evidence_score = Column(Float) - - # Recommendations - priority_actions = Column(JSON) # List of recommended actions before audit - - # Timestamps - created_at = Column(DateTime, default=datetime.utcnow) - - __table_args__ = ( - Index('ix_readiness_date', 'check_date'), - Index('ix_readiness_status', 'overall_status'), - ) - - def __repr__(self): - return f"" diff --git a/backend-compliance/compliance/db/regulation_models.py b/backend-compliance/compliance/db/regulation_models.py new file mode 100644 index 0000000..38c60bd --- /dev/null +++ b/backend-compliance/compliance/db/regulation_models.py @@ -0,0 +1,134 @@ +""" +Regulation & Requirement models — extracted from compliance/db/models.py. + +The foundational compliance aggregate: regulations (GDPR, AI Act, CRA, ...) and +the individual requirements they contain. Re-exported from +``compliance.db.models`` for backwards compatibility. + +DO NOT change __tablename__, column names, or relationship strings. +""" + +import uuid +import enum +from datetime import datetime, timezone + +from sqlalchemy import ( + Column, String, Text, Integer, Boolean, DateTime, Date, + ForeignKey, Enum, JSON, Index, +) +from sqlalchemy.orm import relationship + +from classroom_engine.database import Base + + +# ============================================================================ +# ENUMS +# ============================================================================ + +class RegulationTypeEnum(str, enum.Enum): + """Type of regulation/standard.""" + EU_REGULATION = "eu_regulation" # Directly applicable EU law + EU_DIRECTIVE = "eu_directive" # Requires national implementation + DE_LAW = "de_law" # German national law + BSI_STANDARD = "bsi_standard" # BSI technical guidelines + INDUSTRY_STANDARD = "industry_standard" # ISO, OWASP, etc. + + +# ============================================================================ +# MODELS +# ============================================================================ + +class RegulationDB(Base): + """ + Represents a regulation, directive, or standard. + + Examples: GDPR, AI Act, CRA, BSI-TR-03161 + """ + __tablename__ = 'compliance_regulations' + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + code = Column(String(20), unique=True, nullable=False, index=True) # e.g., "GDPR", "AIACT" + name = Column(String(200), nullable=False) # Short name + full_name = Column(Text) # Full official name + regulation_type = Column(Enum(RegulationTypeEnum), nullable=False) + source_url = Column(String(500)) # EUR-Lex URL or similar + local_pdf_path = Column(String(500)) # Local PDF if available + effective_date = Column(Date) # When it came into force + description = Column(Text) # Brief description + is_active = Column(Boolean, default=True) + + # Timestamps + created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) + + # Relationships + requirements = relationship("RequirementDB", back_populates="regulation", cascade="all, delete-orphan") + + def __repr__(self): + return f"" + + +class RequirementDB(Base): + """ + Individual requirement from a regulation. + + Examples: GDPR Art. 32(1)(a), AI Act Art. 9, BSI-TR O.Auth_1 + """ + __tablename__ = 'compliance_requirements' + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + regulation_id = Column(String(36), ForeignKey('compliance_regulations.id'), nullable=False, index=True) + + # Requirement identification + article = Column(String(50), nullable=False) # e.g., "Art. 32", "O.Auth_1" + paragraph = Column(String(20)) # e.g., "(1)(a)" + requirement_id_external = Column(String(50)) # External ID (e.g., BSI ID) + title = Column(String(300), nullable=False) # Requirement title + description = Column(Text) # Brief description + requirement_text = Column(Text) # Original text from regulation + + # Breakpilot-specific interpretation and implementation + breakpilot_interpretation = Column(Text) # How Breakpilot interprets this + implementation_status = Column(String(30), default="not_started") # not_started, in_progress, implemented, verified + implementation_details = Column(Text) # How we implemented it + code_references = Column(JSON) # List of {"file": "...", "line": ..., "description": "..."} + documentation_links = Column(JSON) # List of internal doc links + + # Evidence for auditors + evidence_description = Column(Text) # What evidence proves compliance + evidence_artifacts = Column(JSON) # List of {"type": "...", "path": "...", "description": "..."} + + # Audit-specific fields + auditor_notes = Column(Text) # Notes from auditor review + audit_status = Column(String(30), default="pending") # pending, in_review, approved, rejected + last_audit_date = Column(DateTime) + last_auditor = Column(String(100)) + + is_applicable = Column(Boolean, default=True) # Applicable to Breakpilot? + applicability_reason = Column(Text) # Why/why not applicable + + priority = Column(Integer, default=2) # 1=Critical, 2=High, 3=Medium + + # Source document reference + source_page = Column(Integer) # Page number in source document + source_section = Column(String(100)) # Section in source document + + # Timestamps + created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) + + # Relationships + regulation = relationship("RegulationDB", back_populates="requirements") + control_mappings = relationship("ControlMappingDB", back_populates="requirement", cascade="all, delete-orphan") + + __table_args__ = ( + Index('ix_requirement_regulation_article', 'regulation_id', 'article'), + Index('ix_requirement_audit_status', 'audit_status'), + Index('ix_requirement_impl_status', 'implementation_status'), + ) + + def __repr__(self): + return f"" + + +__all__ = ["RegulationTypeEnum", "RegulationDB", "RequirementDB"] diff --git a/backend-compliance/compliance/db/repository.py b/backend-compliance/compliance/db/repository.py index 6fc66d7..0122bb5 100644 --- a/backend-compliance/compliance/db/repository.py +++ b/backend-compliance/compliance/db/repository.py @@ -6,7 +6,7 @@ Provides CRUD operations and business logic queries for all compliance entities. from __future__ import annotations import uuid -from datetime import datetime, date +from datetime import datetime, date, timezone from typing import List, Optional, Dict, Any from sqlalchemy.orm import Session as DBSession, selectinload, joinedload @@ -86,7 +86,7 @@ class RegulationRepository: for key, value in kwargs.items(): if hasattr(regulation, key): setattr(regulation, key, value) - regulation.updated_at = datetime.utcnow() + regulation.updated_at = datetime.now(timezone.utc) self.db.commit() self.db.refresh(regulation) return regulation @@ -425,7 +425,7 @@ class ControlRepository: control.status = status if status_notes: control.status_notes = status_notes - control.updated_at = datetime.utcnow() + control.updated_at = datetime.now(timezone.utc) self.db.commit() self.db.refresh(control) return control @@ -435,10 +435,10 @@ class ControlRepository: control = self.get_by_control_id(control_id) if not control: return None - control.last_reviewed_at = datetime.utcnow() + control.last_reviewed_at = datetime.now(timezone.utc) from datetime import timedelta - control.next_review_at = datetime.utcnow() + timedelta(days=control.review_frequency_days) - control.updated_at = datetime.utcnow() + control.next_review_at = datetime.now(timezone.utc) + timedelta(days=control.review_frequency_days) + control.updated_at = datetime.now(timezone.utc) self.db.commit() self.db.refresh(control) return control @@ -450,7 +450,7 @@ class ControlRepository: .filter( or_( ControlDB.next_review_at is None, - ControlDB.next_review_at <= datetime.utcnow() + ControlDB.next_review_at <= datetime.now(timezone.utc) ) ) .order_by(ControlDB.next_review_at) @@ -624,7 +624,7 @@ class EvidenceRepository: if not evidence: return None evidence.status = status - evidence.updated_at = datetime.utcnow() + evidence.updated_at = datetime.now(timezone.utc) self.db.commit() self.db.refresh(evidence) return evidence @@ -749,7 +749,7 @@ class RiskRepository: risk.residual_likelihood, risk.residual_impact ) - risk.updated_at = datetime.utcnow() + risk.updated_at = datetime.now(timezone.utc) self.db.commit() self.db.refresh(risk) return risk @@ -860,9 +860,9 @@ class AuditExportRepository: export.compliance_score = compliance_score if status == ExportStatusEnum.COMPLETED: - export.completed_at = datetime.utcnow() + export.completed_at = datetime.now(timezone.utc) - export.updated_at = datetime.utcnow() + export.updated_at = datetime.now(timezone.utc) self.db.commit() self.db.refresh(export) return export @@ -1156,11 +1156,11 @@ class AuditSessionRepository: session.status = status if status == AuditSessionStatusEnum.IN_PROGRESS and not session.started_at: - session.started_at = datetime.utcnow() + session.started_at = datetime.now(timezone.utc) elif status == AuditSessionStatusEnum.COMPLETED: - session.completed_at = datetime.utcnow() + session.completed_at = datetime.now(timezone.utc) - session.updated_at = datetime.utcnow() + session.updated_at = datetime.now(timezone.utc) self.db.commit() self.db.refresh(session) return session @@ -1183,7 +1183,7 @@ class AuditSessionRepository: if completed_items is not None: session.completed_items = completed_items - session.updated_at = datetime.utcnow() + session.updated_at = datetime.now(timezone.utc) self.db.commit() self.db.refresh(session) return session @@ -1207,9 +1207,9 @@ class AuditSessionRepository: total_requirements = query.scalar() or 0 session.status = AuditSessionStatusEnum.IN_PROGRESS - session.started_at = datetime.utcnow() + session.started_at = datetime.now(timezone.utc) session.total_items = total_requirements - session.updated_at = datetime.utcnow() + session.updated_at = datetime.now(timezone.utc) self.db.commit() self.db.refresh(session) @@ -1344,7 +1344,7 @@ class AuditSignOffRepository: if sign and signed_by: signoff.create_signature(signed_by) - signoff.updated_at = datetime.utcnow() + signoff.updated_at = datetime.now(timezone.utc) self.db.commit() self.db.refresh(signoff) @@ -1376,7 +1376,7 @@ class AuditSignOffRepository: signoff.notes = notes if sign and signed_by: signoff.create_signature(signed_by) - signoff.updated_at = datetime.utcnow() + signoff.updated_at = datetime.now(timezone.utc) else: # Create new signoff = AuditSignOffDB( @@ -1416,7 +1416,7 @@ class AuditSignOffRepository: ).first() if session: session.completed_items = completed - session.updated_at = datetime.utcnow() + session.updated_at = datetime.now(timezone.utc) self.db.commit() def get_checklist( diff --git a/backend-compliance/compliance/db/service_module_models.py b/backend-compliance/compliance/db/service_module_models.py new file mode 100644 index 0000000..475c82a --- /dev/null +++ b/backend-compliance/compliance/db/service_module_models.py @@ -0,0 +1,176 @@ +""" +Service Module Registry models — extracted from compliance/db/models.py. + +Sprint 3: registry of all Breakpilot services/modules for compliance mapping, +per-module regulation applicability, and per-module risk aggregation. +Re-exported from ``compliance.db.models`` for backwards compatibility. + +DO NOT change __tablename__, column names, or relationship strings. +""" + +import uuid +import enum +from datetime import datetime, timezone + +from sqlalchemy import ( + Column, String, Text, Integer, Boolean, DateTime, + ForeignKey, Enum, JSON, Index, Float, +) +from sqlalchemy.orm import relationship + +from classroom_engine.database import Base +# RiskLevelEnum is re-used across aggregates; sourced here from control_models. +from compliance.db.control_models import RiskLevelEnum # noqa: F401 + + +# ============================================================================ +# ENUMS +# ============================================================================ + +class ServiceTypeEnum(str, enum.Enum): + """Type of Breakpilot service/module.""" + BACKEND = "backend" # API/Backend services + DATABASE = "database" # Data storage + AI = "ai" # AI/ML services + COMMUNICATION = "communication" # Chat/Video/Messaging + STORAGE = "storage" # File/Object storage + INFRASTRUCTURE = "infrastructure" # Load balancer, reverse proxy + MONITORING = "monitoring" # Logging, metrics + SECURITY = "security" # Auth, encryption, secrets + + +class RelevanceLevelEnum(str, enum.Enum): + """Relevance level of a regulation to a service.""" + CRITICAL = "critical" # Non-compliance = shutdown + HIGH = "high" # Major risk + MEDIUM = "medium" # Moderate risk + LOW = "low" # Minor risk + + +# ============================================================================ +# MODELS +# ============================================================================ + +class ServiceModuleDB(Base): + """ + Registry of all Breakpilot services/modules for compliance mapping. + + Tracks which regulations apply to which services, enabling: + - Service-specific compliance views + - Aggregated risk per service + - Gap analysis by module + """ + __tablename__ = 'compliance_service_modules' + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + name = Column(String(100), unique=True, nullable=False, index=True) # e.g., "consent-service" + display_name = Column(String(200), nullable=False) # e.g., "Go Consent Service" + description = Column(Text) + + # Technical details + service_type = Column(Enum(ServiceTypeEnum), nullable=False) + port = Column(Integer) # Primary port (if applicable) + technology_stack = Column(JSON) # e.g., ["Go", "Gin", "PostgreSQL"] + repository_path = Column(String(500)) # e.g., "/consent-service" + docker_image = Column(String(200)) # e.g., "breakpilot-pwa-consent-service" + + # Data categories handled + data_categories = Column(JSON) # e.g., ["personal_data", "consent_records"] + processes_pii = Column(Boolean, default=False) # Handles personally identifiable info? + processes_health_data = Column(Boolean, default=False) # Handles special category health data? + ai_components = Column(Boolean, default=False) # Contains AI/ML components? + + # Status + is_active = Column(Boolean, default=True) + criticality = Column(String(20), default="medium") # "critical", "high", "medium", "low" + + # Compliance aggregation + compliance_score = Column(Float) # Calculated score 0-100 + last_compliance_check = Column(DateTime) + + # Owner + owner_team = Column(String(100)) # e.g., "Backend Team" + owner_contact = Column(String(200)) # e.g., "backend@breakpilot.app" + + # Timestamps + created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) + + # Relationships + regulation_mappings = relationship("ModuleRegulationMappingDB", back_populates="module", cascade="all, delete-orphan") + module_risks = relationship("ModuleRiskDB", back_populates="module", cascade="all, delete-orphan") + + __table_args__ = ( + Index('ix_module_type_active', 'service_type', 'is_active'), + ) + + def __repr__(self): + return f"" + + +class ModuleRegulationMappingDB(Base): + """ + Maps services to applicable regulations with relevance level. + + Enables filtering: "Show all GDPR requirements for consent-service" + """ + __tablename__ = 'compliance_module_regulations' + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + module_id = Column(String(36), ForeignKey('compliance_service_modules.id'), nullable=False, index=True) + regulation_id = Column(String(36), ForeignKey('compliance_regulations.id'), nullable=False, index=True) + + relevance_level = Column(Enum(RelevanceLevelEnum), nullable=False, default=RelevanceLevelEnum.MEDIUM) + notes = Column(Text) # Why this regulation applies + applicable_articles = Column(JSON) # List of specific articles that apply + + # Timestamps + created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) + + # Relationships + module = relationship("ServiceModuleDB", back_populates="regulation_mappings") + regulation = relationship("RegulationDB") + + __table_args__ = ( + Index('ix_module_regulation', 'module_id', 'regulation_id', unique=True), + ) + + +class ModuleRiskDB(Base): + """ + Service-specific risks aggregated from requirements and controls. + """ + __tablename__ = 'compliance_module_risks' + + id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) + module_id = Column(String(36), ForeignKey('compliance_service_modules.id'), nullable=False, index=True) + risk_id = Column(String(36), ForeignKey('compliance_risks.id'), nullable=False, index=True) + + # Module-specific assessment + module_likelihood = Column(Integer) # 1-5, may differ from global + module_impact = Column(Integer) # 1-5, may differ from global + module_risk_level = Column(Enum(RiskLevelEnum)) + + assessment_notes = Column(Text) # Module-specific notes + + # Timestamps + created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) + + # Relationships + module = relationship("ServiceModuleDB", back_populates="module_risks") + risk = relationship("RiskDB") + + __table_args__ = ( + Index('ix_module_risk', 'module_id', 'risk_id', unique=True), + ) + + +__all__ = [ + "ServiceTypeEnum", + "RelevanceLevelEnum", + "ServiceModuleDB", + "ModuleRegulationMappingDB", + "ModuleRiskDB", +] diff --git a/backend-compliance/compliance/domain/__init__.py b/backend-compliance/compliance/domain/__init__.py new file mode 100644 index 0000000..f836525 --- /dev/null +++ b/backend-compliance/compliance/domain/__init__.py @@ -0,0 +1,30 @@ +"""Domain layer: value objects, enums, and domain exceptions. + +Pure Python — no FastAPI, no SQLAlchemy, no HTTP concerns. Upper layers depend on +this package; it depends on nothing except the standard library and small libraries +like ``pydantic`` or ``attrs``. +""" + + +class DomainError(Exception): + """Base class for all domain-level errors. + + Services raise subclasses of this; the HTTP layer is responsible for mapping + them to status codes. Never raise ``HTTPException`` from a service. + """ + + +class NotFoundError(DomainError): + """Requested entity does not exist.""" + + +class ConflictError(DomainError): + """Operation conflicts with the current state (e.g. duplicate, stale version).""" + + +class ValidationError(DomainError): + """Input failed domain-level validation (beyond what Pydantic catches).""" + + +class PermissionError(DomainError): + """Caller lacks permission for the operation.""" diff --git a/backend-compliance/compliance/repositories/__init__.py b/backend-compliance/compliance/repositories/__init__.py new file mode 100644 index 0000000..6921516 --- /dev/null +++ b/backend-compliance/compliance/repositories/__init__.py @@ -0,0 +1,10 @@ +"""Repository layer: database access. + +Each aggregate gets its own module (e.g. ``dsr_repository.py``) exposing a single +class with intent-named methods. Repositories own SQLAlchemy session usage; they +do not run business logic, and they do not import anything from +``compliance.api`` or ``compliance.services``. + +Phase 1 refactor target: ``compliance.db.repository`` (1547 lines) is being +decomposed into per-aggregate modules under this package. +""" diff --git a/backend-compliance/compliance/schemas/__init__.py b/backend-compliance/compliance/schemas/__init__.py new file mode 100644 index 0000000..8e95f64 --- /dev/null +++ b/backend-compliance/compliance/schemas/__init__.py @@ -0,0 +1,11 @@ +"""Pydantic schemas, split per domain. + +Phase 1 refactor target: the monolithic ``compliance.api.schemas`` module (1899 lines) +is being decomposed into one module per domain under this package. Until every domain +has been migrated, ``compliance.api.schemas`` re-exports from here so existing imports +continue to work unchanged. + +New code MUST import from the specific domain module (e.g. +``from compliance.schemas.dsr import DSRRequestCreate``) rather than from +``compliance.api.schemas``. +""" diff --git a/backend-compliance/compliance/services/audit_pdf_generator.py b/backend-compliance/compliance/services/audit_pdf_generator.py index d35e553..cc7a9d3 100644 --- a/backend-compliance/compliance/services/audit_pdf_generator.py +++ b/backend-compliance/compliance/services/audit_pdf_generator.py @@ -16,7 +16,7 @@ Uses reportlab for PDF generation (lightweight, no external dependencies). import io import logging -from datetime import datetime +from datetime import datetime, timezone from typing import Dict, List, Any, Optional, Tuple from sqlalchemy.orm import Session @@ -255,7 +255,7 @@ class AuditPDFGenerator: doc.build(story) # Generate filename - date_str = datetime.utcnow().strftime('%Y%m%d') + date_str = datetime.now(timezone.utc).strftime('%Y%m%d') filename = f"audit_report_{session.name.replace(' ', '_')}_{date_str}.pdf" return buffer.getvalue(), filename @@ -429,7 +429,7 @@ class AuditPDFGenerator: story.append(Spacer(1, 30*mm)) gen_label = 'Generiert am' if language == 'de' else 'Generated on' story.append(Paragraph( - f"{gen_label}: {datetime.utcnow().strftime('%d.%m.%Y %H:%M')} UTC", + f"{gen_label}: {datetime.now(timezone.utc).strftime('%d.%m.%Y %H:%M')} UTC", self.styles['Footer'] )) diff --git a/backend-compliance/compliance/services/auto_risk_updater.py b/backend-compliance/compliance/services/auto_risk_updater.py index 077b6bd..69e3bfe 100644 --- a/backend-compliance/compliance/services/auto_risk_updater.py +++ b/backend-compliance/compliance/services/auto_risk_updater.py @@ -11,7 +11,7 @@ Sprint 6: CI/CD Evidence Collection (2026-01-18) """ import logging -from datetime import datetime +from datetime import datetime, timezone from typing import Dict, List, Optional from dataclasses import dataclass from enum import Enum @@ -140,7 +140,7 @@ class AutoRiskUpdater: if new_status != old_status: control.status = ControlStatusEnum(new_status) control.status_notes = self._generate_status_notes(scan_result) - control.updated_at = datetime.utcnow() + control.updated_at = datetime.now(timezone.utc) control_updated = True logger.info(f"Control {scan_result.control_id} status changed: {old_status} -> {new_status}") @@ -225,7 +225,7 @@ class AutoRiskUpdater: source="ci_pipeline", ci_job_id=scan_result.ci_job_id, status=EvidenceStatusEnum.VALID, - valid_from=datetime.utcnow(), + valid_from=datetime.now(timezone.utc), collected_at=scan_result.timestamp, ) @@ -298,8 +298,8 @@ class AutoRiskUpdater: risk_updated = True if risk_updated: - risk.last_assessed_at = datetime.utcnow() - risk.updated_at = datetime.utcnow() + risk.last_assessed_at = datetime.now(timezone.utc) + risk.updated_at = datetime.now(timezone.utc) affected_risks.append(risk.risk_id) logger.info(f"Updated risk {risk.risk_id} due to control {control.control_id} status change") @@ -354,7 +354,7 @@ class AutoRiskUpdater: try: ts = datetime.fromisoformat(timestamp.replace('Z', '+00:00')) except (ValueError, AttributeError): - ts = datetime.utcnow() + ts = datetime.now(timezone.utc) # Determine scan type from evidence_type scan_type = ScanType.SAST # Default diff --git a/backend-compliance/compliance/services/export_generator.py b/backend-compliance/compliance/services/export_generator.py index eeeec1f..d78cc3d 100644 --- a/backend-compliance/compliance/services/export_generator.py +++ b/backend-compliance/compliance/services/export_generator.py @@ -16,7 +16,7 @@ import os import shutil import tempfile import zipfile -from datetime import datetime, date +from datetime import datetime, date, timezone from pathlib import Path from typing import Dict, List, Optional, Any @@ -98,7 +98,7 @@ class AuditExportGenerator: export_record.file_hash = file_hash export_record.file_size_bytes = file_size export_record.status = ExportStatusEnum.COMPLETED - export_record.completed_at = datetime.utcnow() + export_record.completed_at = datetime.now(timezone.utc) # Calculate statistics stats = self._calculate_statistics( diff --git a/backend-compliance/compliance/services/regulation_scraper.py b/backend-compliance/compliance/services/regulation_scraper.py index 83d06e1..f1feb51 100644 --- a/backend-compliance/compliance/services/regulation_scraper.py +++ b/backend-compliance/compliance/services/regulation_scraper.py @@ -11,7 +11,7 @@ Similar pattern to edu-search and zeugnisse-crawler. import logging import re -from datetime import datetime +from datetime import datetime, timezone from typing import Dict, List, Any, Optional from enum import Enum @@ -198,7 +198,7 @@ class RegulationScraperService: async def scrape_all(self) -> Dict[str, Any]: """Scrape all known regulation sources.""" self.status = ScraperStatus.RUNNING - self.stats["last_run"] = datetime.utcnow().isoformat() + self.stats["last_run"] = datetime.now(timezone.utc).isoformat() results = { "success": [], diff --git a/backend-compliance/compliance/services/report_generator.py b/backend-compliance/compliance/services/report_generator.py index 2765b98..52d36dc 100644 --- a/backend-compliance/compliance/services/report_generator.py +++ b/backend-compliance/compliance/services/report_generator.py @@ -11,7 +11,7 @@ Reports include: """ import logging -from datetime import datetime, date, timedelta +from datetime import datetime, date, timedelta, timezone from typing import Dict, List, Any, Optional from enum import Enum @@ -75,7 +75,7 @@ class ComplianceReportGenerator: report = { "report_metadata": { - "generated_at": datetime.utcnow().isoformat(), + "generated_at": datetime.now(timezone.utc).isoformat(), "period": period.value, "as_of_date": as_of_date.isoformat(), "date_range_start": date_range["start"].isoformat(), @@ -415,7 +415,7 @@ class ComplianceReportGenerator: evidence_stats = self.evidence_repo.get_statistics() return { - "generated_at": datetime.utcnow().isoformat(), + "generated_at": datetime.now(timezone.utc).isoformat(), "compliance_score": stats.get("compliance_score", 0), "controls": { "total": stats.get("total", 0), diff --git a/backend-compliance/compliance/tests/test_audit_routes.py b/backend-compliance/compliance/tests/test_audit_routes.py index 5800b5c..2b2fadb 100644 --- a/backend-compliance/compliance/tests/test_audit_routes.py +++ b/backend-compliance/compliance/tests/test_audit_routes.py @@ -8,7 +8,7 @@ Run with: pytest backend/compliance/tests/test_audit_routes.py -v import pytest import hashlib -from datetime import datetime +from datetime import datetime, timezone from unittest.mock import MagicMock from uuid import uuid4 @@ -78,7 +78,7 @@ def sample_session(): completed_items=0, compliant_count=0, non_compliant_count=0, - created_at=datetime.utcnow(), + created_at=datetime.now(timezone.utc), ) @@ -94,7 +94,7 @@ def sample_signoff(sample_session, sample_requirement): signature_hash=None, signed_at=None, signed_by=None, - created_at=datetime.utcnow(), + created_at=datetime.now(timezone.utc), ) @@ -214,7 +214,7 @@ class TestAuditSessionLifecycle: assert sample_session.status == AuditSessionStatusEnum.DRAFT sample_session.status = AuditSessionStatusEnum.IN_PROGRESS - sample_session.started_at = datetime.utcnow() + sample_session.started_at = datetime.now(timezone.utc) assert sample_session.status == AuditSessionStatusEnum.IN_PROGRESS assert sample_session.started_at is not None @@ -231,7 +231,7 @@ class TestAuditSessionLifecycle: sample_session.status = AuditSessionStatusEnum.IN_PROGRESS sample_session.status = AuditSessionStatusEnum.COMPLETED - sample_session.completed_at = datetime.utcnow() + sample_session.completed_at = datetime.now(timezone.utc) assert sample_session.status == AuditSessionStatusEnum.COMPLETED assert sample_session.completed_at is not None @@ -353,7 +353,7 @@ class TestSignOff: def test_signoff_with_signature_creates_hash(self, sample_session, sample_requirement): """Signing off with signature should create SHA-256 hash.""" result = AuditResultEnum.COMPLIANT - timestamp = datetime.utcnow().isoformat() + timestamp = datetime.now(timezone.utc).isoformat() data = f"{result.value}|{sample_requirement.id}|{sample_session.auditor_name}|{timestamp}" signature_hash = hashlib.sha256(data.encode()).hexdigest() @@ -382,7 +382,7 @@ class TestSignOff: # First sign-off should trigger auto-start sample_session.status = AuditSessionStatusEnum.IN_PROGRESS - sample_session.started_at = datetime.utcnow() + sample_session.started_at = datetime.now(timezone.utc) assert sample_session.status == AuditSessionStatusEnum.IN_PROGRESS @@ -390,7 +390,7 @@ class TestSignOff: """Updating an existing sign-off should work.""" sample_signoff.result = AuditResultEnum.NON_COMPLIANT sample_signoff.notes = "Updated: needs improvement" - sample_signoff.updated_at = datetime.utcnow() + sample_signoff.updated_at = datetime.now(timezone.utc) assert sample_signoff.result == AuditResultEnum.NON_COMPLIANT assert "Updated" in sample_signoff.notes @@ -423,7 +423,7 @@ class TestGetSignOff: # With signature sample_signoff.signature_hash = "abc123" - sample_signoff.signed_at = datetime.utcnow() + sample_signoff.signed_at = datetime.now(timezone.utc) sample_signoff.signed_by = "Test Auditor" assert sample_signoff.signature_hash == "abc123" diff --git a/backend-compliance/compliance/tests/test_auto_risk_updater.py b/backend-compliance/compliance/tests/test_auto_risk_updater.py index 7e7c43e..e9d218d 100644 --- a/backend-compliance/compliance/tests/test_auto_risk_updater.py +++ b/backend-compliance/compliance/tests/test_auto_risk_updater.py @@ -4,7 +4,7 @@ Tests for the AutoRiskUpdater Service. Sprint 6: CI/CD Evidence Collection & Automatic Risk Updates (2026-01-18) """ -from datetime import datetime +from datetime import datetime, timezone from unittest.mock import MagicMock from ..services.auto_risk_updater import ( @@ -188,7 +188,7 @@ class TestGenerateAlerts: scan_result = ScanResult( scan_type=ScanType.DEPENDENCY, tool="Trivy", - timestamp=datetime.utcnow(), + timestamp=datetime.now(timezone.utc), commit_sha="abc123", branch="main", control_id="SDLC-002", @@ -209,7 +209,7 @@ class TestGenerateAlerts: scan_result = ScanResult( scan_type=ScanType.SAST, tool="Semgrep", - timestamp=datetime.utcnow(), + timestamp=datetime.now(timezone.utc), commit_sha="def456", branch="main", control_id="SDLC-001", @@ -228,7 +228,7 @@ class TestGenerateAlerts: scan_result = ScanResult( scan_type=ScanType.CONTAINER, tool="Trivy", - timestamp=datetime.utcnow(), + timestamp=datetime.now(timezone.utc), commit_sha="ghi789", branch="main", control_id="SDLC-006", @@ -247,7 +247,7 @@ class TestGenerateAlerts: scan_result = ScanResult( scan_type=ScanType.SAST, tool="Semgrep", - timestamp=datetime.utcnow(), + timestamp=datetime.now(timezone.utc), commit_sha="jkl012", branch="main", control_id="SDLC-001", @@ -369,7 +369,7 @@ class TestScanResult: result = ScanResult( scan_type=ScanType.DEPENDENCY, tool="Trivy", - timestamp=datetime.utcnow(), + timestamp=datetime.now(timezone.utc), commit_sha="xyz789", branch="develop", control_id="SDLC-002", diff --git a/backend-compliance/compliance/tests/test_compliance_routes.py b/backend-compliance/compliance/tests/test_compliance_routes.py index 7195101..1999ecf 100644 --- a/backend-compliance/compliance/tests/test_compliance_routes.py +++ b/backend-compliance/compliance/tests/test_compliance_routes.py @@ -8,7 +8,7 @@ Run with: pytest compliance/tests/test_compliance_routes.py -v """ import pytest -from datetime import datetime +from datetime import datetime, timezone from unittest.mock import MagicMock from uuid import uuid4 @@ -41,8 +41,8 @@ def sample_regulation(): name="Datenschutz-Grundverordnung", full_name="Verordnung (EU) 2016/679", is_active=True, - created_at=datetime.utcnow(), - updated_at=datetime.utcnow(), + created_at=datetime.now(timezone.utc), + updated_at=datetime.now(timezone.utc), ) @@ -57,8 +57,8 @@ def sample_requirement(sample_regulation): description="Personenbezogene Daten duerfen nur verarbeitet werden, wenn eine Rechtsgrundlage vorliegt.", priority=4, is_applicable=True, - created_at=datetime.utcnow(), - updated_at=datetime.utcnow(), + created_at=datetime.now(timezone.utc), + updated_at=datetime.now(timezone.utc), ) @@ -74,8 +74,8 @@ def sample_ai_system(): classification=AIClassificationEnum.UNCLASSIFIED, status=AISystemStatusEnum.DRAFT, obligations=[], - created_at=datetime.utcnow(), - updated_at=datetime.utcnow(), + created_at=datetime.now(timezone.utc), + updated_at=datetime.now(timezone.utc), ) @@ -96,8 +96,8 @@ class TestCreateRequirement: description="Geeignete technische Massnahmen", priority=3, is_applicable=True, - created_at=datetime.utcnow(), - updated_at=datetime.utcnow(), + created_at=datetime.now(timezone.utc), + updated_at=datetime.now(timezone.utc), ) assert req.regulation_id == sample_regulation.id @@ -196,7 +196,7 @@ class TestUpdateRequirement: def test_update_audit_status_sets_audit_date(self, sample_requirement): """Updating audit_status should set last_audit_date.""" sample_requirement.audit_status = "compliant" - sample_requirement.last_audit_date = datetime.utcnow() + sample_requirement.last_audit_date = datetime.now(timezone.utc) assert sample_requirement.audit_status == "compliant" assert sample_requirement.last_audit_date is not None @@ -287,7 +287,7 @@ class TestAISystemCRUD: def test_update_ai_system_with_assessment(self, sample_ai_system): """After assessment, system should have assessment_date and result.""" - sample_ai_system.assessment_date = datetime.utcnow() + sample_ai_system.assessment_date = datetime.now(timezone.utc) sample_ai_system.assessment_result = { "overall_risk": "high", "risk_factors": [{"factor": "education sector", "severity": "high"}], diff --git a/backend-compliance/compliance/tests/test_isms_routes.py b/backend-compliance/compliance/tests/test_isms_routes.py index 01a063b..ec073b3 100644 --- a/backend-compliance/compliance/tests/test_isms_routes.py +++ b/backend-compliance/compliance/tests/test_isms_routes.py @@ -15,7 +15,7 @@ Run with: pytest backend/compliance/tests/test_isms_routes.py -v """ import pytest -from datetime import datetime, date +from datetime import datetime, date, timezone from unittest.mock import MagicMock from uuid import uuid4 @@ -56,7 +56,7 @@ def sample_scope(): status=ApprovalStatusEnum.DRAFT, version="1.0", created_by="admin@breakpilot.de", - created_at=datetime.utcnow(), + created_at=datetime.now(timezone.utc), ) @@ -65,7 +65,7 @@ def sample_approved_scope(sample_scope): """Create an approved ISMS scope for testing.""" sample_scope.status = ApprovalStatusEnum.APPROVED sample_scope.approved_by = "ceo@breakpilot.de" - sample_scope.approved_at = datetime.utcnow() + sample_scope.approved_at = datetime.now(timezone.utc) sample_scope.effective_date = date.today() sample_scope.review_date = date(date.today().year + 1, date.today().month, date.today().day) sample_scope.approval_signature = "sha256_signature_hash" @@ -88,7 +88,7 @@ def sample_policy(): authored_by="iso@breakpilot.de", status=ApprovalStatusEnum.DRAFT, version="1.0", - created_at=datetime.utcnow(), + created_at=datetime.now(timezone.utc), ) @@ -116,7 +116,7 @@ def sample_objective(): related_controls=["OPS-003"], status="active", progress_percentage=0.0, - created_at=datetime.utcnow(), + created_at=datetime.now(timezone.utc), ) @@ -136,7 +136,7 @@ def sample_soa_entry(): coverage_level="full", evidence_description="ISMS Policy v2.0, signed by CEO", version="1.0", - created_at=datetime.utcnow(), + created_at=datetime.now(timezone.utc), ) @@ -158,7 +158,7 @@ def sample_finding(): identified_date=date.today(), due_date=date(2026, 3, 31), status=FindingStatusEnum.OPEN, - created_at=datetime.utcnow(), + created_at=datetime.now(timezone.utc), ) @@ -178,7 +178,7 @@ def sample_major_finding(): identified_date=date.today(), due_date=date(2026, 2, 28), status=FindingStatusEnum.OPEN, - created_at=datetime.utcnow(), + created_at=datetime.now(timezone.utc), ) @@ -198,7 +198,7 @@ def sample_capa(sample_finding): planned_completion=date(2026, 2, 15), effectiveness_criteria="Document approved and distributed to audit team", status="planned", - created_at=datetime.utcnow(), + created_at=datetime.now(timezone.utc), ) @@ -219,7 +219,7 @@ def sample_management_review(): {"name": "ISO", "role": "ISMS Manager"}, ], status="draft", - created_at=datetime.utcnow(), + created_at=datetime.now(timezone.utc), ) @@ -239,7 +239,7 @@ def sample_internal_audit(): lead_auditor="internal.auditor@breakpilot.de", audit_team=["internal.auditor@breakpilot.de", "qa@breakpilot.de"], status="planned", - created_at=datetime.utcnow(), + created_at=datetime.now(timezone.utc), ) @@ -502,7 +502,7 @@ class TestISMSReadinessCheck: """Readiness check should identify potential major findings.""" check = ISMSReadinessCheckDB( id=str(uuid4()), - check_date=datetime.utcnow(), + check_date=datetime.now(timezone.utc), triggered_by="admin@breakpilot.de", overall_status="not_ready", certification_possible=False, @@ -532,7 +532,7 @@ class TestISMSReadinessCheck: """Readiness check should show status for each ISO chapter.""" check = ISMSReadinessCheckDB( id=str(uuid4()), - check_date=datetime.utcnow(), + check_date=datetime.now(timezone.utc), triggered_by="admin@breakpilot.de", overall_status="ready", certification_possible=True, @@ -606,7 +606,7 @@ class TestAuditTrail: entity_name="ISMS Scope v1.0", action="approve", performed_by="ceo@breakpilot.de", - performed_at=datetime.utcnow(), + performed_at=datetime.now(timezone.utc), checksum="sha256_hash", ) @@ -630,7 +630,7 @@ class TestAuditTrail: new_value="approved", change_summary="Policy approved by CEO", performed_by="ceo@breakpilot.de", - performed_at=datetime.utcnow(), + performed_at=datetime.now(timezone.utc), checksum="sha256_hash", ) diff --git a/backend-compliance/consent_client.py b/backend-compliance/consent_client.py index 2bf1daf..d558a81 100644 --- a/backend-compliance/consent_client.py +++ b/backend-compliance/consent_client.py @@ -5,7 +5,7 @@ Kommuniziert mit dem Consent Management Service für GDPR-Compliance import httpx import jwt -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone from typing import Optional, List, Dict, Any from dataclasses import dataclass from enum import Enum @@ -44,8 +44,8 @@ def generate_jwt_token( "user_id": user_id, "email": email, "role": role, - "exp": datetime.utcnow() + timedelta(hours=expires_hours), - "iat": datetime.utcnow(), + "exp": datetime.now(timezone.utc) + timedelta(hours=expires_hours), + "iat": datetime.now(timezone.utc), } return jwt.encode(payload, JWT_SECRET, algorithm="HS256") diff --git a/backend-compliance/tests/contracts/__init__.py b/backend-compliance/tests/contracts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend-compliance/tests/contracts/openapi.baseline.json b/backend-compliance/tests/contracts/openapi.baseline.json new file mode 100644 index 0000000..91f9dd2 --- /dev/null +++ b/backend-compliance/tests/contracts/openapi.baseline.json @@ -0,0 +1,49377 @@ +{ + "components": { + "schemas": { + "AISystemCreate": { + "properties": { + "classification": { + "default": "unclassified", + "title": "Classification", + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "name": { + "title": "Name", + "type": "string" + }, + "obligations": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Obligations" + }, + "purpose": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Purpose" + }, + "sector": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Sector" + }, + "status": { + "default": "draft", + "title": "Status", + "type": "string" + } + }, + "required": [ + "name" + ], + "title": "AISystemCreate", + "type": "object" + }, + "AISystemListResponse": { + "properties": { + "systems": { + "items": { + "$ref": "#/components/schemas/AISystemResponse" + }, + "title": "Systems", + "type": "array" + }, + "total": { + "title": "Total", + "type": "integer" + } + }, + "required": [ + "systems", + "total" + ], + "title": "AISystemListResponse", + "type": "object" + }, + "AISystemResponse": { + "properties": { + "assessment_date": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Assessment Date" + }, + "assessment_result": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Assessment Result" + }, + "classification": { + "default": "unclassified", + "title": "Classification", + "type": "string" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "id": { + "title": "Id", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + }, + "obligations": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Obligations" + }, + "purpose": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Purpose" + }, + "recommendations": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Recommendations" + }, + "risk_factors": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Risk Factors" + }, + "sector": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Sector" + }, + "status": { + "default": "draft", + "title": "Status", + "type": "string" + }, + "updated_at": { + "format": "date-time", + "title": "Updated At", + "type": "string" + } + }, + "required": [ + "name", + "id", + "created_at", + "updated_at" + ], + "title": "AISystemResponse", + "type": "object" + }, + "AISystemUpdate": { + "properties": { + "classification": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Classification" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Name" + }, + "obligations": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Obligations" + }, + "purpose": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Purpose" + }, + "sector": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Sector" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + "title": "AISystemUpdate", + "type": "object" + }, + "ActionRequest": { + "properties": { + "approver": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Approver" + }, + "comment": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Comment" + } + }, + "title": "ActionRequest", + "type": "object" + }, + "ApprovalCommentRequest": { + "properties": { + "comment": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Comment" + }, + "scheduled_publish_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Scheduled Publish At" + } + }, + "title": "ApprovalCommentRequest", + "type": "object" + }, + "ApprovalHistoryEntry": { + "properties": { + "action": { + "title": "Action", + "type": "string" + }, + "approver": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Approver" + }, + "comment": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Comment" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "id": { + "title": "Id", + "type": "string" + }, + "version_id": { + "title": "Version Id", + "type": "string" + } + }, + "required": [ + "id", + "version_id", + "action", + "approver", + "comment", + "created_at" + ], + "title": "ApprovalHistoryEntry", + "type": "object" + }, + "AssignRequest": { + "properties": { + "assignee_id": { + "title": "Assignee Id", + "type": "string" + } + }, + "required": [ + "assignee_id" + ], + "title": "AssignRequest", + "type": "object" + }, + "AuditChecklistItem": { + "description": "A single item in the audit checklist.", + "properties": { + "article": { + "title": "Article", + "type": "string" + }, + "controls_mapped": { + "default": 0, + "title": "Controls Mapped", + "type": "integer" + }, + "current_result": { + "default": "pending", + "title": "Current Result", + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "evidence_count": { + "default": 0, + "title": "Evidence Count", + "type": "integer" + }, + "implementation_status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Implementation Status" + }, + "is_signed": { + "default": false, + "title": "Is Signed", + "type": "boolean" + }, + "notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Notes" + }, + "paragraph": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Paragraph" + }, + "priority": { + "default": 2, + "title": "Priority", + "type": "integer" + }, + "regulation_code": { + "title": "Regulation Code", + "type": "string" + }, + "requirement_id": { + "title": "Requirement Id", + "type": "string" + }, + "signed_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Signed At" + }, + "signed_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Signed By" + }, + "title": { + "title": "Title", + "type": "string" + } + }, + "required": [ + "requirement_id", + "regulation_code", + "article", + "title" + ], + "title": "AuditChecklistItem", + "type": "object" + }, + "AuditChecklistResponse": { + "description": "Response for audit checklist endpoint.", + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/AuditChecklistItem" + }, + "title": "Items", + "type": "array" + }, + "pagination": { + "$ref": "#/components/schemas/PaginationMeta" + }, + "session": { + "$ref": "#/components/schemas/AuditSessionSummary" + }, + "statistics": { + "$ref": "#/components/schemas/AuditStatistics" + } + }, + "required": [ + "session", + "items", + "pagination", + "statistics" + ], + "title": "AuditChecklistResponse", + "type": "object" + }, + "AuditEntryResponse": { + "properties": { + "action": { + "title": "Action", + "type": "string" + }, + "changed_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Changed By" + }, + "changed_fields": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Changed Fields" + }, + "created_at": { + "title": "Created At", + "type": "string" + }, + "id": { + "title": "Id", + "type": "string" + } + }, + "required": [ + "id", + "action", + "changed_fields", + "changed_by", + "created_at" + ], + "title": "AuditEntryResponse", + "type": "object" + }, + "AuditFindingCloseRequest": { + "description": "Request to close an Audit Finding.", + "properties": { + "closed_by": { + "title": "Closed By", + "type": "string" + }, + "closure_notes": { + "title": "Closure Notes", + "type": "string" + }, + "verification_evidence": { + "title": "Verification Evidence", + "type": "string" + }, + "verification_method": { + "title": "Verification Method", + "type": "string" + } + }, + "required": [ + "closure_notes", + "closed_by", + "verification_method", + "verification_evidence" + ], + "title": "AuditFindingCloseRequest", + "type": "object" + }, + "AuditFindingCreate": { + "description": "Schema for creating Audit Finding.", + "properties": { + "affected_assets": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Affected Assets" + }, + "affected_processes": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Affected Processes" + }, + "annex_a_control": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Annex A Control" + }, + "audit_session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Audit Session Id" + }, + "auditor": { + "title": "Auditor", + "type": "string" + }, + "description": { + "title": "Description", + "type": "string" + }, + "due_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Due Date" + }, + "finding_type": { + "title": "Finding Type", + "type": "string" + }, + "impact_description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Impact Description" + }, + "internal_audit_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Internal Audit Id" + }, + "iso_chapter": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Iso Chapter" + }, + "objective_evidence": { + "title": "Objective Evidence", + "type": "string" + }, + "owner": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Owner" + }, + "title": { + "title": "Title", + "type": "string" + } + }, + "required": [ + "finding_type", + "title", + "description", + "objective_evidence", + "auditor" + ], + "title": "AuditFindingCreate", + "type": "object" + }, + "AuditFindingListResponse": { + "description": "List response for Audit Findings.", + "properties": { + "findings": { + "items": { + "$ref": "#/components/schemas/AuditFindingResponse" + }, + "title": "Findings", + "type": "array" + }, + "major_count": { + "title": "Major Count", + "type": "integer" + }, + "minor_count": { + "title": "Minor Count", + "type": "integer" + }, + "ofi_count": { + "title": "Ofi Count", + "type": "integer" + }, + "open_count": { + "title": "Open Count", + "type": "integer" + }, + "total": { + "title": "Total", + "type": "integer" + } + }, + "required": [ + "findings", + "total", + "major_count", + "minor_count", + "ofi_count", + "open_count" + ], + "title": "AuditFindingListResponse", + "type": "object" + }, + "AuditFindingResponse": { + "description": "Response schema for Audit Finding.", + "properties": { + "affected_assets": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Affected Assets" + }, + "affected_processes": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Affected Processes" + }, + "annex_a_control": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Annex A Control" + }, + "audit_session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Audit Session Id" + }, + "auditor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Auditor" + }, + "closed_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Closed By" + }, + "closed_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Closed Date" + }, + "closure_notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Closure Notes" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "description": { + "title": "Description", + "type": "string" + }, + "due_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Due Date" + }, + "finding_id": { + "title": "Finding Id", + "type": "string" + }, + "finding_type": { + "title": "Finding Type", + "type": "string" + }, + "id": { + "title": "Id", + "type": "string" + }, + "identified_date": { + "format": "date", + "title": "Identified Date", + "type": "string" + }, + "impact_description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Impact Description" + }, + "internal_audit_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Internal Audit Id" + }, + "is_blocking": { + "title": "Is Blocking", + "type": "boolean" + }, + "iso_chapter": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Iso Chapter" + }, + "objective_evidence": { + "title": "Objective Evidence", + "type": "string" + }, + "owner": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Owner" + }, + "root_cause": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Root Cause" + }, + "root_cause_method": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Root Cause Method" + }, + "status": { + "title": "Status", + "type": "string" + }, + "title": { + "title": "Title", + "type": "string" + }, + "updated_at": { + "format": "date-time", + "title": "Updated At", + "type": "string" + }, + "verification_method": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Verification Method" + }, + "verified_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Verified At" + }, + "verified_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Verified By" + } + }, + "required": [ + "finding_type", + "title", + "description", + "objective_evidence", + "id", + "finding_id", + "status", + "identified_date", + "is_blocking", + "created_at", + "updated_at" + ], + "title": "AuditFindingResponse", + "type": "object" + }, + "AuditFindingUpdate": { + "description": "Schema for updating Audit Finding.", + "properties": { + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "due_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Due Date" + }, + "owner": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Owner" + }, + "root_cause": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Root Cause" + }, + "root_cause_method": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Root Cause Method" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Title" + } + }, + "title": "AuditFindingUpdate", + "type": "object" + }, + "AuditListResponse": { + "properties": { + "entries": { + "items": { + "$ref": "#/components/schemas/AuditEntryResponse" + }, + "title": "Entries", + "type": "array" + }, + "total": { + "title": "Total", + "type": "integer" + } + }, + "required": [ + "entries", + "total" + ], + "title": "AuditListResponse", + "type": "object" + }, + "AuditSessionDetailResponse": { + "description": "Detailed response including statistics breakdown.", + "properties": { + "auditor_email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Auditor Email" + }, + "auditor_name": { + "title": "Auditor Name", + "type": "string" + }, + "auditor_organization": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Auditor Organization" + }, + "completed_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Completed At" + }, + "completed_items": { + "title": "Completed Items", + "type": "integer" + }, + "completion_percentage": { + "title": "Completion Percentage", + "type": "number" + }, + "compliant_count": { + "default": 0, + "title": "Compliant Count", + "type": "integer" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "id": { + "title": "Id", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + }, + "non_compliant_count": { + "default": 0, + "title": "Non Compliant Count", + "type": "integer" + }, + "regulation_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Regulation Ids" + }, + "started_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Started At" + }, + "statistics": { + "anyOf": [ + { + "$ref": "#/components/schemas/AuditStatistics" + }, + { + "type": "null" + } + ] + }, + "status": { + "title": "Status", + "type": "string" + }, + "total_items": { + "title": "Total Items", + "type": "integer" + }, + "updated_at": { + "format": "date-time", + "title": "Updated At", + "type": "string" + } + }, + "required": [ + "id", + "name", + "auditor_name", + "status", + "total_items", + "completed_items", + "completion_percentage", + "created_at", + "updated_at" + ], + "title": "AuditSessionDetailResponse", + "type": "object" + }, + "AuditSessionResponse": { + "description": "Full response for an audit session.", + "properties": { + "auditor_email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Auditor Email" + }, + "auditor_name": { + "title": "Auditor Name", + "type": "string" + }, + "auditor_organization": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Auditor Organization" + }, + "completed_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Completed At" + }, + "completed_items": { + "title": "Completed Items", + "type": "integer" + }, + "completion_percentage": { + "title": "Completion Percentage", + "type": "number" + }, + "compliant_count": { + "default": 0, + "title": "Compliant Count", + "type": "integer" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "id": { + "title": "Id", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + }, + "non_compliant_count": { + "default": 0, + "title": "Non Compliant Count", + "type": "integer" + }, + "regulation_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Regulation Ids" + }, + "started_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Started At" + }, + "status": { + "title": "Status", + "type": "string" + }, + "total_items": { + "title": "Total Items", + "type": "integer" + }, + "updated_at": { + "format": "date-time", + "title": "Updated At", + "type": "string" + } + }, + "required": [ + "id", + "name", + "auditor_name", + "status", + "total_items", + "completed_items", + "completion_percentage", + "created_at", + "updated_at" + ], + "title": "AuditSessionResponse", + "type": "object" + }, + "AuditSessionSummary": { + "description": "Summary of an audit session for list views.", + "properties": { + "auditor_name": { + "title": "Auditor Name", + "type": "string" + }, + "completed_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Completed At" + }, + "completed_items": { + "title": "Completed Items", + "type": "integer" + }, + "completion_percentage": { + "title": "Completion Percentage", + "type": "number" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "id": { + "title": "Id", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + }, + "started_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Started At" + }, + "status": { + "title": "Status", + "type": "string" + }, + "total_items": { + "title": "Total Items", + "type": "integer" + } + }, + "required": [ + "id", + "name", + "auditor_name", + "status", + "total_items", + "completed_items", + "completion_percentage", + "created_at" + ], + "title": "AuditSessionSummary", + "type": "object" + }, + "AuditStatistics": { + "description": "Statistics for an audit session.", + "properties": { + "completion_percentage": { + "title": "Completion Percentage", + "type": "number" + }, + "compliant": { + "title": "Compliant", + "type": "integer" + }, + "compliant_with_notes": { + "title": "Compliant With Notes", + "type": "integer" + }, + "non_compliant": { + "title": "Non Compliant", + "type": "integer" + }, + "not_applicable": { + "title": "Not Applicable", + "type": "integer" + }, + "pending": { + "title": "Pending", + "type": "integer" + }, + "total": { + "title": "Total", + "type": "integer" + } + }, + "required": [ + "total", + "compliant", + "compliant_with_notes", + "non_compliant", + "not_applicable", + "pending", + "completion_percentage" + ], + "title": "AuditStatistics", + "type": "object" + }, + "AuditTrailEntry": { + "description": "Single audit trail entry.", + "properties": { + "action": { + "title": "Action", + "type": "string" + }, + "change_summary": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Change Summary" + }, + "entity_id": { + "title": "Entity Id", + "type": "string" + }, + "entity_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Entity Name" + }, + "entity_type": { + "title": "Entity Type", + "type": "string" + }, + "field_changed": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Field Changed" + }, + "id": { + "title": "Id", + "type": "string" + }, + "new_value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "New Value" + }, + "old_value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Old Value" + }, + "performed_at": { + "format": "date-time", + "title": "Performed At", + "type": "string" + }, + "performed_by": { + "title": "Performed By", + "type": "string" + } + }, + "required": [ + "id", + "entity_type", + "entity_id", + "action", + "performed_by", + "performed_at" + ], + "title": "AuditTrailEntry", + "type": "object" + }, + "AuditTrailResponse": { + "description": "Response for Audit Trail query.", + "properties": { + "entries": { + "items": { + "$ref": "#/components/schemas/AuditTrailEntry" + }, + "title": "Entries", + "type": "array" + }, + "pagination": { + "$ref": "#/components/schemas/PaginationMeta" + }, + "total": { + "title": "Total", + "type": "integer" + } + }, + "required": [ + "entries", + "total", + "pagination" + ], + "title": "AuditTrailResponse", + "type": "object" + }, + "AuthorityNotificationRequest": { + "properties": { + "authority_name": { + "title": "Authority Name", + "type": "string" + }, + "contact_person": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Contact Person" + }, + "notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Notes" + }, + "reference_number": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Reference Number" + } + }, + "required": [ + "authority_name" + ], + "title": "AuthorityNotificationRequest", + "type": "object" + }, + "BSIAspectResponse": { + "description": "A single extracted BSI-TR Pruefaspekt (test aspect).", + "properties": { + "aspect_id": { + "title": "Aspect Id", + "type": "string" + }, + "category": { + "title": "Category", + "type": "string" + }, + "full_text": { + "title": "Full Text", + "type": "string" + }, + "keywords": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Keywords" + }, + "page_number": { + "title": "Page Number", + "type": "integer" + }, + "related_aspects": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Related Aspects" + }, + "requirement_level": { + "title": "Requirement Level", + "type": "string" + }, + "section": { + "title": "Section", + "type": "string" + }, + "source_document": { + "title": "Source Document", + "type": "string" + }, + "title": { + "title": "Title", + "type": "string" + } + }, + "required": [ + "aspect_id", + "title", + "full_text", + "category", + "page_number", + "section", + "requirement_level", + "source_document" + ], + "title": "BSIAspectResponse", + "type": "object" + }, + "Body_analyze_document_api_v1_import_analyze_post": { + "properties": { + "document_type": { + "default": "OTHER", + "title": "Document Type", + "type": "string" + }, + "file": { + "format": "binary", + "title": "File", + "type": "string" + }, + "tenant_id": { + "default": "default", + "title": "Tenant Id", + "type": "string" + } + }, + "required": [ + "file" + ], + "title": "Body_analyze_document_api_v1_import_analyze_post", + "type": "object" + }, + "Body_scan_dependencies_api_v1_screening_scan_post": { + "properties": { + "file": { + "format": "binary", + "title": "File", + "type": "string" + }, + "tenant_id": { + "default": "default", + "title": "Tenant Id", + "type": "string" + } + }, + "required": [ + "file" + ], + "title": "Body_scan_dependencies_api_v1_screening_scan_post", + "type": "object" + }, + "Body_upload_evidence_api_compliance_evidence_upload_post": { + "properties": { + "file": { + "format": "binary", + "title": "File", + "type": "string" + } + }, + "required": [ + "file" + ], + "title": "Body_upload_evidence_api_compliance_evidence_upload_post", + "type": "object" + }, + "Body_upload_word_api_compliance_legal_documents_versions_upload_word_post": { + "properties": { + "file": { + "format": "binary", + "title": "File", + "type": "string" + } + }, + "required": [ + "file" + ], + "title": "Body_upload_word_api_compliance_legal_documents_versions_upload_word_post", + "type": "object" + }, + "Body_upload_word_document_api_consent_admin_versions_upload_word_post": { + "properties": { + "file": { + "format": "binary", + "title": "File", + "type": "string" + } + }, + "required": [ + "file" + ], + "title": "Body_upload_word_document_api_consent_admin_versions_upload_word_post", + "type": "object" + }, + "CAPAVerifyRequest": { + "description": "Request to verify CAPA effectiveness.", + "properties": { + "effectiveness_notes": { + "title": "Effectiveness Notes", + "type": "string" + }, + "is_effective": { + "title": "Is Effective", + "type": "boolean" + }, + "verified_by": { + "title": "Verified By", + "type": "string" + } + }, + "required": [ + "verified_by", + "effectiveness_notes", + "is_effective" + ], + "title": "CAPAVerifyRequest", + "type": "object" + }, + "CatalogUpsert": { + "properties": { + "custom_data_points": { + "default": [], + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Custom Data Points", + "type": "array" + }, + "selected_data_point_ids": { + "default": [], + "items": { + "type": "string" + }, + "title": "Selected Data Point Ids", + "type": "array" + } + }, + "title": "CatalogUpsert", + "type": "object" + }, + "CategoryConfigCreate": { + "properties": { + "category_key": { + "title": "Category Key", + "type": "string" + }, + "description_de": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description De" + }, + "description_en": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description En" + }, + "is_required": { + "default": false, + "title": "Is Required", + "type": "boolean" + }, + "name_de": { + "title": "Name De", + "type": "string" + }, + "name_en": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Name En" + }, + "sort_order": { + "default": 0, + "title": "Sort Order", + "type": "integer" + } + }, + "required": [ + "category_key", + "name_de" + ], + "title": "CategoryConfigCreate", + "type": "object" + }, + "ChangeRequestCreate": { + "properties": { + "priority": { + "default": "normal", + "title": "Priority", + "type": "string" + }, + "proposal_body": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Proposal Body" + }, + "proposal_title": { + "title": "Proposal Title", + "type": "string" + }, + "proposed_changes": { + "additionalProperties": true, + "default": {}, + "title": "Proposed Changes", + "type": "object" + }, + "target_document_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Target Document Id" + }, + "target_document_type": { + "title": "Target Document Type", + "type": "string" + }, + "target_section": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Target Section" + }, + "trigger_source_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Trigger Source Id" + }, + "trigger_type": { + "default": "manual", + "title": "Trigger Type", + "type": "string" + } + }, + "required": [ + "target_document_type", + "proposal_title" + ], + "title": "ChangeRequestCreate", + "type": "object" + }, + "ChangeRequestEdit": { + "properties": { + "proposal_body": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Proposal Body" + }, + "proposed_changes": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Proposed Changes" + } + }, + "title": "ChangeRequestEdit", + "type": "object" + }, + "ChangeRequestReject": { + "properties": { + "rejection_reason": { + "title": "Rejection Reason", + "type": "string" + } + }, + "required": [ + "rejection_reason" + ], + "title": "ChangeRequestReject", + "type": "object" + }, + "ChecklistCreate": { + "properties": { + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "is_required": { + "default": true, + "title": "Is Required", + "type": "boolean" + }, + "order_index": { + "default": 0, + "title": "Order Index", + "type": "integer" + }, + "scenario_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Scenario Id" + }, + "title": { + "title": "Title", + "type": "string" + } + }, + "required": [ + "title" + ], + "title": "ChecklistCreate", + "type": "object" + }, + "ChecklistUpdate": { + "properties": { + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "is_required": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Is Required" + }, + "order_index": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Order Index" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Title" + } + }, + "title": "ChecklistUpdate", + "type": "object" + }, + "CloseIncidentRequest": { + "properties": { + "lessons_learned": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Lessons Learned" + }, + "root_cause": { + "title": "Root Cause", + "type": "string" + } + }, + "required": [ + "root_cause" + ], + "title": "CloseIncidentRequest", + "type": "object" + }, + "CompanyProfileRequest": { + "properties": { + "ai_systems": { + "default": [], + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Ai Systems", + "type": "array" + }, + "ai_use_cases": { + "default": [], + "items": { + "type": "string" + }, + "title": "Ai Use Cases", + "type": "array" + }, + "annual_revenue": { + "default": "< 2 Mio", + "title": "Annual Revenue", + "type": "string" + }, + "business_model": { + "default": "B2B", + "title": "Business Model", + "type": "string" + }, + "company_name": { + "default": "", + "title": "Company Name", + "type": "string" + }, + "company_size": { + "default": "small", + "title": "Company Size", + "type": "string" + }, + "document_sources": { + "default": [], + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Document Sources", + "type": "array" + }, + "dpo_email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Dpo Email" + }, + "dpo_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Dpo Name" + }, + "employee_count": { + "default": "1-9", + "title": "Employee Count", + "type": "string" + }, + "founded_year": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Founded Year" + }, + "has_international_locations": { + "default": false, + "title": "Has International Locations", + "type": "boolean" + }, + "headquarters_city": { + "default": "", + "title": "Headquarters City", + "type": "string" + }, + "headquarters_country": { + "default": "DE", + "title": "Headquarters Country", + "type": "string" + }, + "headquarters_country_other": { + "default": "", + "title": "Headquarters Country Other", + "type": "string" + }, + "headquarters_state": { + "default": "", + "title": "Headquarters State", + "type": "string" + }, + "headquarters_street": { + "default": "", + "title": "Headquarters Street", + "type": "string" + }, + "headquarters_zip": { + "default": "", + "title": "Headquarters Zip", + "type": "string" + }, + "industry": { + "default": "", + "title": "Industry", + "type": "string" + }, + "international_countries": { + "default": [], + "items": { + "type": "string" + }, + "title": "International Countries", + "type": "array" + }, + "is_complete": { + "default": false, + "title": "Is Complete", + "type": "boolean" + }, + "is_data_controller": { + "default": true, + "title": "Is Data Controller", + "type": "boolean" + }, + "is_data_processor": { + "default": false, + "title": "Is Data Processor", + "type": "boolean" + }, + "legal_contact_email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Legal Contact Email" + }, + "legal_contact_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Legal Contact Name" + }, + "legal_form": { + "default": "GmbH", + "title": "Legal Form", + "type": "string" + }, + "machine_builder": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Machine Builder" + }, + "offering_urls": { + "additionalProperties": true, + "default": {}, + "title": "Offering Urls", + "type": "object" + }, + "offerings": { + "default": [], + "items": { + "type": "string" + }, + "title": "Offerings", + "type": "array" + }, + "primary_jurisdiction": { + "default": "DE", + "title": "Primary Jurisdiction", + "type": "string" + }, + "processing_systems": { + "default": [], + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Processing Systems", + "type": "array" + }, + "project_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Project Id" + }, + "repos": { + "default": [], + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Repos", + "type": "array" + }, + "review_cycle_months": { + "default": 12, + "title": "Review Cycle Months", + "type": "integer" + }, + "subject_to_ai_act": { + "default": false, + "title": "Subject To Ai Act", + "type": "boolean" + }, + "subject_to_iso27001": { + "default": false, + "title": "Subject To Iso27001", + "type": "boolean" + }, + "subject_to_nis2": { + "default": false, + "title": "Subject To Nis2", + "type": "boolean" + }, + "supervisory_authority": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Supervisory Authority" + }, + "target_markets": { + "default": [ + "DE" + ], + "items": { + "type": "string" + }, + "title": "Target Markets", + "type": "array" + }, + "technical_contacts": { + "default": [], + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Technical Contacts", + "type": "array" + }, + "uses_ai": { + "default": false, + "title": "Uses Ai", + "type": "boolean" + } + }, + "title": "CompanyProfileRequest", + "type": "object" + }, + "CompanyProfileResponse": { + "properties": { + "ai_systems": { + "default": [], + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Ai Systems", + "type": "array" + }, + "ai_use_cases": { + "items": { + "type": "string" + }, + "title": "Ai Use Cases", + "type": "array" + }, + "annual_revenue": { + "title": "Annual Revenue", + "type": "string" + }, + "business_model": { + "title": "Business Model", + "type": "string" + }, + "company_name": { + "title": "Company Name", + "type": "string" + }, + "company_size": { + "title": "Company Size", + "type": "string" + }, + "completed_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Completed At" + }, + "created_at": { + "title": "Created At", + "type": "string" + }, + "document_sources": { + "default": [], + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Document Sources", + "type": "array" + }, + "dpo_email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Dpo Email" + }, + "dpo_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Dpo Name" + }, + "employee_count": { + "title": "Employee Count", + "type": "string" + }, + "founded_year": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Founded Year" + }, + "has_international_locations": { + "title": "Has International Locations", + "type": "boolean" + }, + "headquarters_city": { + "default": "", + "title": "Headquarters City", + "type": "string" + }, + "headquarters_country": { + "title": "Headquarters Country", + "type": "string" + }, + "headquarters_country_other": { + "default": "", + "title": "Headquarters Country Other", + "type": "string" + }, + "headquarters_state": { + "default": "", + "title": "Headquarters State", + "type": "string" + }, + "headquarters_street": { + "default": "", + "title": "Headquarters Street", + "type": "string" + }, + "headquarters_zip": { + "default": "", + "title": "Headquarters Zip", + "type": "string" + }, + "id": { + "title": "Id", + "type": "string" + }, + "industry": { + "title": "Industry", + "type": "string" + }, + "international_countries": { + "items": { + "type": "string" + }, + "title": "International Countries", + "type": "array" + }, + "is_complete": { + "title": "Is Complete", + "type": "boolean" + }, + "is_data_controller": { + "title": "Is Data Controller", + "type": "boolean" + }, + "is_data_processor": { + "title": "Is Data Processor", + "type": "boolean" + }, + "legal_contact_email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Legal Contact Email" + }, + "legal_contact_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Legal Contact Name" + }, + "legal_form": { + "title": "Legal Form", + "type": "string" + }, + "machine_builder": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Machine Builder" + }, + "offering_urls": { + "additionalProperties": true, + "default": {}, + "title": "Offering Urls", + "type": "object" + }, + "offerings": { + "items": { + "type": "string" + }, + "title": "Offerings", + "type": "array" + }, + "primary_jurisdiction": { + "title": "Primary Jurisdiction", + "type": "string" + }, + "processing_systems": { + "default": [], + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Processing Systems", + "type": "array" + }, + "project_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Project Id" + }, + "repos": { + "default": [], + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Repos", + "type": "array" + }, + "review_cycle_months": { + "default": 12, + "title": "Review Cycle Months", + "type": "integer" + }, + "subject_to_ai_act": { + "default": false, + "title": "Subject To Ai Act", + "type": "boolean" + }, + "subject_to_iso27001": { + "default": false, + "title": "Subject To Iso27001", + "type": "boolean" + }, + "subject_to_nis2": { + "default": false, + "title": "Subject To Nis2", + "type": "boolean" + }, + "supervisory_authority": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Supervisory Authority" + }, + "target_markets": { + "items": { + "type": "string" + }, + "title": "Target Markets", + "type": "array" + }, + "technical_contacts": { + "default": [], + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Technical Contacts", + "type": "array" + }, + "tenant_id": { + "title": "Tenant Id", + "type": "string" + }, + "updated_at": { + "title": "Updated At", + "type": "string" + }, + "uses_ai": { + "title": "Uses Ai", + "type": "boolean" + } + }, + "required": [ + "id", + "tenant_id", + "company_name", + "legal_form", + "industry", + "founded_year", + "business_model", + "offerings", + "company_size", + "employee_count", + "annual_revenue", + "headquarters_country", + "has_international_locations", + "international_countries", + "target_markets", + "primary_jurisdiction", + "is_data_controller", + "is_data_processor", + "uses_ai", + "ai_use_cases", + "dpo_name", + "dpo_email", + "legal_contact_name", + "legal_contact_email", + "machine_builder", + "is_complete", + "completed_at", + "created_at", + "updated_at" + ], + "title": "CompanyProfileResponse", + "type": "object" + }, + "CompanyUpsert": { + "properties": { + "data": { + "additionalProperties": true, + "default": {}, + "title": "Data", + "type": "object" + } + }, + "title": "CompanyUpsert", + "type": "object" + }, + "CompleteDSR": { + "properties": { + "result_data": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Result Data" + }, + "summary": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Summary" + } + }, + "title": "CompleteDSR", + "type": "object" + }, + "ComplianceScopeRequest": { + "description": "Scope selection submitted by the frontend wizard.", + "properties": { + "scope": { + "additionalProperties": true, + "title": "Scope", + "type": "object" + }, + "tenant_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + "required": [ + "scope" + ], + "title": "ComplianceScopeRequest", + "type": "object" + }, + "ComplianceScopeResponse": { + "description": "Persisted scope object returned to the frontend.", + "properties": { + "created_at": { + "title": "Created At", + "type": "string" + }, + "scope": { + "additionalProperties": true, + "title": "Scope", + "type": "object" + }, + "tenant_id": { + "title": "Tenant Id", + "type": "string" + }, + "updated_at": { + "title": "Updated At", + "type": "string" + } + }, + "required": [ + "tenant_id", + "scope", + "updated_at", + "created_at" + ], + "title": "ComplianceScopeResponse", + "type": "object" + }, + "ConsentRequest": { + "properties": { + "consented": { + "default": true, + "title": "Consented", + "type": "boolean" + }, + "document_type": { + "title": "Document Type", + "type": "string" + }, + "version_id": { + "title": "Version Id", + "type": "string" + } + }, + "required": [ + "document_type", + "version_id" + ], + "title": "ConsentRequest", + "type": "object" + }, + "ConsentTemplateCreate": { + "properties": { + "body": { + "title": "Body", + "type": "string" + }, + "is_active": { + "default": true, + "title": "Is Active", + "type": "boolean" + }, + "language": { + "default": "de", + "title": "Language", + "type": "string" + }, + "subject": { + "title": "Subject", + "type": "string" + }, + "template_key": { + "title": "Template Key", + "type": "string" + } + }, + "required": [ + "template_key", + "subject", + "body" + ], + "title": "ConsentTemplateCreate", + "type": "object" + }, + "ConsentTemplateUpdate": { + "properties": { + "body": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Body" + }, + "is_active": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Is Active" + }, + "subject": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Subject" + } + }, + "title": "ConsentTemplateUpdate", + "type": "object" + }, + "ContactCreate": { + "properties": { + "available_24h": { + "default": false, + "title": "Available 24H", + "type": "boolean" + }, + "email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Email" + }, + "is_primary": { + "default": false, + "title": "Is Primary", + "type": "boolean" + }, + "name": { + "title": "Name", + "type": "string" + }, + "phone": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Phone" + }, + "role": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Role" + } + }, + "required": [ + "name" + ], + "title": "ContactCreate", + "type": "object" + }, + "ContactUpdate": { + "properties": { + "available_24h": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Available 24H" + }, + "email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Email" + }, + "is_primary": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Is Primary" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Name" + }, + "phone": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Phone" + }, + "role": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Role" + } + }, + "title": "ContactUpdate", + "type": "object" + }, + "ContextIssue": { + "description": "Single context issue.", + "properties": { + "impact": { + "title": "Impact", + "type": "string" + }, + "issue": { + "title": "Issue", + "type": "string" + }, + "treatment": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Treatment" + } + }, + "required": [ + "issue", + "impact" + ], + "title": "ContextIssue", + "type": "object" + }, + "ControlCreateRequest": { + "properties": { + "control_id": { + "title": "Control Id", + "type": "string" + }, + "evidence": { + "default": [], + "items": {}, + "title": "Evidence", + "type": "array" + }, + "evidence_confidence": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Evidence Confidence" + }, + "framework_id": { + "title": "Framework Id", + "type": "string" + }, + "implementation_effort": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Implementation Effort" + }, + "objective": { + "title": "Objective", + "type": "string" + }, + "open_anchors": { + "default": [], + "items": {}, + "title": "Open Anchors", + "type": "array" + }, + "rationale": { + "title": "Rationale", + "type": "string" + }, + "release_state": { + "default": "draft", + "title": "Release State", + "type": "string" + }, + "requirements": { + "default": [], + "items": {}, + "title": "Requirements", + "type": "array" + }, + "risk_score": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Risk Score" + }, + "scope": { + "additionalProperties": true, + "default": {}, + "title": "Scope", + "type": "object" + }, + "severity": { + "default": "medium", + "title": "Severity", + "type": "string" + }, + "tags": { + "default": [], + "items": {}, + "title": "Tags", + "type": "array" + }, + "test_procedure": { + "default": [], + "items": {}, + "title": "Test Procedure", + "type": "array" + }, + "title": { + "title": "Title", + "type": "string" + } + }, + "required": [ + "framework_id", + "control_id", + "title", + "objective", + "rationale" + ], + "title": "ControlCreateRequest", + "type": "object" + }, + "ControlListResponse": { + "properties": { + "controls": { + "items": { + "$ref": "#/components/schemas/ControlResponse" + }, + "title": "Controls", + "type": "array" + }, + "total": { + "title": "Total", + "type": "integer" + } + }, + "required": [ + "controls", + "total" + ], + "title": "ControlListResponse", + "type": "object" + }, + "ControlResponse": { + "properties": { + "automation_config": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Automation Config" + }, + "automation_tool": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Automation Tool" + }, + "code_reference": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Code Reference" + }, + "control_id": { + "title": "Control Id", + "type": "string" + }, + "control_type": { + "title": "Control Type", + "type": "string" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "documentation_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Documentation Url" + }, + "domain": { + "title": "Domain", + "type": "string" + }, + "evidence_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Evidence Count" + }, + "id": { + "title": "Id", + "type": "string" + }, + "implementation_guidance": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Implementation Guidance" + }, + "is_automated": { + "default": false, + "title": "Is Automated", + "type": "boolean" + }, + "last_reviewed_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Reviewed At" + }, + "next_review_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Next Review At" + }, + "owner": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Owner" + }, + "pass_criteria": { + "title": "Pass Criteria", + "type": "string" + }, + "requirement_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Requirement Count" + }, + "review_frequency_days": { + "default": 90, + "title": "Review Frequency Days", + "type": "integer" + }, + "status": { + "title": "Status", + "type": "string" + }, + "status_notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status Notes" + }, + "title": { + "title": "Title", + "type": "string" + }, + "updated_at": { + "format": "date-time", + "title": "Updated At", + "type": "string" + } + }, + "required": [ + "control_id", + "domain", + "control_type", + "title", + "pass_criteria", + "id", + "status", + "created_at", + "updated_at" + ], + "title": "ControlResponse", + "type": "object" + }, + "ControlReviewRequest": { + "properties": { + "status": { + "title": "Status", + "type": "string" + }, + "status_notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status Notes" + } + }, + "required": [ + "status" + ], + "title": "ControlReviewRequest", + "type": "object" + }, + "ControlUpdate": { + "properties": { + "automation_config": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Automation Config" + }, + "automation_tool": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Automation Tool" + }, + "code_reference": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Code Reference" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "documentation_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Documentation Url" + }, + "implementation_guidance": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Implementation Guidance" + }, + "is_automated": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Is Automated" + }, + "owner": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Owner" + }, + "pass_criteria": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Pass Criteria" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + }, + "status_notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status Notes" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Title" + } + }, + "title": "ControlUpdate", + "type": "object" + }, + "ControlUpdateRequest": { + "properties": { + "evidence": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Evidence" + }, + "evidence_confidence": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Evidence Confidence" + }, + "implementation_effort": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Implementation Effort" + }, + "objective": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Objective" + }, + "open_anchors": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Open Anchors" + }, + "rationale": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Rationale" + }, + "release_state": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Release State" + }, + "requirements": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Requirements" + }, + "risk_score": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Risk Score" + }, + "scope": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Scope" + }, + "severity": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Severity" + }, + "tags": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Tags" + }, + "test_procedure": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Test Procedure" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Title" + } + }, + "title": "ControlUpdateRequest", + "type": "object" + }, + "CookieCategoryCreate": { + "properties": { + "description_de": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description De" + }, + "description_en": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description En" + }, + "is_required": { + "default": false, + "title": "Is Required", + "type": "boolean" + }, + "name_de": { + "title": "Name De", + "type": "string" + }, + "name_en": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Name En" + }, + "sort_order": { + "default": 0, + "title": "Sort Order", + "type": "integer" + } + }, + "required": [ + "name_de" + ], + "title": "CookieCategoryCreate", + "type": "object" + }, + "CookieCategoryUpdate": { + "properties": { + "description_de": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description De" + }, + "description_en": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description En" + }, + "is_active": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Is Active" + }, + "is_required": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Is Required" + }, + "name_de": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Name De" + }, + "name_en": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Name En" + }, + "sort_order": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Sort Order" + } + }, + "title": "CookieCategoryUpdate", + "type": "object" + }, + "CookieConsentItem": { + "properties": { + "category_id": { + "title": "Category Id", + "type": "string" + }, + "consented": { + "title": "Consented", + "type": "boolean" + } + }, + "required": [ + "category_id", + "consented" + ], + "title": "CookieConsentItem", + "type": "object" + }, + "CookieConsentRequest": { + "properties": { + "categories": { + "items": { + "$ref": "#/components/schemas/CookieConsentItem" + }, + "title": "Categories", + "type": "array" + } + }, + "required": [ + "categories" + ], + "title": "CookieConsentRequest", + "type": "object" + }, + "CookiesUpsert": { + "properties": { + "categories": { + "default": [], + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Categories", + "type": "array" + }, + "config": { + "additionalProperties": true, + "default": {}, + "title": "Config", + "type": "object" + } + }, + "title": "CookiesUpsert", + "type": "object" + }, + "CorrectiveActionCreate": { + "description": "Schema for creating Corrective Action.", + "properties": { + "assigned_to": { + "title": "Assigned To", + "type": "string" + }, + "capa_type": { + "title": "Capa Type", + "type": "string" + }, + "description": { + "title": "Description", + "type": "string" + }, + "effectiveness_criteria": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Effectiveness Criteria" + }, + "estimated_effort_hours": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Estimated Effort Hours" + }, + "expected_outcome": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Expected Outcome" + }, + "finding_id": { + "title": "Finding Id", + "type": "string" + }, + "planned_completion": { + "format": "date", + "title": "Planned Completion", + "type": "string" + }, + "planned_start": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Planned Start" + }, + "resources_required": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Resources Required" + }, + "title": { + "title": "Title", + "type": "string" + } + }, + "required": [ + "capa_type", + "title", + "description", + "assigned_to", + "planned_completion", + "finding_id" + ], + "title": "CorrectiveActionCreate", + "type": "object" + }, + "CorrectiveActionListResponse": { + "description": "List response for Corrective Actions.", + "properties": { + "actions": { + "items": { + "$ref": "#/components/schemas/CorrectiveActionResponse" + }, + "title": "Actions", + "type": "array" + }, + "total": { + "title": "Total", + "type": "integer" + } + }, + "required": [ + "actions", + "total" + ], + "title": "CorrectiveActionListResponse", + "type": "object" + }, + "CorrectiveActionResponse": { + "description": "Response schema for Corrective Action.", + "properties": { + "actual_completion": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Actual Completion" + }, + "actual_effort_hours": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Actual Effort Hours" + }, + "approved_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Approved By" + }, + "assigned_to": { + "title": "Assigned To", + "type": "string" + }, + "capa_id": { + "title": "Capa Id", + "type": "string" + }, + "capa_type": { + "title": "Capa Type", + "type": "string" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "description": { + "title": "Description", + "type": "string" + }, + "effectiveness_criteria": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Effectiveness Criteria" + }, + "effectiveness_notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Effectiveness Notes" + }, + "effectiveness_verification_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Effectiveness Verification Date" + }, + "effectiveness_verified": { + "title": "Effectiveness Verified", + "type": "boolean" + }, + "estimated_effort_hours": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Estimated Effort Hours" + }, + "evidence_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Evidence Ids" + }, + "expected_outcome": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Expected Outcome" + }, + "finding_id": { + "title": "Finding Id", + "type": "string" + }, + "id": { + "title": "Id", + "type": "string" + }, + "implementation_evidence": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Implementation Evidence" + }, + "planned_completion": { + "format": "date", + "title": "Planned Completion", + "type": "string" + }, + "planned_start": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Planned Start" + }, + "progress_percentage": { + "title": "Progress Percentage", + "type": "integer" + }, + "resources_required": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Resources Required" + }, + "status": { + "title": "Status", + "type": "string" + }, + "title": { + "title": "Title", + "type": "string" + }, + "updated_at": { + "format": "date-time", + "title": "Updated At", + "type": "string" + } + }, + "required": [ + "capa_type", + "title", + "description", + "assigned_to", + "planned_completion", + "id", + "capa_id", + "finding_id", + "status", + "progress_percentage", + "effectiveness_verified", + "created_at", + "updated_at" + ], + "title": "CorrectiveActionResponse", + "type": "object" + }, + "CorrectiveActionUpdate": { + "description": "Schema for updating Corrective Action.", + "properties": { + "assigned_to": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Assigned To" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "implementation_evidence": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Implementation Evidence" + }, + "planned_completion": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Planned Completion" + }, + "progress_percentage": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Progress Percentage" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Title" + } + }, + "title": "CorrectiveActionUpdate", + "type": "object" + }, + "CreateAuditSessionRequest": { + "description": "Request to create a new audit session.", + "properties": { + "auditor_email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Auditor Email" + }, + "auditor_name": { + "maxLength": 100, + "minLength": 1, + "title": "Auditor Name", + "type": "string" + }, + "auditor_organization": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Auditor Organization" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "name": { + "maxLength": 200, + "minLength": 1, + "title": "Name", + "type": "string" + }, + "regulation_codes": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Regulation Codes" + } + }, + "required": [ + "name", + "auditor_name" + ], + "title": "CreateAuditSessionRequest", + "type": "object" + }, + "CreateCookieCategoryRequest": { + "properties": { + "description_de": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description De" + }, + "description_en": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description En" + }, + "display_name_de": { + "title": "Display Name De", + "type": "string" + }, + "display_name_en": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Display Name En" + }, + "is_mandatory": { + "default": false, + "title": "Is Mandatory", + "type": "boolean" + }, + "name": { + "title": "Name", + "type": "string" + }, + "sort_order": { + "default": 0, + "title": "Sort Order", + "type": "integer" + } + }, + "required": [ + "name", + "display_name_de" + ], + "title": "CreateCookieCategoryRequest", + "type": "object" + }, + "CreateDocumentRequest": { + "properties": { + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "is_mandatory": { + "default": true, + "title": "Is Mandatory", + "type": "boolean" + }, + "name": { + "title": "Name", + "type": "string" + }, + "type": { + "title": "Type", + "type": "string" + } + }, + "required": [ + "type", + "name" + ], + "title": "CreateDocumentRequest", + "type": "object" + }, + "CreateProjectRequest": { + "properties": { + "copy_from_project_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Copy From Project Id" + }, + "customer_type": { + "default": "new", + "title": "Customer Type", + "type": "string" + }, + "description": { + "default": "", + "title": "Description", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + } + }, + "required": [ + "name" + ], + "title": "CreateProjectRequest", + "type": "object" + }, + "CreateTemplateVersion": { + "properties": { + "body_html": { + "title": "Body Html", + "type": "string" + }, + "body_text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Body Text" + }, + "language": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": "de", + "title": "Language" + }, + "subject": { + "title": "Subject", + "type": "string" + }, + "version": { + "default": "1.0", + "title": "Version", + "type": "string" + } + }, + "required": [ + "subject", + "body_html" + ], + "title": "CreateTemplateVersion", + "type": "object" + }, + "CreateVersionRequest": { + "properties": { + "content": { + "title": "Content", + "type": "string" + }, + "document_id": { + "title": "Document Id", + "type": "string" + }, + "language": { + "default": "de", + "title": "Language", + "type": "string" + }, + "summary": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Summary" + }, + "title": { + "title": "Title", + "type": "string" + }, + "version": { + "title": "Version", + "type": "string" + } + }, + "required": [ + "document_id", + "version", + "title", + "content" + ], + "title": "CreateVersionRequest", + "type": "object" + }, + "DSFAApproveRequest": { + "description": "Body for POST /dsfa/{id}/approve.", + "properties": { + "approved": { + "title": "Approved", + "type": "boolean" + }, + "approved_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Approved By" + }, + "comments": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Comments" + } + }, + "required": [ + "approved" + ], + "title": "DSFAApproveRequest", + "type": "object" + }, + "DSFACreate": { + "properties": { + "affected_rights": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Affected Rights" + }, + "ai_trigger_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Ai Trigger Ids" + }, + "ai_use_case_modules": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Ai Use Case Modules" + }, + "alternatives_considered": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Alternatives Considered" + }, + "art35_abs3_triggered": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Art35 Abs3 Triggered" + }, + "authority_consulted": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Authority Consulted" + }, + "authority_decision": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authority Decision" + }, + "authority_reference": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authority Reference" + }, + "authority_resource_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authority Resource Id" + }, + "conclusion": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Conclusion" + }, + "consultation_requirement": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Consultation Requirement" + }, + "created_by": { + "default": "system", + "title": "Created By", + "type": "string" + }, + "data_categories": { + "default": [], + "items": { + "type": "string" + }, + "title": "Data Categories", + "type": "array" + }, + "data_minimization": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Data Minimization" + }, + "data_subjects": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Data Subjects" + }, + "description": { + "default": "", + "title": "Description", + "type": "string" + }, + "dpo_approved": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Dpo Approved" + }, + "dpo_consulted": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Dpo Consulted" + }, + "dpo_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Dpo Name" + }, + "dpo_opinion": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Dpo Opinion" + }, + "federal_state": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Federal State" + }, + "involves_ai": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Involves Ai" + }, + "legal_basis": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Legal Basis" + }, + "legal_basis_details": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Legal Basis Details" + }, + "measures": { + "default": [], + "items": { + "type": "string" + }, + "title": "Measures", + "type": "array" + }, + "metadata": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Metadata" + }, + "mitigations": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Mitigations" + }, + "necessity_assessment": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Necessity Assessment" + }, + "overall_risk_level": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Overall Risk Level" + }, + "processing_activity": { + "default": "", + "title": "Processing Activity", + "type": "string" + }, + "processing_description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Processing Description" + }, + "processing_purpose": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Processing Purpose" + }, + "proportionality_assessment": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Proportionality Assessment" + }, + "recipients": { + "default": [], + "items": { + "type": "string" + }, + "title": "Recipients", + "type": "array" + }, + "retention_justification": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Retention Justification" + }, + "review_comments": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Review Comments" + }, + "review_schedule": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Review Schedule" + }, + "review_triggers": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Review Triggers" + }, + "risk_level": { + "default": "low", + "title": "Risk Level", + "type": "string" + }, + "risk_score": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Risk Score" + }, + "risks": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Risks" + }, + "section_8_complete": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Section 8 Complete" + }, + "section_progress": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Section Progress" + }, + "stakeholder_consultations": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Stakeholder Consultations" + }, + "status": { + "default": "draft", + "title": "Status", + "type": "string" + }, + "submitted_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Submitted By" + }, + "threshold_analysis": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Threshold Analysis" + }, + "title": { + "title": "Title", + "type": "string" + }, + "tom_references": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Tom References" + }, + "triggered_rule_codes": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Triggered Rule Codes" + }, + "version": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Version" + }, + "wp248_criteria_met": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Wp248 Criteria Met" + } + }, + "required": [ + "title" + ], + "title": "DSFACreate", + "type": "object" + }, + "DSFASectionUpdate": { + "description": "Body for PUT /dsfa/{id}/sections/{section_number}.", + "properties": { + "content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Content" + }, + "extra": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Extra" + } + }, + "title": "DSFASectionUpdate", + "type": "object" + }, + "DSFAStatusUpdate": { + "properties": { + "approved_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Approved By" + }, + "status": { + "title": "Status", + "type": "string" + } + }, + "required": [ + "status" + ], + "title": "DSFAStatusUpdate", + "type": "object" + }, + "DSFAUpdate": { + "properties": { + "affected_rights": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Affected Rights" + }, + "ai_trigger_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Ai Trigger Ids" + }, + "ai_use_case_modules": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Ai Use Case Modules" + }, + "alternatives_considered": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Alternatives Considered" + }, + "approved_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Approved By" + }, + "art35_abs3_triggered": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Art35 Abs3 Triggered" + }, + "authority_consulted": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Authority Consulted" + }, + "authority_decision": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authority Decision" + }, + "authority_reference": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authority Reference" + }, + "authority_resource_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authority Resource Id" + }, + "conclusion": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Conclusion" + }, + "consultation_requirement": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Consultation Requirement" + }, + "data_categories": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Data Categories" + }, + "data_minimization": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Data Minimization" + }, + "data_subjects": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Data Subjects" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "dpo_approved": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Dpo Approved" + }, + "dpo_consulted": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Dpo Consulted" + }, + "dpo_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Dpo Name" + }, + "dpo_opinion": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Dpo Opinion" + }, + "federal_state": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Federal State" + }, + "involves_ai": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Involves Ai" + }, + "legal_basis": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Legal Basis" + }, + "legal_basis_details": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Legal Basis Details" + }, + "measures": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Measures" + }, + "metadata": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Metadata" + }, + "mitigations": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Mitigations" + }, + "necessity_assessment": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Necessity Assessment" + }, + "overall_risk_level": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Overall Risk Level" + }, + "processing_activity": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Processing Activity" + }, + "processing_description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Processing Description" + }, + "processing_purpose": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Processing Purpose" + }, + "proportionality_assessment": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Proportionality Assessment" + }, + "recipients": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Recipients" + }, + "retention_justification": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Retention Justification" + }, + "review_comments": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Review Comments" + }, + "review_schedule": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Review Schedule" + }, + "review_triggers": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Review Triggers" + }, + "risk_level": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Risk Level" + }, + "risk_score": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Risk Score" + }, + "risks": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Risks" + }, + "section_8_complete": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Section 8 Complete" + }, + "section_progress": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Section Progress" + }, + "stakeholder_consultations": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Stakeholder Consultations" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + }, + "submitted_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Submitted By" + }, + "threshold_analysis": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Threshold Analysis" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Title" + }, + "tom_references": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Tom References" + }, + "triggered_rule_codes": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Triggered Rule Codes" + }, + "version": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Version" + }, + "wp248_criteria_met": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Wp248 Criteria Met" + } + }, + "title": "DSFAUpdate", + "type": "object" + }, + "DSRCreate": { + "properties": { + "notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Notes" + }, + "priority": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": "normal", + "title": "Priority" + }, + "request_text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Request Text" + }, + "request_type": { + "default": "access", + "title": "Request Type", + "type": "string" + }, + "requester_address": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Requester Address" + }, + "requester_customer_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Requester Customer Id" + }, + "requester_email": { + "title": "Requester Email", + "type": "string" + }, + "requester_name": { + "title": "Requester Name", + "type": "string" + }, + "requester_phone": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Requester Phone" + }, + "source": { + "default": "email", + "title": "Source", + "type": "string" + }, + "source_details": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source Details" + } + }, + "required": [ + "requester_name", + "requester_email" + ], + "title": "DSRCreate", + "type": "object" + }, + "DSRUpdate": { + "properties": { + "affected_systems": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Affected Systems" + }, + "assigned_to": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Assigned To" + }, + "erasure_checklist": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Erasure Checklist" + }, + "internal_notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Internal Notes" + }, + "notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Notes" + }, + "objection_details": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Objection Details" + }, + "priority": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Priority" + }, + "rectification_details": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Rectification Details" + }, + "request_text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Request Text" + } + }, + "title": "DSRUpdate", + "type": "object" + }, + "DashboardResponse": { + "properties": { + "compliance_score": { + "title": "Compliance Score", + "type": "number" + }, + "controls_by_domain": { + "additionalProperties": { + "additionalProperties": { + "type": "integer" + }, + "type": "object" + }, + "title": "Controls By Domain", + "type": "object" + }, + "controls_by_status": { + "additionalProperties": { + "type": "integer" + }, + "title": "Controls By Status", + "type": "object" + }, + "evidence_by_status": { + "additionalProperties": { + "type": "integer" + }, + "title": "Evidence By Status", + "type": "object" + }, + "recent_activity": { + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Recent Activity", + "type": "array" + }, + "risks_by_level": { + "additionalProperties": { + "type": "integer" + }, + "title": "Risks By Level", + "type": "object" + }, + "total_controls": { + "title": "Total Controls", + "type": "integer" + }, + "total_evidence": { + "title": "Total Evidence", + "type": "integer" + }, + "total_regulations": { + "title": "Total Regulations", + "type": "integer" + }, + "total_requirements": { + "title": "Total Requirements", + "type": "integer" + }, + "total_risks": { + "title": "Total Risks", + "type": "integer" + } + }, + "required": [ + "compliance_score", + "total_regulations", + "total_requirements", + "total_controls", + "controls_by_status", + "controls_by_domain", + "total_evidence", + "evidence_by_status", + "total_risks", + "risks_by_level", + "recent_activity" + ], + "title": "DashboardResponse", + "type": "object" + }, + "DataDeletionRequest": { + "properties": { + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Reason" + } + }, + "title": "DataDeletionRequest", + "type": "object" + }, + "DataSubjectNotificationRequest": { + "properties": { + "affected_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": 0, + "title": "Affected Count" + }, + "channel": { + "default": "email", + "title": "Channel", + "type": "string" + }, + "notification_text": { + "title": "Notification Text", + "type": "string" + } + }, + "required": [ + "notification_text" + ], + "title": "DataSubjectNotificationRequest", + "type": "object" + }, + "DeadlineItem": { + "description": "An upcoming deadline for executive display.", + "properties": { + "days_remaining": { + "title": "Days Remaining", + "type": "integer" + }, + "deadline": { + "title": "Deadline", + "type": "string" + }, + "id": { + "title": "Id", + "type": "string" + }, + "owner": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Owner" + }, + "status": { + "title": "Status", + "type": "string" + }, + "title": { + "title": "Title", + "type": "string" + }, + "type": { + "title": "Type", + "type": "string" + } + }, + "required": [ + "id", + "title", + "deadline", + "days_remaining", + "type", + "status" + ], + "title": "DeadlineItem", + "type": "object" + }, + "DeletionRequest": { + "properties": { + "confirm": { + "default": false, + "title": "Confirm", + "type": "boolean" + }, + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Reason" + } + }, + "title": "DeletionRequest", + "type": "object" + }, + "DocumentAnalysisResponse": { + "properties": { + "confidence": { + "title": "Confidence", + "type": "number" + }, + "detected_type": { + "title": "Detected Type", + "type": "string" + }, + "document_id": { + "title": "Document Id", + "type": "string" + }, + "extracted_entities": { + "items": { + "type": "string" + }, + "title": "Extracted Entities", + "type": "array" + }, + "filename": { + "title": "Filename", + "type": "string" + }, + "gap_analysis": { + "additionalProperties": true, + "title": "Gap Analysis", + "type": "object" + }, + "recommendations": { + "items": { + "type": "string" + }, + "title": "Recommendations", + "type": "array" + } + }, + "required": [ + "document_id", + "filename", + "detected_type", + "confidence", + "extracted_entities", + "recommendations", + "gap_analysis" + ], + "title": "DocumentAnalysisResponse", + "type": "object" + }, + "DocumentCreate": { + "properties": { + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "mandatory": { + "default": false, + "title": "Mandatory", + "type": "boolean" + }, + "name": { + "title": "Name", + "type": "string" + }, + "tenant_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + }, + "type": { + "title": "Type", + "type": "string" + } + }, + "required": [ + "type", + "name" + ], + "title": "DocumentCreate", + "type": "object" + }, + "DocumentListResponse": { + "properties": { + "documents": { + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Documents", + "type": "array" + }, + "total": { + "title": "Total", + "type": "integer" + } + }, + "required": [ + "documents", + "total" + ], + "title": "DocumentListResponse", + "type": "object" + }, + "DocumentResponse": { + "properties": { + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "id": { + "title": "Id", + "type": "string" + }, + "mandatory": { + "title": "Mandatory", + "type": "boolean" + }, + "name": { + "title": "Name", + "type": "string" + }, + "tenant_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + }, + "type": { + "title": "Type", + "type": "string" + }, + "updated_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Updated At" + } + }, + "required": [ + "id", + "tenant_id", + "type", + "name", + "description", + "mandatory", + "created_at", + "updated_at" + ], + "title": "DocumentResponse", + "type": "object" + }, + "EscalationCreate": { + "properties": { + "assignee": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Assignee" + }, + "category": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Category" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "due_date": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Due Date" + }, + "priority": { + "default": "medium", + "title": "Priority", + "type": "string" + }, + "reporter": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Reporter" + }, + "source_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source Id" + }, + "source_module": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source Module" + }, + "title": { + "title": "Title", + "type": "string" + } + }, + "required": [ + "title" + ], + "title": "EscalationCreate", + "type": "object" + }, + "EscalationStatusUpdate": { + "properties": { + "resolved_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Resolved At" + }, + "status": { + "title": "Status", + "type": "string" + } + }, + "required": [ + "status" + ], + "title": "EscalationStatusUpdate", + "type": "object" + }, + "EscalationUpdate": { + "properties": { + "assignee": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Assignee" + }, + "category": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Category" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "due_date": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Due Date" + }, + "priority": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Priority" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Title" + } + }, + "title": "EscalationUpdate", + "type": "object" + }, + "EvidenceCreate": { + "properties": { + "artifact_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Artifact Url" + }, + "ci_job_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Ci Job Id" + }, + "control_id": { + "title": "Control Id", + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "evidence_type": { + "title": "Evidence Type", + "type": "string" + }, + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source" + }, + "title": { + "title": "Title", + "type": "string" + }, + "valid_from": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Valid From" + }, + "valid_until": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Valid Until" + } + }, + "required": [ + "control_id", + "evidence_type", + "title" + ], + "title": "EvidenceCreate", + "type": "object" + }, + "EvidenceListResponse": { + "properties": { + "evidence": { + "items": { + "$ref": "#/components/schemas/EvidenceResponse" + }, + "title": "Evidence", + "type": "array" + }, + "total": { + "title": "Total", + "type": "integer" + } + }, + "required": [ + "evidence", + "total" + ], + "title": "EvidenceListResponse", + "type": "object" + }, + "EvidenceResponse": { + "properties": { + "artifact_hash": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Artifact Hash" + }, + "artifact_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Artifact Path" + }, + "artifact_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Artifact Url" + }, + "ci_job_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Ci Job Id" + }, + "collected_at": { + "format": "date-time", + "title": "Collected At", + "type": "string" + }, + "control_id": { + "title": "Control Id", + "type": "string" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "evidence_type": { + "title": "Evidence Type", + "type": "string" + }, + "file_size_bytes": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "File Size Bytes" + }, + "id": { + "title": "Id", + "type": "string" + }, + "mime_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Mime Type" + }, + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source" + }, + "status": { + "title": "Status", + "type": "string" + }, + "title": { + "title": "Title", + "type": "string" + }, + "uploaded_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Uploaded By" + }, + "valid_from": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Valid From" + }, + "valid_until": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Valid Until" + } + }, + "required": [ + "control_id", + "evidence_type", + "title", + "id", + "status", + "collected_at", + "created_at" + ], + "title": "EvidenceResponse", + "type": "object" + }, + "ExecutiveDashboardResponse": { + "description": "Executive Dashboard Response\n\nProvides a high-level overview for managers and executives:\n- Traffic light status (green/yellow/red)\n- Overall compliance score\n- 12-month trend data\n- Top 5 risks\n- Upcoming deadlines\n- Team workload distribution", + "properties": { + "last_updated": { + "title": "Last Updated", + "type": "string" + }, + "open_risks": { + "title": "Open Risks", + "type": "integer" + }, + "overall_score": { + "title": "Overall Score", + "type": "number" + }, + "previous_score": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Previous Score" + }, + "score_change": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Score Change" + }, + "score_trend": { + "items": { + "$ref": "#/components/schemas/TrendDataPoint" + }, + "title": "Score Trend", + "type": "array" + }, + "team_workload": { + "items": { + "$ref": "#/components/schemas/TeamWorkloadItem" + }, + "title": "Team Workload", + "type": "array" + }, + "top_risks": { + "items": { + "$ref": "#/components/schemas/RiskSummary" + }, + "title": "Top Risks", + "type": "array" + }, + "total_controls": { + "title": "Total Controls", + "type": "integer" + }, + "total_regulations": { + "title": "Total Regulations", + "type": "integer" + }, + "total_requirements": { + "title": "Total Requirements", + "type": "integer" + }, + "traffic_light_status": { + "title": "Traffic Light Status", + "type": "string" + }, + "upcoming_deadlines": { + "items": { + "$ref": "#/components/schemas/DeadlineItem" + }, + "title": "Upcoming Deadlines", + "type": "array" + } + }, + "required": [ + "traffic_light_status", + "overall_score", + "score_trend", + "total_regulations", + "total_requirements", + "total_controls", + "open_risks", + "top_risks", + "upcoming_deadlines", + "team_workload", + "last_updated" + ], + "title": "ExecutiveDashboardResponse", + "type": "object" + }, + "ExerciseCreate": { + "properties": { + "exercise_date": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Exercise Date" + }, + "exercise_type": { + "default": "tabletop", + "title": "Exercise Type", + "type": "string" + }, + "notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Notes" + }, + "outcome": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Outcome" + }, + "participants": { + "default": [], + "items": {}, + "title": "Participants", + "type": "array" + }, + "scenario_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Scenario Id" + }, + "title": { + "title": "Title", + "type": "string" + } + }, + "required": [ + "title" + ], + "title": "ExerciseCreate", + "type": "object" + }, + "ExportListResponse": { + "properties": { + "exports": { + "items": { + "$ref": "#/components/schemas/ExportResponse" + }, + "title": "Exports", + "type": "array" + }, + "total": { + "title": "Total", + "type": "integer" + } + }, + "required": [ + "exports", + "total" + ], + "title": "ExportListResponse", + "type": "object" + }, + "ExportRequest": { + "properties": { + "date_range_end": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Date Range End" + }, + "date_range_start": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Date Range Start" + }, + "export_type": { + "default": "full", + "title": "Export Type", + "type": "string" + }, + "included_domains": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Included Domains" + }, + "included_regulations": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Included Regulations" + } + }, + "title": "ExportRequest", + "type": "object" + }, + "ExportResponse": { + "properties": { + "completed_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Completed At" + }, + "compliance_score": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Compliance Score" + }, + "error_message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Error Message" + }, + "export_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Export Name" + }, + "export_type": { + "title": "Export Type", + "type": "string" + }, + "file_hash": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "File Hash" + }, + "file_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "File Path" + }, + "file_size_bytes": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "File Size Bytes" + }, + "id": { + "title": "Id", + "type": "string" + }, + "requested_at": { + "format": "date-time", + "title": "Requested At", + "type": "string" + }, + "requested_by": { + "title": "Requested By", + "type": "string" + }, + "status": { + "title": "Status", + "type": "string" + }, + "total_controls": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Total Controls" + }, + "total_evidence": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Total Evidence" + } + }, + "required": [ + "id", + "export_type", + "status", + "requested_by", + "requested_at" + ], + "title": "ExportResponse", + "type": "object" + }, + "ExtendDeadline": { + "properties": { + "days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": 60, + "title": "Days" + }, + "reason": { + "title": "Reason", + "type": "string" + } + }, + "required": [ + "reason" + ], + "title": "ExtendDeadline", + "type": "object" + }, + "ExtractedRequirement": { + "properties": { + "action": { + "title": "Action", + "type": "string" + }, + "article": { + "title": "Article", + "type": "string" + }, + "regulation_code": { + "title": "Regulation Code", + "type": "string" + }, + "requirement_text": { + "title": "Requirement Text", + "type": "string" + }, + "score": { + "title": "Score", + "type": "number" + }, + "source_url": { + "title": "Source Url", + "type": "string" + }, + "title": { + "title": "Title", + "type": "string" + } + }, + "required": [ + "regulation_code", + "article", + "title", + "requirement_text", + "source_url", + "score", + "action" + ], + "title": "ExtractedRequirement", + "type": "object" + }, + "ExtractionRequest": { + "properties": { + "collections": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Collections" + }, + "dry_run": { + "default": false, + "title": "Dry Run", + "type": "boolean" + }, + "max_per_query": { + "default": 20, + "title": "Max Per Query", + "type": "integer" + }, + "regulation_codes": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Regulation Codes" + }, + "search_queries": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Search Queries" + } + }, + "title": "ExtractionRequest", + "type": "object" + }, + "ExtractionResponse": { + "properties": { + "collections_searched": { + "items": { + "type": "string" + }, + "title": "Collections Searched", + "type": "array" + }, + "created": { + "title": "Created", + "type": "integer" + }, + "dry_run": { + "title": "Dry Run", + "type": "boolean" + }, + "failed": { + "title": "Failed", + "type": "integer" + }, + "message": { + "title": "Message", + "type": "string" + }, + "queries_used": { + "items": { + "type": "string" + }, + "title": "Queries Used", + "type": "array" + }, + "requirements": { + "items": { + "$ref": "#/components/schemas/ExtractedRequirement" + }, + "title": "Requirements", + "type": "array" + }, + "skipped_duplicates": { + "title": "Skipped Duplicates", + "type": "integer" + }, + "skipped_no_article": { + "title": "Skipped No Article", + "type": "integer" + } + }, + "required": [ + "created", + "skipped_duplicates", + "skipped_no_article", + "failed", + "collections_searched", + "queries_used", + "requirements", + "dry_run", + "message" + ], + "title": "ExtractionResponse", + "type": "object" + }, + "GDPRProcessUpdate": { + "properties": { + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "is_active": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Is Active" + }, + "legal_basis": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Legal Basis" + }, + "retention_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Retention Days" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Title" + } + }, + "title": "GDPRProcessUpdate", + "type": "object" + }, + "GenerateRequest": { + "properties": { + "batch_size": { + "default": 5, + "title": "Batch Size", + "type": "integer" + }, + "collections": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Collections" + }, + "domain": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Domain" + }, + "dry_run": { + "default": false, + "title": "Dry Run", + "type": "boolean" + }, + "max_controls": { + "default": 50, + "title": "Max Controls", + "type": "integer" + }, + "skip_web_search": { + "default": false, + "title": "Skip Web Search", + "type": "boolean" + } + }, + "title": "GenerateRequest", + "type": "object" + }, + "GenerateResponse": { + "properties": { + "controls": { + "default": [], + "items": {}, + "title": "Controls", + "type": "array" + }, + "controls_duplicates_found": { + "default": 0, + "title": "Controls Duplicates Found", + "type": "integer" + }, + "controls_generated": { + "default": 0, + "title": "Controls Generated", + "type": "integer" + }, + "controls_needs_review": { + "default": 0, + "title": "Controls Needs Review", + "type": "integer" + }, + "controls_too_close": { + "default": 0, + "title": "Controls Too Close", + "type": "integer" + }, + "controls_verified": { + "default": 0, + "title": "Controls Verified", + "type": "integer" + }, + "errors": { + "default": [], + "items": {}, + "title": "Errors", + "type": "array" + }, + "job_id": { + "title": "Job Id", + "type": "string" + }, + "message": { + "title": "Message", + "type": "string" + }, + "status": { + "title": "Status", + "type": "string" + }, + "total_chunks_scanned": { + "default": 0, + "title": "Total Chunks Scanned", + "type": "integer" + } + }, + "required": [ + "job_id", + "status", + "message" + ], + "title": "GenerateResponse", + "type": "object" + }, + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "title": "Detail", + "type": "array" + } + }, + "title": "HTTPValidationError", + "type": "object" + }, + "ISMSContextCreate": { + "description": "Schema for creating ISMS Context.", + "properties": { + "contractual_requirements": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Contractual Requirements" + }, + "external_issues": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/ContextIssue" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "External Issues" + }, + "interested_parties": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/InterestedParty" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Interested Parties" + }, + "internal_issues": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/ContextIssue" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Internal Issues" + }, + "regulatory_requirements": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Regulatory Requirements" + }, + "swot_opportunities": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Swot Opportunities" + }, + "swot_strengths": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Swot Strengths" + }, + "swot_threats": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Swot Threats" + }, + "swot_weaknesses": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Swot Weaknesses" + } + }, + "title": "ISMSContextCreate", + "type": "object" + }, + "ISMSContextResponse": { + "description": "Response schema for ISMS Context.", + "properties": { + "approved_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Approved At" + }, + "approved_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Approved By" + }, + "contractual_requirements": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Contractual Requirements" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "external_issues": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/ContextIssue" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "External Issues" + }, + "id": { + "title": "Id", + "type": "string" + }, + "interested_parties": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/InterestedParty" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Interested Parties" + }, + "internal_issues": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/ContextIssue" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Internal Issues" + }, + "last_reviewed_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Reviewed At" + }, + "next_review_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Next Review Date" + }, + "regulatory_requirements": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Regulatory Requirements" + }, + "status": { + "title": "Status", + "type": "string" + }, + "swot_opportunities": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Swot Opportunities" + }, + "swot_strengths": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Swot Strengths" + }, + "swot_threats": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Swot Threats" + }, + "swot_weaknesses": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Swot Weaknesses" + }, + "updated_at": { + "format": "date-time", + "title": "Updated At", + "type": "string" + }, + "version": { + "title": "Version", + "type": "string" + } + }, + "required": [ + "id", + "version", + "status", + "created_at", + "updated_at" + ], + "title": "ISMSContextResponse", + "type": "object" + }, + "ISMSPolicyApproveRequest": { + "description": "Request to approve ISMS Policy.", + "properties": { + "approved_by": { + "title": "Approved By", + "type": "string" + }, + "effective_date": { + "format": "date", + "title": "Effective Date", + "type": "string" + }, + "reviewed_by": { + "title": "Reviewed By", + "type": "string" + } + }, + "required": [ + "reviewed_by", + "approved_by", + "effective_date" + ], + "title": "ISMSPolicyApproveRequest", + "type": "object" + }, + "ISMSPolicyCreate": { + "description": "Schema for creating ISMS Policy.", + "properties": { + "applies_to": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Applies To" + }, + "authored_by": { + "title": "Authored By", + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "policy_id": { + "title": "Policy Id", + "type": "string" + }, + "policy_text": { + "title": "Policy Text", + "type": "string" + }, + "policy_type": { + "title": "Policy Type", + "type": "string" + }, + "related_controls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Related Controls" + }, + "review_frequency_months": { + "default": 12, + "title": "Review Frequency Months", + "type": "integer" + }, + "title": { + "title": "Title", + "type": "string" + } + }, + "required": [ + "policy_id", + "title", + "policy_type", + "policy_text", + "authored_by" + ], + "title": "ISMSPolicyCreate", + "type": "object" + }, + "ISMSPolicyListResponse": { + "description": "List response for ISMS Policies.", + "properties": { + "policies": { + "items": { + "$ref": "#/components/schemas/ISMSPolicyResponse" + }, + "title": "Policies", + "type": "array" + }, + "total": { + "title": "Total", + "type": "integer" + } + }, + "required": [ + "policies", + "total" + ], + "title": "ISMSPolicyListResponse", + "type": "object" + }, + "ISMSPolicyResponse": { + "description": "Response schema for ISMS Policy.", + "properties": { + "applies_to": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Applies To" + }, + "approved_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Approved At" + }, + "approved_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Approved By" + }, + "authored_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authored By" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "document_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Document Path" + }, + "effective_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Effective Date" + }, + "id": { + "title": "Id", + "type": "string" + }, + "next_review_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Next Review Date" + }, + "policy_id": { + "title": "Policy Id", + "type": "string" + }, + "policy_text": { + "title": "Policy Text", + "type": "string" + }, + "policy_type": { + "title": "Policy Type", + "type": "string" + }, + "related_controls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Related Controls" + }, + "review_frequency_months": { + "default": 12, + "title": "Review Frequency Months", + "type": "integer" + }, + "reviewed_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Reviewed By" + }, + "status": { + "title": "Status", + "type": "string" + }, + "title": { + "title": "Title", + "type": "string" + }, + "updated_at": { + "format": "date-time", + "title": "Updated At", + "type": "string" + }, + "version": { + "title": "Version", + "type": "string" + } + }, + "required": [ + "policy_id", + "title", + "policy_type", + "policy_text", + "id", + "version", + "status", + "created_at", + "updated_at" + ], + "title": "ISMSPolicyResponse", + "type": "object" + }, + "ISMSPolicyUpdate": { + "description": "Schema for updating ISMS Policy.", + "properties": { + "applies_to": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Applies To" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "policy_text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Policy Text" + }, + "related_controls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Related Controls" + }, + "review_frequency_months": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Review Frequency Months" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Title" + } + }, + "title": "ISMSPolicyUpdate", + "type": "object" + }, + "ISMSReadinessCheckRequest": { + "description": "Request to run ISMS Readiness Check.", + "properties": { + "triggered_by": { + "default": "manual", + "title": "Triggered By", + "type": "string" + } + }, + "title": "ISMSReadinessCheckRequest", + "type": "object" + }, + "ISMSReadinessCheckResponse": { + "description": "Response for ISMS Readiness Check.", + "properties": { + "certification_possible": { + "title": "Certification Possible", + "type": "boolean" + }, + "chapter_10_status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Chapter 10 Status" + }, + "chapter_4_status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Chapter 4 Status" + }, + "chapter_5_status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Chapter 5 Status" + }, + "chapter_6_status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Chapter 6 Status" + }, + "chapter_7_status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Chapter 7 Status" + }, + "chapter_8_status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Chapter 8 Status" + }, + "chapter_9_status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Chapter 9 Status" + }, + "check_date": { + "format": "date-time", + "title": "Check Date", + "type": "string" + }, + "documentation_score": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Documentation Score" + }, + "evidence_score": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Evidence Score" + }, + "id": { + "title": "Id", + "type": "string" + }, + "implementation_score": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Implementation Score" + }, + "improvement_opportunities": { + "items": { + "$ref": "#/components/schemas/PotentialFinding" + }, + "title": "Improvement Opportunities", + "type": "array" + }, + "overall_status": { + "title": "Overall Status", + "type": "string" + }, + "potential_majors": { + "items": { + "$ref": "#/components/schemas/PotentialFinding" + }, + "title": "Potential Majors", + "type": "array" + }, + "potential_minors": { + "items": { + "$ref": "#/components/schemas/PotentialFinding" + }, + "title": "Potential Minors", + "type": "array" + }, + "priority_actions": { + "items": { + "type": "string" + }, + "title": "Priority Actions", + "type": "array" + }, + "readiness_score": { + "title": "Readiness Score", + "type": "number" + }, + "triggered_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Triggered By" + } + }, + "required": [ + "id", + "check_date", + "overall_status", + "certification_possible", + "potential_majors", + "potential_minors", + "improvement_opportunities", + "readiness_score", + "priority_actions" + ], + "title": "ISMSReadinessCheckResponse", + "type": "object" + }, + "ISMSScopeApproveRequest": { + "description": "Request to approve ISMS Scope.", + "properties": { + "approved_by": { + "title": "Approved By", + "type": "string" + }, + "effective_date": { + "format": "date", + "title": "Effective Date", + "type": "string" + }, + "review_date": { + "format": "date", + "title": "Review Date", + "type": "string" + } + }, + "required": [ + "approved_by", + "effective_date", + "review_date" + ], + "title": "ISMSScopeApproveRequest", + "type": "object" + }, + "ISMSScopeCreate": { + "description": "Schema for creating ISMS Scope.", + "properties": { + "excluded_items": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Excluded Items" + }, + "exclusion_justification": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Exclusion Justification" + }, + "included_locations": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Included Locations" + }, + "included_processes": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Included Processes" + }, + "included_services": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Included Services" + }, + "organizational_boundary": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Organizational Boundary" + }, + "physical_boundary": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Physical Boundary" + }, + "scope_statement": { + "title": "Scope Statement", + "type": "string" + }, + "technical_boundary": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Technical Boundary" + } + }, + "required": [ + "scope_statement" + ], + "title": "ISMSScopeCreate", + "type": "object" + }, + "ISMSScopeResponse": { + "description": "Response schema for ISMS Scope.", + "properties": { + "approved_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Approved At" + }, + "approved_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Approved By" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "effective_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Effective Date" + }, + "excluded_items": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Excluded Items" + }, + "exclusion_justification": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Exclusion Justification" + }, + "id": { + "title": "Id", + "type": "string" + }, + "included_locations": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Included Locations" + }, + "included_processes": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Included Processes" + }, + "included_services": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Included Services" + }, + "organizational_boundary": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Organizational Boundary" + }, + "physical_boundary": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Physical Boundary" + }, + "review_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Review Date" + }, + "scope_statement": { + "title": "Scope Statement", + "type": "string" + }, + "status": { + "title": "Status", + "type": "string" + }, + "technical_boundary": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Technical Boundary" + }, + "updated_at": { + "format": "date-time", + "title": "Updated At", + "type": "string" + }, + "version": { + "title": "Version", + "type": "string" + } + }, + "required": [ + "scope_statement", + "id", + "version", + "status", + "created_at", + "updated_at" + ], + "title": "ISMSScopeResponse", + "type": "object" + }, + "ISMSScopeUpdate": { + "description": "Schema for updating ISMS Scope.", + "properties": { + "excluded_items": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Excluded Items" + }, + "exclusion_justification": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Exclusion Justification" + }, + "included_locations": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Included Locations" + }, + "included_processes": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Included Processes" + }, + "included_services": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Included Services" + }, + "organizational_boundary": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Organizational Boundary" + }, + "physical_boundary": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Physical Boundary" + }, + "scope_statement": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Scope Statement" + }, + "technical_boundary": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Technical Boundary" + } + }, + "title": "ISMSScopeUpdate", + "type": "object" + }, + "ISO27001ChapterStatus": { + "description": "Status of a single ISO 27001 chapter.", + "properties": { + "chapter": { + "title": "Chapter", + "type": "string" + }, + "completion_percentage": { + "title": "Completion Percentage", + "type": "number" + }, + "key_documents": { + "items": { + "type": "string" + }, + "title": "Key Documents", + "type": "array" + }, + "last_reviewed": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Reviewed" + }, + "open_findings": { + "title": "Open Findings", + "type": "integer" + }, + "status": { + "title": "Status", + "type": "string" + }, + "title": { + "title": "Title", + "type": "string" + } + }, + "required": [ + "chapter", + "title", + "status", + "completion_percentage", + "open_findings", + "key_documents" + ], + "title": "ISO27001ChapterStatus", + "type": "object" + }, + "ISO27001OverviewResponse": { + "description": "Complete ISO 27001 status overview.", + "properties": { + "certification_readiness": { + "title": "Certification Readiness", + "type": "number" + }, + "chapters": { + "items": { + "$ref": "#/components/schemas/ISO27001ChapterStatus" + }, + "title": "Chapters", + "type": "array" + }, + "last_internal_audit": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Internal Audit" + }, + "last_management_review": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Management Review" + }, + "objectives_achieved": { + "title": "Objectives Achieved", + "type": "integer" + }, + "objectives_count": { + "title": "Objectives Count", + "type": "integer" + }, + "open_major_findings": { + "title": "Open Major Findings", + "type": "integer" + }, + "open_minor_findings": { + "title": "Open Minor Findings", + "type": "integer" + }, + "overall_status": { + "title": "Overall Status", + "type": "string" + }, + "policies_approved": { + "title": "Policies Approved", + "type": "integer" + }, + "policies_count": { + "title": "Policies Count", + "type": "integer" + }, + "scope_approved": { + "title": "Scope Approved", + "type": "boolean" + }, + "soa_approved": { + "title": "Soa Approved", + "type": "boolean" + } + }, + "required": [ + "overall_status", + "certification_readiness", + "chapters", + "scope_approved", + "soa_approved", + "open_major_findings", + "open_minor_findings", + "policies_count", + "policies_approved", + "objectives_count", + "objectives_achieved" + ], + "title": "ISO27001OverviewResponse", + "type": "object" + }, + "InterestedParty": { + "description": "Single interested party.", + "properties": { + "party": { + "title": "Party", + "type": "string" + }, + "relevance": { + "title": "Relevance", + "type": "string" + }, + "requirements": { + "items": { + "type": "string" + }, + "title": "Requirements", + "type": "array" + } + }, + "required": [ + "party", + "requirements", + "relevance" + ], + "title": "InterestedParty", + "type": "object" + }, + "InternalAuditCompleteRequest": { + "description": "Request to complete Internal Audit.", + "properties": { + "audit_conclusion": { + "title": "Audit Conclusion", + "type": "string" + }, + "follow_up_audit_required": { + "title": "Follow Up Audit Required", + "type": "boolean" + }, + "overall_assessment": { + "title": "Overall Assessment", + "type": "string" + } + }, + "required": [ + "audit_conclusion", + "overall_assessment", + "follow_up_audit_required" + ], + "title": "InternalAuditCompleteRequest", + "type": "object" + }, + "InternalAuditCreate": { + "description": "Schema for creating Internal Audit.", + "properties": { + "annex_a_controls_covered": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Annex A Controls Covered" + }, + "audit_team": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Audit Team" + }, + "audit_type": { + "title": "Audit Type", + "type": "string" + }, + "criteria": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Criteria" + }, + "departments_covered": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Departments Covered" + }, + "iso_chapters_covered": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Iso Chapters Covered" + }, + "lead_auditor": { + "title": "Lead Auditor", + "type": "string" + }, + "planned_date": { + "format": "date", + "title": "Planned Date", + "type": "string" + }, + "processes_covered": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Processes Covered" + }, + "scope_description": { + "title": "Scope Description", + "type": "string" + }, + "title": { + "title": "Title", + "type": "string" + } + }, + "required": [ + "title", + "audit_type", + "scope_description", + "planned_date", + "lead_auditor" + ], + "title": "InternalAuditCreate", + "type": "object" + }, + "InternalAuditListResponse": { + "description": "List response for Internal Audits.", + "properties": { + "audits": { + "items": { + "$ref": "#/components/schemas/InternalAuditResponse" + }, + "title": "Audits", + "type": "array" + }, + "total": { + "title": "Total", + "type": "integer" + } + }, + "required": [ + "audits", + "total" + ], + "title": "InternalAuditListResponse", + "type": "object" + }, + "InternalAuditResponse": { + "description": "Response schema for Internal Audit.", + "properties": { + "actual_end_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Actual End Date" + }, + "actual_start_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Actual Start Date" + }, + "annex_a_controls_covered": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Annex A Controls Covered" + }, + "audit_conclusion": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Audit Conclusion" + }, + "audit_id": { + "title": "Audit Id", + "type": "string" + }, + "audit_team": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Audit Team" + }, + "audit_type": { + "title": "Audit Type", + "type": "string" + }, + "auditee_representatives": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Auditee Representatives" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "criteria": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Criteria" + }, + "departments_covered": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Departments Covered" + }, + "follow_up_audit_required": { + "title": "Follow Up Audit Required", + "type": "boolean" + }, + "id": { + "title": "Id", + "type": "string" + }, + "iso_chapters_covered": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Iso Chapters Covered" + }, + "lead_auditor": { + "title": "Lead Auditor", + "type": "string" + }, + "major_findings": { + "title": "Major Findings", + "type": "integer" + }, + "minor_findings": { + "title": "Minor Findings", + "type": "integer" + }, + "ofi_count": { + "title": "Ofi Count", + "type": "integer" + }, + "overall_assessment": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Overall Assessment" + }, + "planned_date": { + "format": "date", + "title": "Planned Date", + "type": "string" + }, + "positive_observations": { + "title": "Positive Observations", + "type": "integer" + }, + "processes_covered": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Processes Covered" + }, + "report_approved_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Report Approved At" + }, + "report_approved_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Report Approved By" + }, + "report_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Report Date" + }, + "report_document_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Report Document Path" + }, + "scope_description": { + "title": "Scope Description", + "type": "string" + }, + "status": { + "title": "Status", + "type": "string" + }, + "title": { + "title": "Title", + "type": "string" + }, + "total_findings": { + "title": "Total Findings", + "type": "integer" + }, + "updated_at": { + "format": "date-time", + "title": "Updated At", + "type": "string" + } + }, + "required": [ + "title", + "audit_type", + "scope_description", + "planned_date", + "lead_auditor", + "id", + "audit_id", + "status", + "total_findings", + "major_findings", + "minor_findings", + "ofi_count", + "positive_observations", + "follow_up_audit_required", + "created_at", + "updated_at" + ], + "title": "InternalAuditResponse", + "type": "object" + }, + "InternalAuditUpdate": { + "description": "Schema for updating Internal Audit.", + "properties": { + "actual_end_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Actual End Date" + }, + "actual_start_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Actual Start Date" + }, + "audit_conclusion": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Audit Conclusion" + }, + "auditee_representatives": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Auditee Representatives" + }, + "overall_assessment": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Overall Assessment" + }, + "scope_description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Scope Description" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Title" + } + }, + "title": "InternalAuditUpdate", + "type": "object" + }, + "LegalTemplateCreate": { + "properties": { + "attribution_required": { + "default": false, + "title": "Attribution Required", + "type": "boolean" + }, + "attribution_text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Attribution Text" + }, + "content": { + "title": "Content", + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "document_type": { + "title": "Document Type", + "type": "string" + }, + "inspiration_sources": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Inspiration Sources" + }, + "is_complete_document": { + "default": true, + "title": "Is Complete Document", + "type": "boolean" + }, + "jurisdiction": { + "default": "DE", + "title": "Jurisdiction", + "type": "string" + }, + "language": { + "default": "de", + "title": "Language", + "type": "string" + }, + "license_id": { + "default": "mit", + "title": "License Id", + "type": "string" + }, + "license_name": { + "default": "MIT License", + "title": "License Name", + "type": "string" + }, + "placeholders": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Placeholders" + }, + "source_file_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source File Path" + }, + "source_name": { + "default": "BreakPilot Compliance", + "title": "Source Name", + "type": "string" + }, + "source_repo": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source Repo" + }, + "source_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source Url" + }, + "status": { + "default": "published", + "title": "Status", + "type": "string" + }, + "title": { + "title": "Title", + "type": "string" + }, + "version": { + "default": "1.0.0", + "title": "Version", + "type": "string" + } + }, + "required": [ + "document_type", + "title", + "content" + ], + "title": "LegalTemplateCreate", + "type": "object" + }, + "LegalTemplateUpdate": { + "properties": { + "attribution_required": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Attribution Required" + }, + "attribution_text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Attribution Text" + }, + "content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Content" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "document_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Document Type" + }, + "inspiration_sources": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Inspiration Sources" + }, + "is_complete_document": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Is Complete Document" + }, + "jurisdiction": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Jurisdiction" + }, + "language": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Language" + }, + "license_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "License Id" + }, + "license_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "License Name" + }, + "placeholders": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Placeholders" + }, + "source_file_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source File Path" + }, + "source_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source Name" + }, + "source_repo": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source Repo" + }, + "source_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source Url" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Title" + }, + "version": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Version" + } + }, + "title": "LegalTemplateUpdate", + "type": "object" + }, + "LoeschfristCreate": { + "properties": { + "affected_groups": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Affected Groups" + }, + "data_categories": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Data Categories" + }, + "data_object_name": { + "title": "Data Object Name", + "type": "string" + }, + "deletion_method": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Deletion Method" + }, + "deletion_method_detail": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Deletion Method Detail" + }, + "deletion_trigger": { + "default": "PURPOSE_END", + "title": "Deletion Trigger", + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "has_active_legal_hold": { + "default": false, + "title": "Has Active Legal Hold", + "type": "boolean" + }, + "last_review_date": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Review Date" + }, + "legal_holds": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Legal Holds" + }, + "linked_vvt_activity_ids": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Linked Vvt Activity Ids" + }, + "next_review_date": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Next Review Date" + }, + "policy_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Policy Id" + }, + "primary_purpose": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Primary Purpose" + }, + "release_process": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Release Process" + }, + "responsible_person": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Responsible Person" + }, + "responsible_role": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Responsible Role" + }, + "retention_description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Retention Description" + }, + "retention_driver": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Retention Driver" + }, + "retention_driver_detail": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Retention Driver Detail" + }, + "retention_duration": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Retention Duration" + }, + "retention_unit": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Retention Unit" + }, + "review_interval": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Review Interval" + }, + "start_event": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Start Event" + }, + "status": { + "default": "DRAFT", + "title": "Status", + "type": "string" + }, + "storage_locations": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Storage Locations" + }, + "tags": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Tags" + } + }, + "required": [ + "data_object_name" + ], + "title": "LoeschfristCreate", + "type": "object" + }, + "LoeschfristUpdate": { + "properties": { + "affected_groups": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Affected Groups" + }, + "data_categories": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Data Categories" + }, + "data_object_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Data Object Name" + }, + "deletion_method": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Deletion Method" + }, + "deletion_method_detail": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Deletion Method Detail" + }, + "deletion_trigger": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Deletion Trigger" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "has_active_legal_hold": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Has Active Legal Hold" + }, + "last_review_date": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Review Date" + }, + "legal_holds": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Legal Holds" + }, + "linked_vvt_activity_ids": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Linked Vvt Activity Ids" + }, + "next_review_date": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Next Review Date" + }, + "policy_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Policy Id" + }, + "primary_purpose": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Primary Purpose" + }, + "release_process": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Release Process" + }, + "responsible_person": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Responsible Person" + }, + "responsible_role": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Responsible Role" + }, + "retention_description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Retention Description" + }, + "retention_driver": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Retention Driver" + }, + "retention_driver_detail": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Retention Driver Detail" + }, + "retention_duration": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Retention Duration" + }, + "retention_unit": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Retention Unit" + }, + "review_interval": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Review Interval" + }, + "start_event": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Start Event" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + }, + "storage_locations": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Storage Locations" + }, + "tags": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Tags" + } + }, + "title": "LoeschfristUpdate", + "type": "object" + }, + "ManagementReviewApproveRequest": { + "description": "Request to approve Management Review.", + "properties": { + "approved_by": { + "title": "Approved By", + "type": "string" + }, + "minutes_document_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Minutes Document Path" + }, + "next_review_date": { + "format": "date", + "title": "Next Review Date", + "type": "string" + } + }, + "required": [ + "approved_by", + "next_review_date" + ], + "title": "ManagementReviewApproveRequest", + "type": "object" + }, + "ManagementReviewCreate": { + "description": "Schema for creating Management Review.", + "properties": { + "attendees": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/ReviewAttendee" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Attendees" + }, + "chairperson": { + "title": "Chairperson", + "type": "string" + }, + "review_date": { + "format": "date", + "title": "Review Date", + "type": "string" + }, + "review_period_end": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Review Period End" + }, + "review_period_start": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Review Period Start" + }, + "title": { + "title": "Title", + "type": "string" + } + }, + "required": [ + "title", + "review_date", + "chairperson" + ], + "title": "ManagementReviewCreate", + "type": "object" + }, + "ManagementReviewListResponse": { + "description": "List response for Management Reviews.", + "properties": { + "reviews": { + "items": { + "$ref": "#/components/schemas/ManagementReviewResponse" + }, + "title": "Reviews", + "type": "array" + }, + "total": { + "title": "Total", + "type": "integer" + } + }, + "required": [ + "reviews", + "total" + ], + "title": "ManagementReviewListResponse", + "type": "object" + }, + "ManagementReviewResponse": { + "description": "Response schema for Management Review.", + "properties": { + "action_items": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/ReviewActionItem" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Action Items" + }, + "approved_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Approved At" + }, + "approved_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Approved By" + }, + "attendees": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/ReviewAttendee" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Attendees" + }, + "chairperson": { + "title": "Chairperson", + "type": "string" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "id": { + "title": "Id", + "type": "string" + }, + "input_improvement_opportunities": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Input Improvement Opportunities" + }, + "input_interested_party_feedback": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Input Interested Party Feedback" + }, + "input_isms_changes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Input Isms Changes" + }, + "input_objective_achievement": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Input Objective Achievement" + }, + "input_policy_effectiveness": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Input Policy Effectiveness" + }, + "input_previous_actions": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Input Previous Actions" + }, + "input_resource_adequacy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Input Resource Adequacy" + }, + "input_risk_assessment_results": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Input Risk Assessment Results" + }, + "input_security_performance": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Input Security Performance" + }, + "isms_effectiveness_rating": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Isms Effectiveness Rating" + }, + "key_decisions": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Key Decisions" + }, + "minutes_document_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Minutes Document Path" + }, + "next_review_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Next Review Date" + }, + "output_improvement_decisions": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Output Improvement Decisions" + }, + "output_isms_changes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Output Isms Changes" + }, + "output_resource_needs": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Output Resource Needs" + }, + "review_date": { + "format": "date", + "title": "Review Date", + "type": "string" + }, + "review_id": { + "title": "Review Id", + "type": "string" + }, + "review_period_end": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Review Period End" + }, + "review_period_start": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Review Period Start" + }, + "status": { + "title": "Status", + "type": "string" + }, + "title": { + "title": "Title", + "type": "string" + }, + "updated_at": { + "format": "date-time", + "title": "Updated At", + "type": "string" + } + }, + "required": [ + "title", + "review_date", + "chairperson", + "id", + "review_id", + "status", + "created_at", + "updated_at" + ], + "title": "ManagementReviewResponse", + "type": "object" + }, + "ManagementReviewUpdate": { + "description": "Schema for updating Management Review.", + "properties": { + "action_items": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/ReviewActionItem" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Action Items" + }, + "input_improvement_opportunities": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Input Improvement Opportunities" + }, + "input_interested_party_feedback": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Input Interested Party Feedback" + }, + "input_isms_changes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Input Isms Changes" + }, + "input_objective_achievement": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Input Objective Achievement" + }, + "input_policy_effectiveness": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Input Policy Effectiveness" + }, + "input_previous_actions": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Input Previous Actions" + }, + "input_resource_adequacy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Input Resource Adequacy" + }, + "input_risk_assessment_results": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Input Risk Assessment Results" + }, + "input_security_performance": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Input Security Performance" + }, + "isms_effectiveness_rating": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Isms Effectiveness Rating" + }, + "key_decisions": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Key Decisions" + }, + "output_improvement_decisions": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Output Improvement Decisions" + }, + "output_isms_changes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Output Isms Changes" + }, + "output_resource_needs": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Output Resource Needs" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + "title": "ManagementReviewUpdate", + "type": "object" + }, + "MeasureCreate": { + "properties": { + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "due_date": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Due Date" + }, + "measure_type": { + "default": "corrective", + "title": "Measure Type", + "type": "string" + }, + "responsible": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Responsible" + }, + "title": { + "title": "Title", + "type": "string" + } + }, + "required": [ + "title" + ], + "title": "MeasureCreate", + "type": "object" + }, + "MeasureUpdate": { + "properties": { + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "due_date": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Due Date" + }, + "measure_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Measure Type" + }, + "responsible": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Responsible" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Title" + } + }, + "title": "MeasureUpdate", + "type": "object" + }, + "MetricCreate": { + "properties": { + "ai_system": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Ai System" + }, + "category": { + "default": "accuracy", + "title": "Category", + "type": "string" + }, + "last_measured": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Measured" + }, + "name": { + "title": "Name", + "type": "string" + }, + "score": { + "default": 0.0, + "title": "Score", + "type": "number" + }, + "threshold": { + "default": 80.0, + "title": "Threshold", + "type": "number" + }, + "trend": { + "default": "stable", + "title": "Trend", + "type": "string" + } + }, + "required": [ + "name" + ], + "title": "MetricCreate", + "type": "object" + }, + "MetricUpdate": { + "properties": { + "ai_system": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Ai System" + }, + "category": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Category" + }, + "last_measured": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Measured" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Name" + }, + "score": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Score" + }, + "threshold": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Threshold" + }, + "trend": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Trend" + } + }, + "title": "MetricUpdate", + "type": "object" + }, + "ModuleComplianceOverview": { + "description": "Overview of compliance status for all modules.", + "properties": { + "average_compliance_score": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Average Compliance Score" + }, + "modules_by_criticality": { + "additionalProperties": { + "type": "integer" + }, + "title": "Modules By Criticality", + "type": "object" + }, + "modules_by_type": { + "additionalProperties": { + "type": "integer" + }, + "title": "Modules By Type", + "type": "object" + }, + "modules_processing_pii": { + "title": "Modules Processing Pii", + "type": "integer" + }, + "modules_with_ai": { + "title": "Modules With Ai", + "type": "integer" + }, + "regulations_coverage": { + "additionalProperties": { + "type": "integer" + }, + "title": "Regulations Coverage", + "type": "object" + }, + "total_modules": { + "title": "Total Modules", + "type": "integer" + } + }, + "required": [ + "total_modules", + "modules_by_type", + "modules_by_criticality", + "modules_processing_pii", + "modules_with_ai", + "regulations_coverage" + ], + "title": "ModuleComplianceOverview", + "type": "object" + }, + "ModuleRegulationMappingCreate": { + "description": "Schema for creating a module-regulation mapping.", + "properties": { + "applicable_articles": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Applicable Articles" + }, + "module_id": { + "title": "Module Id", + "type": "string" + }, + "notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Notes" + }, + "regulation_id": { + "title": "Regulation Id", + "type": "string" + }, + "relevance_level": { + "default": "medium", + "title": "Relevance Level", + "type": "string" + } + }, + "required": [ + "module_id", + "regulation_id" + ], + "title": "ModuleRegulationMappingCreate", + "type": "object" + }, + "ModuleRegulationMappingResponse": { + "description": "Response schema for module-regulation mapping.", + "properties": { + "applicable_articles": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Applicable Articles" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "id": { + "title": "Id", + "type": "string" + }, + "module_id": { + "title": "Module Id", + "type": "string" + }, + "module_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Module Name" + }, + "notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Notes" + }, + "regulation_code": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Regulation Code" + }, + "regulation_id": { + "title": "Regulation Id", + "type": "string" + }, + "regulation_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Regulation Name" + }, + "relevance_level": { + "default": "medium", + "title": "Relevance Level", + "type": "string" + } + }, + "required": [ + "module_id", + "regulation_id", + "id", + "created_at" + ], + "title": "ModuleRegulationMappingResponse", + "type": "object" + }, + "ModuleSeedRequest": { + "description": "Request to seed service modules.", + "properties": { + "force": { + "default": false, + "title": "Force", + "type": "boolean" + } + }, + "title": "ModuleSeedRequest", + "type": "object" + }, + "ModuleSeedResponse": { + "description": "Response from seeding service modules.", + "properties": { + "mappings_created": { + "title": "Mappings Created", + "type": "integer" + }, + "message": { + "title": "Message", + "type": "string" + }, + "modules_created": { + "title": "Modules Created", + "type": "integer" + }, + "success": { + "title": "Success", + "type": "boolean" + } + }, + "required": [ + "success", + "message", + "modules_created", + "mappings_created" + ], + "title": "ModuleSeedResponse", + "type": "object" + }, + "ObligationCreate": { + "properties": { + "assessment_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Assessment Id" + }, + "deadline": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Deadline" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "linked_systems": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Linked Systems" + }, + "notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Notes" + }, + "priority": { + "default": "medium", + "title": "Priority", + "type": "string" + }, + "responsible": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Responsible" + }, + "rule_code": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Rule Code" + }, + "source": { + "default": "DSGVO", + "title": "Source", + "type": "string" + }, + "source_article": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source Article" + }, + "status": { + "default": "pending", + "title": "Status", + "type": "string" + }, + "title": { + "title": "Title", + "type": "string" + } + }, + "required": [ + "title" + ], + "title": "ObligationCreate", + "type": "object" + }, + "ObligationStatusUpdate": { + "properties": { + "status": { + "title": "Status", + "type": "string" + } + }, + "required": [ + "status" + ], + "title": "ObligationStatusUpdate", + "type": "object" + }, + "ObligationUpdate": { + "properties": { + "deadline": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Deadline" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "linked_systems": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Linked Systems" + }, + "notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Notes" + }, + "priority": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Priority" + }, + "responsible": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Responsible" + }, + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source" + }, + "source_article": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source Article" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Title" + } + }, + "title": "ObligationUpdate", + "type": "object" + }, + "OperationUpdate": { + "properties": { + "allowed": { + "title": "Allowed", + "type": "boolean" + }, + "conditions": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Conditions" + } + }, + "required": [ + "allowed" + ], + "title": "OperationUpdate", + "type": "object" + }, + "PDFExtractionRequest": { + "description": "Request for PDF extraction.", + "properties": { + "document_code": { + "description": "BSI-TR document code, e.g. BSI-TR-03161-2", + "title": "Document Code", + "type": "string" + }, + "force": { + "default": false, + "description": "Force re-extraction even if requirements exist", + "title": "Force", + "type": "boolean" + }, + "save_to_db": { + "default": true, + "description": "Whether to save extracted requirements to database", + "title": "Save To Db", + "type": "boolean" + } + }, + "required": [ + "document_code" + ], + "title": "PDFExtractionRequest", + "type": "object" + }, + "PDFExtractionResponse": { + "description": "Response from PDF extraction endpoint.", + "properties": { + "aspects": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/BSIAspectResponse" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Aspects" + }, + "doc_code": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Doc Code" + }, + "requirements_created": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Requirements Created" + }, + "saved_to_db": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Saved To Db" + }, + "source_document": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source Document" + }, + "statistics": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Statistics" + }, + "success": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Success" + }, + "total_aspects": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Total Aspects" + }, + "total_extracted": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Total Extracted" + } + }, + "title": "PDFExtractionResponse", + "type": "object" + }, + "PIIRuleCreate": { + "properties": { + "action": { + "default": "mask", + "title": "Action", + "type": "string" + }, + "active": { + "default": true, + "title": "Active", + "type": "boolean" + }, + "category": { + "title": "Category", + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "name": { + "title": "Name", + "type": "string" + }, + "pattern": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Pattern" + } + }, + "required": [ + "name", + "category" + ], + "title": "PIIRuleCreate", + "type": "object" + }, + "PIIRuleUpdate": { + "properties": { + "action": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Action" + }, + "active": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Active" + }, + "category": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Category" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Name" + }, + "pattern": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Pattern" + } + }, + "title": "PIIRuleUpdate", + "type": "object" + }, + "PaginatedControlResponse": { + "description": "Paginated response for controls - optimized for large datasets.", + "properties": { + "data": { + "items": { + "$ref": "#/components/schemas/ControlResponse" + }, + "title": "Data", + "type": "array" + }, + "pagination": { + "$ref": "#/components/schemas/PaginationMeta" + } + }, + "required": [ + "data", + "pagination" + ], + "title": "PaginatedControlResponse", + "type": "object" + }, + "PaginatedRequirementResponse": { + "description": "Paginated response for requirements - optimized for large datasets.", + "properties": { + "data": { + "items": { + "$ref": "#/components/schemas/RequirementResponse" + }, + "title": "Data", + "type": "array" + }, + "pagination": { + "$ref": "#/components/schemas/PaginationMeta" + } + }, + "required": [ + "data", + "pagination" + ], + "title": "PaginatedRequirementResponse", + "type": "object" + }, + "PaginationMeta": { + "description": "Pagination metadata for list responses.", + "properties": { + "has_next": { + "title": "Has Next", + "type": "boolean" + }, + "has_prev": { + "title": "Has Prev", + "type": "boolean" + }, + "page": { + "title": "Page", + "type": "integer" + }, + "page_size": { + "title": "Page Size", + "type": "integer" + }, + "total": { + "title": "Total", + "type": "integer" + }, + "total_pages": { + "title": "Total Pages", + "type": "integer" + } + }, + "required": [ + "page", + "page_size", + "total", + "total_pages", + "has_next", + "has_prev" + ], + "title": "PaginationMeta", + "type": "object" + }, + "PotentialFinding": { + "description": "Potential finding from readiness check.", + "properties": { + "check": { + "title": "Check", + "type": "string" + }, + "iso_reference": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Iso Reference" + }, + "recommendation": { + "title": "Recommendation", + "type": "string" + }, + "status": { + "title": "Status", + "type": "string" + } + }, + "required": [ + "check", + "status", + "recommendation" + ], + "title": "PotentialFinding", + "type": "object" + }, + "PreviewRequest": { + "properties": { + "variables": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Variables" + } + }, + "title": "PreviewRequest", + "type": "object" + }, + "RegulationListResponse": { + "properties": { + "regulations": { + "items": { + "$ref": "#/components/schemas/RegulationResponse" + }, + "title": "Regulations", + "type": "array" + }, + "total": { + "title": "Total", + "type": "integer" + } + }, + "required": [ + "regulations", + "total" + ], + "title": "RegulationListResponse", + "type": "object" + }, + "RegulationResponse": { + "properties": { + "code": { + "title": "Code", + "type": "string" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "effective_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Effective Date" + }, + "full_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Full Name" + }, + "id": { + "title": "Id", + "type": "string" + }, + "is_active": { + "default": true, + "title": "Is Active", + "type": "boolean" + }, + "local_pdf_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Local Pdf Path" + }, + "name": { + "title": "Name", + "type": "string" + }, + "regulation_type": { + "title": "Regulation Type", + "type": "string" + }, + "requirement_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Requirement Count" + }, + "source_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source Url" + }, + "updated_at": { + "format": "date-time", + "title": "Updated At", + "type": "string" + } + }, + "required": [ + "code", + "name", + "regulation_type", + "id", + "created_at", + "updated_at" + ], + "title": "RegulationResponse", + "type": "object" + }, + "RejectDSR": { + "properties": { + "legal_basis": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Legal Basis" + }, + "reason": { + "title": "Reason", + "type": "string" + } + }, + "required": [ + "reason" + ], + "title": "RejectDSR", + "type": "object" + }, + "RejectRequest": { + "properties": { + "comment": { + "title": "Comment", + "type": "string" + } + }, + "required": [ + "comment" + ], + "title": "RejectRequest", + "type": "object" + }, + "RequirementCreate": { + "properties": { + "applicability_reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Applicability Reason" + }, + "article": { + "title": "Article", + "type": "string" + }, + "breakpilot_interpretation": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Breakpilot Interpretation" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "is_applicable": { + "default": true, + "title": "Is Applicable", + "type": "boolean" + }, + "paragraph": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Paragraph" + }, + "priority": { + "default": 2, + "title": "Priority", + "type": "integer" + }, + "regulation_id": { + "title": "Regulation Id", + "type": "string" + }, + "requirement_text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Requirement Text" + }, + "title": { + "title": "Title", + "type": "string" + } + }, + "required": [ + "article", + "title", + "regulation_id" + ], + "title": "RequirementCreate", + "type": "object" + }, + "RequirementListResponse": { + "properties": { + "requirements": { + "items": { + "$ref": "#/components/schemas/RequirementResponse" + }, + "title": "Requirements", + "type": "array" + }, + "total": { + "title": "Total", + "type": "integer" + } + }, + "required": [ + "requirements", + "total" + ], + "title": "RequirementListResponse", + "type": "object" + }, + "RequirementResponse": { + "properties": { + "applicability_reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Applicability Reason" + }, + "article": { + "title": "Article", + "type": "string" + }, + "audit_status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": "pending", + "title": "Audit Status" + }, + "auditor_notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Auditor Notes" + }, + "breakpilot_interpretation": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Breakpilot Interpretation" + }, + "code_references": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Code References" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "documentation_links": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Documentation Links" + }, + "evidence_artifacts": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Evidence Artifacts" + }, + "evidence_description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Evidence Description" + }, + "id": { + "title": "Id", + "type": "string" + }, + "implementation_details": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Implementation Details" + }, + "implementation_status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": "not_started", + "title": "Implementation Status" + }, + "is_applicable": { + "default": true, + "title": "Is Applicable", + "type": "boolean" + }, + "last_audit_date": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Audit Date" + }, + "last_auditor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Auditor" + }, + "paragraph": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Paragraph" + }, + "priority": { + "default": 2, + "title": "Priority", + "type": "integer" + }, + "regulation_code": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Regulation Code" + }, + "regulation_id": { + "title": "Regulation Id", + "type": "string" + }, + "requirement_text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Requirement Text" + }, + "source_page": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Source Page" + }, + "source_section": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source Section" + }, + "title": { + "title": "Title", + "type": "string" + }, + "updated_at": { + "format": "date-time", + "title": "Updated At", + "type": "string" + } + }, + "required": [ + "article", + "title", + "id", + "regulation_id", + "created_at", + "updated_at" + ], + "title": "RequirementResponse", + "type": "object" + }, + "ReviewActionItem": { + "description": "Single action item from management review.", + "properties": { + "action": { + "title": "Action", + "type": "string" + }, + "due_date": { + "format": "date", + "title": "Due Date", + "type": "string" + }, + "owner": { + "title": "Owner", + "type": "string" + } + }, + "required": [ + "action", + "owner", + "due_date" + ], + "title": "ReviewActionItem", + "type": "object" + }, + "ReviewAttendee": { + "description": "Single attendee in management review.", + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "role": { + "title": "Role", + "type": "string" + } + }, + "required": [ + "name", + "role" + ], + "title": "ReviewAttendee", + "type": "object" + }, + "ReviewRequest": { + "properties": { + "action": { + "title": "Action", + "type": "string" + }, + "notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Notes" + }, + "release_state": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Release State" + } + }, + "required": [ + "action" + ], + "title": "ReviewRequest", + "type": "object" + }, + "RiskAssessmentRequest": { + "properties": { + "impact": { + "title": "Impact", + "type": "integer" + }, + "likelihood": { + "title": "Likelihood", + "type": "integer" + }, + "notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Notes" + } + }, + "required": [ + "likelihood", + "impact" + ], + "title": "RiskAssessmentRequest", + "type": "object" + }, + "RiskCreate": { + "properties": { + "category": { + "title": "Category", + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "impact": { + "maximum": 5.0, + "minimum": 1.0, + "title": "Impact", + "type": "integer" + }, + "likelihood": { + "maximum": 5.0, + "minimum": 1.0, + "title": "Likelihood", + "type": "integer" + }, + "mitigating_controls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Mitigating Controls" + }, + "owner": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Owner" + }, + "risk_id": { + "title": "Risk Id", + "type": "string" + }, + "title": { + "title": "Title", + "type": "string" + }, + "treatment_plan": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Treatment Plan" + } + }, + "required": [ + "risk_id", + "title", + "category", + "likelihood", + "impact" + ], + "title": "RiskCreate", + "type": "object" + }, + "RiskListResponse": { + "properties": { + "risks": { + "items": { + "$ref": "#/components/schemas/RiskResponse" + }, + "title": "Risks", + "type": "array" + }, + "total": { + "title": "Total", + "type": "integer" + } + }, + "required": [ + "risks", + "total" + ], + "title": "RiskListResponse", + "type": "object" + }, + "RiskMatrixResponse": { + "description": "Risk matrix data for visualization.", + "properties": { + "matrix": { + "additionalProperties": { + "additionalProperties": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": "object" + }, + "title": "Matrix", + "type": "object" + }, + "risks": { + "items": { + "$ref": "#/components/schemas/RiskResponse" + }, + "title": "Risks", + "type": "array" + } + }, + "required": [ + "matrix", + "risks" + ], + "title": "RiskMatrixResponse", + "type": "object" + }, + "RiskResponse": { + "properties": { + "category": { + "title": "Category", + "type": "string" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "id": { + "title": "Id", + "type": "string" + }, + "identified_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Identified Date" + }, + "impact": { + "maximum": 5.0, + "minimum": 1.0, + "title": "Impact", + "type": "integer" + }, + "inherent_risk": { + "title": "Inherent Risk", + "type": "string" + }, + "last_assessed_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Assessed At" + }, + "likelihood": { + "maximum": 5.0, + "minimum": 1.0, + "title": "Likelihood", + "type": "integer" + }, + "mitigating_controls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Mitigating Controls" + }, + "owner": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Owner" + }, + "residual_impact": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Residual Impact" + }, + "residual_likelihood": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Residual Likelihood" + }, + "residual_risk": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Residual Risk" + }, + "review_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Review Date" + }, + "risk_id": { + "title": "Risk Id", + "type": "string" + }, + "status": { + "title": "Status", + "type": "string" + }, + "title": { + "title": "Title", + "type": "string" + }, + "treatment_plan": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Treatment Plan" + }, + "updated_at": { + "format": "date-time", + "title": "Updated At", + "type": "string" + } + }, + "required": [ + "risk_id", + "title", + "category", + "likelihood", + "impact", + "id", + "inherent_risk", + "status", + "created_at", + "updated_at" + ], + "title": "RiskResponse", + "type": "object" + }, + "RiskSummary": { + "description": "Summary of a risk for executive display.", + "properties": { + "category": { + "title": "Category", + "type": "string" + }, + "id": { + "title": "Id", + "type": "string" + }, + "impact": { + "title": "Impact", + "type": "integer" + }, + "likelihood": { + "title": "Likelihood", + "type": "integer" + }, + "owner": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Owner" + }, + "risk_id": { + "title": "Risk Id", + "type": "string" + }, + "risk_level": { + "title": "Risk Level", + "type": "string" + }, + "status": { + "title": "Status", + "type": "string" + }, + "title": { + "title": "Title", + "type": "string" + } + }, + "required": [ + "id", + "risk_id", + "title", + "risk_level", + "status", + "category", + "impact", + "likelihood" + ], + "title": "RiskSummary", + "type": "object" + }, + "RiskUpdate": { + "properties": { + "category": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Category" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "impact": { + "anyOf": [ + { + "maximum": 5.0, + "minimum": 1.0, + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Impact" + }, + "likelihood": { + "anyOf": [ + { + "maximum": 5.0, + "minimum": 1.0, + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Likelihood" + }, + "mitigating_controls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Mitigating Controls" + }, + "owner": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Owner" + }, + "residual_impact": { + "anyOf": [ + { + "maximum": 5.0, + "minimum": 1.0, + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Residual Impact" + }, + "residual_likelihood": { + "anyOf": [ + { + "maximum": 5.0, + "minimum": 1.0, + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Residual Likelihood" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Title" + }, + "treatment_plan": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Treatment Plan" + } + }, + "title": "RiskUpdate", + "type": "object" + }, + "SBOMComponentResponse": { + "properties": { + "licenses": { + "items": { + "type": "string" + }, + "title": "Licenses", + "type": "array" + }, + "name": { + "title": "Name", + "type": "string" + }, + "purl": { + "title": "Purl", + "type": "string" + }, + "type": { + "title": "Type", + "type": "string" + }, + "version": { + "title": "Version", + "type": "string" + }, + "vulnerabilities": { + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Vulnerabilities", + "type": "array" + } + }, + "required": [ + "name", + "version", + "type", + "purl", + "licenses", + "vulnerabilities" + ], + "title": "SBOMComponentResponse", + "type": "object" + }, + "ScenarioCreate": { + "properties": { + "category": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Category" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "estimated_recovery_time": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Estimated Recovery Time" + }, + "is_active": { + "default": true, + "title": "Is Active", + "type": "boolean" + }, + "response_steps": { + "default": [], + "items": {}, + "title": "Response Steps", + "type": "array" + }, + "severity": { + "default": "medium", + "title": "Severity", + "type": "string" + }, + "title": { + "title": "Title", + "type": "string" + } + }, + "required": [ + "title" + ], + "title": "ScenarioCreate", + "type": "object" + }, + "ScenarioUpdate": { + "properties": { + "category": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Category" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "estimated_recovery_time": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Estimated Recovery Time" + }, + "is_active": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Is Active" + }, + "last_tested": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Tested" + }, + "response_steps": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Response Steps" + }, + "severity": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Severity" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Title" + } + }, + "title": "ScenarioUpdate", + "type": "object" + }, + "ScreeningListResponse": { + "properties": { + "screenings": { + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Screenings", + "type": "array" + }, + "total": { + "title": "Total", + "type": "integer" + } + }, + "required": [ + "screenings", + "total" + ], + "title": "ScreeningListResponse", + "type": "object" + }, + "ScreeningResponse": { + "properties": { + "completed_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Completed At" + }, + "components": { + "items": { + "$ref": "#/components/schemas/SBOMComponentResponse" + }, + "title": "Components", + "type": "array" + }, + "critical_issues": { + "title": "Critical Issues", + "type": "integer" + }, + "high_issues": { + "title": "High Issues", + "type": "integer" + }, + "id": { + "title": "Id", + "type": "string" + }, + "issues": { + "items": { + "$ref": "#/components/schemas/SecurityIssueResponse" + }, + "title": "Issues", + "type": "array" + }, + "low_issues": { + "title": "Low Issues", + "type": "integer" + }, + "medium_issues": { + "title": "Medium Issues", + "type": "integer" + }, + "sbom_format": { + "title": "Sbom Format", + "type": "string" + }, + "sbom_version": { + "title": "Sbom Version", + "type": "string" + }, + "started_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Started At" + }, + "status": { + "title": "Status", + "type": "string" + }, + "total_components": { + "title": "Total Components", + "type": "integer" + }, + "total_issues": { + "title": "Total Issues", + "type": "integer" + } + }, + "required": [ + "id", + "status", + "sbom_format", + "sbom_version", + "total_components", + "total_issues", + "critical_issues", + "high_issues", + "medium_issues", + "low_issues", + "components", + "issues" + ], + "title": "ScreeningResponse", + "type": "object" + }, + "SecurityIssueResponse": { + "properties": { + "affected_component": { + "title": "Affected Component", + "type": "string" + }, + "affected_version": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Affected Version" + }, + "cve": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Cve" + }, + "cvss": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Cvss" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "fixed_in": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Fixed In" + }, + "id": { + "title": "Id", + "type": "string" + }, + "remediation": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Remediation" + }, + "severity": { + "title": "Severity", + "type": "string" + }, + "status": { + "default": "OPEN", + "title": "Status", + "type": "string" + }, + "title": { + "title": "Title", + "type": "string" + } + }, + "required": [ + "id", + "severity", + "title", + "affected_component" + ], + "title": "SecurityIssueResponse", + "type": "object" + }, + "SecurityItemCreate": { + "properties": { + "affected_asset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Affected Asset" + }, + "assigned_to": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Assigned To" + }, + "cve": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Cve" + }, + "cvss": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Cvss" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "due_date": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Due Date" + }, + "remediation": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Remediation" + }, + "severity": { + "default": "medium", + "title": "Severity", + "type": "string" + }, + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source" + }, + "status": { + "default": "open", + "title": "Status", + "type": "string" + }, + "title": { + "title": "Title", + "type": "string" + }, + "type": { + "default": "vulnerability", + "title": "Type", + "type": "string" + } + }, + "required": [ + "title" + ], + "title": "SecurityItemCreate", + "type": "object" + }, + "SecurityItemUpdate": { + "properties": { + "affected_asset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Affected Asset" + }, + "assigned_to": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Assigned To" + }, + "cve": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Cve" + }, + "cvss": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Cvss" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "due_date": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Due Date" + }, + "remediation": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Remediation" + }, + "severity": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Severity" + }, + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Title" + }, + "type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Type" + } + }, + "title": "SecurityItemUpdate", + "type": "object" + }, + "SecurityObjectiveCreate": { + "description": "Schema for creating Security Objective.", + "properties": { + "achievable": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Achievable" + }, + "category": { + "title": "Category", + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "kpi_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Kpi Name" + }, + "kpi_target": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Kpi Target" + }, + "kpi_unit": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Kpi Unit" + }, + "measurable": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Measurable" + }, + "measurement_frequency": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Measurement Frequency" + }, + "objective_id": { + "title": "Objective Id", + "type": "string" + }, + "owner": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Owner" + }, + "related_controls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Related Controls" + }, + "related_risks": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Related Risks" + }, + "relevant": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Relevant" + }, + "specific": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Specific" + }, + "target_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Target Date" + }, + "time_bound": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Time Bound" + }, + "title": { + "title": "Title", + "type": "string" + } + }, + "required": [ + "objective_id", + "title", + "category" + ], + "title": "SecurityObjectiveCreate", + "type": "object" + }, + "SecurityObjectiveListResponse": { + "description": "List response for Security Objectives.", + "properties": { + "objectives": { + "items": { + "$ref": "#/components/schemas/SecurityObjectiveResponse" + }, + "title": "Objectives", + "type": "array" + }, + "total": { + "title": "Total", + "type": "integer" + } + }, + "required": [ + "objectives", + "total" + ], + "title": "SecurityObjectiveListResponse", + "type": "object" + }, + "SecurityObjectiveResponse": { + "description": "Response schema for Security Objective.", + "properties": { + "achievable": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Achievable" + }, + "achieved_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Achieved Date" + }, + "approved_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Approved At" + }, + "approved_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Approved By" + }, + "category": { + "title": "Category", + "type": "string" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "id": { + "title": "Id", + "type": "string" + }, + "kpi_current": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Kpi Current" + }, + "kpi_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Kpi Name" + }, + "kpi_target": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Kpi Target" + }, + "kpi_unit": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Kpi Unit" + }, + "measurable": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Measurable" + }, + "measurement_frequency": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Measurement Frequency" + }, + "objective_id": { + "title": "Objective Id", + "type": "string" + }, + "owner": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Owner" + }, + "progress_percentage": { + "title": "Progress Percentage", + "type": "integer" + }, + "related_controls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Related Controls" + }, + "related_risks": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Related Risks" + }, + "relevant": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Relevant" + }, + "specific": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Specific" + }, + "status": { + "title": "Status", + "type": "string" + }, + "target_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Target Date" + }, + "time_bound": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Time Bound" + }, + "title": { + "title": "Title", + "type": "string" + }, + "updated_at": { + "format": "date-time", + "title": "Updated At", + "type": "string" + } + }, + "required": [ + "objective_id", + "title", + "category", + "id", + "status", + "progress_percentage", + "created_at", + "updated_at" + ], + "title": "SecurityObjectiveResponse", + "type": "object" + }, + "SecurityObjectiveUpdate": { + "description": "Schema for updating Security Objective.", + "properties": { + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "kpi_current": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Kpi Current" + }, + "progress_percentage": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Progress Percentage" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Title" + } + }, + "title": "SecurityObjectiveUpdate", + "type": "object" + }, + "SeedRequest": { + "properties": { + "force": { + "default": false, + "title": "Force", + "type": "boolean" + } + }, + "title": "SeedRequest", + "type": "object" + }, + "SeedResponse": { + "properties": { + "counts": { + "additionalProperties": { + "type": "integer" + }, + "title": "Counts", + "type": "object" + }, + "message": { + "title": "Message", + "type": "string" + }, + "success": { + "title": "Success", + "type": "boolean" + } + }, + "required": [ + "success", + "message", + "counts" + ], + "title": "SeedResponse", + "type": "object" + }, + "SendCommunication": { + "properties": { + "channel": { + "default": "email", + "title": "Channel", + "type": "string" + }, + "communication_type": { + "default": "outgoing", + "title": "Communication Type", + "type": "string" + }, + "content": { + "title": "Content", + "type": "string" + }, + "subject": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Subject" + }, + "template_used": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Template Used" + } + }, + "required": [ + "content" + ], + "title": "SendCommunication", + "type": "object" + }, + "SendTestRequest": { + "properties": { + "recipient": { + "title": "Recipient", + "type": "string" + }, + "variables": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Variables" + } + }, + "required": [ + "recipient" + ], + "title": "SendTestRequest", + "type": "object" + }, + "ServiceModuleDetailResponse": { + "description": "Detailed response including regulations and risks.", + "properties": { + "ai_components": { + "default": false, + "title": "Ai Components", + "type": "boolean" + }, + "compliance_score": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Compliance Score" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "criticality": { + "default": "medium", + "title": "Criticality", + "type": "string" + }, + "data_categories": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Data Categories" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "display_name": { + "title": "Display Name", + "type": "string" + }, + "docker_image": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Docker Image" + }, + "id": { + "title": "Id", + "type": "string" + }, + "is_active": { + "title": "Is Active", + "type": "boolean" + }, + "last_compliance_check": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Compliance Check" + }, + "name": { + "title": "Name", + "type": "string" + }, + "owner_contact": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Owner Contact" + }, + "owner_team": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Owner Team" + }, + "port": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Port" + }, + "processes_health_data": { + "default": false, + "title": "Processes Health Data", + "type": "boolean" + }, + "processes_pii": { + "default": false, + "title": "Processes Pii", + "type": "boolean" + }, + "regulation_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Regulation Count" + }, + "regulations": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Regulations" + }, + "repository_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Repository Path" + }, + "risk_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Risk Count" + }, + "risks": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Risks" + }, + "service_type": { + "title": "Service Type", + "type": "string" + }, + "technology_stack": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Technology Stack" + }, + "updated_at": { + "format": "date-time", + "title": "Updated At", + "type": "string" + } + }, + "required": [ + "name", + "display_name", + "service_type", + "id", + "is_active", + "created_at", + "updated_at" + ], + "title": "ServiceModuleDetailResponse", + "type": "object" + }, + "ServiceModuleListResponse": { + "description": "List response for service modules.", + "properties": { + "modules": { + "items": { + "$ref": "#/components/schemas/ServiceModuleResponse" + }, + "title": "Modules", + "type": "array" + }, + "total": { + "title": "Total", + "type": "integer" + } + }, + "required": [ + "modules", + "total" + ], + "title": "ServiceModuleListResponse", + "type": "object" + }, + "ServiceModuleResponse": { + "description": "Response schema for service module.", + "properties": { + "ai_components": { + "default": false, + "title": "Ai Components", + "type": "boolean" + }, + "compliance_score": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Compliance Score" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "criticality": { + "default": "medium", + "title": "Criticality", + "type": "string" + }, + "data_categories": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Data Categories" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "display_name": { + "title": "Display Name", + "type": "string" + }, + "docker_image": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Docker Image" + }, + "id": { + "title": "Id", + "type": "string" + }, + "is_active": { + "title": "Is Active", + "type": "boolean" + }, + "last_compliance_check": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Compliance Check" + }, + "name": { + "title": "Name", + "type": "string" + }, + "owner_contact": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Owner Contact" + }, + "owner_team": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Owner Team" + }, + "port": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Port" + }, + "processes_health_data": { + "default": false, + "title": "Processes Health Data", + "type": "boolean" + }, + "processes_pii": { + "default": false, + "title": "Processes Pii", + "type": "boolean" + }, + "regulation_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Regulation Count" + }, + "repository_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Repository Path" + }, + "risk_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Risk Count" + }, + "service_type": { + "title": "Service Type", + "type": "string" + }, + "technology_stack": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Technology Stack" + }, + "updated_at": { + "format": "date-time", + "title": "Updated At", + "type": "string" + } + }, + "required": [ + "name", + "display_name", + "service_type", + "id", + "is_active", + "created_at", + "updated_at" + ], + "title": "ServiceModuleResponse", + "type": "object" + }, + "SettingsUpdate": { + "properties": { + "company_address": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Company Address" + }, + "company_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Company Name" + }, + "footer_text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Footer Text" + }, + "logo_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Logo Url" + }, + "primary_color": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Primary Color" + }, + "reply_to": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Reply To" + }, + "secondary_color": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Secondary Color" + }, + "sender_email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Sender Email" + }, + "sender_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Sender Name" + } + }, + "title": "SettingsUpdate", + "type": "object" + }, + "SignOffRequest": { + "description": "Request to sign off a single requirement.", + "properties": { + "notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Notes" + }, + "result": { + "description": "Audit result: compliant, compliant_notes, non_compliant, not_applicable, pending", + "title": "Result", + "type": "string" + }, + "sign": { + "default": false, + "description": "Whether to create digital signature", + "title": "Sign", + "type": "boolean" + } + }, + "required": [ + "result" + ], + "title": "SignOffRequest", + "type": "object" + }, + "SignOffResponse": { + "description": "Response for a sign-off operation.", + "properties": { + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "id": { + "title": "Id", + "type": "string" + }, + "is_signed": { + "title": "Is Signed", + "type": "boolean" + }, + "notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Notes" + }, + "requirement_id": { + "title": "Requirement Id", + "type": "string" + }, + "result": { + "title": "Result", + "type": "string" + }, + "session_id": { + "title": "Session Id", + "type": "string" + }, + "signature_hash": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Signature Hash" + }, + "signed_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Signed At" + }, + "signed_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Signed By" + }, + "updated_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Updated At" + } + }, + "required": [ + "id", + "session_id", + "requirement_id", + "result", + "is_signed", + "created_at" + ], + "title": "SignOffResponse", + "type": "object" + }, + "SimilarityCheckRequest": { + "properties": { + "candidate_text": { + "title": "Candidate Text", + "type": "string" + }, + "source_text": { + "title": "Source Text", + "type": "string" + } + }, + "required": [ + "source_text", + "candidate_text" + ], + "title": "SimilarityCheckRequest", + "type": "object" + }, + "SiteConfigCreate": { + "properties": { + "banner_description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Banner Description" + }, + "banner_title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Banner Title" + }, + "dsb_email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Dsb Email" + }, + "dsb_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Dsb Name" + }, + "imprint_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Imprint Url" + }, + "privacy_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Privacy Url" + }, + "site_id": { + "title": "Site Id", + "type": "string" + }, + "site_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Site Name" + }, + "site_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Site Url" + }, + "tcf_enabled": { + "default": false, + "title": "Tcf Enabled", + "type": "boolean" + }, + "theme": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Theme" + } + }, + "required": [ + "site_id" + ], + "title": "SiteConfigCreate", + "type": "object" + }, + "SiteConfigUpdate": { + "properties": { + "banner_description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Banner Description" + }, + "banner_title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Banner Title" + }, + "dsb_email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Dsb Email" + }, + "dsb_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Dsb Name" + }, + "imprint_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Imprint Url" + }, + "is_active": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Is Active" + }, + "privacy_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Privacy Url" + }, + "site_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Site Name" + }, + "site_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Site Url" + }, + "tcf_enabled": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Tcf Enabled" + }, + "theme": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Theme" + } + }, + "title": "SiteConfigUpdate", + "type": "object" + }, + "SoAApproveRequest": { + "description": "Request to approve SoA entry.", + "properties": { + "approved_by": { + "title": "Approved By", + "type": "string" + }, + "reviewed_by": { + "title": "Reviewed By", + "type": "string" + } + }, + "required": [ + "reviewed_by", + "approved_by" + ], + "title": "SoAApproveRequest", + "type": "object" + }, + "SoAEntryCreate": { + "description": "Schema for creating SoA Entry.", + "properties": { + "annex_a_category": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Annex A Category" + }, + "annex_a_control": { + "title": "Annex A Control", + "type": "string" + }, + "annex_a_title": { + "title": "Annex A Title", + "type": "string" + }, + "applicability_justification": { + "title": "Applicability Justification", + "type": "string" + }, + "breakpilot_control_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Breakpilot Control Ids" + }, + "compensating_controls": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Compensating Controls" + }, + "coverage_level": { + "default": "full", + "title": "Coverage Level", + "type": "string" + }, + "evidence_description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Evidence Description" + }, + "implementation_notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Implementation Notes" + }, + "implementation_status": { + "default": "planned", + "title": "Implementation Status", + "type": "string" + }, + "is_applicable": { + "title": "Is Applicable", + "type": "boolean" + }, + "risk_assessment_notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Risk Assessment Notes" + } + }, + "required": [ + "annex_a_control", + "annex_a_title", + "is_applicable", + "applicability_justification" + ], + "title": "SoAEntryCreate", + "type": "object" + }, + "SoAEntryResponse": { + "description": "Response schema for SoA Entry.", + "properties": { + "annex_a_category": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Annex A Category" + }, + "annex_a_control": { + "title": "Annex A Control", + "type": "string" + }, + "annex_a_title": { + "title": "Annex A Title", + "type": "string" + }, + "applicability_justification": { + "title": "Applicability Justification", + "type": "string" + }, + "approved_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Approved At" + }, + "approved_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Approved By" + }, + "breakpilot_control_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Breakpilot Control Ids" + }, + "compensating_controls": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Compensating Controls" + }, + "coverage_level": { + "default": "full", + "title": "Coverage Level", + "type": "string" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "evidence_description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Evidence Description" + }, + "evidence_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Evidence Ids" + }, + "id": { + "title": "Id", + "type": "string" + }, + "implementation_notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Implementation Notes" + }, + "implementation_status": { + "default": "planned", + "title": "Implementation Status", + "type": "string" + }, + "is_applicable": { + "title": "Is Applicable", + "type": "boolean" + }, + "reviewed_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Reviewed At" + }, + "reviewed_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Reviewed By" + }, + "risk_assessment_notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Risk Assessment Notes" + }, + "updated_at": { + "format": "date-time", + "title": "Updated At", + "type": "string" + }, + "version": { + "title": "Version", + "type": "string" + } + }, + "required": [ + "annex_a_control", + "annex_a_title", + "is_applicable", + "applicability_justification", + "id", + "version", + "created_at", + "updated_at" + ], + "title": "SoAEntryResponse", + "type": "object" + }, + "SoAEntryUpdate": { + "description": "Schema for updating SoA Entry.", + "properties": { + "applicability_justification": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Applicability Justification" + }, + "breakpilot_control_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Breakpilot Control Ids" + }, + "coverage_level": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Coverage Level" + }, + "evidence_description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Evidence Description" + }, + "implementation_notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Implementation Notes" + }, + "implementation_status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Implementation Status" + }, + "is_applicable": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Is Applicable" + } + }, + "title": "SoAEntryUpdate", + "type": "object" + }, + "SoAListResponse": { + "description": "List response for SoA.", + "properties": { + "applicable_count": { + "title": "Applicable Count", + "type": "integer" + }, + "entries": { + "items": { + "$ref": "#/components/schemas/SoAEntryResponse" + }, + "title": "Entries", + "type": "array" + }, + "implemented_count": { + "title": "Implemented Count", + "type": "integer" + }, + "not_applicable_count": { + "title": "Not Applicable Count", + "type": "integer" + }, + "planned_count": { + "title": "Planned Count", + "type": "integer" + }, + "total": { + "title": "Total", + "type": "integer" + } + }, + "required": [ + "entries", + "total", + "applicable_count", + "not_applicable_count", + "implemented_count", + "planned_count" + ], + "title": "SoAListResponse", + "type": "object" + }, + "SourceCreate": { + "properties": { + "active": { + "default": true, + "title": "Active", + "type": "boolean" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "domain": { + "title": "Domain", + "type": "string" + }, + "legal_basis": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Legal Basis" + }, + "license": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "License" + }, + "metadata": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Metadata" + }, + "name": { + "title": "Name", + "type": "string" + }, + "source_type": { + "default": "legal", + "title": "Source Type", + "type": "string" + }, + "trust_boost": { + "default": 0.5, + "maximum": 1.0, + "minimum": 0.0, + "title": "Trust Boost", + "type": "number" + } + }, + "required": [ + "domain", + "name" + ], + "title": "SourceCreate", + "type": "object" + }, + "SourceUpdate": { + "properties": { + "active": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Active" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "domain": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Domain" + }, + "legal_basis": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Legal Basis" + }, + "license": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "License" + }, + "metadata": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Metadata" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Name" + }, + "source_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source Type" + }, + "trust_boost": { + "anyOf": [ + { + "maximum": 1.0, + "minimum": 0.0, + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Trust Boost" + } + }, + "title": "SourceUpdate", + "type": "object" + }, + "StatusChange": { + "properties": { + "comment": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Comment" + }, + "status": { + "title": "Status", + "type": "string" + } + }, + "required": [ + "status" + ], + "title": "StatusChange", + "type": "object" + }, + "TOMMeasureBulkBody": { + "properties": { + "measures": { + "items": { + "$ref": "#/components/schemas/TOMMeasureBulkItem" + }, + "title": "Measures", + "type": "array" + }, + "tenant_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + "required": [ + "measures" + ], + "title": "TOMMeasureBulkBody", + "type": "object" + }, + "TOMMeasureBulkItem": { + "properties": { + "applicability": { + "default": "REQUIRED", + "title": "Applicability", + "type": "string" + }, + "applicability_reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Applicability Reason" + }, + "category": { + "title": "Category", + "type": "string" + }, + "complexity": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Complexity" + }, + "control_id": { + "title": "Control Id", + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "evidence_gaps": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Evidence Gaps" + }, + "implementation_date": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Implementation Date" + }, + "implementation_status": { + "default": "NOT_IMPLEMENTED", + "title": "Implementation Status", + "type": "string" + }, + "linked_evidence": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Linked Evidence" + }, + "name": { + "title": "Name", + "type": "string" + }, + "priority": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Priority" + }, + "related_controls": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Related Controls" + }, + "responsible_department": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Responsible Department" + }, + "responsible_person": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Responsible Person" + }, + "review_date": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Review Date" + }, + "review_frequency": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Review Frequency" + }, + "type": { + "title": "Type", + "type": "string" + } + }, + "required": [ + "control_id", + "name", + "category", + "type" + ], + "title": "TOMMeasureBulkItem", + "type": "object" + }, + "TOMMeasureCreate": { + "properties": { + "applicability": { + "default": "REQUIRED", + "title": "Applicability", + "type": "string" + }, + "applicability_reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Applicability Reason" + }, + "category": { + "title": "Category", + "type": "string" + }, + "complexity": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Complexity" + }, + "control_id": { + "title": "Control Id", + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "effectiveness_rating": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Effectiveness Rating" + }, + "evidence_gaps": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Evidence Gaps" + }, + "implementation_date": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Implementation Date" + }, + "implementation_status": { + "default": "NOT_IMPLEMENTED", + "title": "Implementation Status", + "type": "string" + }, + "linked_evidence": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Linked Evidence" + }, + "name": { + "title": "Name", + "type": "string" + }, + "priority": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Priority" + }, + "related_controls": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Related Controls" + }, + "responsible_department": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Responsible Department" + }, + "responsible_person": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Responsible Person" + }, + "review_date": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Review Date" + }, + "review_frequency": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Review Frequency" + }, + "type": { + "title": "Type", + "type": "string" + }, + "verified_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Verified At" + }, + "verified_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Verified By" + } + }, + "required": [ + "control_id", + "name", + "category", + "type" + ], + "title": "TOMMeasureCreate", + "type": "object" + }, + "TOMMeasureUpdate": { + "properties": { + "applicability": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Applicability" + }, + "applicability_reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Applicability Reason" + }, + "category": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Category" + }, + "complexity": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Complexity" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "effectiveness_rating": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Effectiveness Rating" + }, + "evidence_gaps": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Evidence Gaps" + }, + "implementation_date": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Implementation Date" + }, + "implementation_status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Implementation Status" + }, + "linked_evidence": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Linked Evidence" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Name" + }, + "priority": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Priority" + }, + "related_controls": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Related Controls" + }, + "responsible_department": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Responsible Department" + }, + "responsible_person": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Responsible Person" + }, + "review_date": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Review Date" + }, + "review_frequency": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Review Frequency" + }, + "type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Type" + }, + "verified_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Verified At" + }, + "verified_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Verified By" + } + }, + "title": "TOMMeasureUpdate", + "type": "object" + }, + "TOMStateBody": { + "properties": { + "state": { + "additionalProperties": true, + "title": "State", + "type": "object" + }, + "tenantId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenantid" + }, + "tenant_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + }, + "version": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Version" + } + }, + "required": [ + "state" + ], + "title": "TOMStateBody", + "type": "object" + }, + "TeamWorkloadItem": { + "description": "Workload distribution for a team or person.", + "properties": { + "completed_tasks": { + "title": "Completed Tasks", + "type": "integer" + }, + "completion_rate": { + "title": "Completion Rate", + "type": "number" + }, + "in_progress_tasks": { + "title": "In Progress Tasks", + "type": "integer" + }, + "name": { + "title": "Name", + "type": "string" + }, + "pending_tasks": { + "title": "Pending Tasks", + "type": "integer" + }, + "total_tasks": { + "title": "Total Tasks", + "type": "integer" + } + }, + "required": [ + "name", + "pending_tasks", + "in_progress_tasks", + "completed_tasks", + "total_tasks", + "completion_rate" + ], + "title": "TeamWorkloadItem", + "type": "object" + }, + "TemplateUpdate": { + "properties": { + "content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Content" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Title" + }, + "type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Type" + } + }, + "title": "TemplateUpdate", + "type": "object" + }, + "TestCreate": { + "properties": { + "ai_system": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Ai System" + }, + "details": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Details" + }, + "duration": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Duration" + }, + "last_run": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Run" + }, + "name": { + "title": "Name", + "type": "string" + }, + "status": { + "default": "pending", + "title": "Status", + "type": "string" + } + }, + "required": [ + "name" + ], + "title": "TestCreate", + "type": "object" + }, + "TestUpdate": { + "properties": { + "ai_system": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Ai System" + }, + "details": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Details" + }, + "duration": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Duration" + }, + "last_run": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Run" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Name" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + "title": "TestUpdate", + "type": "object" + }, + "TimelineEntryRequest": { + "properties": { + "action": { + "title": "Action", + "type": "string" + }, + "details": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Details" + } + }, + "required": [ + "action" + ], + "title": "TimelineEntryRequest", + "type": "object" + }, + "TrendDataPoint": { + "description": "A single data point for trend charts.", + "properties": { + "date": { + "title": "Date", + "type": "string" + }, + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Label" + }, + "score": { + "title": "Score", + "type": "number" + } + }, + "required": [ + "date", + "score" + ], + "title": "TrendDataPoint", + "type": "object" + }, + "UpdateDocumentRequest": { + "properties": { + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "is_active": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Is Active" + }, + "is_mandatory": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Is Mandatory" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Name" + }, + "sort_order": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Sort Order" + } + }, + "title": "UpdateDocumentRequest", + "type": "object" + }, + "UpdateExceptionCheck": { + "properties": { + "applies": { + "title": "Applies", + "type": "boolean" + }, + "notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Notes" + } + }, + "required": [ + "applies" + ], + "title": "UpdateExceptionCheck", + "type": "object" + }, + "UpdateProjectRequest": { + "properties": { + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Name" + } + }, + "title": "UpdateProjectRequest", + "type": "object" + }, + "UpdateVersionRequest": { + "properties": { + "content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Content" + }, + "summary": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Summary" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Title" + } + }, + "title": "UpdateVersionRequest", + "type": "object" + }, + "UserConsentCreate": { + "properties": { + "consented": { + "default": true, + "title": "Consented", + "type": "boolean" + }, + "document_id": { + "title": "Document Id", + "type": "string" + }, + "document_type": { + "title": "Document Type", + "type": "string" + }, + "document_version_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Document Version Id" + }, + "ip_address": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Ip Address" + }, + "user_agent": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "User Agent" + }, + "user_id": { + "title": "User Id", + "type": "string" + } + }, + "required": [ + "user_id", + "document_id", + "document_type" + ], + "title": "UserConsentCreate", + "type": "object" + }, + "VVTActivityCreate": { + "properties": { + "business_function": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Business Function" + }, + "created_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Created By" + }, + "data_flows": { + "default": [], + "items": {}, + "title": "Data Flows", + "type": "array" + }, + "data_sources": { + "default": [], + "items": {}, + "title": "Data Sources", + "type": "array" + }, + "data_subject_categories": { + "default": [], + "items": { + "type": "string" + }, + "title": "Data Subject Categories", + "type": "array" + }, + "deployment_model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Deployment Model" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "dpia_required": { + "default": false, + "title": "Dpia Required", + "type": "boolean" + }, + "dsfa_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Dsfa Id" + }, + "last_reviewed_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Reviewed At" + }, + "legal_bases": { + "default": [], + "items": { + "type": "string" + }, + "title": "Legal Bases", + "type": "array" + }, + "name": { + "title": "Name", + "type": "string" + }, + "next_review_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Next Review At" + }, + "owner": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Owner" + }, + "personal_data_categories": { + "default": [], + "items": { + "type": "string" + }, + "title": "Personal Data Categories", + "type": "array" + }, + "protection_level": { + "default": "MEDIUM", + "title": "Protection Level", + "type": "string" + }, + "purposes": { + "default": [], + "items": { + "type": "string" + }, + "title": "Purposes", + "type": "array" + }, + "recipient_categories": { + "default": [], + "items": { + "type": "string" + }, + "title": "Recipient Categories", + "type": "array" + }, + "responsible": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Responsible" + }, + "retention_period": { + "additionalProperties": true, + "default": {}, + "title": "Retention Period", + "type": "object" + }, + "status": { + "default": "DRAFT", + "title": "Status", + "type": "string" + }, + "structured_toms": { + "additionalProperties": true, + "default": {}, + "title": "Structured Toms", + "type": "object" + }, + "systems": { + "default": [], + "items": { + "type": "string" + }, + "title": "Systems", + "type": "array" + }, + "third_country_transfers": { + "default": [], + "items": {}, + "title": "Third Country Transfers", + "type": "array" + }, + "tom_description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tom Description" + }, + "vvt_id": { + "title": "Vvt Id", + "type": "string" + } + }, + "required": [ + "vvt_id", + "name" + ], + "title": "VVTActivityCreate", + "type": "object" + }, + "VVTActivityResponse": { + "properties": { + "business_function": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Business Function" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "created_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Created By" + }, + "data_flows": { + "default": [], + "items": {}, + "title": "Data Flows", + "type": "array" + }, + "data_sources": { + "default": [], + "items": {}, + "title": "Data Sources", + "type": "array" + }, + "data_subject_categories": { + "default": [], + "items": {}, + "title": "Data Subject Categories", + "type": "array" + }, + "deployment_model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Deployment Model" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "dpia_required": { + "default": false, + "title": "Dpia Required", + "type": "boolean" + }, + "dsfa_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Dsfa Id" + }, + "id": { + "title": "Id", + "type": "string" + }, + "last_reviewed_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Reviewed At" + }, + "legal_bases": { + "default": [], + "items": {}, + "title": "Legal Bases", + "type": "array" + }, + "name": { + "title": "Name", + "type": "string" + }, + "next_review_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Next Review At" + }, + "owner": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Owner" + }, + "personal_data_categories": { + "default": [], + "items": {}, + "title": "Personal Data Categories", + "type": "array" + }, + "protection_level": { + "default": "MEDIUM", + "title": "Protection Level", + "type": "string" + }, + "purposes": { + "default": [], + "items": {}, + "title": "Purposes", + "type": "array" + }, + "recipient_categories": { + "default": [], + "items": {}, + "title": "Recipient Categories", + "type": "array" + }, + "responsible": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Responsible" + }, + "retention_period": { + "additionalProperties": true, + "default": {}, + "title": "Retention Period", + "type": "object" + }, + "status": { + "default": "DRAFT", + "title": "Status", + "type": "string" + }, + "structured_toms": { + "additionalProperties": true, + "default": {}, + "title": "Structured Toms", + "type": "object" + }, + "systems": { + "default": [], + "items": {}, + "title": "Systems", + "type": "array" + }, + "third_country_transfers": { + "default": [], + "items": {}, + "title": "Third Country Transfers", + "type": "array" + }, + "tom_description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tom Description" + }, + "updated_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Updated At" + }, + "vvt_id": { + "title": "Vvt Id", + "type": "string" + } + }, + "required": [ + "id", + "vvt_id", + "name", + "created_at" + ], + "title": "VVTActivityResponse", + "type": "object" + }, + "VVTActivityUpdate": { + "properties": { + "business_function": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Business Function" + }, + "created_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Created By" + }, + "data_flows": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Data Flows" + }, + "data_sources": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Data Sources" + }, + "data_subject_categories": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Data Subject Categories" + }, + "deployment_model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Deployment Model" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "dpia_required": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Dpia Required" + }, + "dsfa_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Dsfa Id" + }, + "last_reviewed_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Reviewed At" + }, + "legal_bases": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Legal Bases" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Name" + }, + "next_review_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Next Review At" + }, + "owner": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Owner" + }, + "personal_data_categories": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Personal Data Categories" + }, + "protection_level": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Protection Level" + }, + "purposes": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Purposes" + }, + "recipient_categories": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Recipient Categories" + }, + "responsible": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Responsible" + }, + "retention_period": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Retention Period" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + }, + "structured_toms": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Structured Toms" + }, + "systems": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Systems" + }, + "third_country_transfers": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Third Country Transfers" + }, + "tom_description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tom Description" + } + }, + "title": "VVTActivityUpdate", + "type": "object" + }, + "VVTAuditLogEntry": { + "properties": { + "action": { + "title": "Action", + "type": "string" + }, + "changed_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Changed By" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "entity_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Entity Id" + }, + "entity_type": { + "title": "Entity Type", + "type": "string" + }, + "id": { + "title": "Id", + "type": "string" + }, + "new_values": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "New Values" + }, + "old_values": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Old Values" + } + }, + "required": [ + "id", + "action", + "entity_type", + "created_at" + ], + "title": "VVTAuditLogEntry", + "type": "object" + }, + "VVTOrganizationResponse": { + "properties": { + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "dpo_contact": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Dpo Contact" + }, + "dpo_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Dpo Name" + }, + "employee_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Employee Count" + }, + "id": { + "title": "Id", + "type": "string" + }, + "industry": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Industry" + }, + "last_review_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Review Date" + }, + "locations": { + "default": [], + "items": {}, + "title": "Locations", + "type": "array" + }, + "next_review_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Next Review Date" + }, + "organization_name": { + "title": "Organization Name", + "type": "string" + }, + "review_interval": { + "default": "annual", + "title": "Review Interval", + "type": "string" + }, + "updated_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Updated At" + }, + "vvt_version": { + "default": "1.0", + "title": "Vvt Version", + "type": "string" + } + }, + "required": [ + "id", + "organization_name", + "created_at" + ], + "title": "VVTOrganizationResponse", + "type": "object" + }, + "VVTOrganizationUpdate": { + "properties": { + "dpo_contact": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Dpo Contact" + }, + "dpo_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Dpo Name" + }, + "employee_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Employee Count" + }, + "industry": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Industry" + }, + "last_review_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Review Date" + }, + "locations": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Locations" + }, + "next_review_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Next Review Date" + }, + "organization_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Organization Name" + }, + "review_interval": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Review Interval" + }, + "vvt_version": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Vvt Version" + } + }, + "title": "VVTOrganizationUpdate", + "type": "object" + }, + "VVTStatsResponse": { + "properties": { + "approved_count": { + "title": "Approved Count", + "type": "integer" + }, + "by_business_function": { + "additionalProperties": { + "type": "integer" + }, + "title": "By Business Function", + "type": "object" + }, + "by_status": { + "additionalProperties": { + "type": "integer" + }, + "title": "By Status", + "type": "object" + }, + "dpia_required_count": { + "title": "Dpia Required Count", + "type": "integer" + }, + "draft_count": { + "title": "Draft Count", + "type": "integer" + }, + "overdue_review_count": { + "default": 0, + "title": "Overdue Review Count", + "type": "integer" + }, + "third_country_count": { + "title": "Third Country Count", + "type": "integer" + }, + "total": { + "title": "Total", + "type": "integer" + } + }, + "required": [ + "total", + "by_status", + "by_business_function", + "dpia_required_count", + "third_country_count", + "draft_count", + "approved_count" + ], + "title": "VVTStatsResponse", + "type": "object" + }, + "ValidationError": { + "properties": { + "loc": { + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + }, + "title": "Location", + "type": "array" + }, + "msg": { + "title": "Message", + "type": "string" + }, + "type": { + "title": "Error Type", + "type": "string" + } + }, + "required": [ + "loc", + "msg", + "type" + ], + "title": "ValidationError", + "type": "object" + }, + "VendorConfigCreate": { + "properties": { + "category_key": { + "title": "Category Key", + "type": "string" + }, + "cookie_names": { + "default": [], + "items": { + "type": "string" + }, + "title": "Cookie Names", + "type": "array" + }, + "description_de": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description De" + }, + "description_en": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description En" + }, + "retention_days": { + "default": 365, + "title": "Retention Days", + "type": "integer" + }, + "vendor_name": { + "title": "Vendor Name", + "type": "string" + }, + "vendor_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Vendor Url" + } + }, + "required": [ + "vendor_name", + "category_key" + ], + "title": "VendorConfigCreate", + "type": "object" + }, + "VerifyIdentity": { + "properties": { + "document_ref": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Document Ref" + }, + "method": { + "title": "Method", + "type": "string" + }, + "notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Notes" + } + }, + "required": [ + "method" + ], + "title": "VerifyIdentity", + "type": "object" + }, + "VersionResponse": { + "properties": { + "approved_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Approved At" + }, + "approved_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Approved By" + }, + "content": { + "title": "Content", + "type": "string" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "created_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Created By" + }, + "document_id": { + "title": "Document Id", + "type": "string" + }, + "id": { + "title": "Id", + "type": "string" + }, + "language": { + "title": "Language", + "type": "string" + }, + "rejection_reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Rejection Reason" + }, + "status": { + "title": "Status", + "type": "string" + }, + "summary": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Summary" + }, + "title": { + "title": "Title", + "type": "string" + }, + "updated_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Updated At" + }, + "version": { + "title": "Version", + "type": "string" + } + }, + "required": [ + "id", + "document_id", + "version", + "language", + "title", + "content", + "summary", + "status", + "created_by", + "approved_by", + "approved_at", + "rejection_reason", + "created_at", + "updated_at" + ], + "title": "VersionResponse", + "type": "object" + }, + "compliance__api__banner_routes__ConsentCreate": { + "properties": { + "categories": { + "default": [], + "items": { + "type": "string" + }, + "title": "Categories", + "type": "array" + }, + "consent_string": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Consent String" + }, + "device_fingerprint": { + "title": "Device Fingerprint", + "type": "string" + }, + "ip_address": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Ip Address" + }, + "site_id": { + "title": "Site Id", + "type": "string" + }, + "user_agent": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "User Agent" + }, + "vendors": { + "default": [], + "items": { + "type": "string" + }, + "title": "Vendors", + "type": "array" + } + }, + "required": [ + "site_id", + "device_fingerprint" + ], + "title": "ConsentCreate", + "type": "object" + }, + "compliance__api__einwilligungen_routes__ConsentCreate": { + "properties": { + "consent_version": { + "default": "1.0", + "title": "Consent Version", + "type": "string" + }, + "data_point_id": { + "title": "Data Point Id", + "type": "string" + }, + "granted": { + "title": "Granted", + "type": "boolean" + }, + "ip_address": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Ip Address" + }, + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source" + }, + "user_agent": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "User Agent" + }, + "user_id": { + "title": "User Id", + "type": "string" + } + }, + "required": [ + "user_id", + "data_point_id", + "granted" + ], + "title": "ConsentCreate", + "type": "object" + }, + "compliance__api__email_template_routes__TemplateCreate": { + "properties": { + "category": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Category" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "is_active": { + "default": true, + "title": "Is Active", + "type": "boolean" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Name" + }, + "template_type": { + "title": "Template Type", + "type": "string" + } + }, + "required": [ + "template_type" + ], + "title": "TemplateCreate", + "type": "object" + }, + "compliance__api__email_template_routes__VersionCreate": { + "properties": { + "body_html": { + "title": "Body Html", + "type": "string" + }, + "body_text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Body Text" + }, + "language": { + "default": "de", + "title": "Language", + "type": "string" + }, + "subject": { + "title": "Subject", + "type": "string" + }, + "version": { + "default": "1.0", + "title": "Version", + "type": "string" + } + }, + "required": [ + "subject", + "body_html" + ], + "title": "VersionCreate", + "type": "object" + }, + "compliance__api__email_template_routes__VersionUpdate": { + "properties": { + "body_html": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Body Html" + }, + "body_text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Body Text" + }, + "subject": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Subject" + } + }, + "title": "VersionUpdate", + "type": "object" + }, + "compliance__api__incident_routes__IncidentCreate": { + "properties": { + "affected_data_categories": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Affected Data Categories" + }, + "affected_data_subject_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": 0, + "title": "Affected Data Subject Count" + }, + "affected_systems": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Affected Systems" + }, + "category": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": "data_breach", + "title": "Category" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "detected_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Detected At" + }, + "severity": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": "medium", + "title": "Severity" + }, + "title": { + "title": "Title", + "type": "string" + } + }, + "required": [ + "title" + ], + "title": "IncidentCreate", + "type": "object" + }, + "compliance__api__incident_routes__IncidentUpdate": { + "properties": { + "affected_data_categories": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Affected Data Categories" + }, + "affected_data_subject_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Affected Data Subject Count" + }, + "affected_systems": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Affected Systems" + }, + "category": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Category" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "severity": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Severity" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Title" + } + }, + "title": "IncidentUpdate", + "type": "object" + }, + "compliance__api__incident_routes__StatusUpdate": { + "properties": { + "status": { + "title": "Status", + "type": "string" + } + }, + "required": [ + "status" + ], + "title": "StatusUpdate", + "type": "object" + }, + "compliance__api__legal_document_routes__VersionCreate": { + "properties": { + "content": { + "title": "Content", + "type": "string" + }, + "created_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Created By" + }, + "document_id": { + "title": "Document Id", + "type": "string" + }, + "language": { + "default": "de", + "title": "Language", + "type": "string" + }, + "summary": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Summary" + }, + "title": { + "title": "Title", + "type": "string" + }, + "version": { + "title": "Version", + "type": "string" + } + }, + "required": [ + "document_id", + "version", + "title", + "content" + ], + "title": "VersionCreate", + "type": "object" + }, + "compliance__api__legal_document_routes__VersionUpdate": { + "properties": { + "content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Content" + }, + "language": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Language" + }, + "summary": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Summary" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Title" + }, + "version": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Version" + } + }, + "title": "VersionUpdate", + "type": "object" + }, + "compliance__api__notfallplan_routes__IncidentCreate": { + "properties": { + "affected_data_categories": { + "default": [], + "items": {}, + "title": "Affected Data Categories", + "type": "array" + }, + "art34_justification": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Art34 Justification" + }, + "art34_required": { + "default": false, + "title": "Art34 Required", + "type": "boolean" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "detected_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Detected By" + }, + "estimated_affected_persons": { + "default": 0, + "title": "Estimated Affected Persons", + "type": "integer" + }, + "measures": { + "default": [], + "items": {}, + "title": "Measures", + "type": "array" + }, + "severity": { + "default": "medium", + "title": "Severity", + "type": "string" + }, + "status": { + "default": "detected", + "title": "Status", + "type": "string" + }, + "title": { + "title": "Title", + "type": "string" + } + }, + "required": [ + "title" + ], + "title": "IncidentCreate", + "type": "object" + }, + "compliance__api__notfallplan_routes__IncidentUpdate": { + "properties": { + "affected_data_categories": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Affected Data Categories" + }, + "art34_justification": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Art34 Justification" + }, + "art34_required": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Art34 Required" + }, + "closed_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Closed At" + }, + "closed_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Closed By" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "detected_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Detected By" + }, + "estimated_affected_persons": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Estimated Affected Persons" + }, + "lessons_learned": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Lessons Learned" + }, + "measures": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Measures" + }, + "notified_affected_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Notified Affected At" + }, + "reported_to_authority_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Reported To Authority At" + }, + "severity": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Severity" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Title" + } + }, + "title": "IncidentUpdate", + "type": "object" + }, + "compliance__api__notfallplan_routes__TemplateCreate": { + "properties": { + "content": { + "title": "Content", + "type": "string" + }, + "title": { + "title": "Title", + "type": "string" + }, + "type": { + "default": "art33", + "title": "Type", + "type": "string" + } + }, + "required": [ + "title", + "content" + ], + "title": "TemplateCreate", + "type": "object" + } + } + }, + "info": { + "description": "GDPR/DSGVO Compliance, Consent Management, Data Subject Requests, and Regulatory Compliance Framework", + "title": "BreakPilot Compliance Backend", + "version": "1.0.0" + }, + "openapi": "3.1.0", + "paths": { + "/api/compliance/ai/systems": { + "get": { + "description": "List all registered AI systems.", + "operationId": "list_ai_systems_api_compliance_ai_systems_get", + "parameters": [ + { + "description": "Filter by classification", + "in": "query", + "name": "classification", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter by classification", + "title": "Classification" + } + }, + { + "description": "Filter by status", + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter by status", + "title": "Status" + } + }, + { + "description": "Filter by sector", + "in": "query", + "name": "sector", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter by sector", + "title": "Sector" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AISystemListResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Ai Systems", + "tags": [ + "compliance", + "compliance-ai" + ] + }, + "post": { + "description": "Register a new AI system.", + "operationId": "create_ai_system_api_compliance_ai_systems_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AISystemCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AISystemResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Ai System", + "tags": [ + "compliance", + "compliance-ai" + ] + } + }, + "/api/compliance/ai/systems/{system_id}": { + "delete": { + "description": "Delete an AI system.", + "operationId": "delete_ai_system_api_compliance_ai_systems__system_id__delete", + "parameters": [ + { + "in": "path", + "name": "system_id", + "required": true, + "schema": { + "title": "System Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Ai System", + "tags": [ + "compliance", + "compliance-ai" + ] + }, + "get": { + "description": "Get a specific AI system by ID.", + "operationId": "get_ai_system_api_compliance_ai_systems__system_id__get", + "parameters": [ + { + "in": "path", + "name": "system_id", + "required": true, + "schema": { + "title": "System Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AISystemResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Ai System", + "tags": [ + "compliance", + "compliance-ai" + ] + }, + "put": { + "description": "Update an AI system.", + "operationId": "update_ai_system_api_compliance_ai_systems__system_id__put", + "parameters": [ + { + "in": "path", + "name": "system_id", + "required": true, + "schema": { + "title": "System Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AISystemUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AISystemResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Ai System", + "tags": [ + "compliance", + "compliance-ai" + ] + } + }, + "/api/compliance/ai/systems/{system_id}/assess": { + "post": { + "description": "Run AI Act risk assessment for an AI system.", + "operationId": "assess_ai_system_api_compliance_ai_systems__system_id__assess_post", + "parameters": [ + { + "in": "path", + "name": "system_id", + "required": true, + "schema": { + "title": "System Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AISystemResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Assess Ai System", + "tags": [ + "compliance", + "compliance-ai" + ] + } + }, + "/api/compliance/audit/checklist/{session_id}": { + "get": { + "description": "Get the audit checklist for a session with pagination.\n\nReturns requirements with their current sign-off status.", + "operationId": "get_audit_checklist_api_compliance_audit_checklist__session_id__get", + "parameters": [ + { + "in": "path", + "name": "session_id", + "required": true, + "schema": { + "title": "Session Id", + "type": "string" + } + }, + { + "in": "query", + "name": "page", + "required": false, + "schema": { + "default": 1, + "minimum": 1, + "title": "Page", + "type": "integer" + } + }, + { + "in": "query", + "name": "page_size", + "required": false, + "schema": { + "default": 50, + "maximum": 200, + "minimum": 1, + "title": "Page Size", + "type": "integer" + } + }, + { + "in": "query", + "name": "status_filter", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status Filter" + } + }, + { + "in": "query", + "name": "regulation_filter", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Regulation Filter" + } + }, + { + "in": "query", + "name": "search", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Search" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuditChecklistResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Audit Checklist", + "tags": [ + "compliance", + "compliance-audit" + ] + } + }, + "/api/compliance/audit/checklist/{session_id}/items/{requirement_id}": { + "get": { + "description": "Get the current sign-off status for a specific requirement.", + "operationId": "get_sign_off_api_compliance_audit_checklist__session_id__items__requirement_id__get", + "parameters": [ + { + "in": "path", + "name": "session_id", + "required": true, + "schema": { + "title": "Session Id", + "type": "string" + } + }, + { + "in": "path", + "name": "requirement_id", + "required": true, + "schema": { + "title": "Requirement Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SignOffResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Sign Off", + "tags": [ + "compliance", + "compliance-audit" + ] + } + }, + "/api/compliance/audit/checklist/{session_id}/items/{requirement_id}/sign-off": { + "put": { + "description": "Sign off on a specific requirement in an audit session.\n\nIf sign=True, creates a digital signature (SHA-256 hash).", + "operationId": "sign_off_item_api_compliance_audit_checklist__session_id__items__requirement_id__sign_off_put", + "parameters": [ + { + "in": "path", + "name": "session_id", + "required": true, + "schema": { + "title": "Session Id", + "type": "string" + } + }, + { + "in": "path", + "name": "requirement_id", + "required": true, + "schema": { + "title": "Requirement Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SignOffRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SignOffResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Sign Off Item", + "tags": [ + "compliance", + "compliance-audit" + ] + } + }, + "/api/compliance/audit/sessions": { + "get": { + "description": "List all audit sessions, optionally filtered by status.", + "operationId": "list_audit_sessions_api_compliance_audit_sessions_get", + "parameters": [ + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "items": { + "$ref": "#/components/schemas/AuditSessionSummary" + }, + "title": "Response List Audit Sessions Api Compliance Audit Sessions Get", + "type": "array" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Audit Sessions", + "tags": [ + "compliance", + "compliance-audit" + ] + }, + "post": { + "description": "Create a new audit session for structured compliance reviews.\n\nAn audit session groups requirements for systematic review by an auditor.", + "operationId": "create_audit_session_api_compliance_audit_sessions_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateAuditSessionRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuditSessionResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Audit Session", + "tags": [ + "compliance", + "compliance-audit" + ] + } + }, + "/api/compliance/audit/sessions/{session_id}": { + "delete": { + "description": "Delete an audit session and all its sign-offs.\n\nOnly draft sessions can be deleted.", + "operationId": "delete_audit_session_api_compliance_audit_sessions__session_id__delete", + "parameters": [ + { + "in": "path", + "name": "session_id", + "required": true, + "schema": { + "title": "Session Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Audit Session", + "tags": [ + "compliance", + "compliance-audit" + ] + }, + "get": { + "description": "Get detailed information about a specific audit session.", + "operationId": "get_audit_session_api_compliance_audit_sessions__session_id__get", + "parameters": [ + { + "in": "path", + "name": "session_id", + "required": true, + "schema": { + "title": "Session Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuditSessionDetailResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Audit Session", + "tags": [ + "compliance", + "compliance-audit" + ] + } + }, + "/api/compliance/audit/sessions/{session_id}/archive": { + "put": { + "description": "Archive a completed audit session.", + "operationId": "archive_audit_session_api_compliance_audit_sessions__session_id__archive_put", + "parameters": [ + { + "in": "path", + "name": "session_id", + "required": true, + "schema": { + "title": "Session Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Archive Audit Session", + "tags": [ + "compliance", + "compliance-audit" + ] + } + }, + "/api/compliance/audit/sessions/{session_id}/complete": { + "put": { + "description": "Complete an audit session (change status from in_progress to completed).", + "operationId": "complete_audit_session_api_compliance_audit_sessions__session_id__complete_put", + "parameters": [ + { + "in": "path", + "name": "session_id", + "required": true, + "schema": { + "title": "Session Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Complete Audit Session", + "tags": [ + "compliance", + "compliance-audit" + ] + } + }, + "/api/compliance/audit/sessions/{session_id}/report/pdf": { + "get": { + "description": "Generate a PDF report for an audit session.\n\nParameters:\n- session_id: The audit session ID\n- language: Output language ('de' or 'en'), default 'de'\n- include_signatures: Include digital signature verification section\n\nReturns:\n- PDF file as streaming response", + "operationId": "generate_audit_pdf_report_api_compliance_audit_sessions__session_id__report_pdf_get", + "parameters": [ + { + "in": "path", + "name": "session_id", + "required": true, + "schema": { + "title": "Session Id", + "type": "string" + } + }, + { + "in": "query", + "name": "language", + "required": false, + "schema": { + "default": "de", + "pattern": "^(de|en)$", + "title": "Language", + "type": "string" + } + }, + { + "in": "query", + "name": "include_signatures", + "required": false, + "schema": { + "default": true, + "title": "Include Signatures", + "type": "boolean" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Generate Audit Pdf Report", + "tags": [ + "compliance", + "compliance-audit" + ] + } + }, + "/api/compliance/audit/sessions/{session_id}/start": { + "put": { + "description": "Start an audit session (change status from draft to in_progress).", + "operationId": "start_audit_session_api_compliance_audit_sessions__session_id__start_put", + "parameters": [ + { + "in": "path", + "name": "session_id", + "required": true, + "schema": { + "title": "Session Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Start Audit Session", + "tags": [ + "compliance", + "compliance-audit" + ] + } + }, + "/api/compliance/banner/admin/categories/{category_id}": { + "delete": { + "description": "Delete a category.", + "operationId": "delete_category_api_compliance_banner_admin_categories__category_id__delete", + "parameters": [ + { + "in": "path", + "name": "category_id", + "required": true, + "schema": { + "title": "Category Id", + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Category", + "tags": [ + "compliance", + "compliance-banner" + ] + } + }, + "/api/compliance/banner/admin/sites": { + "get": { + "description": "List all site configurations.", + "operationId": "list_site_configs_api_compliance_banner_admin_sites_get", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Site Configs", + "tags": [ + "compliance", + "compliance-banner" + ] + }, + "post": { + "description": "Create a site configuration.", + "operationId": "create_site_config_api_compliance_banner_admin_sites_post", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SiteConfigCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Site Config", + "tags": [ + "compliance", + "compliance-banner" + ] + } + }, + "/api/compliance/banner/admin/sites/{site_id}": { + "delete": { + "description": "Delete a site configuration.", + "operationId": "delete_site_config_api_compliance_banner_admin_sites__site_id__delete", + "parameters": [ + { + "in": "path", + "name": "site_id", + "required": true, + "schema": { + "title": "Site Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "204": { + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Site Config", + "tags": [ + "compliance", + "compliance-banner" + ] + }, + "put": { + "description": "Update a site configuration.", + "operationId": "update_site_config_api_compliance_banner_admin_sites__site_id__put", + "parameters": [ + { + "in": "path", + "name": "site_id", + "required": true, + "schema": { + "title": "Site Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SiteConfigUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Site Config", + "tags": [ + "compliance", + "compliance-banner" + ] + } + }, + "/api/compliance/banner/admin/sites/{site_id}/categories": { + "get": { + "description": "List categories for a site.", + "operationId": "list_categories_api_compliance_banner_admin_sites__site_id__categories_get", + "parameters": [ + { + "in": "path", + "name": "site_id", + "required": true, + "schema": { + "title": "Site Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Categories", + "tags": [ + "compliance", + "compliance-banner" + ] + }, + "post": { + "description": "Create a category for a site.", + "operationId": "create_category_api_compliance_banner_admin_sites__site_id__categories_post", + "parameters": [ + { + "in": "path", + "name": "site_id", + "required": true, + "schema": { + "title": "Site Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CategoryConfigCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Category", + "tags": [ + "compliance", + "compliance-banner" + ] + } + }, + "/api/compliance/banner/admin/sites/{site_id}/vendors": { + "get": { + "description": "List vendors for a site.", + "operationId": "list_vendors_api_compliance_banner_admin_sites__site_id__vendors_get", + "parameters": [ + { + "in": "path", + "name": "site_id", + "required": true, + "schema": { + "title": "Site Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Vendors", + "tags": [ + "compliance", + "compliance-banner" + ] + }, + "post": { + "description": "Create a vendor for a site.", + "operationId": "create_vendor_api_compliance_banner_admin_sites__site_id__vendors_post", + "parameters": [ + { + "in": "path", + "name": "site_id", + "required": true, + "schema": { + "title": "Site Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VendorConfigCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Vendor", + "tags": [ + "compliance", + "compliance-banner" + ] + } + }, + "/api/compliance/banner/admin/stats/{site_id}": { + "get": { + "description": "Consent statistics per site.", + "operationId": "get_site_stats_api_compliance_banner_admin_stats__site_id__get", + "parameters": [ + { + "in": "path", + "name": "site_id", + "required": true, + "schema": { + "title": "Site Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Site Stats", + "tags": [ + "compliance", + "compliance-banner" + ] + } + }, + "/api/compliance/banner/admin/vendors/{vendor_id}": { + "delete": { + "description": "Delete a vendor.", + "operationId": "delete_vendor_api_compliance_banner_admin_vendors__vendor_id__delete", + "parameters": [ + { + "in": "path", + "name": "vendor_id", + "required": true, + "schema": { + "title": "Vendor Id", + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Vendor", + "tags": [ + "compliance", + "compliance-banner" + ] + } + }, + "/api/compliance/banner/config/{site_id}": { + "get": { + "description": "Load site configuration for banner display.", + "operationId": "get_site_config_api_compliance_banner_config__site_id__get", + "parameters": [ + { + "in": "path", + "name": "site_id", + "required": true, + "schema": { + "title": "Site Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Site Config", + "tags": [ + "compliance", + "compliance-banner" + ] + } + }, + "/api/compliance/banner/consent": { + "get": { + "description": "Retrieve consent for a device.", + "operationId": "get_consent_api_compliance_banner_consent_get", + "parameters": [ + { + "in": "query", + "name": "site_id", + "required": true, + "schema": { + "title": "Site Id", + "type": "string" + } + }, + { + "in": "query", + "name": "device_fingerprint", + "required": true, + "schema": { + "title": "Device Fingerprint", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Consent", + "tags": [ + "compliance", + "compliance-banner" + ] + }, + "post": { + "description": "Record device consent (upsert by site_id + device_fingerprint).", + "operationId": "record_consent_api_compliance_banner_consent_post", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/compliance__api__banner_routes__ConsentCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Record Consent", + "tags": [ + "compliance", + "compliance-banner" + ] + } + }, + "/api/compliance/banner/consent/export": { + "get": { + "description": "DSGVO export of all consent data for a device.", + "operationId": "export_consent_api_compliance_banner_consent_export_get", + "parameters": [ + { + "in": "query", + "name": "site_id", + "required": true, + "schema": { + "title": "Site Id", + "type": "string" + } + }, + { + "in": "query", + "name": "device_fingerprint", + "required": true, + "schema": { + "title": "Device Fingerprint", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Export Consent", + "tags": [ + "compliance", + "compliance-banner" + ] + } + }, + "/api/compliance/banner/consent/{consent_id}": { + "delete": { + "description": "Withdraw a banner consent.", + "operationId": "withdraw_consent_api_compliance_banner_consent__consent_id__delete", + "parameters": [ + { + "in": "path", + "name": "consent_id", + "required": true, + "schema": { + "title": "Consent Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Withdraw Consent", + "tags": [ + "compliance", + "compliance-banner" + ] + } + }, + "/api/compliance/change-requests": { + "get": { + "description": "List change requests with optional filters.", + "operationId": "list_change_requests_api_compliance_change_requests_get", + "parameters": [ + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "in": "query", + "name": "target_document_type", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Target Document Type" + } + }, + { + "in": "query", + "name": "priority", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Priority" + } + }, + { + "in": "query", + "name": "skip", + "required": false, + "schema": { + "default": 0, + "minimum": 0, + "title": "Skip", + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 100, + "maximum": 500, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Change Requests", + "tags": [ + "compliance", + "change-requests" + ] + }, + "post": { + "description": "Create a change request manually.", + "operationId": "create_change_request_api_compliance_change_requests_post", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-User-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-User-Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChangeRequestCreate" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Change Request", + "tags": [ + "compliance", + "change-requests" + ] + } + }, + "/api/compliance/change-requests/stats": { + "get": { + "description": "Summary counts for change requests.", + "operationId": "get_stats_api_compliance_change_requests_stats_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Stats", + "tags": [ + "compliance", + "change-requests" + ] + } + }, + "/api/compliance/change-requests/{cr_id}": { + "delete": { + "description": "Soft-delete a change request.", + "operationId": "delete_change_request_api_compliance_change_requests__cr_id__delete", + "parameters": [ + { + "in": "path", + "name": "cr_id", + "required": true, + "schema": { + "title": "Cr Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-User-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-User-Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Change Request", + "tags": [ + "compliance", + "change-requests" + ] + }, + "get": { + "description": "Get change request detail with audit log.", + "operationId": "get_change_request_api_compliance_change_requests__cr_id__get", + "parameters": [ + { + "in": "path", + "name": "cr_id", + "required": true, + "schema": { + "title": "Cr Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Change Request", + "tags": [ + "compliance", + "change-requests" + ] + } + }, + "/api/compliance/change-requests/{cr_id}/accept": { + "post": { + "description": "Accept a change request \u2192 creates a new document version.", + "operationId": "accept_change_request_api_compliance_change_requests__cr_id__accept_post", + "parameters": [ + { + "in": "path", + "name": "cr_id", + "required": true, + "schema": { + "title": "Cr Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-User-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-User-Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Accept Change Request", + "tags": [ + "compliance", + "change-requests" + ] + } + }, + "/api/compliance/change-requests/{cr_id}/edit": { + "post": { + "description": "Edit the proposal, then auto-accept.", + "operationId": "edit_change_request_api_compliance_change_requests__cr_id__edit_post", + "parameters": [ + { + "in": "path", + "name": "cr_id", + "required": true, + "schema": { + "title": "Cr Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-User-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-User-Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChangeRequestEdit" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Edit Change Request", + "tags": [ + "compliance", + "change-requests" + ] + } + }, + "/api/compliance/change-requests/{cr_id}/reject": { + "post": { + "description": "Reject a change request with reason.", + "operationId": "reject_change_request_api_compliance_change_requests__cr_id__reject_post", + "parameters": [ + { + "in": "path", + "name": "cr_id", + "required": true, + "schema": { + "title": "Cr Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-User-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-User-Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChangeRequestReject" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Reject Change Request", + "tags": [ + "compliance", + "change-requests" + ] + } + }, + "/api/compliance/compliance/extract-requirements-from-rag": { + "post": { + "description": "Search all RAG collections for Pr\u00fcfaspekte / audit criteria and create\nRequirement entries in the compliance DB.\n\n- Deduplicates by (regulation_code, article) \u2014 safe to call multiple times.\n- Auto-creates Regulation stubs for previously unknown regulation_codes.\n- Use `dry_run=true` to preview results without any DB writes.\n- Use `regulation_codes` to restrict to specific regulations (e.g. [\"BSI-TR-03161-1\"]).", + "operationId": "extract_requirements_from_rag_api_compliance_compliance_extract_requirements_from_rag_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExtractionRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExtractionResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Extract Requirements From Rag", + "tags": [ + "compliance", + "extraction" + ] + } + }, + "/api/compliance/consent-templates": { + "get": { + "description": "List all email templates for a tenant.", + "operationId": "list_consent_templates_api_compliance_consent_templates_get", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Consent Templates", + "tags": [ + "compliance", + "consent-templates" + ] + }, + "post": { + "description": "Create a new email template.", + "operationId": "create_consent_template_api_compliance_consent_templates_post", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConsentTemplateCreate" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Consent Template", + "tags": [ + "compliance", + "consent-templates" + ] + } + }, + "/api/compliance/consent-templates/{template_id}": { + "delete": { + "description": "Delete an email template.", + "operationId": "delete_consent_template_api_compliance_consent_templates__template_id__delete", + "parameters": [ + { + "in": "path", + "name": "template_id", + "required": true, + "schema": { + "title": "Template Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Consent Template", + "tags": [ + "compliance", + "consent-templates" + ] + }, + "put": { + "description": "Update an existing email template.", + "operationId": "update_consent_template_api_compliance_consent_templates__template_id__put", + "parameters": [ + { + "in": "path", + "name": "template_id", + "required": true, + "schema": { + "title": "Template Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConsentTemplateUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Consent Template", + "tags": [ + "compliance", + "consent-templates" + ] + } + }, + "/api/compliance/controls": { + "get": { + "description": "List all controls with optional filters.", + "operationId": "list_controls_api_compliance_controls_get", + "parameters": [ + { + "in": "query", + "name": "domain", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Domain" + } + }, + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "in": "query", + "name": "is_automated", + "required": false, + "schema": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Is Automated" + } + }, + { + "in": "query", + "name": "search", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Search" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ControlListResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Controls", + "tags": [ + "compliance" + ] + } + }, + "/api/compliance/controls/by-domain/{domain}": { + "get": { + "description": "Get controls by domain.", + "operationId": "get_controls_by_domain_api_compliance_controls_by_domain__domain__get", + "parameters": [ + { + "in": "path", + "name": "domain", + "required": true, + "schema": { + "title": "Domain", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ControlListResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Controls By Domain", + "tags": [ + "compliance" + ] + } + }, + "/api/compliance/controls/paginated": { + "get": { + "description": "List controls with pagination and eager-loaded relationships.\n\nThis endpoint is optimized for large datasets with:\n- Eager loading to prevent N+1 queries\n- Server-side pagination\n- Full-text search support", + "operationId": "list_controls_paginated_api_compliance_controls_paginated_get", + "parameters": [ + { + "description": "Page number", + "in": "query", + "name": "page", + "required": false, + "schema": { + "default": 1, + "description": "Page number", + "minimum": 1, + "title": "Page", + "type": "integer" + } + }, + { + "description": "Items per page", + "in": "query", + "name": "page_size", + "required": false, + "schema": { + "default": 50, + "description": "Items per page", + "maximum": 500, + "minimum": 1, + "title": "Page Size", + "type": "integer" + } + }, + { + "description": "Filter by domain", + "in": "query", + "name": "domain", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter by domain", + "title": "Domain" + } + }, + { + "description": "Filter by status", + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter by status", + "title": "Status" + } + }, + { + "description": "Filter by automation", + "in": "query", + "name": "is_automated", + "required": false, + "schema": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Filter by automation", + "title": "Is Automated" + } + }, + { + "description": "Search in title/description", + "in": "query", + "name": "search", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Search in title/description", + "title": "Search" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaginatedControlResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Controls Paginated", + "tags": [ + "compliance" + ] + } + }, + "/api/compliance/controls/{control_id}": { + "get": { + "description": "Get a specific control by control_id.", + "operationId": "get_control_api_compliance_controls__control_id__get", + "parameters": [ + { + "in": "path", + "name": "control_id", + "required": true, + "schema": { + "title": "Control Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ControlResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Control", + "tags": [ + "compliance" + ] + }, + "put": { + "description": "Update a control.", + "operationId": "update_control_api_compliance_controls__control_id__put", + "parameters": [ + { + "in": "path", + "name": "control_id", + "required": true, + "schema": { + "title": "Control Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ControlUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ControlResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Control", + "tags": [ + "compliance" + ] + } + }, + "/api/compliance/controls/{control_id}/review": { + "put": { + "description": "Mark a control as reviewed with new status.", + "operationId": "review_control_api_compliance_controls__control_id__review_put", + "parameters": [ + { + "in": "path", + "name": "control_id", + "required": true, + "schema": { + "title": "Control Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ControlReviewRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ControlResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Review Control", + "tags": [ + "compliance" + ] + } + }, + "/api/compliance/create-indexes": { + "post": { + "description": "Create additional performance indexes for large datasets.\n\nThese indexes are optimized for:\n- Pagination queries (1000+ requirements)\n- Full-text search\n- Filtering by status/priority", + "operationId": "create_performance_indexes_api_compliance_create_indexes_post", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "Create Performance Indexes", + "tags": [ + "compliance" + ] + } + }, + "/api/compliance/dashboard": { + "get": { + "description": "Get compliance dashboard statistics.", + "operationId": "get_dashboard_api_compliance_dashboard_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DashboardResponse" + } + } + }, + "description": "Successful Response" + } + }, + "summary": "Get Dashboard", + "tags": [ + "compliance", + "compliance-dashboard" + ] + } + }, + "/api/compliance/dashboard/executive": { + "get": { + "description": "Get executive dashboard for managers and decision makers.\n\nProvides:\n- Traffic light status (green/yellow/red)\n- Overall compliance score with trend\n- Top 5 open risks\n- Upcoming deadlines (control reviews, evidence expiry)\n- Team workload distribution", + "operationId": "get_executive_dashboard_api_compliance_dashboard_executive_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExecutiveDashboardResponse" + } + } + }, + "description": "Successful Response" + } + }, + "summary": "Get Executive Dashboard", + "tags": [ + "compliance", + "compliance-dashboard" + ] + } + }, + "/api/compliance/dashboard/trend": { + "get": { + "description": "Get compliance score trend over time.\n\nReturns monthly compliance scores for trend visualization.", + "operationId": "get_compliance_trend_api_compliance_dashboard_trend_get", + "parameters": [ + { + "description": "Number of months to include", + "in": "query", + "name": "months", + "required": false, + "schema": { + "default": 12, + "description": "Number of months to include", + "maximum": 24, + "minimum": 1, + "title": "Months", + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Compliance Trend", + "tags": [ + "compliance", + "compliance-dashboard" + ] + } + }, + "/api/compliance/dsfa": { + "get": { + "description": "Liste aller DSFAs f\u00fcr einen Tenant.", + "operationId": "list_dsfas_api_compliance_dsfa_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "in": "query", + "name": "risk_level", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Risk Level" + } + }, + { + "in": "query", + "name": "skip", + "required": false, + "schema": { + "default": 0, + "minimum": 0, + "title": "Skip", + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 100, + "maximum": 500, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Dsfas", + "tags": [ + "compliance", + "compliance-dsfa" + ] + }, + "post": { + "description": "Neue DSFA erstellen.", + "operationId": "create_dsfa_api_compliance_dsfa_post", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DSFACreate" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Dsfa", + "tags": [ + "compliance", + "compliance-dsfa" + ] + } + }, + "/api/compliance/dsfa/audit-log": { + "get": { + "description": "DSFA Audit-Trail.", + "operationId": "get_audit_log_api_compliance_dsfa_audit_log_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 50, + "maximum": 500, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "minimum": 0, + "title": "Offset", + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Audit Log", + "tags": [ + "compliance", + "compliance-dsfa" + ] + } + }, + "/api/compliance/dsfa/by-assessment/{assessment_id}": { + "get": { + "description": "Stub: Get DSFA by linked UCCA assessment ID.", + "operationId": "get_by_assessment_api_compliance_dsfa_by_assessment__assessment_id__get", + "parameters": [ + { + "in": "path", + "name": "assessment_id", + "required": true, + "schema": { + "title": "Assessment Id", + "type": "string" + } + } + ], + "responses": { + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + }, + "501": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "Get By Assessment", + "tags": [ + "compliance", + "compliance-dsfa" + ] + } + }, + "/api/compliance/dsfa/export/csv": { + "get": { + "description": "Export all DSFAs as CSV.", + "operationId": "export_dsfas_csv_api_compliance_dsfa_export_csv_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Export Dsfas Csv", + "tags": [ + "compliance", + "compliance-dsfa" + ] + } + }, + "/api/compliance/dsfa/from-assessment/{assessment_id}": { + "post": { + "description": "Stub: Create DSFA from UCCA assessment. Requires cross-service communication.", + "operationId": "create_from_assessment_api_compliance_dsfa_from_assessment__assessment_id__post", + "parameters": [ + { + "in": "path", + "name": "assessment_id", + "required": true, + "schema": { + "title": "Assessment Id", + "type": "string" + } + } + ], + "responses": { + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + }, + "501": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "Create From Assessment", + "tags": [ + "compliance", + "compliance-dsfa" + ] + } + }, + "/api/compliance/dsfa/stats": { + "get": { + "description": "Z\u00e4hler nach Status und Risiko-Level.", + "operationId": "get_stats_api_compliance_dsfa_stats_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Stats", + "tags": [ + "compliance", + "compliance-dsfa" + ] + } + }, + "/api/compliance/dsfa/{dsfa_id}": { + "delete": { + "description": "DSFA l\u00f6schen (Art. 17 DSGVO).", + "operationId": "delete_dsfa_api_compliance_dsfa__dsfa_id__delete", + "parameters": [ + { + "in": "path", + "name": "dsfa_id", + "required": true, + "schema": { + "title": "Dsfa Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Dsfa", + "tags": [ + "compliance", + "compliance-dsfa" + ] + }, + "get": { + "description": "Einzelne DSFA abrufen.", + "operationId": "get_dsfa_api_compliance_dsfa__dsfa_id__get", + "parameters": [ + { + "in": "path", + "name": "dsfa_id", + "required": true, + "schema": { + "title": "Dsfa Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Dsfa", + "tags": [ + "compliance", + "compliance-dsfa" + ] + }, + "put": { + "description": "DSFA aktualisieren.", + "operationId": "update_dsfa_api_compliance_dsfa__dsfa_id__put", + "parameters": [ + { + "in": "path", + "name": "dsfa_id", + "required": true, + "schema": { + "title": "Dsfa Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DSFAUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Dsfa", + "tags": [ + "compliance", + "compliance-dsfa" + ] + } + }, + "/api/compliance/dsfa/{dsfa_id}/approve": { + "post": { + "description": "Approve or reject a DSFA (DPO/CISO action).", + "operationId": "approve_dsfa_api_compliance_dsfa__dsfa_id__approve_post", + "parameters": [ + { + "in": "path", + "name": "dsfa_id", + "required": true, + "schema": { + "title": "Dsfa Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DSFAApproveRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Approve Dsfa", + "tags": [ + "compliance", + "compliance-dsfa" + ] + } + }, + "/api/compliance/dsfa/{dsfa_id}/export": { + "get": { + "description": "Export a single DSFA as JSON.", + "operationId": "export_dsfa_json_api_compliance_dsfa__dsfa_id__export_get", + "parameters": [ + { + "in": "path", + "name": "dsfa_id", + "required": true, + "schema": { + "title": "Dsfa Id", + "type": "string" + } + }, + { + "in": "query", + "name": "format", + "required": false, + "schema": { + "default": "json", + "title": "Format", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Export Dsfa Json", + "tags": [ + "compliance", + "compliance-dsfa" + ] + } + }, + "/api/compliance/dsfa/{dsfa_id}/sections/{section_number}": { + "put": { + "description": "Update a specific DSFA section (1-8).", + "operationId": "update_section_api_compliance_dsfa__dsfa_id__sections__section_number__put", + "parameters": [ + { + "in": "path", + "name": "dsfa_id", + "required": true, + "schema": { + "title": "Dsfa Id", + "type": "string" + } + }, + { + "in": "path", + "name": "section_number", + "required": true, + "schema": { + "title": "Section Number", + "type": "integer" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DSFASectionUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Section", + "tags": [ + "compliance", + "compliance-dsfa" + ] + } + }, + "/api/compliance/dsfa/{dsfa_id}/status": { + "patch": { + "description": "Schnell-Statuswechsel.", + "operationId": "update_dsfa_status_api_compliance_dsfa__dsfa_id__status_patch", + "parameters": [ + { + "in": "path", + "name": "dsfa_id", + "required": true, + "schema": { + "title": "Dsfa Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DSFAStatusUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Dsfa Status", + "tags": [ + "compliance", + "compliance-dsfa" + ] + } + }, + "/api/compliance/dsfa/{dsfa_id}/submit-for-review": { + "post": { + "description": "Submit a DSFA for DPO review (draft \u2192 in-review).", + "operationId": "submit_for_review_api_compliance_dsfa__dsfa_id__submit_for_review_post", + "parameters": [ + { + "in": "path", + "name": "dsfa_id", + "required": true, + "schema": { + "title": "Dsfa Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Submit For Review", + "tags": [ + "compliance", + "compliance-dsfa" + ] + } + }, + "/api/compliance/dsfa/{dsfa_id}/versions": { + "get": { + "description": "List all versions for a DSFA.", + "operationId": "list_dsfa_versions_api_compliance_dsfa__dsfa_id__versions_get", + "parameters": [ + { + "in": "path", + "name": "dsfa_id", + "required": true, + "schema": { + "title": "Dsfa Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Dsfa Versions", + "tags": [ + "compliance", + "compliance-dsfa" + ] + } + }, + "/api/compliance/dsfa/{dsfa_id}/versions/{version_number}": { + "get": { + "description": "Get a specific DSFA version with full snapshot.", + "operationId": "get_dsfa_version_api_compliance_dsfa__dsfa_id__versions__version_number__get", + "parameters": [ + { + "in": "path", + "name": "dsfa_id", + "required": true, + "schema": { + "title": "Dsfa Id", + "type": "string" + } + }, + { + "in": "path", + "name": "version_number", + "required": true, + "schema": { + "title": "Version Number", + "type": "integer" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Dsfa Version", + "tags": [ + "compliance", + "compliance-dsfa" + ] + } + }, + "/api/compliance/dsr": { + "get": { + "description": "Liste aller DSRs mit Filtern.", + "operationId": "list_dsrs_api_compliance_dsr_get", + "parameters": [ + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "in": "query", + "name": "request_type", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Request Type" + } + }, + { + "in": "query", + "name": "assigned_to", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Assigned To" + } + }, + { + "in": "query", + "name": "priority", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Priority" + } + }, + { + "in": "query", + "name": "overdue_only", + "required": false, + "schema": { + "default": false, + "title": "Overdue Only", + "type": "boolean" + } + }, + { + "in": "query", + "name": "search", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Search" + } + }, + { + "in": "query", + "name": "from_date", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "From Date" + } + }, + { + "in": "query", + "name": "to_date", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "To Date" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 20, + "maximum": 100, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "minimum": 0, + "title": "Offset", + "type": "integer" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Dsrs", + "tags": [ + "compliance", + "compliance-dsr" + ] + }, + "post": { + "description": "Erstellt eine neue Betroffenenanfrage.", + "operationId": "create_dsr_api_compliance_dsr_post", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DSRCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Dsr", + "tags": [ + "compliance", + "compliance-dsr" + ] + } + }, + "/api/compliance/dsr/deadlines/process": { + "post": { + "description": "Verarbeitet Fristen und markiert ueberfaellige DSRs.", + "operationId": "process_deadlines_api_compliance_dsr_deadlines_process_post", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Process Deadlines", + "tags": [ + "compliance", + "compliance-dsr" + ] + } + }, + "/api/compliance/dsr/export": { + "get": { + "description": "Exportiert alle DSRs als CSV oder JSON.", + "operationId": "export_dsrs_api_compliance_dsr_export_get", + "parameters": [ + { + "in": "query", + "name": "format", + "required": false, + "schema": { + "default": "csv", + "pattern": "^(csv|json)$", + "title": "Format", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Export Dsrs", + "tags": [ + "compliance", + "compliance-dsr" + ] + } + }, + "/api/compliance/dsr/stats": { + "get": { + "description": "Dashboard-Statistiken fuer DSRs.", + "operationId": "get_dsr_stats_api_compliance_dsr_stats_get", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Dsr Stats", + "tags": [ + "compliance", + "compliance-dsr" + ] + } + }, + "/api/compliance/dsr/template-versions/{version_id}/publish": { + "put": { + "description": "Veroeffentlicht eine Vorlagen-Version.", + "operationId": "publish_template_version_api_compliance_dsr_template_versions__version_id__publish_put", + "parameters": [ + { + "in": "path", + "name": "version_id", + "required": true, + "schema": { + "title": "Version Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Publish Template Version", + "tags": [ + "compliance", + "compliance-dsr" + ] + } + }, + "/api/compliance/dsr/templates": { + "get": { + "description": "Gibt alle DSR-Vorlagen zurueck.", + "operationId": "get_templates_api_compliance_dsr_templates_get", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Templates", + "tags": [ + "compliance", + "compliance-dsr" + ] + } + }, + "/api/compliance/dsr/templates/published": { + "get": { + "description": "Gibt publizierte Vorlagen zurueck.", + "operationId": "get_published_templates_api_compliance_dsr_templates_published_get", + "parameters": [ + { + "in": "query", + "name": "request_type", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Request Type" + } + }, + { + "in": "query", + "name": "language", + "required": false, + "schema": { + "default": "de", + "title": "Language", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Published Templates", + "tags": [ + "compliance", + "compliance-dsr" + ] + } + }, + "/api/compliance/dsr/templates/{template_id}/versions": { + "get": { + "description": "Gibt alle Versionen einer Vorlage zurueck.", + "operationId": "get_template_versions_api_compliance_dsr_templates__template_id__versions_get", + "parameters": [ + { + "in": "path", + "name": "template_id", + "required": true, + "schema": { + "title": "Template Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Template Versions", + "tags": [ + "compliance", + "compliance-dsr" + ] + }, + "post": { + "description": "Erstellt eine neue Version einer Vorlage.", + "operationId": "create_template_version_api_compliance_dsr_templates__template_id__versions_post", + "parameters": [ + { + "in": "path", + "name": "template_id", + "required": true, + "schema": { + "title": "Template Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateTemplateVersion" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Template Version", + "tags": [ + "compliance", + "compliance-dsr" + ] + } + }, + "/api/compliance/dsr/{dsr_id}": { + "delete": { + "description": "Storniert eine DSR (Soft Delete \u2192 Status cancelled).", + "operationId": "delete_dsr_api_compliance_dsr__dsr_id__delete", + "parameters": [ + { + "in": "path", + "name": "dsr_id", + "required": true, + "schema": { + "title": "Dsr Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Dsr", + "tags": [ + "compliance", + "compliance-dsr" + ] + }, + "get": { + "description": "Detail einer Betroffenenanfrage.", + "operationId": "get_dsr_api_compliance_dsr__dsr_id__get", + "parameters": [ + { + "in": "path", + "name": "dsr_id", + "required": true, + "schema": { + "title": "Dsr Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Dsr", + "tags": [ + "compliance", + "compliance-dsr" + ] + }, + "put": { + "description": "Aktualisiert eine Betroffenenanfrage.", + "operationId": "update_dsr_api_compliance_dsr__dsr_id__put", + "parameters": [ + { + "in": "path", + "name": "dsr_id", + "required": true, + "schema": { + "title": "Dsr Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DSRUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Dsr", + "tags": [ + "compliance", + "compliance-dsr" + ] + } + }, + "/api/compliance/dsr/{dsr_id}/assign": { + "post": { + "description": "Weist eine DSR einem Bearbeiter zu.", + "operationId": "assign_dsr_api_compliance_dsr__dsr_id__assign_post", + "parameters": [ + { + "in": "path", + "name": "dsr_id", + "required": true, + "schema": { + "title": "Dsr Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AssignRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Assign Dsr", + "tags": [ + "compliance", + "compliance-dsr" + ] + } + }, + "/api/compliance/dsr/{dsr_id}/communicate": { + "post": { + "description": "Sendet eine Kommunikation.", + "operationId": "send_communication_api_compliance_dsr__dsr_id__communicate_post", + "parameters": [ + { + "in": "path", + "name": "dsr_id", + "required": true, + "schema": { + "title": "Dsr Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SendCommunication" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Send Communication", + "tags": [ + "compliance", + "compliance-dsr" + ] + } + }, + "/api/compliance/dsr/{dsr_id}/communications": { + "get": { + "description": "Gibt die Kommunikationshistorie zurueck.", + "operationId": "get_communications_api_compliance_dsr__dsr_id__communications_get", + "parameters": [ + { + "in": "path", + "name": "dsr_id", + "required": true, + "schema": { + "title": "Dsr Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Communications", + "tags": [ + "compliance", + "compliance-dsr" + ] + } + }, + "/api/compliance/dsr/{dsr_id}/complete": { + "post": { + "description": "Schliesst eine DSR erfolgreich ab.", + "operationId": "complete_dsr_api_compliance_dsr__dsr_id__complete_post", + "parameters": [ + { + "in": "path", + "name": "dsr_id", + "required": true, + "schema": { + "title": "Dsr Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CompleteDSR" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Complete Dsr", + "tags": [ + "compliance", + "compliance-dsr" + ] + } + }, + "/api/compliance/dsr/{dsr_id}/exception-checks": { + "get": { + "description": "Gibt die Art. 17(3) Ausnahmepruefungen zurueck.", + "operationId": "get_exception_checks_api_compliance_dsr__dsr_id__exception_checks_get", + "parameters": [ + { + "in": "path", + "name": "dsr_id", + "required": true, + "schema": { + "title": "Dsr Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Exception Checks", + "tags": [ + "compliance", + "compliance-dsr" + ] + } + }, + "/api/compliance/dsr/{dsr_id}/exception-checks/init": { + "post": { + "description": "Initialisiert die Art. 17(3) Ausnahmepruefungen fuer eine Loeschanfrage.", + "operationId": "init_exception_checks_api_compliance_dsr__dsr_id__exception_checks_init_post", + "parameters": [ + { + "in": "path", + "name": "dsr_id", + "required": true, + "schema": { + "title": "Dsr Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Init Exception Checks", + "tags": [ + "compliance", + "compliance-dsr" + ] + } + }, + "/api/compliance/dsr/{dsr_id}/exception-checks/{check_id}": { + "put": { + "description": "Aktualisiert eine einzelne Ausnahmepruefung.", + "operationId": "update_exception_check_api_compliance_dsr__dsr_id__exception_checks__check_id__put", + "parameters": [ + { + "in": "path", + "name": "dsr_id", + "required": true, + "schema": { + "title": "Dsr Id", + "type": "string" + } + }, + { + "in": "path", + "name": "check_id", + "required": true, + "schema": { + "title": "Check Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateExceptionCheck" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Exception Check", + "tags": [ + "compliance", + "compliance-dsr" + ] + } + }, + "/api/compliance/dsr/{dsr_id}/extend": { + "post": { + "description": "Verlaengert die Bearbeitungsfrist (Art. 12 Abs. 3 DSGVO).", + "operationId": "extend_deadline_api_compliance_dsr__dsr_id__extend_post", + "parameters": [ + { + "in": "path", + "name": "dsr_id", + "required": true, + "schema": { + "title": "Dsr Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExtendDeadline" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Extend Deadline", + "tags": [ + "compliance", + "compliance-dsr" + ] + } + }, + "/api/compliance/dsr/{dsr_id}/history": { + "get": { + "description": "Gibt die Status-Historie zurueck.", + "operationId": "get_history_api_compliance_dsr__dsr_id__history_get", + "parameters": [ + { + "in": "path", + "name": "dsr_id", + "required": true, + "schema": { + "title": "Dsr Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get History", + "tags": [ + "compliance", + "compliance-dsr" + ] + } + }, + "/api/compliance/dsr/{dsr_id}/reject": { + "post": { + "description": "Lehnt eine DSR mit Rechtsgrundlage ab.", + "operationId": "reject_dsr_api_compliance_dsr__dsr_id__reject_post", + "parameters": [ + { + "in": "path", + "name": "dsr_id", + "required": true, + "schema": { + "title": "Dsr Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RejectDSR" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Reject Dsr", + "tags": [ + "compliance", + "compliance-dsr" + ] + } + }, + "/api/compliance/dsr/{dsr_id}/status": { + "post": { + "description": "Aendert den Status einer DSR.", + "operationId": "change_status_api_compliance_dsr__dsr_id__status_post", + "parameters": [ + { + "in": "path", + "name": "dsr_id", + "required": true, + "schema": { + "title": "Dsr Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StatusChange" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Change Status", + "tags": [ + "compliance", + "compliance-dsr" + ] + } + }, + "/api/compliance/dsr/{dsr_id}/verify-identity": { + "post": { + "description": "Verifiziert die Identitaet des Antragstellers.", + "operationId": "verify_identity_api_compliance_dsr__dsr_id__verify_identity_post", + "parameters": [ + { + "in": "path", + "name": "dsr_id", + "required": true, + "schema": { + "title": "Dsr Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VerifyIdentity" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Verify Identity", + "tags": [ + "compliance", + "compliance-dsr" + ] + } + }, + "/api/compliance/einwilligungen/catalog": { + "get": { + "description": "Load the data point catalog for a tenant.", + "operationId": "get_catalog_api_compliance_einwilligungen_catalog_get", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Catalog", + "tags": [ + "compliance", + "einwilligungen" + ] + }, + "put": { + "description": "Create or update the data point catalog for a tenant.", + "operationId": "upsert_catalog_api_compliance_einwilligungen_catalog_put", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CatalogUpsert" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Upsert Catalog", + "tags": [ + "compliance", + "einwilligungen" + ] + } + }, + "/api/compliance/einwilligungen/company": { + "get": { + "description": "Load company information for DSI generation.", + "operationId": "get_company_api_compliance_einwilligungen_company_get", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Company", + "tags": [ + "compliance", + "einwilligungen" + ] + }, + "put": { + "description": "Create or update company information for a tenant.", + "operationId": "upsert_company_api_compliance_einwilligungen_company_put", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CompanyUpsert" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Upsert Company", + "tags": [ + "compliance", + "einwilligungen" + ] + } + }, + "/api/compliance/einwilligungen/consents": { + "get": { + "description": "List consent records with optional filters and pagination.", + "operationId": "list_consents_api_compliance_einwilligungen_consents_get", + "parameters": [ + { + "in": "query", + "name": "user_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "User Id" + } + }, + { + "in": "query", + "name": "data_point_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Data Point Id" + } + }, + { + "in": "query", + "name": "granted", + "required": false, + "schema": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Granted" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 50, + "maximum": 500, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "minimum": 0, + "title": "Offset", + "type": "integer" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Consents", + "tags": [ + "compliance", + "einwilligungen" + ] + }, + "post": { + "description": "Record a new consent entry.", + "operationId": "create_consent_api_compliance_einwilligungen_consents_post", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/compliance__api__einwilligungen_routes__ConsentCreate" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Consent", + "tags": [ + "compliance", + "einwilligungen" + ] + } + }, + "/api/compliance/einwilligungen/consents/stats": { + "get": { + "description": "Get consent statistics for a tenant.", + "operationId": "get_consent_stats_api_compliance_einwilligungen_consents_stats_get", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Consent Stats", + "tags": [ + "compliance", + "einwilligungen" + ] + } + }, + "/api/compliance/einwilligungen/consents/{consent_id}/history": { + "get": { + "description": "Get the change history for a specific consent record.", + "operationId": "get_consent_history_api_compliance_einwilligungen_consents__consent_id__history_get", + "parameters": [ + { + "in": "path", + "name": "consent_id", + "required": true, + "schema": { + "title": "Consent Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Consent History", + "tags": [ + "compliance", + "einwilligungen" + ] + } + }, + "/api/compliance/einwilligungen/consents/{consent_id}/revoke": { + "put": { + "description": "Revoke an active consent.", + "operationId": "revoke_consent_api_compliance_einwilligungen_consents__consent_id__revoke_put", + "parameters": [ + { + "in": "path", + "name": "consent_id", + "required": true, + "schema": { + "title": "Consent Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Revoke Consent", + "tags": [ + "compliance", + "einwilligungen" + ] + } + }, + "/api/compliance/einwilligungen/cookies": { + "get": { + "description": "Load cookie banner configuration for a tenant.", + "operationId": "get_cookies_api_compliance_einwilligungen_cookies_get", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Cookies", + "tags": [ + "compliance", + "einwilligungen" + ] + }, + "put": { + "description": "Create or update cookie banner configuration for a tenant.", + "operationId": "upsert_cookies_api_compliance_einwilligungen_cookies_put", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CookiesUpsert" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Upsert Cookies", + "tags": [ + "compliance", + "einwilligungen" + ] + } + }, + "/api/compliance/email-templates": { + "get": { + "description": "Alle Templates mit letzter publizierter Version.", + "operationId": "list_templates_api_compliance_email_templates_get", + "parameters": [ + { + "in": "query", + "name": "category", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Category" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Templates", + "tags": [ + "compliance", + "compliance-email-templates" + ] + }, + "post": { + "description": "Template erstellen.", + "operationId": "create_template_api_compliance_email_templates_post", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/compliance__api__email_template_routes__TemplateCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Template", + "tags": [ + "compliance", + "compliance-email-templates" + ] + } + }, + "/api/compliance/email-templates/default/{template_type}": { + "get": { + "description": "Default-Content fuer einen Template-Typ.", + "operationId": "get_default_content_api_compliance_email_templates_default__template_type__get", + "parameters": [ + { + "in": "path", + "name": "template_type", + "required": true, + "schema": { + "title": "Template Type", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Default Content", + "tags": [ + "compliance", + "compliance-email-templates" + ] + } + }, + "/api/compliance/email-templates/initialize": { + "post": { + "description": "Default-Templates fuer einen Tenant initialisieren.", + "operationId": "initialize_defaults_api_compliance_email_templates_initialize_post", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Initialize Defaults", + "tags": [ + "compliance", + "compliance-email-templates" + ] + } + }, + "/api/compliance/email-templates/logs": { + "get": { + "description": "Send-Logs (paginiert).", + "operationId": "get_send_logs_api_compliance_email_templates_logs_get", + "parameters": [ + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 20, + "maximum": 100, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "minimum": 0, + "title": "Offset", + "type": "integer" + } + }, + { + "in": "query", + "name": "template_type", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Template Type" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Send Logs", + "tags": [ + "compliance", + "compliance-email-templates" + ] + } + }, + "/api/compliance/email-templates/settings": { + "get": { + "description": "Globale E-Mail-Einstellungen laden.", + "operationId": "get_settings_api_compliance_email_templates_settings_get", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Settings", + "tags": [ + "compliance", + "compliance-email-templates" + ] + }, + "put": { + "description": "Globale E-Mail-Einstellungen speichern.", + "operationId": "update_settings_api_compliance_email_templates_settings_put", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SettingsUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Settings", + "tags": [ + "compliance", + "compliance-email-templates" + ] + } + }, + "/api/compliance/email-templates/stats": { + "get": { + "description": "Statistiken ueber E-Mail-Templates.", + "operationId": "get_stats_api_compliance_email_templates_stats_get", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Stats", + "tags": [ + "compliance", + "compliance-email-templates" + ] + } + }, + "/api/compliance/email-templates/types": { + "get": { + "description": "Gibt alle verfuegbaren Template-Typen mit Variablen zurueck.", + "operationId": "get_template_types_api_compliance_email_templates_types_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "Get Template Types", + "tags": [ + "compliance", + "compliance-email-templates" + ] + } + }, + "/api/compliance/email-templates/versions": { + "post": { + "description": "Neue Version erstellen (via query param template_id).", + "operationId": "create_version_api_compliance_email_templates_versions_post", + "parameters": [ + { + "in": "query", + "name": "template_id", + "required": true, + "schema": { + "title": "Template Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/compliance__api__email_template_routes__VersionCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Version", + "tags": [ + "compliance", + "compliance-email-templates" + ] + } + }, + "/api/compliance/email-templates/versions/{version_id}": { + "get": { + "description": "Version-Detail.", + "operationId": "get_version_api_compliance_email_templates_versions__version_id__get", + "parameters": [ + { + "in": "path", + "name": "version_id", + "required": true, + "schema": { + "title": "Version Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Version", + "tags": [ + "compliance", + "compliance-email-templates" + ] + }, + "put": { + "description": "Draft aktualisieren.", + "operationId": "update_version_api_compliance_email_templates_versions__version_id__put", + "parameters": [ + { + "in": "path", + "name": "version_id", + "required": true, + "schema": { + "title": "Version Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/compliance__api__email_template_routes__VersionUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Version", + "tags": [ + "compliance", + "compliance-email-templates" + ] + } + }, + "/api/compliance/email-templates/versions/{version_id}/approve": { + "post": { + "description": "Genehmigen.", + "operationId": "approve_version_api_compliance_email_templates_versions__version_id__approve_post", + "parameters": [ + { + "in": "path", + "name": "version_id", + "required": true, + "schema": { + "title": "Version Id", + "type": "string" + } + }, + { + "in": "query", + "name": "comment", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Comment" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Approve Version", + "tags": [ + "compliance", + "compliance-email-templates" + ] + } + }, + "/api/compliance/email-templates/versions/{version_id}/preview": { + "post": { + "description": "Vorschau mit Test-Variablen.", + "operationId": "preview_version_api_compliance_email_templates_versions__version_id__preview_post", + "parameters": [ + { + "in": "path", + "name": "version_id", + "required": true, + "schema": { + "title": "Version Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PreviewRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Preview Version", + "tags": [ + "compliance", + "compliance-email-templates" + ] + } + }, + "/api/compliance/email-templates/versions/{version_id}/publish": { + "post": { + "description": "Publizieren.", + "operationId": "publish_version_api_compliance_email_templates_versions__version_id__publish_post", + "parameters": [ + { + "in": "path", + "name": "version_id", + "required": true, + "schema": { + "title": "Version Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Publish Version", + "tags": [ + "compliance", + "compliance-email-templates" + ] + } + }, + "/api/compliance/email-templates/versions/{version_id}/reject": { + "post": { + "description": "Ablehnen.", + "operationId": "reject_version_api_compliance_email_templates_versions__version_id__reject_post", + "parameters": [ + { + "in": "path", + "name": "version_id", + "required": true, + "schema": { + "title": "Version Id", + "type": "string" + } + }, + { + "in": "query", + "name": "comment", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Comment" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Reject Version", + "tags": [ + "compliance", + "compliance-email-templates" + ] + } + }, + "/api/compliance/email-templates/versions/{version_id}/send-test": { + "post": { + "description": "Test-E-Mail senden (Simulation \u2014 loggt nur).", + "operationId": "send_test_email_api_compliance_email_templates_versions__version_id__send_test_post", + "parameters": [ + { + "in": "path", + "name": "version_id", + "required": true, + "schema": { + "title": "Version Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SendTestRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Send Test Email", + "tags": [ + "compliance", + "compliance-email-templates" + ] + } + }, + "/api/compliance/email-templates/versions/{version_id}/submit": { + "post": { + "description": "Zur Pruefung einreichen.", + "operationId": "submit_version_api_compliance_email_templates_versions__version_id__submit_post", + "parameters": [ + { + "in": "path", + "name": "version_id", + "required": true, + "schema": { + "title": "Version Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Submit Version", + "tags": [ + "compliance", + "compliance-email-templates" + ] + } + }, + "/api/compliance/email-templates/{template_id}": { + "get": { + "description": "Template-Detail.", + "operationId": "get_template_api_compliance_email_templates__template_id__get", + "parameters": [ + { + "in": "path", + "name": "template_id", + "required": true, + "schema": { + "title": "Template Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Template", + "tags": [ + "compliance", + "compliance-email-templates" + ] + } + }, + "/api/compliance/email-templates/{template_id}/versions": { + "get": { + "description": "Versionen eines Templates.", + "operationId": "get_versions_api_compliance_email_templates__template_id__versions_get", + "parameters": [ + { + "in": "path", + "name": "template_id", + "required": true, + "schema": { + "title": "Template Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Versions", + "tags": [ + "compliance", + "compliance-email-templates" + ] + }, + "post": { + "description": "Neue Version fuer ein Template erstellen.", + "operationId": "create_version_for_template_api_compliance_email_templates__template_id__versions_post", + "parameters": [ + { + "in": "path", + "name": "template_id", + "required": true, + "schema": { + "title": "Template Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/compliance__api__email_template_routes__VersionCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Version For Template", + "tags": [ + "compliance", + "compliance-email-templates" + ] + } + }, + "/api/compliance/escalations": { + "get": { + "description": "List escalations with optional filters.", + "operationId": "list_escalations_api_compliance_escalations_get", + "parameters": [ + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "in": "query", + "name": "priority", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Priority" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 50, + "maximum": 500, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "minimum": 0, + "title": "Offset", + "type": "integer" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Escalations", + "tags": [ + "compliance", + "escalations" + ] + }, + "post": { + "description": "Create a new escalation.", + "operationId": "create_escalation_api_compliance_escalations_post", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "x-user-id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-User-Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EscalationCreate" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Escalation", + "tags": [ + "compliance", + "escalations" + ] + } + }, + "/api/compliance/escalations/stats": { + "get": { + "description": "Return counts per status and priority.", + "operationId": "get_stats_api_compliance_escalations_stats_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Stats", + "tags": [ + "compliance", + "escalations" + ] + } + }, + "/api/compliance/escalations/{escalation_id}": { + "delete": { + "description": "Delete an escalation.", + "operationId": "delete_escalation_api_compliance_escalations__escalation_id__delete", + "parameters": [ + { + "in": "path", + "name": "escalation_id", + "required": true, + "schema": { + "title": "Escalation Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Escalation", + "tags": [ + "compliance", + "escalations" + ] + }, + "get": { + "description": "Get a single escalation by ID.", + "operationId": "get_escalation_api_compliance_escalations__escalation_id__get", + "parameters": [ + { + "in": "path", + "name": "escalation_id", + "required": true, + "schema": { + "title": "Escalation Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Escalation", + "tags": [ + "compliance", + "escalations" + ] + }, + "put": { + "description": "Update an escalation's fields.", + "operationId": "update_escalation_api_compliance_escalations__escalation_id__put", + "parameters": [ + { + "in": "path", + "name": "escalation_id", + "required": true, + "schema": { + "title": "Escalation Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EscalationUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Escalation", + "tags": [ + "compliance", + "escalations" + ] + } + }, + "/api/compliance/escalations/{escalation_id}/status": { + "put": { + "description": "Update only the status of an escalation.", + "operationId": "update_status_api_compliance_escalations__escalation_id__status_put", + "parameters": [ + { + "in": "path", + "name": "escalation_id", + "required": true, + "schema": { + "title": "Escalation Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EscalationStatusUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Status", + "tags": [ + "compliance", + "escalations" + ] + } + }, + "/api/compliance/evidence": { + "get": { + "description": "List evidence with optional filters and pagination.", + "operationId": "list_evidence_api_compliance_evidence_get", + "parameters": [ + { + "in": "query", + "name": "control_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Control Id" + } + }, + { + "in": "query", + "name": "evidence_type", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Evidence Type" + } + }, + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "description": "Page number (1-based)", + "in": "query", + "name": "page", + "required": false, + "schema": { + "anyOf": [ + { + "minimum": 1, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Page number (1-based)", + "title": "Page" + } + }, + { + "description": "Items per page", + "in": "query", + "name": "limit", + "required": false, + "schema": { + "anyOf": [ + { + "maximum": 500, + "minimum": 1, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Items per page", + "title": "Limit" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvidenceListResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Evidence", + "tags": [ + "compliance", + "compliance-evidence" + ] + }, + "post": { + "description": "Create new evidence record.", + "operationId": "create_evidence_api_compliance_evidence_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvidenceCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvidenceResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Evidence", + "tags": [ + "compliance", + "compliance-evidence" + ] + } + }, + "/api/compliance/evidence/ci-status": { + "get": { + "description": "Get CI/CD evidence collection status.\n\nReturns overview of recent evidence collected from CI/CD pipelines,\nuseful for dashboards and monitoring.", + "operationId": "get_ci_evidence_status_api_compliance_evidence_ci_status_get", + "parameters": [ + { + "description": "Filter by control ID", + "in": "query", + "name": "control_id", + "required": false, + "schema": { + "description": "Filter by control ID", + "title": "Control Id", + "type": "string" + } + }, + { + "description": "Look back N days", + "in": "query", + "name": "days", + "required": false, + "schema": { + "default": 30, + "description": "Look back N days", + "title": "Days", + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Ci Evidence Status", + "tags": [ + "compliance", + "compliance-evidence" + ] + } + }, + "/api/compliance/evidence/collect": { + "post": { + "description": "Collect evidence from CI/CD pipeline.\n\nThis endpoint is designed to be called from CI/CD workflows (GitHub Actions,\nGitLab CI, Jenkins, etc.) to automatically collect compliance evidence.\n\nSupported sources:\n- sast: Static Application Security Testing (Semgrep, SonarQube, etc.)\n- dependency_scan: Dependency vulnerability scanning (Trivy, Grype, Snyk)\n- sbom: Software Bill of Materials (CycloneDX, SPDX)\n- container_scan: Container image scanning (Trivy, Grype)\n- test_results: Test coverage and results\n- secret_scan: Secret detection (Gitleaks, TruffleHog)\n- code_review: Code review metrics", + "operationId": "collect_ci_evidence_api_compliance_evidence_collect_post", + "parameters": [ + { + "description": "Evidence source: sast, dependency_scan, sbom, container_scan, test_results", + "in": "query", + "name": "source", + "required": true, + "schema": { + "description": "Evidence source: sast, dependency_scan, sbom, container_scan, test_results", + "title": "Source", + "type": "string" + } + }, + { + "description": "CI/CD Job ID for traceability", + "in": "query", + "name": "ci_job_id", + "required": false, + "schema": { + "description": "CI/CD Job ID for traceability", + "title": "Ci Job Id", + "type": "string" + } + }, + { + "description": "URL to CI/CD job", + "in": "query", + "name": "ci_job_url", + "required": false, + "schema": { + "description": "URL to CI/CD job", + "title": "Ci Job Url", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "title": "Report Data", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Collect Ci Evidence", + "tags": [ + "compliance", + "compliance-evidence" + ] + } + }, + "/api/compliance/evidence/upload": { + "post": { + "description": "Upload evidence file.", + "operationId": "upload_evidence_api_compliance_evidence_upload_post", + "parameters": [ + { + "in": "query", + "name": "control_id", + "required": true, + "schema": { + "title": "Control Id", + "type": "string" + } + }, + { + "in": "query", + "name": "evidence_type", + "required": true, + "schema": { + "title": "Evidence Type", + "type": "string" + } + }, + { + "in": "query", + "name": "title", + "required": true, + "schema": { + "title": "Title", + "type": "string" + } + }, + { + "in": "query", + "name": "description", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + } + } + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_upload_evidence_api_compliance_evidence_upload_post" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Upload Evidence", + "tags": [ + "compliance", + "compliance-evidence" + ] + } + }, + "/api/compliance/evidence/{evidence_id}": { + "delete": { + "description": "Delete an evidence record.", + "operationId": "delete_evidence_api_compliance_evidence__evidence_id__delete", + "parameters": [ + { + "in": "path", + "name": "evidence_id", + "required": true, + "schema": { + "title": "Evidence Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Evidence", + "tags": [ + "compliance", + "compliance-evidence" + ] + } + }, + "/api/compliance/export": { + "post": { + "description": "Create a new audit export.", + "operationId": "create_export_api_compliance_export_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExportRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExportResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Export", + "tags": [ + "compliance" + ] + } + }, + "/api/compliance/export/{export_id}": { + "get": { + "description": "Get export status.", + "operationId": "get_export_api_compliance_export__export_id__get", + "parameters": [ + { + "in": "path", + "name": "export_id", + "required": true, + "schema": { + "title": "Export Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExportResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Export", + "tags": [ + "compliance" + ] + } + }, + "/api/compliance/export/{export_id}/download": { + "get": { + "description": "Download export file.", + "operationId": "download_export_api_compliance_export__export_id__download_get", + "parameters": [ + { + "in": "path", + "name": "export_id", + "required": true, + "schema": { + "title": "Export Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Download Export", + "tags": [ + "compliance" + ] + } + }, + "/api/compliance/exports": { + "get": { + "description": "List recent exports.", + "operationId": "list_exports_api_compliance_exports_get", + "parameters": [ + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 20, + "title": "Limit", + "type": "integer" + } + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "title": "Offset", + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExportListResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Exports", + "tags": [ + "compliance" + ] + } + }, + "/api/compliance/gdpr-processes": { + "get": { + "description": "List all GDPR processes for a tenant.", + "operationId": "list_gdpr_processes_api_compliance_gdpr_processes_get", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Gdpr Processes", + "tags": [ + "compliance", + "consent-templates" + ] + } + }, + "/api/compliance/gdpr-processes/{process_id}": { + "put": { + "description": "Update an existing GDPR process.", + "operationId": "update_gdpr_process_api_compliance_gdpr_processes__process_id__put", + "parameters": [ + { + "in": "path", + "name": "process_id", + "required": true, + "schema": { + "title": "Process Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GDPRProcessUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Gdpr Process", + "tags": [ + "compliance", + "consent-templates" + ] + } + }, + "/api/compliance/generation/apply/{doc_type}": { + "post": { + "description": "Generate drafts and create Change-Requests for each.\n\nDoes NOT create documents directly \u2014 all go through the CR inbox.", + "operationId": "apply_generation_api_compliance_generation_apply__doc_type__post", + "parameters": [ + { + "in": "path", + "name": "doc_type", + "required": true, + "schema": { + "title": "Doc Type", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-User-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-User-Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Apply Generation", + "tags": [ + "compliance", + "generation" + ] + } + }, + "/api/compliance/generation/preview/{doc_type}": { + "get": { + "description": "Preview what documents would be generated (no DB writes).", + "operationId": "preview_generation_api_compliance_generation_preview__doc_type__get", + "parameters": [ + { + "in": "path", + "name": "doc_type", + "required": true, + "schema": { + "title": "Doc Type", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Preview Generation", + "tags": [ + "compliance", + "generation" + ] + } + }, + "/api/compliance/incidents": { + "get": { + "operationId": "list_incidents_api_compliance_incidents_get", + "parameters": [ + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "in": "query", + "name": "severity", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Severity" + } + }, + { + "in": "query", + "name": "category", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Category" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 50, + "title": "Limit", + "type": "integer" + } + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "title": "Offset", + "type": "integer" + } + }, + { + "in": "header", + "name": "x-tenant-id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Incidents", + "tags": [ + "compliance", + "incidents" + ] + }, + "post": { + "operationId": "create_incident_api_compliance_incidents_post", + "parameters": [ + { + "in": "header", + "name": "x-tenant-id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + }, + { + "in": "header", + "name": "x-user-id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-User-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/compliance__api__incident_routes__IncidentCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Incident", + "tags": [ + "compliance", + "incidents" + ] + } + }, + "/api/compliance/incidents/stats": { + "get": { + "operationId": "get_stats_api_compliance_incidents_stats_get", + "parameters": [ + { + "in": "header", + "name": "x-tenant-id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Stats", + "tags": [ + "compliance", + "incidents" + ] + } + }, + "/api/compliance/incidents/{incident_id}": { + "delete": { + "operationId": "delete_incident_api_compliance_incidents__incident_id__delete", + "parameters": [ + { + "in": "path", + "name": "incident_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Incident Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Incident", + "tags": [ + "compliance", + "incidents" + ] + }, + "get": { + "operationId": "get_incident_api_compliance_incidents__incident_id__get", + "parameters": [ + { + "in": "path", + "name": "incident_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Incident Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Incident", + "tags": [ + "compliance", + "incidents" + ] + }, + "put": { + "operationId": "update_incident_api_compliance_incidents__incident_id__put", + "parameters": [ + { + "in": "path", + "name": "incident_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Incident Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/compliance__api__incident_routes__IncidentUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Incident", + "tags": [ + "compliance", + "incidents" + ] + } + }, + "/api/compliance/incidents/{incident_id}/assess-risk": { + "post": { + "operationId": "assess_risk_api_compliance_incidents__incident_id__assess_risk_post", + "parameters": [ + { + "in": "path", + "name": "incident_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Incident Id", + "type": "string" + } + }, + { + "in": "header", + "name": "x-user-id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-User-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RiskAssessmentRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Assess Risk", + "tags": [ + "compliance", + "incidents" + ] + } + }, + "/api/compliance/incidents/{incident_id}/close": { + "post": { + "operationId": "close_incident_api_compliance_incidents__incident_id__close_post", + "parameters": [ + { + "in": "path", + "name": "incident_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Incident Id", + "type": "string" + } + }, + { + "in": "header", + "name": "x-user-id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-User-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CloseIncidentRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Close Incident", + "tags": [ + "compliance", + "incidents" + ] + } + }, + "/api/compliance/incidents/{incident_id}/measures": { + "post": { + "operationId": "add_measure_api_compliance_incidents__incident_id__measures_post", + "parameters": [ + { + "in": "path", + "name": "incident_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Incident Id", + "type": "string" + } + }, + { + "in": "header", + "name": "x-user-id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-User-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MeasureCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Add Measure", + "tags": [ + "compliance", + "incidents" + ] + } + }, + "/api/compliance/incidents/{incident_id}/measures/{measure_id}": { + "put": { + "operationId": "update_measure_api_compliance_incidents__incident_id__measures__measure_id__put", + "parameters": [ + { + "in": "path", + "name": "incident_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Incident Id", + "type": "string" + } + }, + { + "in": "path", + "name": "measure_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Measure Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MeasureUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Measure", + "tags": [ + "compliance", + "incidents" + ] + } + }, + "/api/compliance/incidents/{incident_id}/measures/{measure_id}/complete": { + "post": { + "operationId": "complete_measure_api_compliance_incidents__incident_id__measures__measure_id__complete_post", + "parameters": [ + { + "in": "path", + "name": "incident_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Incident Id", + "type": "string" + } + }, + { + "in": "path", + "name": "measure_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Measure Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Complete Measure", + "tags": [ + "compliance", + "incidents" + ] + } + }, + "/api/compliance/incidents/{incident_id}/notify-authority": { + "post": { + "operationId": "notify_authority_api_compliance_incidents__incident_id__notify_authority_post", + "parameters": [ + { + "in": "path", + "name": "incident_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Incident Id", + "type": "string" + } + }, + { + "in": "header", + "name": "x-user-id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-User-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthorityNotificationRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Notify Authority", + "tags": [ + "compliance", + "incidents" + ] + } + }, + "/api/compliance/incidents/{incident_id}/notify-subjects": { + "post": { + "operationId": "notify_subjects_api_compliance_incidents__incident_id__notify_subjects_post", + "parameters": [ + { + "in": "path", + "name": "incident_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Incident Id", + "type": "string" + } + }, + { + "in": "header", + "name": "x-user-id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-User-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataSubjectNotificationRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Notify Subjects", + "tags": [ + "compliance", + "incidents" + ] + } + }, + "/api/compliance/incidents/{incident_id}/status": { + "put": { + "operationId": "update_status_api_compliance_incidents__incident_id__status_put", + "parameters": [ + { + "in": "path", + "name": "incident_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Incident Id", + "type": "string" + } + }, + { + "in": "header", + "name": "x-user-id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-User-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/compliance__api__incident_routes__StatusUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Status", + "tags": [ + "compliance", + "incidents" + ] + } + }, + "/api/compliance/incidents/{incident_id}/timeline": { + "post": { + "operationId": "add_timeline_entry_api_compliance_incidents__incident_id__timeline_post", + "parameters": [ + { + "in": "path", + "name": "incident_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Incident Id", + "type": "string" + } + }, + { + "in": "header", + "name": "x-user-id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-User-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TimelineEntryRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Add Timeline Entry", + "tags": [ + "compliance", + "incidents" + ] + } + }, + "/api/compliance/init-tables": { + "post": { + "description": "Create compliance tables if they don't exist.", + "operationId": "init_tables_api_compliance_init_tables_post", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "Init Tables", + "tags": [ + "compliance" + ] + } + }, + "/api/compliance/isms/audit-trail": { + "get": { + "description": "Query the audit trail with filters.", + "operationId": "get_audit_trail_api_compliance_isms_audit_trail_get", + "parameters": [ + { + "in": "query", + "name": "entity_type", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Entity Type" + } + }, + { + "in": "query", + "name": "entity_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Entity Id" + } + }, + { + "in": "query", + "name": "performed_by", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Performed By" + } + }, + { + "in": "query", + "name": "action", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Action" + } + }, + { + "in": "query", + "name": "page", + "required": false, + "schema": { + "default": 1, + "minimum": 1, + "title": "Page", + "type": "integer" + } + }, + { + "in": "query", + "name": "page_size", + "required": false, + "schema": { + "default": 50, + "maximum": 200, + "minimum": 1, + "title": "Page Size", + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuditTrailResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Audit Trail", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/capa": { + "get": { + "description": "List all corrective/preventive actions.", + "operationId": "list_capas_api_compliance_isms_capa_get", + "parameters": [ + { + "in": "query", + "name": "finding_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Finding Id" + } + }, + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "in": "query", + "name": "assigned_to", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Assigned To" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CorrectiveActionListResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Capas", + "tags": [ + "compliance", + "ISMS" + ] + }, + "post": { + "description": "Create a new corrective/preventive action for a finding.", + "operationId": "create_capa_api_compliance_isms_capa_post", + "parameters": [ + { + "in": "query", + "name": "created_by", + "required": true, + "schema": { + "title": "Created By", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CorrectiveActionCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CorrectiveActionResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Capa", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/capa/{capa_id}": { + "put": { + "description": "Update a CAPA's progress.", + "operationId": "update_capa_api_compliance_isms_capa__capa_id__put", + "parameters": [ + { + "in": "path", + "name": "capa_id", + "required": true, + "schema": { + "title": "Capa Id", + "type": "string" + } + }, + { + "in": "query", + "name": "updated_by", + "required": true, + "schema": { + "title": "Updated By", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CorrectiveActionUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CorrectiveActionResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Capa", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/capa/{capa_id}/verify": { + "post": { + "description": "Verify the effectiveness of a CAPA.", + "operationId": "verify_capa_api_compliance_isms_capa__capa_id__verify_post", + "parameters": [ + { + "in": "path", + "name": "capa_id", + "required": true, + "schema": { + "title": "Capa Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CAPAVerifyRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CorrectiveActionResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Verify Capa", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/context": { + "get": { + "description": "Get the current ISMS context analysis.", + "operationId": "get_isms_context_api_compliance_isms_context_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ISMSContextResponse" + } + } + }, + "description": "Successful Response" + } + }, + "summary": "Get Isms Context", + "tags": [ + "compliance", + "ISMS" + ] + }, + "post": { + "description": "Create or update ISMS context analysis.", + "operationId": "create_isms_context_api_compliance_isms_context_post", + "parameters": [ + { + "in": "query", + "name": "created_by", + "required": true, + "schema": { + "title": "Created By", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ISMSContextCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ISMSContextResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Isms Context", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/findings": { + "get": { + "description": "List all audit findings.", + "operationId": "list_findings_api_compliance_isms_findings_get", + "parameters": [ + { + "in": "query", + "name": "finding_type", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Finding Type" + } + }, + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "in": "query", + "name": "internal_audit_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Internal Audit Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuditFindingListResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Findings", + "tags": [ + "compliance", + "ISMS" + ] + }, + "post": { + "description": "Create a new audit finding.\n\nFinding types:\n- major: Blocks certification, requires immediate CAPA\n- minor: Requires CAPA within deadline\n- ofi: Opportunity for improvement (no mandatory action)\n- positive: Good practice observation", + "operationId": "create_finding_api_compliance_isms_findings_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuditFindingCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuditFindingResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Finding", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/findings/{finding_id}": { + "put": { + "description": "Update an audit finding.", + "operationId": "update_finding_api_compliance_isms_findings__finding_id__put", + "parameters": [ + { + "in": "path", + "name": "finding_id", + "required": true, + "schema": { + "title": "Finding Id", + "type": "string" + } + }, + { + "in": "query", + "name": "updated_by", + "required": true, + "schema": { + "title": "Updated By", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuditFindingUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuditFindingResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Finding", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/findings/{finding_id}/close": { + "post": { + "description": "Close an audit finding after verification.\n\nRequires:\n- All CAPAs to be completed and verified\n- Verification evidence documenting the fix", + "operationId": "close_finding_api_compliance_isms_findings__finding_id__close_post", + "parameters": [ + { + "in": "path", + "name": "finding_id", + "required": true, + "schema": { + "title": "Finding Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuditFindingCloseRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuditFindingResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Close Finding", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/internal-audits": { + "get": { + "description": "List all internal audits.", + "operationId": "list_internal_audits_api_compliance_isms_internal_audits_get", + "parameters": [ + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "in": "query", + "name": "audit_type", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Audit Type" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InternalAuditListResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Internal Audits", + "tags": [ + "compliance", + "ISMS" + ] + }, + "post": { + "description": "Create a new internal audit.", + "operationId": "create_internal_audit_api_compliance_isms_internal_audits_post", + "parameters": [ + { + "in": "query", + "name": "created_by", + "required": true, + "schema": { + "title": "Created By", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InternalAuditCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InternalAuditResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Internal Audit", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/internal-audits/{audit_id}": { + "put": { + "description": "Update an internal audit.", + "operationId": "update_internal_audit_api_compliance_isms_internal_audits__audit_id__put", + "parameters": [ + { + "in": "path", + "name": "audit_id", + "required": true, + "schema": { + "title": "Audit Id", + "type": "string" + } + }, + { + "in": "query", + "name": "updated_by", + "required": true, + "schema": { + "title": "Updated By", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InternalAuditUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InternalAuditResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Internal Audit", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/internal-audits/{audit_id}/complete": { + "post": { + "description": "Complete an internal audit with conclusion.", + "operationId": "complete_internal_audit_api_compliance_isms_internal_audits__audit_id__complete_post", + "parameters": [ + { + "in": "path", + "name": "audit_id", + "required": true, + "schema": { + "title": "Audit Id", + "type": "string" + } + }, + { + "in": "query", + "name": "completed_by", + "required": true, + "schema": { + "title": "Completed By", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InternalAuditCompleteRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InternalAuditResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Complete Internal Audit", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/management-reviews": { + "get": { + "description": "List all management reviews.", + "operationId": "list_management_reviews_api_compliance_isms_management_reviews_get", + "parameters": [ + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ManagementReviewListResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Management Reviews", + "tags": [ + "compliance", + "ISMS" + ] + }, + "post": { + "description": "Create a new management review.", + "operationId": "create_management_review_api_compliance_isms_management_reviews_post", + "parameters": [ + { + "in": "query", + "name": "created_by", + "required": true, + "schema": { + "title": "Created By", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ManagementReviewCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ManagementReviewResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Management Review", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/management-reviews/{review_id}": { + "get": { + "description": "Get a specific management review.", + "operationId": "get_management_review_api_compliance_isms_management_reviews__review_id__get", + "parameters": [ + { + "in": "path", + "name": "review_id", + "required": true, + "schema": { + "title": "Review Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ManagementReviewResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Management Review", + "tags": [ + "compliance", + "ISMS" + ] + }, + "put": { + "description": "Update a management review with inputs/outputs.", + "operationId": "update_management_review_api_compliance_isms_management_reviews__review_id__put", + "parameters": [ + { + "in": "path", + "name": "review_id", + "required": true, + "schema": { + "title": "Review Id", + "type": "string" + } + }, + { + "in": "query", + "name": "updated_by", + "required": true, + "schema": { + "title": "Updated By", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ManagementReviewUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ManagementReviewResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Management Review", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/management-reviews/{review_id}/approve": { + "post": { + "description": "Approve a management review.", + "operationId": "approve_management_review_api_compliance_isms_management_reviews__review_id__approve_post", + "parameters": [ + { + "in": "path", + "name": "review_id", + "required": true, + "schema": { + "title": "Review Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ManagementReviewApproveRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ManagementReviewResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Approve Management Review", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/objectives": { + "get": { + "description": "List all security objectives.", + "operationId": "list_objectives_api_compliance_isms_objectives_get", + "parameters": [ + { + "in": "query", + "name": "category", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Category" + } + }, + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SecurityObjectiveListResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Objectives", + "tags": [ + "compliance", + "ISMS" + ] + }, + "post": { + "description": "Create a new security objective.", + "operationId": "create_objective_api_compliance_isms_objectives_post", + "parameters": [ + { + "in": "query", + "name": "created_by", + "required": true, + "schema": { + "title": "Created By", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SecurityObjectiveCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SecurityObjectiveResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Objective", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/objectives/{objective_id}": { + "put": { + "description": "Update a security objective's progress.", + "operationId": "update_objective_api_compliance_isms_objectives__objective_id__put", + "parameters": [ + { + "in": "path", + "name": "objective_id", + "required": true, + "schema": { + "title": "Objective Id", + "type": "string" + } + }, + { + "in": "query", + "name": "updated_by", + "required": true, + "schema": { + "title": "Updated By", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SecurityObjectiveUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SecurityObjectiveResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Objective", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/overview": { + "get": { + "description": "Get complete ISO 27001 compliance overview.\n\nShows status of all chapters, key metrics, and readiness for certification.", + "operationId": "get_iso27001_overview_api_compliance_isms_overview_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ISO27001OverviewResponse" + } + } + }, + "description": "Successful Response" + } + }, + "summary": "Get Iso27001 Overview", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/policies": { + "get": { + "description": "List all ISMS policies.", + "operationId": "list_policies_api_compliance_isms_policies_get", + "parameters": [ + { + "in": "query", + "name": "policy_type", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Policy Type" + } + }, + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ISMSPolicyListResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Policies", + "tags": [ + "compliance", + "ISMS" + ] + }, + "post": { + "description": "Create a new ISMS policy.", + "operationId": "create_policy_api_compliance_isms_policies_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ISMSPolicyCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ISMSPolicyResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Policy", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/policies/{policy_id}": { + "get": { + "description": "Get a specific policy by ID.", + "operationId": "get_policy_api_compliance_isms_policies__policy_id__get", + "parameters": [ + { + "in": "path", + "name": "policy_id", + "required": true, + "schema": { + "title": "Policy Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ISMSPolicyResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Policy", + "tags": [ + "compliance", + "ISMS" + ] + }, + "put": { + "description": "Update a policy (creates new version if approved).", + "operationId": "update_policy_api_compliance_isms_policies__policy_id__put", + "parameters": [ + { + "in": "path", + "name": "policy_id", + "required": true, + "schema": { + "title": "Policy Id", + "type": "string" + } + }, + { + "in": "query", + "name": "updated_by", + "required": true, + "schema": { + "title": "Updated By", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ISMSPolicyUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ISMSPolicyResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Policy", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/policies/{policy_id}/approve": { + "post": { + "description": "Approve a policy. Must be approved by top management.", + "operationId": "approve_policy_api_compliance_isms_policies__policy_id__approve_post", + "parameters": [ + { + "in": "path", + "name": "policy_id", + "required": true, + "schema": { + "title": "Policy Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ISMSPolicyApproveRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ISMSPolicyResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Approve Policy", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/readiness-check": { + "post": { + "description": "Run ISMS readiness check.\n\nIdentifies potential Major/Minor findings BEFORE external audit.\nThis helps achieve ISO 27001 certification on the first attempt.", + "operationId": "run_readiness_check_api_compliance_isms_readiness_check_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ISMSReadinessCheckRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ISMSReadinessCheckResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Run Readiness Check", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/readiness-check/latest": { + "get": { + "description": "Get the most recent readiness check result.", + "operationId": "get_latest_readiness_check_api_compliance_isms_readiness_check_latest_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ISMSReadinessCheckResponse" + } + } + }, + "description": "Successful Response" + } + }, + "summary": "Get Latest Readiness Check", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/scope": { + "get": { + "description": "Get the current ISMS scope.\n\nThe scope defines the boundaries and applicability of the ISMS.\nOnly one active scope should exist at a time.", + "operationId": "get_isms_scope_api_compliance_isms_scope_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ISMSScopeResponse" + } + } + }, + "description": "Successful Response" + } + }, + "summary": "Get Isms Scope", + "tags": [ + "compliance", + "ISMS" + ] + }, + "post": { + "description": "Create a new ISMS scope definition.\n\nSupersedes any existing scope.", + "operationId": "create_isms_scope_api_compliance_isms_scope_post", + "parameters": [ + { + "description": "User creating the scope", + "in": "query", + "name": "created_by", + "required": true, + "schema": { + "description": "User creating the scope", + "title": "Created By", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ISMSScopeCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ISMSScopeResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Isms Scope", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/scope/{scope_id}": { + "put": { + "description": "Update ISMS scope (only if in draft status).", + "operationId": "update_isms_scope_api_compliance_isms_scope__scope_id__put", + "parameters": [ + { + "in": "path", + "name": "scope_id", + "required": true, + "schema": { + "title": "Scope Id", + "type": "string" + } + }, + { + "description": "User updating the scope", + "in": "query", + "name": "updated_by", + "required": true, + "schema": { + "description": "User updating the scope", + "title": "Updated By", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ISMSScopeUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ISMSScopeResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Isms Scope", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/scope/{scope_id}/approve": { + "post": { + "description": "Approve the ISMS scope.\n\nThis is a MANDATORY step for ISO 27001 certification.\nMust be approved by top management.", + "operationId": "approve_isms_scope_api_compliance_isms_scope__scope_id__approve_post", + "parameters": [ + { + "in": "path", + "name": "scope_id", + "required": true, + "schema": { + "title": "Scope Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ISMSScopeApproveRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ISMSScopeResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Approve Isms Scope", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/soa": { + "get": { + "description": "List all Statement of Applicability entries.", + "operationId": "list_soa_entries_api_compliance_isms_soa_get", + "parameters": [ + { + "in": "query", + "name": "is_applicable", + "required": false, + "schema": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Is Applicable" + } + }, + { + "in": "query", + "name": "implementation_status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Implementation Status" + } + }, + { + "in": "query", + "name": "category", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Category" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SoAListResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Soa Entries", + "tags": [ + "compliance", + "ISMS" + ] + }, + "post": { + "description": "Create a new SoA entry for an Annex A control.", + "operationId": "create_soa_entry_api_compliance_isms_soa_post", + "parameters": [ + { + "in": "query", + "name": "created_by", + "required": true, + "schema": { + "title": "Created By", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SoAEntryCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SoAEntryResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Soa Entry", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/soa/{entry_id}": { + "put": { + "description": "Update an SoA entry.", + "operationId": "update_soa_entry_api_compliance_isms_soa__entry_id__put", + "parameters": [ + { + "in": "path", + "name": "entry_id", + "required": true, + "schema": { + "title": "Entry Id", + "type": "string" + } + }, + { + "in": "query", + "name": "updated_by", + "required": true, + "schema": { + "title": "Updated By", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SoAEntryUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SoAEntryResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Soa Entry", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/isms/soa/{entry_id}/approve": { + "post": { + "description": "Approve an SoA entry.", + "operationId": "approve_soa_entry_api_compliance_isms_soa__entry_id__approve_post", + "parameters": [ + { + "in": "path", + "name": "entry_id", + "required": true, + "schema": { + "title": "Entry Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SoAApproveRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SoAEntryResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Approve Soa Entry", + "tags": [ + "compliance", + "ISMS" + ] + } + }, + "/api/compliance/legal-documents/audit-log": { + "get": { + "description": "Consent audit trail (paginated).", + "operationId": "get_audit_log_api_compliance_legal_documents_audit_log_get", + "parameters": [ + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 50, + "maximum": 200, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "minimum": 0, + "title": "Offset", + "type": "integer" + } + }, + { + "in": "query", + "name": "action", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Action" + } + }, + { + "in": "query", + "name": "entity_type", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Entity Type" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Audit Log", + "tags": [ + "compliance", + "legal-documents" + ] + } + }, + "/api/compliance/legal-documents/consents": { + "post": { + "description": "Record user consent for a legal document.", + "operationId": "record_consent_api_compliance_legal_documents_consents_post", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserConsentCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Record Consent", + "tags": [ + "compliance", + "legal-documents" + ] + } + }, + "/api/compliance/legal-documents/consents/check/{document_type}": { + "get": { + "description": "Check if user has active consent for a document type.", + "operationId": "check_consent_api_compliance_legal_documents_consents_check__document_type__get", + "parameters": [ + { + "in": "path", + "name": "document_type", + "required": true, + "schema": { + "title": "Document Type", + "type": "string" + } + }, + { + "in": "query", + "name": "user_id", + "required": true, + "schema": { + "title": "User Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Check Consent", + "tags": [ + "compliance", + "legal-documents" + ] + } + }, + "/api/compliance/legal-documents/consents/my": { + "get": { + "description": "Get all consents for a specific user.", + "operationId": "get_my_consents_api_compliance_legal_documents_consents_my_get", + "parameters": [ + { + "in": "query", + "name": "user_id", + "required": true, + "schema": { + "title": "User Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get My Consents", + "tags": [ + "compliance", + "legal-documents" + ] + } + }, + "/api/compliance/legal-documents/consents/{consent_id}": { + "delete": { + "description": "Withdraw a consent (DSGVO Art. 7 Abs. 3).", + "operationId": "withdraw_consent_api_compliance_legal_documents_consents__consent_id__delete", + "parameters": [ + { + "in": "path", + "name": "consent_id", + "required": true, + "schema": { + "title": "Consent Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Withdraw Consent", + "tags": [ + "compliance", + "legal-documents" + ] + } + }, + "/api/compliance/legal-documents/cookie-categories": { + "get": { + "description": "List all cookie categories.", + "operationId": "list_cookie_categories_api_compliance_legal_documents_cookie_categories_get", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Cookie Categories", + "tags": [ + "compliance", + "legal-documents" + ] + }, + "post": { + "description": "Create a cookie category.", + "operationId": "create_cookie_category_api_compliance_legal_documents_cookie_categories_post", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CookieCategoryCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Cookie Category", + "tags": [ + "compliance", + "legal-documents" + ] + } + }, + "/api/compliance/legal-documents/cookie-categories/{category_id}": { + "delete": { + "description": "Delete a cookie category.", + "operationId": "delete_cookie_category_api_compliance_legal_documents_cookie_categories__category_id__delete", + "parameters": [ + { + "in": "path", + "name": "category_id", + "required": true, + "schema": { + "title": "Category Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "204": { + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Cookie Category", + "tags": [ + "compliance", + "legal-documents" + ] + }, + "put": { + "description": "Update a cookie category.", + "operationId": "update_cookie_category_api_compliance_legal_documents_cookie_categories__category_id__put", + "parameters": [ + { + "in": "path", + "name": "category_id", + "required": true, + "schema": { + "title": "Category Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CookieCategoryUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Cookie Category", + "tags": [ + "compliance", + "legal-documents" + ] + } + }, + "/api/compliance/legal-documents/documents": { + "get": { + "description": "List all legal documents, optionally filtered by tenant or type.", + "operationId": "list_documents_api_compliance_legal_documents_documents_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "query", + "name": "type", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Type" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "title": "Response List Documents Api Compliance Legal Documents Documents Get", + "type": "object" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Documents", + "tags": [ + "compliance", + "legal-documents" + ] + }, + "post": { + "description": "Create a new legal document type.", + "operationId": "create_document_api_compliance_legal_documents_documents_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentCreate" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Document", + "tags": [ + "compliance", + "legal-documents" + ] + } + }, + "/api/compliance/legal-documents/documents/{document_id}": { + "delete": { + "description": "Delete a legal document and all its versions.", + "operationId": "delete_document_api_compliance_legal_documents_documents__document_id__delete", + "parameters": [ + { + "in": "path", + "name": "document_id", + "required": true, + "schema": { + "title": "Document Id", + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Document", + "tags": [ + "compliance", + "legal-documents" + ] + }, + "get": { + "description": "Get a single legal document by ID.", + "operationId": "get_document_api_compliance_legal_documents_documents__document_id__get", + "parameters": [ + { + "in": "path", + "name": "document_id", + "required": true, + "schema": { + "title": "Document Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Document", + "tags": [ + "compliance", + "legal-documents" + ] + } + }, + "/api/compliance/legal-documents/documents/{document_id}/versions": { + "get": { + "description": "List all versions for a legal document.", + "operationId": "list_versions_api_compliance_legal_documents_documents__document_id__versions_get", + "parameters": [ + { + "in": "path", + "name": "document_id", + "required": true, + "schema": { + "title": "Document Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "items": { + "$ref": "#/components/schemas/VersionResponse" + }, + "title": "Response List Versions Api Compliance Legal Documents Documents Document Id Versions Get", + "type": "array" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Versions", + "tags": [ + "compliance", + "legal-documents" + ] + } + }, + "/api/compliance/legal-documents/public": { + "get": { + "description": "Active documents for end-user display.", + "operationId": "list_public_documents_api_compliance_legal_documents_public_get", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Public Documents", + "tags": [ + "compliance", + "legal-documents" + ] + } + }, + "/api/compliance/legal-documents/public/{document_type}/latest": { + "get": { + "description": "Get the latest published version of a document type.", + "operationId": "get_latest_published_api_compliance_legal_documents_public__document_type__latest_get", + "parameters": [ + { + "in": "path", + "name": "document_type", + "required": true, + "schema": { + "title": "Document Type", + "type": "string" + } + }, + { + "in": "query", + "name": "language", + "required": false, + "schema": { + "default": "de", + "title": "Language", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Latest Published", + "tags": [ + "compliance", + "legal-documents" + ] + } + }, + "/api/compliance/legal-documents/stats/consents": { + "get": { + "description": "Consent statistics for dashboard.", + "operationId": "get_consent_stats_api_compliance_legal_documents_stats_consents_get", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Consent Stats", + "tags": [ + "compliance", + "legal-documents" + ] + } + }, + "/api/compliance/legal-documents/versions": { + "post": { + "description": "Create a new version for a legal document.", + "operationId": "create_version_api_compliance_legal_documents_versions_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/compliance__api__legal_document_routes__VersionCreate" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VersionResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Version", + "tags": [ + "compliance", + "legal-documents" + ] + } + }, + "/api/compliance/legal-documents/versions/upload-word": { + "post": { + "description": "Convert DOCX to HTML using mammoth (if available) or return raw text.", + "operationId": "upload_word_api_compliance_legal_documents_versions_upload_word_post", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_upload_word_api_compliance_legal_documents_versions_upload_word_post" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "title": "Response Upload Word Api Compliance Legal Documents Versions Upload Word Post", + "type": "object" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Upload Word", + "tags": [ + "compliance", + "legal-documents" + ] + } + }, + "/api/compliance/legal-documents/versions/{version_id}": { + "get": { + "description": "Get a single version by ID.", + "operationId": "get_version_api_compliance_legal_documents_versions__version_id__get", + "parameters": [ + { + "in": "path", + "name": "version_id", + "required": true, + "schema": { + "title": "Version Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VersionResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Version", + "tags": [ + "compliance", + "legal-documents" + ] + }, + "put": { + "description": "Update a draft legal document version.", + "operationId": "update_version_api_compliance_legal_documents_versions__version_id__put", + "parameters": [ + { + "in": "path", + "name": "version_id", + "required": true, + "schema": { + "title": "Version Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/compliance__api__legal_document_routes__VersionUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VersionResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Version", + "tags": [ + "compliance", + "legal-documents" + ] + } + }, + "/api/compliance/legal-documents/versions/{version_id}/approval-history": { + "get": { + "description": "Get the full approval audit trail for a version.", + "operationId": "get_approval_history_api_compliance_legal_documents_versions__version_id__approval_history_get", + "parameters": [ + { + "in": "path", + "name": "version_id", + "required": true, + "schema": { + "title": "Version Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "items": { + "$ref": "#/components/schemas/ApprovalHistoryEntry" + }, + "title": "Response Get Approval History Api Compliance Legal Documents Versions Version Id Approval History Get", + "type": "array" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Approval History", + "tags": [ + "compliance", + "legal-documents" + ] + } + }, + "/api/compliance/legal-documents/versions/{version_id}/approve": { + "post": { + "description": "Approve a version under review.", + "operationId": "approve_version_api_compliance_legal_documents_versions__version_id__approve_post", + "parameters": [ + { + "in": "path", + "name": "version_id", + "required": true, + "schema": { + "title": "Version Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ActionRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VersionResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Approve Version", + "tags": [ + "compliance", + "legal-documents" + ] + } + }, + "/api/compliance/legal-documents/versions/{version_id}/publish": { + "post": { + "description": "Publish an approved version.", + "operationId": "publish_version_api_compliance_legal_documents_versions__version_id__publish_post", + "parameters": [ + { + "in": "path", + "name": "version_id", + "required": true, + "schema": { + "title": "Version Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ActionRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VersionResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Publish Version", + "tags": [ + "compliance", + "legal-documents" + ] + } + }, + "/api/compliance/legal-documents/versions/{version_id}/reject": { + "post": { + "description": "Reject a version under review.", + "operationId": "reject_version_api_compliance_legal_documents_versions__version_id__reject_post", + "parameters": [ + { + "in": "path", + "name": "version_id", + "required": true, + "schema": { + "title": "Version Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ActionRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VersionResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Reject Version", + "tags": [ + "compliance", + "legal-documents" + ] + } + }, + "/api/compliance/legal-documents/versions/{version_id}/submit-review": { + "post": { + "description": "Submit a draft version for review.", + "operationId": "submit_review_api_compliance_legal_documents_versions__version_id__submit_review_post", + "parameters": [ + { + "in": "path", + "name": "version_id", + "required": true, + "schema": { + "title": "Version Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ActionRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VersionResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Submit Review", + "tags": [ + "compliance", + "legal-documents" + ] + } + }, + "/api/compliance/legal-templates": { + "get": { + "description": "List legal templates with optional filters.", + "operationId": "list_legal_templates_api_compliance_legal_templates_get", + "parameters": [ + { + "description": "Full-text ILIKE search on title/description/content", + "in": "query", + "name": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Full-text ILIKE search on title/description/content", + "title": "Query" + } + }, + { + "in": "query", + "name": "document_type", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Document Type" + } + }, + { + "in": "query", + "name": "language", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Language" + } + }, + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": "published", + "title": "Status" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 50, + "maximum": 200, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "minimum": 0, + "title": "Offset", + "type": "integer" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Legal Templates", + "tags": [ + "compliance", + "legal-templates" + ] + }, + "post": { + "description": "Create a new legal template.", + "operationId": "create_legal_template_api_compliance_legal_templates_post", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LegalTemplateCreate" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Legal Template", + "tags": [ + "compliance", + "legal-templates" + ] + } + }, + "/api/compliance/legal-templates/sources": { + "get": { + "description": "Return distinct source_name values.", + "operationId": "get_template_sources_api_compliance_legal_templates_sources_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Template Sources", + "tags": [ + "compliance", + "legal-templates" + ] + } + }, + "/api/compliance/legal-templates/status": { + "get": { + "description": "Return template counts by document_type.", + "operationId": "get_templates_status_api_compliance_legal_templates_status_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Templates Status", + "tags": [ + "compliance", + "legal-templates" + ] + } + }, + "/api/compliance/legal-templates/{template_id}": { + "delete": { + "description": "Delete a legal template.", + "operationId": "delete_legal_template_api_compliance_legal_templates__template_id__delete", + "parameters": [ + { + "in": "path", + "name": "template_id", + "required": true, + "schema": { + "title": "Template Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "204": { + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Legal Template", + "tags": [ + "compliance", + "legal-templates" + ] + }, + "get": { + "description": "Fetch a single template by ID.", + "operationId": "get_legal_template_api_compliance_legal_templates__template_id__get", + "parameters": [ + { + "in": "path", + "name": "template_id", + "required": true, + "schema": { + "title": "Template Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Legal Template", + "tags": [ + "compliance", + "legal-templates" + ] + }, + "put": { + "description": "Update an existing legal template.", + "operationId": "update_legal_template_api_compliance_legal_templates__template_id__put", + "parameters": [ + { + "in": "path", + "name": "template_id", + "required": true, + "schema": { + "title": "Template Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LegalTemplateUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Legal Template", + "tags": [ + "compliance", + "legal-templates" + ] + } + }, + "/api/compliance/loeschfristen": { + "get": { + "description": "List Loeschfristen with optional filters.", + "operationId": "list_loeschfristen_api_compliance_loeschfristen_get", + "parameters": [ + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "in": "query", + "name": "retention_driver", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Retention Driver" + } + }, + { + "in": "query", + "name": "search", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Search" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 500, + "maximum": 1000, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "minimum": 0, + "title": "Offset", + "type": "integer" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Loeschfristen", + "tags": [ + "compliance", + "loeschfristen" + ] + }, + "post": { + "description": "Create a new Loeschfrist policy.", + "operationId": "create_loeschfrist_api_compliance_loeschfristen_post", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LoeschfristCreate" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Loeschfrist", + "tags": [ + "compliance", + "loeschfristen" + ] + } + }, + "/api/compliance/loeschfristen/stats": { + "get": { + "description": "Return Loeschfristen statistics.", + "operationId": "get_loeschfristen_stats_api_compliance_loeschfristen_stats_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Loeschfristen Stats", + "tags": [ + "compliance", + "loeschfristen" + ] + } + }, + "/api/compliance/loeschfristen/{policy_id}": { + "delete": { + "operationId": "delete_loeschfrist_api_compliance_loeschfristen__policy_id__delete", + "parameters": [ + { + "in": "path", + "name": "policy_id", + "required": true, + "schema": { + "title": "Policy Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "204": { + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Loeschfrist", + "tags": [ + "compliance", + "loeschfristen" + ] + }, + "get": { + "operationId": "get_loeschfrist_api_compliance_loeschfristen__policy_id__get", + "parameters": [ + { + "in": "path", + "name": "policy_id", + "required": true, + "schema": { + "title": "Policy Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Loeschfrist", + "tags": [ + "compliance", + "loeschfristen" + ] + }, + "put": { + "description": "Full update of a Loeschfrist policy.", + "operationId": "update_loeschfrist_api_compliance_loeschfristen__policy_id__put", + "parameters": [ + { + "in": "path", + "name": "policy_id", + "required": true, + "schema": { + "title": "Policy Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LoeschfristUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Loeschfrist", + "tags": [ + "compliance", + "loeschfristen" + ] + } + }, + "/api/compliance/loeschfristen/{policy_id}/status": { + "put": { + "description": "Quick status update.", + "operationId": "update_loeschfrist_status_api_compliance_loeschfristen__policy_id__status_put", + "parameters": [ + { + "in": "path", + "name": "policy_id", + "required": true, + "schema": { + "title": "Policy Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/compliance__api__incident_routes__StatusUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Loeschfrist Status", + "tags": [ + "compliance", + "loeschfristen" + ] + } + }, + "/api/compliance/loeschfristen/{policy_id}/versions": { + "get": { + "description": "List all versions for a Loeschfrist.", + "operationId": "list_loeschfristen_versions_api_compliance_loeschfristen__policy_id__versions_get", + "parameters": [ + { + "in": "path", + "name": "policy_id", + "required": true, + "schema": { + "title": "Policy Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Loeschfristen Versions", + "tags": [ + "compliance", + "loeschfristen" + ] + } + }, + "/api/compliance/loeschfristen/{policy_id}/versions/{version_number}": { + "get": { + "description": "Get a specific Loeschfristen version with full snapshot.", + "operationId": "get_loeschfristen_version_api_compliance_loeschfristen__policy_id__versions__version_number__get", + "parameters": [ + { + "in": "path", + "name": "policy_id", + "required": true, + "schema": { + "title": "Policy Id", + "type": "string" + } + }, + { + "in": "path", + "name": "version_number", + "required": true, + "schema": { + "title": "Version Number", + "type": "integer" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Loeschfristen Version", + "tags": [ + "compliance", + "loeschfristen" + ] + } + }, + "/api/compliance/modules": { + "get": { + "description": "List all service modules with optional filters.", + "operationId": "list_modules_api_compliance_modules_get", + "parameters": [ + { + "in": "query", + "name": "service_type", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Service Type" + } + }, + { + "in": "query", + "name": "criticality", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Criticality" + } + }, + { + "in": "query", + "name": "processes_pii", + "required": false, + "schema": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Processes Pii" + } + }, + { + "in": "query", + "name": "ai_components", + "required": false, + "schema": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Ai Components" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceModuleListResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Modules", + "tags": [ + "compliance", + "compliance-modules" + ] + } + }, + "/api/compliance/modules/overview": { + "get": { + "description": "Get overview statistics for all modules.", + "operationId": "get_modules_overview_api_compliance_modules_overview_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ModuleComplianceOverview" + } + } + }, + "description": "Successful Response" + } + }, + "summary": "Get Modules Overview", + "tags": [ + "compliance", + "compliance-modules" + ] + } + }, + "/api/compliance/modules/seed": { + "post": { + "description": "Seed service modules from predefined data.", + "operationId": "seed_modules_api_compliance_modules_seed_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ModuleSeedRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ModuleSeedResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Seed Modules", + "tags": [ + "compliance", + "compliance-modules" + ] + } + }, + "/api/compliance/modules/{module_id}": { + "get": { + "description": "Get a specific module with its regulations and risks.", + "operationId": "get_module_api_compliance_modules__module_id__get", + "parameters": [ + { + "in": "path", + "name": "module_id", + "required": true, + "schema": { + "title": "Module Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceModuleDetailResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Module", + "tags": [ + "compliance", + "compliance-modules" + ] + } + }, + "/api/compliance/modules/{module_id}/activate": { + "post": { + "description": "Activate a service module.", + "operationId": "activate_module_api_compliance_modules__module_id__activate_post", + "parameters": [ + { + "in": "path", + "name": "module_id", + "required": true, + "schema": { + "title": "Module Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Activate Module", + "tags": [ + "compliance", + "compliance-modules" + ] + } + }, + "/api/compliance/modules/{module_id}/deactivate": { + "post": { + "description": "Deactivate a service module.", + "operationId": "deactivate_module_api_compliance_modules__module_id__deactivate_post", + "parameters": [ + { + "in": "path", + "name": "module_id", + "required": true, + "schema": { + "title": "Module Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Deactivate Module", + "tags": [ + "compliance", + "compliance-modules" + ] + } + }, + "/api/compliance/modules/{module_id}/regulations": { + "post": { + "description": "Add a regulation mapping to a module.", + "operationId": "add_module_regulation_api_compliance_modules__module_id__regulations_post", + "parameters": [ + { + "in": "path", + "name": "module_id", + "required": true, + "schema": { + "title": "Module Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ModuleRegulationMappingCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ModuleRegulationMappingResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Add Module Regulation", + "tags": [ + "compliance", + "compliance-modules" + ] + } + }, + "/api/compliance/notfallplan/checklists": { + "get": { + "description": "List checklist items, optionally filtered by scenario_id.", + "operationId": "list_checklists_api_compliance_notfallplan_checklists_get", + "parameters": [ + { + "in": "query", + "name": "scenario_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Scenario Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Checklists", + "tags": [ + "compliance", + "notfallplan" + ] + }, + "post": { + "description": "Create a new checklist item.", + "operationId": "create_checklist_api_compliance_notfallplan_checklists_post", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChecklistCreate" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Checklist", + "tags": [ + "compliance", + "notfallplan" + ] + } + }, + "/api/compliance/notfallplan/checklists/{checklist_id}": { + "delete": { + "description": "Delete a checklist item.", + "operationId": "delete_checklist_api_compliance_notfallplan_checklists__checklist_id__delete", + "parameters": [ + { + "in": "path", + "name": "checklist_id", + "required": true, + "schema": { + "title": "Checklist Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Checklist", + "tags": [ + "compliance", + "notfallplan" + ] + }, + "put": { + "description": "Update a checklist item.", + "operationId": "update_checklist_api_compliance_notfallplan_checklists__checklist_id__put", + "parameters": [ + { + "in": "path", + "name": "checklist_id", + "required": true, + "schema": { + "title": "Checklist Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChecklistUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Checklist", + "tags": [ + "compliance", + "notfallplan" + ] + } + }, + "/api/compliance/notfallplan/contacts": { + "get": { + "description": "List all emergency contacts for a tenant.", + "operationId": "list_contacts_api_compliance_notfallplan_contacts_get", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Contacts", + "tags": [ + "compliance", + "notfallplan" + ] + }, + "post": { + "description": "Create a new emergency contact.", + "operationId": "create_contact_api_compliance_notfallplan_contacts_post", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContactCreate" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Contact", + "tags": [ + "compliance", + "notfallplan" + ] + } + }, + "/api/compliance/notfallplan/contacts/{contact_id}": { + "delete": { + "description": "Delete an emergency contact.", + "operationId": "delete_contact_api_compliance_notfallplan_contacts__contact_id__delete", + "parameters": [ + { + "in": "path", + "name": "contact_id", + "required": true, + "schema": { + "title": "Contact Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Contact", + "tags": [ + "compliance", + "notfallplan" + ] + }, + "put": { + "description": "Update an existing emergency contact.", + "operationId": "update_contact_api_compliance_notfallplan_contacts__contact_id__put", + "parameters": [ + { + "in": "path", + "name": "contact_id", + "required": true, + "schema": { + "title": "Contact Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContactUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Contact", + "tags": [ + "compliance", + "notfallplan" + ] + } + }, + "/api/compliance/notfallplan/exercises": { + "get": { + "description": "List all exercises for a tenant.", + "operationId": "list_exercises_api_compliance_notfallplan_exercises_get", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Exercises", + "tags": [ + "compliance", + "notfallplan" + ] + }, + "post": { + "description": "Create a new exercise.", + "operationId": "create_exercise_api_compliance_notfallplan_exercises_post", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExerciseCreate" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Exercise", + "tags": [ + "compliance", + "notfallplan" + ] + } + }, + "/api/compliance/notfallplan/incidents": { + "get": { + "description": "List all incidents for a tenant.", + "operationId": "list_incidents_api_compliance_notfallplan_incidents_get", + "parameters": [ + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "in": "query", + "name": "severity", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Severity" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Incidents", + "tags": [ + "compliance", + "notfallplan" + ] + }, + "post": { + "description": "Create a new incident.", + "operationId": "create_incident_api_compliance_notfallplan_incidents_post", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/compliance__api__notfallplan_routes__IncidentCreate" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Incident", + "tags": [ + "compliance", + "notfallplan" + ] + } + }, + "/api/compliance/notfallplan/incidents/{incident_id}": { + "delete": { + "description": "Delete an incident.", + "operationId": "delete_incident_api_compliance_notfallplan_incidents__incident_id__delete", + "parameters": [ + { + "in": "path", + "name": "incident_id", + "required": true, + "schema": { + "title": "Incident Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "204": { + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Incident", + "tags": [ + "compliance", + "notfallplan" + ] + }, + "put": { + "description": "Update an incident (including status transitions).", + "operationId": "update_incident_api_compliance_notfallplan_incidents__incident_id__put", + "parameters": [ + { + "in": "path", + "name": "incident_id", + "required": true, + "schema": { + "title": "Incident Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/compliance__api__notfallplan_routes__IncidentUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Incident", + "tags": [ + "compliance", + "notfallplan" + ] + } + }, + "/api/compliance/notfallplan/scenarios": { + "get": { + "description": "List all scenarios for a tenant.", + "operationId": "list_scenarios_api_compliance_notfallplan_scenarios_get", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Scenarios", + "tags": [ + "compliance", + "notfallplan" + ] + }, + "post": { + "description": "Create a new scenario.", + "operationId": "create_scenario_api_compliance_notfallplan_scenarios_post", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScenarioCreate" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Scenario", + "tags": [ + "compliance", + "notfallplan" + ] + } + }, + "/api/compliance/notfallplan/scenarios/{scenario_id}": { + "delete": { + "description": "Delete a scenario.", + "operationId": "delete_scenario_api_compliance_notfallplan_scenarios__scenario_id__delete", + "parameters": [ + { + "in": "path", + "name": "scenario_id", + "required": true, + "schema": { + "title": "Scenario Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Scenario", + "tags": [ + "compliance", + "notfallplan" + ] + }, + "put": { + "description": "Update an existing scenario.", + "operationId": "update_scenario_api_compliance_notfallplan_scenarios__scenario_id__put", + "parameters": [ + { + "in": "path", + "name": "scenario_id", + "required": true, + "schema": { + "title": "Scenario Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScenarioUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Scenario", + "tags": [ + "compliance", + "notfallplan" + ] + } + }, + "/api/compliance/notfallplan/stats": { + "get": { + "description": "Return statistics for the Notfallplan module.", + "operationId": "get_stats_api_compliance_notfallplan_stats_get", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Stats", + "tags": [ + "compliance", + "notfallplan" + ] + } + }, + "/api/compliance/notfallplan/templates": { + "get": { + "description": "List Melde-Templates for a tenant.", + "operationId": "list_templates_api_compliance_notfallplan_templates_get", + "parameters": [ + { + "in": "query", + "name": "type", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Type" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Templates", + "tags": [ + "compliance", + "notfallplan" + ] + }, + "post": { + "description": "Create a new Melde-Template.", + "operationId": "create_template_api_compliance_notfallplan_templates_post", + "parameters": [ + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/compliance__api__notfallplan_routes__TemplateCreate" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Template", + "tags": [ + "compliance", + "notfallplan" + ] + } + }, + "/api/compliance/notfallplan/templates/{template_id}": { + "delete": { + "description": "Delete a Melde-Template.", + "operationId": "delete_template_api_compliance_notfallplan_templates__template_id__delete", + "parameters": [ + { + "in": "path", + "name": "template_id", + "required": true, + "schema": { + "title": "Template Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "204": { + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Template", + "tags": [ + "compliance", + "notfallplan" + ] + }, + "put": { + "description": "Update a Melde-Template.", + "operationId": "update_template_api_compliance_notfallplan_templates__template_id__put", + "parameters": [ + { + "in": "path", + "name": "template_id", + "required": true, + "schema": { + "title": "Template Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TemplateUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Template", + "tags": [ + "compliance", + "notfallplan" + ] + } + }, + "/api/compliance/obligations": { + "get": { + "description": "List obligations with optional filters.", + "operationId": "list_obligations_api_compliance_obligations_get", + "parameters": [ + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "in": "query", + "name": "priority", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Priority" + } + }, + { + "in": "query", + "name": "source", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source" + } + }, + { + "in": "query", + "name": "search", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Search" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 100, + "maximum": 500, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "minimum": 0, + "title": "Offset", + "type": "integer" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Obligations", + "tags": [ + "compliance", + "obligations" + ] + }, + "post": { + "description": "Create a new compliance obligation.", + "operationId": "create_obligation_api_compliance_obligations_post", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "x-user-id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-User-Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ObligationCreate" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Obligation", + "tags": [ + "compliance", + "obligations" + ] + } + }, + "/api/compliance/obligations/stats": { + "get": { + "description": "Return obligation counts per status and priority.", + "operationId": "get_obligation_stats_api_compliance_obligations_stats_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Obligation Stats", + "tags": [ + "compliance", + "obligations" + ] + } + }, + "/api/compliance/obligations/{obligation_id}": { + "delete": { + "operationId": "delete_obligation_api_compliance_obligations__obligation_id__delete", + "parameters": [ + { + "in": "path", + "name": "obligation_id", + "required": true, + "schema": { + "title": "Obligation Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "x-user-id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-User-Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "204": { + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Obligation", + "tags": [ + "compliance", + "obligations" + ] + }, + "get": { + "operationId": "get_obligation_api_compliance_obligations__obligation_id__get", + "parameters": [ + { + "in": "path", + "name": "obligation_id", + "required": true, + "schema": { + "title": "Obligation Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Obligation", + "tags": [ + "compliance", + "obligations" + ] + }, + "put": { + "description": "Update an obligation's fields.", + "operationId": "update_obligation_api_compliance_obligations__obligation_id__put", + "parameters": [ + { + "in": "path", + "name": "obligation_id", + "required": true, + "schema": { + "title": "Obligation Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "x-user-id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-User-Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ObligationUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Obligation", + "tags": [ + "compliance", + "obligations" + ] + } + }, + "/api/compliance/obligations/{obligation_id}/status": { + "put": { + "description": "Quick status update for an obligation.", + "operationId": "update_obligation_status_api_compliance_obligations__obligation_id__status_put", + "parameters": [ + { + "in": "path", + "name": "obligation_id", + "required": true, + "schema": { + "title": "Obligation Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "x-user-id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-User-Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ObligationStatusUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Obligation Status", + "tags": [ + "compliance", + "obligations" + ] + } + }, + "/api/compliance/obligations/{obligation_id}/versions": { + "get": { + "description": "List all versions for an Obligation.", + "operationId": "list_obligation_versions_api_compliance_obligations__obligation_id__versions_get", + "parameters": [ + { + "in": "path", + "name": "obligation_id", + "required": true, + "schema": { + "title": "Obligation Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Obligation Versions", + "tags": [ + "compliance", + "obligations" + ] + } + }, + "/api/compliance/obligations/{obligation_id}/versions/{version_number}": { + "get": { + "description": "Get a specific Obligation version with full snapshot.", + "operationId": "get_obligation_version_api_compliance_obligations__obligation_id__versions__version_number__get", + "parameters": [ + { + "in": "path", + "name": "obligation_id", + "required": true, + "schema": { + "title": "Obligation Id", + "type": "string" + } + }, + { + "in": "path", + "name": "version_number", + "required": true, + "schema": { + "title": "Version Number", + "type": "integer" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Obligation Version", + "tags": [ + "compliance", + "obligations" + ] + } + }, + "/api/compliance/quality/metrics": { + "get": { + "description": "List quality metrics.", + "operationId": "list_metrics_api_compliance_quality_metrics_get", + "parameters": [ + { + "in": "query", + "name": "category", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Category" + } + }, + { + "in": "query", + "name": "ai_system", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Ai System" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 100, + "maximum": 500, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "minimum": 0, + "title": "Offset", + "type": "integer" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Metrics", + "tags": [ + "compliance", + "quality" + ] + }, + "post": { + "description": "Create a new quality metric.", + "operationId": "create_metric_api_compliance_quality_metrics_post", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MetricCreate" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Metric", + "tags": [ + "compliance", + "quality" + ] + } + }, + "/api/compliance/quality/metrics/{metric_id}": { + "delete": { + "operationId": "delete_metric_api_compliance_quality_metrics__metric_id__delete", + "parameters": [ + { + "in": "path", + "name": "metric_id", + "required": true, + "schema": { + "title": "Metric Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "204": { + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Metric", + "tags": [ + "compliance", + "quality" + ] + }, + "put": { + "description": "Update a quality metric.", + "operationId": "update_metric_api_compliance_quality_metrics__metric_id__put", + "parameters": [ + { + "in": "path", + "name": "metric_id", + "required": true, + "schema": { + "title": "Metric Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MetricUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Metric", + "tags": [ + "compliance", + "quality" + ] + } + }, + "/api/compliance/quality/stats": { + "get": { + "description": "Return quality dashboard stats.", + "operationId": "get_quality_stats_api_compliance_quality_stats_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Quality Stats", + "tags": [ + "compliance", + "quality" + ] + } + }, + "/api/compliance/quality/tests": { + "get": { + "description": "List quality tests.", + "operationId": "list_tests_api_compliance_quality_tests_get", + "parameters": [ + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "in": "query", + "name": "ai_system", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Ai System" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 100, + "maximum": 500, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "minimum": 0, + "title": "Offset", + "type": "integer" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Tests", + "tags": [ + "compliance", + "quality" + ] + }, + "post": { + "description": "Create a new quality test entry.", + "operationId": "create_test_api_compliance_quality_tests_post", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TestCreate" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Test", + "tags": [ + "compliance", + "quality" + ] + } + }, + "/api/compliance/quality/tests/{test_id}": { + "delete": { + "operationId": "delete_test_api_compliance_quality_tests__test_id__delete", + "parameters": [ + { + "in": "path", + "name": "test_id", + "required": true, + "schema": { + "title": "Test Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "204": { + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Test", + "tags": [ + "compliance", + "quality" + ] + }, + "put": { + "description": "Update a quality test.", + "operationId": "update_test_api_compliance_quality_tests__test_id__put", + "parameters": [ + { + "in": "path", + "name": "test_id", + "required": true, + "schema": { + "title": "Test Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TestUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Test", + "tags": [ + "compliance", + "quality" + ] + } + }, + "/api/compliance/regulations": { + "get": { + "description": "List all regulations.", + "operationId": "list_regulations_api_compliance_regulations_get", + "parameters": [ + { + "in": "query", + "name": "is_active", + "required": false, + "schema": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Is Active" + } + }, + { + "in": "query", + "name": "regulation_type", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Regulation Type" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RegulationListResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Regulations", + "tags": [ + "compliance" + ] + } + }, + "/api/compliance/regulations/{code}": { + "get": { + "description": "Get a specific regulation by code.", + "operationId": "get_regulation_api_compliance_regulations__code__get", + "parameters": [ + { + "in": "path", + "name": "code", + "required": true, + "schema": { + "title": "Code", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RegulationResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Regulation", + "tags": [ + "compliance" + ] + } + }, + "/api/compliance/regulations/{code}/requirements": { + "get": { + "description": "Get requirements for a specific regulation.", + "operationId": "get_regulation_requirements_api_compliance_regulations__code__requirements_get", + "parameters": [ + { + "in": "path", + "name": "code", + "required": true, + "schema": { + "title": "Code", + "type": "string" + } + }, + { + "in": "query", + "name": "is_applicable", + "required": false, + "schema": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Is Applicable" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RequirementListResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Regulation Requirements", + "tags": [ + "compliance" + ] + } + }, + "/api/compliance/reports/summary": { + "get": { + "description": "Get a quick summary report for the dashboard.", + "operationId": "get_summary_report_api_compliance_reports_summary_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "Get Summary Report", + "tags": [ + "compliance", + "compliance-dashboard" + ] + } + }, + "/api/compliance/reports/{period}": { + "get": { + "description": "Generate a compliance report for the specified period.\n\nArgs:\n period: One of 'weekly', 'monthly', 'quarterly', 'yearly'\n as_of_date: Report date (YYYY-MM-DD format, defaults to today)\n\nReturns:\n Complete compliance report", + "operationId": "generate_period_report_api_compliance_reports__period__get", + "parameters": [ + { + "in": "path", + "name": "period", + "required": true, + "schema": { + "title": "Period", + "type": "string" + } + }, + { + "in": "query", + "name": "as_of_date", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "As Of Date" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Generate Period Report", + "tags": [ + "compliance", + "compliance-dashboard" + ] + } + }, + "/api/compliance/requirements": { + "get": { + "description": "List requirements with pagination and eager-loaded relationships.\n\nThis endpoint is optimized for large datasets (1000+ requirements) with:\n- Eager loading to prevent N+1 queries\n- Server-side pagination\n- Full-text search support", + "operationId": "list_requirements_paginated_api_compliance_requirements_get", + "parameters": [ + { + "description": "Page number", + "in": "query", + "name": "page", + "required": false, + "schema": { + "default": 1, + "description": "Page number", + "minimum": 1, + "title": "Page", + "type": "integer" + } + }, + { + "description": "Items per page", + "in": "query", + "name": "page_size", + "required": false, + "schema": { + "default": 50, + "description": "Items per page", + "maximum": 500, + "minimum": 1, + "title": "Page Size", + "type": "integer" + } + }, + { + "description": "Filter by regulation code", + "in": "query", + "name": "regulation_code", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter by regulation code", + "title": "Regulation Code" + } + }, + { + "description": "Filter by implementation status", + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter by implementation status", + "title": "Status" + } + }, + { + "description": "Filter by applicability", + "in": "query", + "name": "is_applicable", + "required": false, + "schema": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Filter by applicability", + "title": "Is Applicable" + } + }, + { + "description": "Search in title/description", + "in": "query", + "name": "search", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Search in title/description", + "title": "Search" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaginatedRequirementResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Requirements Paginated", + "tags": [ + "compliance" + ] + }, + "post": { + "description": "Create a new requirement.", + "operationId": "create_requirement_api_compliance_requirements_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RequirementCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RequirementResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Requirement", + "tags": [ + "compliance" + ] + } + }, + "/api/compliance/requirements/{requirement_id}": { + "delete": { + "description": "Delete a requirement by ID.", + "operationId": "delete_requirement_api_compliance_requirements__requirement_id__delete", + "parameters": [ + { + "in": "path", + "name": "requirement_id", + "required": true, + "schema": { + "title": "Requirement Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Requirement", + "tags": [ + "compliance" + ] + }, + "get": { + "description": "Get a specific requirement by ID, optionally with RAG legal context.", + "operationId": "get_requirement_api_compliance_requirements__requirement_id__get", + "parameters": [ + { + "in": "path", + "name": "requirement_id", + "required": true, + "schema": { + "title": "Requirement Id", + "type": "string" + } + }, + { + "description": "Include RAG legal context", + "in": "query", + "name": "include_legal_context", + "required": false, + "schema": { + "default": false, + "description": "Include RAG legal context", + "title": "Include Legal Context", + "type": "boolean" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Requirement", + "tags": [ + "compliance" + ] + }, + "put": { + "description": "Update a requirement with implementation/audit details.", + "operationId": "update_requirement_api_compliance_requirements__requirement_id__put", + "parameters": [ + { + "in": "path", + "name": "requirement_id", + "required": true, + "schema": { + "title": "Requirement Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "title": "Updates", + "type": "object" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Requirement", + "tags": [ + "compliance" + ] + } + }, + "/api/compliance/risks": { + "get": { + "description": "List risks with optional filters.", + "operationId": "list_risks_api_compliance_risks_get", + "parameters": [ + { + "in": "query", + "name": "category", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Category" + } + }, + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "in": "query", + "name": "risk_level", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Risk Level" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RiskListResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Risks", + "tags": [ + "compliance", + "compliance-risks" + ] + }, + "post": { + "description": "Create a new risk.", + "operationId": "create_risk_api_compliance_risks_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RiskCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RiskResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Risk", + "tags": [ + "compliance", + "compliance-risks" + ] + } + }, + "/api/compliance/risks/matrix": { + "get": { + "description": "Get risk matrix data for visualization.", + "operationId": "get_risk_matrix_api_compliance_risks_matrix_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RiskMatrixResponse" + } + } + }, + "description": "Successful Response" + } + }, + "summary": "Get Risk Matrix", + "tags": [ + "compliance", + "compliance-risks" + ] + } + }, + "/api/compliance/risks/{risk_id}": { + "delete": { + "description": "Delete a risk.", + "operationId": "delete_risk_api_compliance_risks__risk_id__delete", + "parameters": [ + { + "in": "path", + "name": "risk_id", + "required": true, + "schema": { + "title": "Risk Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Risk", + "tags": [ + "compliance", + "compliance-risks" + ] + }, + "put": { + "description": "Update a risk.", + "operationId": "update_risk_api_compliance_risks__risk_id__put", + "parameters": [ + { + "in": "path", + "name": "risk_id", + "required": true, + "schema": { + "title": "Risk Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RiskUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RiskResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Risk", + "tags": [ + "compliance", + "compliance-risks" + ] + } + }, + "/api/compliance/score": { + "get": { + "description": "Get just the compliance score.", + "operationId": "get_compliance_score_api_compliance_score_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "Get Compliance Score", + "tags": [ + "compliance", + "compliance-dashboard" + ] + } + }, + "/api/compliance/scraper/extract-bsi": { + "post": { + "description": "Extract requirements from BSI Technical Guidelines.\n\nUses pre-defined Pruefaspekte from BSI-TR-03161 documents.", + "operationId": "extract_bsi_requirements_api_compliance_scraper_extract_bsi_post", + "parameters": [ + { + "description": "BSI TR code", + "in": "query", + "name": "code", + "required": false, + "schema": { + "default": "BSI-TR-03161-2", + "description": "BSI TR code", + "title": "Code", + "type": "string" + } + }, + { + "in": "query", + "name": "force", + "required": false, + "schema": { + "default": false, + "title": "Force", + "type": "boolean" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Extract Bsi Requirements", + "tags": [ + "compliance", + "compliance-scraper" + ] + } + }, + "/api/compliance/scraper/extract-pdf": { + "post": { + "description": "Extract Pruefaspekte from BSI-TR PDF documents using PyMuPDF.\n\nSupported documents:\n- BSI-TR-03161-1: General security requirements\n- BSI-TR-03161-2: Web application security (OAuth, Sessions, etc.)\n- BSI-TR-03161-3: Backend/server security", + "operationId": "extract_pdf_requirements_api_compliance_scraper_extract_pdf_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PDFExtractionRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PDFExtractionResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Extract Pdf Requirements", + "tags": [ + "compliance", + "compliance-scraper" + ] + } + }, + "/api/compliance/scraper/pdf-documents": { + "get": { + "description": "List available PDF documents for extraction.", + "operationId": "list_pdf_documents_api_compliance_scraper_pdf_documents_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "List Pdf Documents", + "tags": [ + "compliance", + "compliance-scraper" + ] + } + }, + "/api/compliance/scraper/scrape-all": { + "post": { + "description": "Start scraping all known regulation sources.", + "operationId": "scrape_all_sources_api_compliance_scraper_scrape_all_post", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "Scrape All Sources", + "tags": [ + "compliance", + "compliance-scraper" + ] + } + }, + "/api/compliance/scraper/scrape/{code}": { + "post": { + "description": "Scrape a specific regulation source.", + "operationId": "scrape_single_source_api_compliance_scraper_scrape__code__post", + "parameters": [ + { + "in": "path", + "name": "code", + "required": true, + "schema": { + "title": "Code", + "type": "string" + } + }, + { + "description": "Force re-scrape even if data exists", + "in": "query", + "name": "force", + "required": false, + "schema": { + "default": false, + "description": "Force re-scrape even if data exists", + "title": "Force", + "type": "boolean" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Scrape Single Source", + "tags": [ + "compliance", + "compliance-scraper" + ] + } + }, + "/api/compliance/scraper/sources": { + "get": { + "description": "Get list of known regulation sources.", + "operationId": "get_scraper_sources_api_compliance_scraper_sources_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "Get Scraper Sources", + "tags": [ + "compliance", + "compliance-scraper" + ] + } + }, + "/api/compliance/scraper/status": { + "get": { + "description": "Get current scraper status.", + "operationId": "get_scraper_status_api_compliance_scraper_status_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "Get Scraper Status", + "tags": [ + "compliance", + "compliance-scraper" + ] + } + }, + "/api/compliance/security-backlog": { + "get": { + "description": "List security backlog items with optional filters.", + "operationId": "list_security_items_api_compliance_security_backlog_get", + "parameters": [ + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "in": "query", + "name": "severity", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Severity" + } + }, + { + "in": "query", + "name": "type", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Type" + } + }, + { + "in": "query", + "name": "search", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Search" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 100, + "maximum": 500, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "minimum": 0, + "title": "Offset", + "type": "integer" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Security Items", + "tags": [ + "compliance", + "security-backlog" + ] + }, + "post": { + "description": "Create a new security backlog item.", + "operationId": "create_security_item_api_compliance_security_backlog_post", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SecurityItemCreate" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Security Item", + "tags": [ + "compliance", + "security-backlog" + ] + } + }, + "/api/compliance/security-backlog/stats": { + "get": { + "description": "Return security backlog counts.", + "operationId": "get_security_stats_api_compliance_security_backlog_stats_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Security Stats", + "tags": [ + "compliance", + "security-backlog" + ] + } + }, + "/api/compliance/security-backlog/{item_id}": { + "delete": { + "operationId": "delete_security_item_api_compliance_security_backlog__item_id__delete", + "parameters": [ + { + "in": "path", + "name": "item_id", + "required": true, + "schema": { + "title": "Item Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "204": { + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Security Item", + "tags": [ + "compliance", + "security-backlog" + ] + }, + "put": { + "description": "Update a security backlog item.", + "operationId": "update_security_item_api_compliance_security_backlog__item_id__put", + "parameters": [ + { + "in": "path", + "name": "item_id", + "required": true, + "schema": { + "title": "Item Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SecurityItemUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Security Item", + "tags": [ + "compliance", + "security-backlog" + ] + } + }, + "/api/compliance/seed": { + "post": { + "description": "Seed the compliance database with initial data.", + "operationId": "seed_database_api_compliance_seed_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SeedRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SeedResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Seed Database", + "tags": [ + "compliance" + ] + } + }, + "/api/compliance/seed-risks": { + "post": { + "description": "Seed only risks (incremental update for existing databases).", + "operationId": "seed_risks_only_api_compliance_seed_risks_post", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "Seed Risks Only", + "tags": [ + "compliance" + ] + } + }, + "/api/compliance/tom/export": { + "get": { + "description": "Export TOM measures as CSV (semicolon-separated) or JSON.", + "operationId": "export_measures_api_compliance_tom_export_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "query", + "name": "format", + "required": false, + "schema": { + "default": "csv", + "title": "Format", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Export Measures", + "tags": [ + "compliance", + "tom" + ] + } + }, + "/api/compliance/tom/measures": { + "get": { + "description": "List TOM measures with optional filters.", + "operationId": "list_measures_api_compliance_tom_measures_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "query", + "name": "category", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Category" + } + }, + { + "in": "query", + "name": "implementation_status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Implementation Status" + } + }, + { + "in": "query", + "name": "priority", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Priority" + } + }, + { + "in": "query", + "name": "search", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Search" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 100, + "maximum": 500, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "minimum": 0, + "title": "Offset", + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Measures", + "tags": [ + "compliance", + "tom" + ] + }, + "post": { + "description": "Create a single TOM measure.", + "operationId": "create_measure_api_compliance_tom_measures_post", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TOMMeasureCreate" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Measure", + "tags": [ + "compliance", + "tom" + ] + } + }, + "/api/compliance/tom/measures/bulk": { + "post": { + "description": "Bulk upsert measures \u2014 used by deriveTOMs sync from frontend.", + "operationId": "bulk_upsert_measures_api_compliance_tom_measures_bulk_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TOMMeasureBulkBody" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Bulk Upsert Measures", + "tags": [ + "compliance", + "tom" + ] + } + }, + "/api/compliance/tom/measures/{measure_id}": { + "put": { + "description": "Update a TOM measure.", + "operationId": "update_measure_api_compliance_tom_measures__measure_id__put", + "parameters": [ + { + "in": "path", + "name": "measure_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Measure Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TOMMeasureUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Measure", + "tags": [ + "compliance", + "tom" + ] + } + }, + "/api/compliance/tom/measures/{measure_id}/versions": { + "get": { + "description": "List all versions for a TOM measure.", + "operationId": "list_measure_versions_api_compliance_tom_measures__measure_id__versions_get", + "parameters": [ + { + "in": "path", + "name": "measure_id", + "required": true, + "schema": { + "title": "Measure Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "query", + "name": "tenantId", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenantid" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Measure Versions", + "tags": [ + "compliance", + "tom" + ] + } + }, + "/api/compliance/tom/measures/{measure_id}/versions/{version_number}": { + "get": { + "description": "Get a specific TOM measure version with full snapshot.", + "operationId": "get_measure_version_api_compliance_tom_measures__measure_id__versions__version_number__get", + "parameters": [ + { + "in": "path", + "name": "measure_id", + "required": true, + "schema": { + "title": "Measure Id", + "type": "string" + } + }, + { + "in": "path", + "name": "version_number", + "required": true, + "schema": { + "title": "Version Number", + "type": "integer" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "query", + "name": "tenantId", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenantid" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Measure Version", + "tags": [ + "compliance", + "tom" + ] + } + }, + "/api/compliance/tom/state": { + "delete": { + "description": "Clear TOM generator state for a tenant.", + "operationId": "delete_tom_state_api_compliance_tom_state_delete", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "query", + "name": "tenantId", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenantid" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Tom State", + "tags": [ + "compliance", + "tom" + ] + }, + "get": { + "description": "Load TOM generator state for a tenant.", + "operationId": "get_tom_state_api_compliance_tom_state_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "query", + "name": "tenantId", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenantid" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Tom State", + "tags": [ + "compliance", + "tom" + ] + }, + "post": { + "description": "Save TOM generator state with optimistic locking (version check).", + "operationId": "save_tom_state_api_compliance_tom_state_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TOMStateBody" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Save Tom State", + "tags": [ + "compliance", + "tom" + ] + } + }, + "/api/compliance/tom/stats": { + "get": { + "description": "Return TOM statistics for a tenant.", + "operationId": "get_tom_stats_api_compliance_tom_stats_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Tom Stats", + "tags": [ + "compliance", + "tom" + ] + } + }, + "/api/compliance/v1/canonical/blocked-sources": { + "get": { + "description": "List all blocked (Rule 3) sources.", + "operationId": "list_blocked_sources_api_compliance_v1_canonical_blocked_sources_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "List Blocked Sources", + "tags": [ + "compliance", + "control-generator" + ] + } + }, + "/api/compliance/v1/canonical/blocked-sources/cleanup": { + "post": { + "description": "Start cleanup workflow for blocked sources.\n\nThis marks all pending blocked sources for deletion.\nActual RAG chunk deletion and file removal is a separate manual step.", + "operationId": "start_cleanup_api_compliance_v1_canonical_blocked_sources_cleanup_post", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "Start Cleanup", + "tags": [ + "compliance", + "control-generator" + ] + } + }, + "/api/compliance/v1/canonical/controls": { + "get": { + "description": "List all canonical controls, with optional filters.", + "operationId": "list_controls_api_compliance_v1_canonical_controls_get", + "parameters": [ + { + "in": "query", + "name": "severity", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Severity" + } + }, + { + "in": "query", + "name": "domain", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Domain" + } + }, + { + "in": "query", + "name": "release_state", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Release State" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Controls", + "tags": [ + "compliance", + "canonical-controls" + ] + }, + "post": { + "description": "Create a new canonical control.", + "operationId": "create_control_api_compliance_v1_canonical_controls_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ControlCreateRequest" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Control", + "tags": [ + "compliance", + "canonical-controls" + ] + } + }, + "/api/compliance/v1/canonical/controls-customer": { + "get": { + "description": "Get controls filtered for customer visibility.\n\nRule 3 controls have source_citation and source_original_text hidden.\ngeneration_metadata is NEVER shown to customers.", + "operationId": "get_controls_customer_view_api_compliance_v1_canonical_controls_customer_get", + "parameters": [ + { + "in": "query", + "name": "severity", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Severity" + } + }, + { + "in": "query", + "name": "domain", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Domain" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Controls Customer View", + "tags": [ + "compliance", + "control-generator" + ] + } + }, + "/api/compliance/v1/canonical/controls/{control_id}": { + "delete": { + "description": "Delete a canonical control.", + "operationId": "delete_control_api_compliance_v1_canonical_controls__control_id__delete", + "parameters": [ + { + "in": "path", + "name": "control_id", + "required": true, + "schema": { + "title": "Control Id", + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Control", + "tags": [ + "compliance", + "canonical-controls" + ] + }, + "get": { + "description": "Get a single canonical control by its control_id (e.g. AUTH-001).", + "operationId": "get_control_api_compliance_v1_canonical_controls__control_id__get", + "parameters": [ + { + "in": "path", + "name": "control_id", + "required": true, + "schema": { + "title": "Control Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Control", + "tags": [ + "compliance", + "canonical-controls" + ] + }, + "put": { + "description": "Update an existing canonical control (partial update).", + "operationId": "update_control_api_compliance_v1_canonical_controls__control_id__put", + "parameters": [ + { + "in": "path", + "name": "control_id", + "required": true, + "schema": { + "title": "Control Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ControlUpdateRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Control", + "tags": [ + "compliance", + "canonical-controls" + ] + } + }, + "/api/compliance/v1/canonical/controls/{control_id}/similarity-check": { + "post": { + "description": "Run the too-close detector against a source/candidate text pair.", + "operationId": "similarity_check_api_compliance_v1_canonical_controls__control_id__similarity_check_post", + "parameters": [ + { + "in": "path", + "name": "control_id", + "required": true, + "schema": { + "title": "Control Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SimilarityCheckRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Similarity Check", + "tags": [ + "compliance", + "canonical-controls" + ] + } + }, + "/api/compliance/v1/canonical/frameworks": { + "get": { + "description": "List all registered control frameworks.", + "operationId": "list_frameworks_api_compliance_v1_canonical_frameworks_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "List Frameworks", + "tags": [ + "compliance", + "canonical-controls" + ] + } + }, + "/api/compliance/v1/canonical/frameworks/{framework_id}": { + "get": { + "description": "Get a single framework by its framework_id.", + "operationId": "get_framework_api_compliance_v1_canonical_frameworks__framework_id__get", + "parameters": [ + { + "in": "path", + "name": "framework_id", + "required": true, + "schema": { + "title": "Framework Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Framework", + "tags": [ + "compliance", + "canonical-controls" + ] + } + }, + "/api/compliance/v1/canonical/frameworks/{framework_id}/controls": { + "get": { + "description": "List controls belonging to a framework.", + "operationId": "list_framework_controls_api_compliance_v1_canonical_frameworks__framework_id__controls_get", + "parameters": [ + { + "in": "path", + "name": "framework_id", + "required": true, + "schema": { + "title": "Framework Id", + "type": "string" + } + }, + { + "in": "query", + "name": "severity", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Severity" + } + }, + { + "in": "query", + "name": "release_state", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Release State" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Framework Controls", + "tags": [ + "compliance", + "canonical-controls" + ] + } + }, + "/api/compliance/v1/canonical/generate": { + "post": { + "description": "Start a control generation run.", + "operationId": "start_generation_api_compliance_v1_canonical_generate_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GenerateRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GenerateResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Start Generation", + "tags": [ + "compliance", + "control-generator" + ] + } + }, + "/api/compliance/v1/canonical/generate/jobs": { + "get": { + "description": "List all generation jobs.", + "operationId": "list_jobs_api_compliance_v1_canonical_generate_jobs_get", + "parameters": [ + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 20, + "maximum": 100, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "minimum": 0, + "title": "Offset", + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Jobs", + "tags": [ + "compliance", + "control-generator" + ] + } + }, + "/api/compliance/v1/canonical/generate/processed-stats": { + "get": { + "description": "Get processing statistics per collection.", + "operationId": "get_processed_stats_api_compliance_v1_canonical_generate_processed_stats_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "Get Processed Stats", + "tags": [ + "compliance", + "control-generator" + ] + } + }, + "/api/compliance/v1/canonical/generate/review-queue": { + "get": { + "description": "Get controls that need manual review.", + "operationId": "get_review_queue_api_compliance_v1_canonical_generate_review_queue_get", + "parameters": [ + { + "in": "query", + "name": "release_state", + "required": false, + "schema": { + "default": "needs_review", + "pattern": "^(needs_review|too_close|duplicate)$", + "title": "Release State", + "type": "string" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 50, + "maximum": 200, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Review Queue", + "tags": [ + "compliance", + "control-generator" + ] + } + }, + "/api/compliance/v1/canonical/generate/review/{control_id}": { + "post": { + "description": "Complete review of a generated control.", + "operationId": "review_control_api_compliance_v1_canonical_generate_review__control_id__post", + "parameters": [ + { + "in": "path", + "name": "control_id", + "required": true, + "schema": { + "title": "Control Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReviewRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Review Control", + "tags": [ + "compliance", + "control-generator" + ] + } + }, + "/api/compliance/v1/canonical/generate/status/{job_id}": { + "get": { + "description": "Get status of a generation job.", + "operationId": "get_job_status_api_compliance_v1_canonical_generate_status__job_id__get", + "parameters": [ + { + "in": "path", + "name": "job_id", + "required": true, + "schema": { + "title": "Job Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Job Status", + "tags": [ + "compliance", + "control-generator" + ] + } + }, + "/api/compliance/v1/canonical/licenses": { + "get": { + "description": "Return the license matrix.", + "operationId": "list_licenses_api_compliance_v1_canonical_licenses_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "List Licenses", + "tags": [ + "compliance", + "canonical-controls" + ] + } + }, + "/api/compliance/v1/canonical/sources": { + "get": { + "description": "List all registered sources with permission flags.", + "operationId": "list_sources_api_compliance_v1_canonical_sources_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "List Sources", + "tags": [ + "compliance", + "canonical-controls" + ] + } + }, + "/api/compliance/v1/compliance-scope": { + "get": { + "description": "Return the persisted compliance scope for a tenant, or 404 if not set.", + "operationId": "get_compliance_scope_api_compliance_v1_compliance_scope_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "default": "default", + "title": "Tenant Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ComplianceScopeResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Compliance Scope", + "tags": [ + "compliance", + "compliance-scope" + ] + }, + "post": { + "description": "Create or update the compliance scope for a tenant (UPSERT).", + "operationId": "upsert_compliance_scope_api_compliance_v1_compliance_scope_post", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "default": "default", + "title": "Tenant Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ComplianceScopeRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ComplianceScopeResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Upsert Compliance Scope", + "tags": [ + "compliance", + "compliance-scope" + ] + } + }, + "/api/compliance/v1/projects": { + "get": { + "description": "List all projects for the tenant.", + "operationId": "list_projects_api_compliance_v1_projects_get", + "parameters": [ + { + "in": "query", + "name": "include_archived", + "required": false, + "schema": { + "default": false, + "title": "Include Archived", + "type": "boolean" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Projects", + "tags": [ + "compliance", + "projects" + ] + }, + "post": { + "description": "Create a new compliance project.\n\nOptionally copies the company profile (companyProfile) from an existing\nproject's sdk_states into the new project's state. This allows a tenant\nto start a new project for a subsidiary with the same base data.", + "operationId": "create_project_api_compliance_v1_projects_post", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateProjectRequest" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Project", + "tags": [ + "compliance", + "projects" + ] + } + }, + "/api/compliance/v1/projects/{project_id}": { + "delete": { + "description": "Soft-delete (archive) a project.", + "operationId": "archive_project_api_compliance_v1_projects__project_id__delete", + "parameters": [ + { + "in": "path", + "name": "project_id", + "required": true, + "schema": { + "title": "Project Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Archive Project", + "tags": [ + "compliance", + "projects" + ] + }, + "get": { + "description": "Get a single project by ID (tenant-scoped).", + "operationId": "get_project_api_compliance_v1_projects__project_id__get", + "parameters": [ + { + "in": "path", + "name": "project_id", + "required": true, + "schema": { + "title": "Project Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Project", + "tags": [ + "compliance", + "projects" + ] + }, + "patch": { + "description": "Update project name/description.", + "operationId": "update_project_api_compliance_v1_projects__project_id__patch", + "parameters": [ + { + "in": "path", + "name": "project_id", + "required": true, + "schema": { + "title": "Project Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateProjectRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Project", + "tags": [ + "compliance", + "projects" + ] + } + }, + "/api/compliance/v1/projects/{project_id}/permanent": { + "delete": { + "description": "Permanently delete a project and all associated data.", + "operationId": "permanently_delete_project_api_compliance_v1_projects__project_id__permanent_delete", + "parameters": [ + { + "in": "path", + "name": "project_id", + "required": true, + "schema": { + "title": "Project Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Permanently Delete Project", + "tags": [ + "compliance", + "projects" + ] + } + }, + "/api/compliance/v1/projects/{project_id}/restore": { + "post": { + "description": "Restore an archived project back to active.", + "operationId": "restore_project_api_compliance_v1_projects__project_id__restore_post", + "parameters": [ + { + "in": "path", + "name": "project_id", + "required": true, + "schema": { + "title": "Project Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Restore Project", + "tags": [ + "compliance", + "projects" + ] + } + }, + "/api/compliance/v1/wiki/articles": { + "get": { + "description": "List all wiki articles, optionally filtered by category.", + "operationId": "list_articles_api_compliance_v1_wiki_articles_get", + "parameters": [ + { + "description": "Filter by category", + "in": "query", + "name": "category_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter by category", + "title": "Category Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Articles", + "tags": [ + "compliance", + "wiki" + ] + } + }, + "/api/compliance/v1/wiki/articles/{article_id}": { + "get": { + "description": "Get a single wiki article by ID.", + "operationId": "get_article_api_compliance_v1_wiki_articles__article_id__get", + "parameters": [ + { + "in": "path", + "name": "article_id", + "required": true, + "schema": { + "title": "Article Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Article", + "tags": [ + "compliance", + "wiki" + ] + } + }, + "/api/compliance/v1/wiki/categories": { + "get": { + "description": "List all wiki categories with article counts.", + "operationId": "list_categories_api_compliance_v1_wiki_categories_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "List Categories", + "tags": [ + "compliance", + "wiki" + ] + } + }, + "/api/compliance/v1/wiki/search": { + "get": { + "description": "Full-text search across wiki articles using PostgreSQL tsvector.", + "operationId": "search_wiki_api_compliance_v1_wiki_search_get", + "parameters": [ + { + "description": "Search query", + "in": "query", + "name": "q", + "required": true, + "schema": { + "description": "Search query", + "minLength": 2, + "title": "Q", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Search Wiki", + "tags": [ + "compliance", + "wiki" + ] + } + }, + "/api/compliance/vendor-compliance/contracts": { + "get": { + "operationId": "list_contracts_api_compliance_vendor_compliance_contracts_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "query", + "name": "vendor_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Vendor Id" + } + }, + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "in": "query", + "name": "skip", + "required": false, + "schema": { + "default": 0, + "minimum": 0, + "title": "Skip", + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 100, + "maximum": 500, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Contracts", + "tags": [ + "compliance", + "vendor-compliance" + ] + }, + "post": { + "operationId": "create_contract_api_compliance_vendor_compliance_contracts_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "default": {}, + "title": "Body", + "type": "object" + } + } + } + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Contract", + "tags": [ + "compliance", + "vendor-compliance" + ] + } + }, + "/api/compliance/vendor-compliance/contracts/{contract_id}": { + "delete": { + "operationId": "delete_contract_api_compliance_vendor_compliance_contracts__contract_id__delete", + "parameters": [ + { + "in": "path", + "name": "contract_id", + "required": true, + "schema": { + "title": "Contract Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Contract", + "tags": [ + "compliance", + "vendor-compliance" + ] + }, + "get": { + "operationId": "get_contract_api_compliance_vendor_compliance_contracts__contract_id__get", + "parameters": [ + { + "in": "path", + "name": "contract_id", + "required": true, + "schema": { + "title": "Contract Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Contract", + "tags": [ + "compliance", + "vendor-compliance" + ] + }, + "put": { + "operationId": "update_contract_api_compliance_vendor_compliance_contracts__contract_id__put", + "parameters": [ + { + "in": "path", + "name": "contract_id", + "required": true, + "schema": { + "title": "Contract Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "default": {}, + "title": "Body", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Contract", + "tags": [ + "compliance", + "vendor-compliance" + ] + } + }, + "/api/compliance/vendor-compliance/control-instances": { + "get": { + "operationId": "list_control_instances_api_compliance_vendor_compliance_control_instances_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "query", + "name": "vendor_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Vendor Id" + } + }, + { + "in": "query", + "name": "skip", + "required": false, + "schema": { + "default": 0, + "minimum": 0, + "title": "Skip", + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 100, + "maximum": 500, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Control Instances", + "tags": [ + "compliance", + "vendor-compliance" + ] + }, + "post": { + "operationId": "create_control_instance_api_compliance_vendor_compliance_control_instances_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "default": {}, + "title": "Body", + "type": "object" + } + } + } + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Control Instance", + "tags": [ + "compliance", + "vendor-compliance" + ] + } + }, + "/api/compliance/vendor-compliance/control-instances/{instance_id}": { + "delete": { + "operationId": "delete_control_instance_api_compliance_vendor_compliance_control_instances__instance_id__delete", + "parameters": [ + { + "in": "path", + "name": "instance_id", + "required": true, + "schema": { + "title": "Instance Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Control Instance", + "tags": [ + "compliance", + "vendor-compliance" + ] + }, + "get": { + "operationId": "get_control_instance_api_compliance_vendor_compliance_control_instances__instance_id__get", + "parameters": [ + { + "in": "path", + "name": "instance_id", + "required": true, + "schema": { + "title": "Instance Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Control Instance", + "tags": [ + "compliance", + "vendor-compliance" + ] + }, + "put": { + "operationId": "update_control_instance_api_compliance_vendor_compliance_control_instances__instance_id__put", + "parameters": [ + { + "in": "path", + "name": "instance_id", + "required": true, + "schema": { + "title": "Instance Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "default": {}, + "title": "Body", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Control Instance", + "tags": [ + "compliance", + "vendor-compliance" + ] + } + }, + "/api/compliance/vendor-compliance/controls": { + "get": { + "operationId": "list_controls_api_compliance_vendor_compliance_controls_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "query", + "name": "domain", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Domain" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Controls", + "tags": [ + "compliance", + "vendor-compliance" + ] + }, + "post": { + "operationId": "create_control_api_compliance_vendor_compliance_controls_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "default": {}, + "title": "Body", + "type": "object" + } + } + } + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Control", + "tags": [ + "compliance", + "vendor-compliance" + ] + } + }, + "/api/compliance/vendor-compliance/controls/{control_id}": { + "delete": { + "operationId": "delete_control_api_compliance_vendor_compliance_controls__control_id__delete", + "parameters": [ + { + "in": "path", + "name": "control_id", + "required": true, + "schema": { + "title": "Control Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Control", + "tags": [ + "compliance", + "vendor-compliance" + ] + } + }, + "/api/compliance/vendor-compliance/export": { + "post": { + "operationId": "export_report_api_compliance_vendor_compliance_export_post", + "responses": { + "501": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "Export Report", + "tags": [ + "compliance", + "vendor-compliance" + ] + } + }, + "/api/compliance/vendor-compliance/export/{report_id}": { + "get": { + "operationId": "get_export_api_compliance_vendor_compliance_export__report_id__get", + "parameters": [ + { + "in": "path", + "name": "report_id", + "required": true, + "schema": { + "title": "Report Id", + "type": "string" + } + } + ], + "responses": { + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + }, + "501": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "Get Export", + "tags": [ + "compliance", + "vendor-compliance" + ] + } + }, + "/api/compliance/vendor-compliance/export/{report_id}/download": { + "get": { + "operationId": "download_export_api_compliance_vendor_compliance_export__report_id__download_get", + "parameters": [ + { + "in": "path", + "name": "report_id", + "required": true, + "schema": { + "title": "Report Id", + "type": "string" + } + } + ], + "responses": { + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + }, + "501": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "Download Export", + "tags": [ + "compliance", + "vendor-compliance" + ] + } + }, + "/api/compliance/vendor-compliance/findings": { + "get": { + "operationId": "list_findings_api_compliance_vendor_compliance_findings_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "query", + "name": "vendor_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Vendor Id" + } + }, + { + "in": "query", + "name": "severity", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Severity" + } + }, + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "in": "query", + "name": "skip", + "required": false, + "schema": { + "default": 0, + "minimum": 0, + "title": "Skip", + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 100, + "maximum": 500, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Findings", + "tags": [ + "compliance", + "vendor-compliance" + ] + }, + "post": { + "operationId": "create_finding_api_compliance_vendor_compliance_findings_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "default": {}, + "title": "Body", + "type": "object" + } + } + } + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Finding", + "tags": [ + "compliance", + "vendor-compliance" + ] + } + }, + "/api/compliance/vendor-compliance/findings/{finding_id}": { + "delete": { + "operationId": "delete_finding_api_compliance_vendor_compliance_findings__finding_id__delete", + "parameters": [ + { + "in": "path", + "name": "finding_id", + "required": true, + "schema": { + "title": "Finding Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Finding", + "tags": [ + "compliance", + "vendor-compliance" + ] + }, + "get": { + "operationId": "get_finding_api_compliance_vendor_compliance_findings__finding_id__get", + "parameters": [ + { + "in": "path", + "name": "finding_id", + "required": true, + "schema": { + "title": "Finding Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Finding", + "tags": [ + "compliance", + "vendor-compliance" + ] + }, + "put": { + "operationId": "update_finding_api_compliance_vendor_compliance_findings__finding_id__put", + "parameters": [ + { + "in": "path", + "name": "finding_id", + "required": true, + "schema": { + "title": "Finding Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "default": {}, + "title": "Body", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Finding", + "tags": [ + "compliance", + "vendor-compliance" + ] + } + }, + "/api/compliance/vendor-compliance/vendors": { + "get": { + "operationId": "list_vendors_api_compliance_vendor_compliance_vendors_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "in": "query", + "name": "riskLevel", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Risklevel" + } + }, + { + "in": "query", + "name": "search", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Search" + } + }, + { + "in": "query", + "name": "skip", + "required": false, + "schema": { + "default": 0, + "minimum": 0, + "title": "Skip", + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 100, + "maximum": 500, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Vendors", + "tags": [ + "compliance", + "vendor-compliance" + ] + }, + "post": { + "operationId": "create_vendor_api_compliance_vendor_compliance_vendors_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "default": {}, + "title": "Body", + "type": "object" + } + } + } + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Vendor", + "tags": [ + "compliance", + "vendor-compliance" + ] + } + }, + "/api/compliance/vendor-compliance/vendors/stats": { + "get": { + "operationId": "get_vendor_stats_api_compliance_vendor_compliance_vendors_stats_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Vendor Stats", + "tags": [ + "compliance", + "vendor-compliance" + ] + } + }, + "/api/compliance/vendor-compliance/vendors/{vendor_id}": { + "delete": { + "operationId": "delete_vendor_api_compliance_vendor_compliance_vendors__vendor_id__delete", + "parameters": [ + { + "in": "path", + "name": "vendor_id", + "required": true, + "schema": { + "title": "Vendor Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Vendor", + "tags": [ + "compliance", + "vendor-compliance" + ] + }, + "get": { + "operationId": "get_vendor_api_compliance_vendor_compliance_vendors__vendor_id__get", + "parameters": [ + { + "in": "path", + "name": "vendor_id", + "required": true, + "schema": { + "title": "Vendor Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Vendor", + "tags": [ + "compliance", + "vendor-compliance" + ] + }, + "put": { + "operationId": "update_vendor_api_compliance_vendor_compliance_vendors__vendor_id__put", + "parameters": [ + { + "in": "path", + "name": "vendor_id", + "required": true, + "schema": { + "title": "Vendor Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "default": {}, + "title": "Body", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Vendor", + "tags": [ + "compliance", + "vendor-compliance" + ] + } + }, + "/api/compliance/vendor-compliance/vendors/{vendor_id}/status": { + "patch": { + "operationId": "patch_vendor_status_api_compliance_vendor_compliance_vendors__vendor_id__status_patch", + "parameters": [ + { + "in": "path", + "name": "vendor_id", + "required": true, + "schema": { + "title": "Vendor Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "default": {}, + "title": "Body", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Patch Vendor Status", + "tags": [ + "compliance", + "vendor-compliance" + ] + } + }, + "/api/compliance/vvt/activities": { + "get": { + "description": "List all processing activities with optional filters.", + "operationId": "list_activities_api_compliance_vvt_activities_get", + "parameters": [ + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "in": "query", + "name": "business_function", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Business Function" + } + }, + { + "in": "query", + "name": "search", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Search" + } + }, + { + "in": "query", + "name": "review_overdue", + "required": false, + "schema": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Review Overdue" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "items": { + "$ref": "#/components/schemas/VVTActivityResponse" + }, + "title": "Response List Activities Api Compliance Vvt Activities Get", + "type": "array" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Activities", + "tags": [ + "compliance", + "compliance-vvt" + ] + }, + "post": { + "description": "Create a new processing activity.", + "operationId": "create_activity_api_compliance_vvt_activities_post", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VVTActivityCreate" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VVTActivityResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Activity", + "tags": [ + "compliance", + "compliance-vvt" + ] + } + }, + "/api/compliance/vvt/activities/{activity_id}": { + "delete": { + "description": "Delete a processing activity.", + "operationId": "delete_activity_api_compliance_vvt_activities__activity_id__delete", + "parameters": [ + { + "in": "path", + "name": "activity_id", + "required": true, + "schema": { + "title": "Activity Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Activity", + "tags": [ + "compliance", + "compliance-vvt" + ] + }, + "get": { + "description": "Get a single processing activity by ID.", + "operationId": "get_activity_api_compliance_vvt_activities__activity_id__get", + "parameters": [ + { + "in": "path", + "name": "activity_id", + "required": true, + "schema": { + "title": "Activity Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VVTActivityResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Activity", + "tags": [ + "compliance", + "compliance-vvt" + ] + }, + "put": { + "description": "Update a processing activity.", + "operationId": "update_activity_api_compliance_vvt_activities__activity_id__put", + "parameters": [ + { + "in": "path", + "name": "activity_id", + "required": true, + "schema": { + "title": "Activity Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VVTActivityUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VVTActivityResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Activity", + "tags": [ + "compliance", + "compliance-vvt" + ] + } + }, + "/api/compliance/vvt/activities/{activity_id}/versions": { + "get": { + "description": "List all versions for a VVT activity.", + "operationId": "list_activity_versions_api_compliance_vvt_activities__activity_id__versions_get", + "parameters": [ + { + "in": "path", + "name": "activity_id", + "required": true, + "schema": { + "title": "Activity Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Activity Versions", + "tags": [ + "compliance", + "compliance-vvt" + ] + } + }, + "/api/compliance/vvt/activities/{activity_id}/versions/{version_number}": { + "get": { + "description": "Get a specific VVT activity version with full snapshot.", + "operationId": "get_activity_version_api_compliance_vvt_activities__activity_id__versions__version_number__get", + "parameters": [ + { + "in": "path", + "name": "activity_id", + "required": true, + "schema": { + "title": "Activity Id", + "type": "string" + } + }, + { + "in": "path", + "name": "version_number", + "required": true, + "schema": { + "title": "Version Number", + "type": "integer" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Activity Version", + "tags": [ + "compliance", + "compliance-vvt" + ] + } + }, + "/api/compliance/vvt/audit-log": { + "get": { + "description": "Get the VVT audit trail.", + "operationId": "get_audit_log_api_compliance_vvt_audit_log_get", + "parameters": [ + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 50, + "maximum": 500, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "minimum": 0, + "title": "Offset", + "type": "integer" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "items": { + "$ref": "#/components/schemas/VVTAuditLogEntry" + }, + "title": "Response Get Audit Log Api Compliance Vvt Audit Log Get", + "type": "array" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Audit Log", + "tags": [ + "compliance", + "compliance-vvt" + ] + } + }, + "/api/compliance/vvt/export": { + "get": { + "description": "Export all activities as JSON or CSV (semicolon-separated, DE locale).", + "operationId": "export_activities_api_compliance_vvt_export_get", + "parameters": [ + { + "in": "query", + "name": "format", + "required": false, + "schema": { + "default": "json", + "pattern": "^(json|csv)$", + "title": "Format", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Export Activities", + "tags": [ + "compliance", + "compliance-vvt" + ] + } + }, + "/api/compliance/vvt/organization": { + "get": { + "description": "Load the VVT organization header for the given tenant.", + "operationId": "get_organization_api_compliance_vvt_organization_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/VVTOrganizationResponse" + }, + { + "type": "null" + } + ], + "title": "Response Get Organization Api Compliance Vvt Organization Get" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Organization", + "tags": [ + "compliance", + "compliance-vvt" + ] + }, + "put": { + "description": "Create or update the VVT organization header.", + "operationId": "upsert_organization_api_compliance_vvt_organization_put", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VVTOrganizationUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VVTOrganizationResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Upsert Organization", + "tags": [ + "compliance", + "compliance-vvt" + ] + } + }, + "/api/compliance/vvt/stats": { + "get": { + "description": "Get VVT statistics summary.", + "operationId": "get_stats_api_compliance_vvt_stats_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tenant Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VVTStatsResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Stats", + "tags": [ + "compliance", + "compliance-vvt" + ] + } + }, + "/api/consent/admin/audit-log": { + "get": { + "description": "Gibt das Audit-Log zur\u00fcck", + "operationId": "admin_get_audit_log_api_consent_admin_audit_log_get", + "parameters": [ + { + "in": "query", + "name": "page", + "required": false, + "schema": { + "default": 1, + "minimum": 1, + "title": "Page", + "type": "integer" + } + }, + { + "in": "query", + "name": "per_page", + "required": false, + "schema": { + "default": 50, + "maximum": 100, + "minimum": 1, + "title": "Per Page", + "type": "integer" + } + }, + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Get Audit Log", + "tags": [ + "consent-admin" + ] + } + }, + "/api/consent/admin/cookies/categories": { + "get": { + "description": "Gibt alle Cookie-Kategorien zur\u00fcck", + "operationId": "admin_get_cookie_categories_api_consent_admin_cookies_categories_get", + "parameters": [ + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Get Cookie Categories", + "tags": [ + "consent-admin" + ] + }, + "post": { + "description": "Erstellt eine neue Cookie-Kategorie", + "operationId": "admin_create_cookie_category_api_consent_admin_cookies_categories_post", + "parameters": [ + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateCookieCategoryRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Create Cookie Category", + "tags": [ + "consent-admin" + ] + } + }, + "/api/consent/admin/cookies/categories/{cat_id}": { + "delete": { + "description": "Deaktiviert eine Cookie-Kategorie", + "operationId": "admin_delete_cookie_category_api_consent_admin_cookies_categories__cat_id__delete", + "parameters": [ + { + "in": "path", + "name": "cat_id", + "required": true, + "schema": { + "title": "Cat Id", + "type": "string" + } + }, + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Delete Cookie Category", + "tags": [ + "consent-admin" + ] + }, + "put": { + "description": "Aktualisiert eine Cookie-Kategorie", + "operationId": "admin_update_cookie_category_api_consent_admin_cookies_categories__cat_id__put", + "parameters": [ + { + "in": "path", + "name": "cat_id", + "required": true, + "schema": { + "title": "Cat Id", + "type": "string" + } + }, + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "title": "Request", + "type": "object" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Update Cookie Category", + "tags": [ + "consent-admin" + ] + } + }, + "/api/consent/admin/documents": { + "get": { + "description": "Gibt alle Dokumente zur\u00fcck (inkl. inaktive)", + "operationId": "admin_get_documents_api_consent_admin_documents_get", + "parameters": [ + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Get Documents", + "tags": [ + "consent-admin" + ] + }, + "post": { + "description": "Erstellt ein neues rechtliches Dokument", + "operationId": "admin_create_document_api_consent_admin_documents_post", + "parameters": [ + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateDocumentRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Create Document", + "tags": [ + "consent-admin" + ] + } + }, + "/api/consent/admin/documents/{doc_id}": { + "delete": { + "description": "Deaktiviert ein rechtliches Dokument (Soft-Delete)", + "operationId": "admin_delete_document_api_consent_admin_documents__doc_id__delete", + "parameters": [ + { + "in": "path", + "name": "doc_id", + "required": true, + "schema": { + "title": "Doc Id", + "type": "string" + } + }, + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Delete Document", + "tags": [ + "consent-admin" + ] + }, + "put": { + "description": "Aktualisiert ein rechtliches Dokument", + "operationId": "admin_update_document_api_consent_admin_documents__doc_id__put", + "parameters": [ + { + "in": "path", + "name": "doc_id", + "required": true, + "schema": { + "title": "Doc Id", + "type": "string" + } + }, + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateDocumentRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Update Document", + "tags": [ + "consent-admin" + ] + } + }, + "/api/consent/admin/documents/{doc_id}/versions": { + "get": { + "description": "Gibt alle Versionen eines Dokuments zur\u00fcck", + "operationId": "admin_get_versions_api_consent_admin_documents__doc_id__versions_get", + "parameters": [ + { + "in": "path", + "name": "doc_id", + "required": true, + "schema": { + "title": "Doc Id", + "type": "string" + } + }, + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Get Versions", + "tags": [ + "consent-admin" + ] + } + }, + "/api/consent/admin/privacy/deletion-requests": { + "get": { + "description": "[Admin] Gibt alle L\u00f6schantr\u00e4ge zur\u00fcck.", + "operationId": "admin_get_deletion_requests_api_consent_admin_privacy_deletion_requests_get", + "parameters": [ + { + "description": "Filter: pending, processing, completed", + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter: pending, processing, completed", + "title": "Status" + } + }, + { + "in": "query", + "name": "page", + "required": false, + "schema": { + "default": 1, + "minimum": 1, + "title": "Page", + "type": "integer" + } + }, + { + "in": "query", + "name": "per_page", + "required": false, + "schema": { + "default": 20, + "maximum": 100, + "minimum": 1, + "title": "Per Page", + "type": "integer" + } + }, + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Get Deletion Requests", + "tags": [ + "gdpr-admin" + ] + } + }, + "/api/consent/admin/privacy/deletion-requests/{request_id}/process": { + "post": { + "description": "[Admin] Bearbeitet einen L\u00f6schantrag.", + "operationId": "admin_process_deletion_request_api_consent_admin_privacy_deletion_requests__request_id__process_post", + "parameters": [ + { + "in": "path", + "name": "request_id", + "required": true, + "schema": { + "title": "Request Id", + "type": "string" + } + }, + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Process Deletion Request", + "tags": [ + "gdpr-admin" + ] + } + }, + "/api/consent/admin/privacy/export-pdf/{user_id}": { + "get": { + "description": "[Admin] Generiert PDF-Datenauskunft f\u00fcr einen beliebigen Nutzer.\n\nNur f\u00fcr Admins: Erm\u00f6glicht Export von Nutzerdaten f\u00fcr Support-Anfragen\noder Beh\u00f6rdenanfragen.", + "operationId": "admin_export_user_data_pdf_api_consent_admin_privacy_export_pdf__user_id__get", + "parameters": [ + { + "in": "path", + "name": "user_id", + "required": true, + "schema": { + "title": "User Id", + "type": "string" + } + }, + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Export User Data Pdf", + "tags": [ + "gdpr-admin" + ] + } + }, + "/api/consent/admin/privacy/retention-stats": { + "get": { + "description": "[Admin] Gibt Statistiken \u00fcber Daten und L\u00f6schfristen zur\u00fcck.", + "operationId": "admin_get_retention_stats_api_consent_admin_privacy_retention_stats_get", + "parameters": [ + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Get Retention Stats", + "tags": [ + "gdpr-admin" + ] + } + }, + "/api/consent/admin/scheduled-publishing/process": { + "post": { + "description": "Verarbeitet alle f\u00e4lligen geplanten Ver\u00f6ffentlichungen.\nSollte von einem Cronjob regelm\u00e4\u00dfig aufgerufen werden.", + "operationId": "admin_process_scheduled_publishing_api_consent_admin_scheduled_publishing_process_post", + "parameters": [ + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Process Scheduled Publishing", + "tags": [ + "consent-admin" + ] + } + }, + "/api/consent/admin/scheduled-versions": { + "get": { + "description": "Gibt alle f\u00fcr Ver\u00f6ffentlichung geplanten Versionen zur\u00fcck", + "operationId": "admin_get_scheduled_versions_api_consent_admin_scheduled_versions_get", + "parameters": [ + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Get Scheduled Versions", + "tags": [ + "consent-admin" + ] + } + }, + "/api/consent/admin/statistics": { + "get": { + "description": "Gibt Statistiken \u00fcber Consents zur\u00fcck", + "operationId": "admin_get_statistics_api_consent_admin_statistics_get", + "parameters": [ + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Get Statistics", + "tags": [ + "consent-admin" + ] + } + }, + "/api/consent/admin/versions": { + "post": { + "description": "Erstellt eine neue Dokumentversion", + "operationId": "admin_create_version_api_consent_admin_versions_post", + "parameters": [ + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateVersionRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Create Version", + "tags": [ + "consent-admin" + ] + } + }, + "/api/consent/admin/versions/upload-word": { + "post": { + "description": "Konvertiert ein Word-Dokument (.docx) zu HTML.\nErfordert mammoth Library.", + "operationId": "upload_word_document_api_consent_admin_versions_upload_word_post", + "parameters": [ + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_upload_word_document_api_consent_admin_versions_upload_word_post" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Upload Word Document", + "tags": [ + "consent-admin" + ] + } + }, + "/api/consent/admin/versions/{version_id}": { + "delete": { + "description": "L\u00f6scht eine Dokumentversion dauerhaft.\n\nNur Versionen im Status 'draft' oder 'rejected' k\u00f6nnen gel\u00f6scht werden.\nVer\u00f6ffentlichte Versionen m\u00fcssen stattdessen archiviert werden.\nDie Versionsnummer wird nach dem L\u00f6schen wieder frei.", + "operationId": "admin_delete_version_api_consent_admin_versions__version_id__delete", + "parameters": [ + { + "in": "path", + "name": "version_id", + "required": true, + "schema": { + "title": "Version Id", + "type": "string" + } + }, + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Delete Version", + "tags": [ + "consent-admin" + ] + }, + "put": { + "description": "Aktualisiert eine Dokumentversion (nur draft Status)", + "operationId": "admin_update_version_api_consent_admin_versions__version_id__put", + "parameters": [ + { + "in": "path", + "name": "version_id", + "required": true, + "schema": { + "title": "Version Id", + "type": "string" + } + }, + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateVersionRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Update Version", + "tags": [ + "consent-admin" + ] + } + }, + "/api/consent/admin/versions/{version_id}/approval-history": { + "get": { + "description": "Gibt die Genehmigungshistorie einer Version zur\u00fcck", + "operationId": "admin_get_approval_history_api_consent_admin_versions__version_id__approval_history_get", + "parameters": [ + { + "in": "path", + "name": "version_id", + "required": true, + "schema": { + "title": "Version Id", + "type": "string" + } + }, + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Get Approval History", + "tags": [ + "consent-admin" + ] + } + }, + "/api/consent/admin/versions/{version_id}/approve": { + "post": { + "description": "Genehmigt eine Version (nur DSB).\n\nMit scheduled_publish_at kann ein Ver\u00f6ffentlichungszeitpunkt festgelegt werden.\nFormat: ISO 8601 (z.B. \"2026-01-01T00:00:00Z\")", + "operationId": "admin_approve_version_api_consent_admin_versions__version_id__approve_post", + "parameters": [ + { + "in": "path", + "name": "version_id", + "required": true, + "schema": { + "title": "Version Id", + "type": "string" + } + }, + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApprovalCommentRequest" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Approve Version", + "tags": [ + "consent-admin" + ] + } + }, + "/api/consent/admin/versions/{version_id}/archive": { + "post": { + "description": "Archiviert eine Dokumentversion", + "operationId": "admin_archive_version_api_consent_admin_versions__version_id__archive_post", + "parameters": [ + { + "in": "path", + "name": "version_id", + "required": true, + "schema": { + "title": "Version Id", + "type": "string" + } + }, + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Archive Version", + "tags": [ + "consent-admin" + ] + } + }, + "/api/consent/admin/versions/{version_id}/compare": { + "get": { + "description": "Vergleicht Version mit aktuell ver\u00f6ffentlichter Version", + "operationId": "admin_compare_versions_api_consent_admin_versions__version_id__compare_get", + "parameters": [ + { + "in": "path", + "name": "version_id", + "required": true, + "schema": { + "title": "Version Id", + "type": "string" + } + }, + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Compare Versions", + "tags": [ + "consent-admin" + ] + } + }, + "/api/consent/admin/versions/{version_id}/publish": { + "post": { + "description": "Ver\u00f6ffentlicht eine Dokumentversion", + "operationId": "admin_publish_version_api_consent_admin_versions__version_id__publish_post", + "parameters": [ + { + "in": "path", + "name": "version_id", + "required": true, + "schema": { + "title": "Version Id", + "type": "string" + } + }, + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Publish Version", + "tags": [ + "consent-admin" + ] + } + }, + "/api/consent/admin/versions/{version_id}/reject": { + "post": { + "description": "Lehnt eine Version ab (nur DSB)", + "operationId": "admin_reject_version_api_consent_admin_versions__version_id__reject_post", + "parameters": [ + { + "in": "path", + "name": "version_id", + "required": true, + "schema": { + "title": "Version Id", + "type": "string" + } + }, + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RejectRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Reject Version", + "tags": [ + "consent-admin" + ] + } + }, + "/api/consent/admin/versions/{version_id}/submit-review": { + "post": { + "description": "Reicht eine Version zur DSB-Pr\u00fcfung ein", + "operationId": "admin_submit_for_review_api_consent_admin_versions__version_id__submit_review_post", + "parameters": [ + { + "in": "path", + "name": "version_id", + "required": true, + "schema": { + "title": "Version Id", + "type": "string" + } + }, + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Admin Submit For Review", + "tags": [ + "consent-admin" + ] + } + }, + "/api/consent/check/{document_type}": { + "get": { + "description": "Pr\u00fcft ob der Benutzer einem Dokument zugestimmt hat.\nGibt zur\u00fcck ob Zustimmung vorliegt und ob sie aktualisiert werden muss.", + "operationId": "check_consent_api_consent_check__document_type__get", + "parameters": [ + { + "in": "path", + "name": "document_type", + "required": true, + "schema": { + "title": "Document Type", + "type": "string" + } + }, + { + "in": "query", + "name": "language", + "required": false, + "schema": { + "default": "de", + "title": "Language", + "type": "string" + } + }, + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Check Consent", + "tags": [ + "consent" + ] + } + }, + "/api/consent/cookies": { + "post": { + "description": "Speichert die Cookie-Pr\u00e4ferenzen des Benutzers", + "operationId": "set_cookie_consent_api_consent_cookies_post", + "parameters": [ + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CookieConsentRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Set Cookie Consent", + "tags": [ + "consent" + ] + } + }, + "/api/consent/cookies/categories": { + "get": { + "description": "Holt alle Cookie-Kategorien f\u00fcr das Cookie-Banner", + "operationId": "get_cookie_categories_api_consent_cookies_categories_get", + "parameters": [ + { + "in": "query", + "name": "language", + "required": false, + "schema": { + "default": "de", + "title": "Language", + "type": "string" + } + }, + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Cookie Categories", + "tags": [ + "consent" + ] + } + }, + "/api/consent/documents/{document_type}/latest": { + "get": { + "description": "Holt die aktuellste Version eines rechtlichen Dokuments", + "operationId": "get_latest_document_api_consent_documents__document_type__latest_get", + "parameters": [ + { + "in": "path", + "name": "document_type", + "required": true, + "schema": { + "title": "Document Type", + "type": "string" + } + }, + { + "in": "query", + "name": "language", + "required": false, + "schema": { + "default": "de", + "title": "Language", + "type": "string" + } + }, + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Latest Document", + "tags": [ + "consent" + ] + } + }, + "/api/consent/give": { + "post": { + "description": "Speichert die Zustimmung des Benutzers zu einem Dokument", + "operationId": "give_consent_api_consent_give_post", + "parameters": [ + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConsentRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Give Consent", + "tags": [ + "consent" + ] + } + }, + "/api/consent/health": { + "get": { + "description": "Pr\u00fcft die Verbindung zum Consent Service", + "operationId": "consent_health_api_consent_health_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "Consent Health", + "tags": [ + "consent" + ] + } + }, + "/api/consent/pending": { + "get": { + "description": "Gibt alle Dokumente zur\u00fcck, die noch Zustimmung ben\u00f6tigen.\nN\u00fctzlich f\u00fcr Anzeige beim Login oder in den Einstellungen.", + "operationId": "get_pending_consents_api_consent_pending_get", + "parameters": [ + { + "in": "query", + "name": "language", + "required": false, + "schema": { + "default": "de", + "title": "Language", + "type": "string" + } + }, + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Pending Consents", + "tags": [ + "consent" + ] + } + }, + "/api/consent/privacy/data-categories": { + "get": { + "description": "Gibt alle Datenkategorien mit ihren L\u00f6schfristen zur\u00fcck.\n\nDiese Information wird auch im PDF-Export angezeigt und gibt Nutzern\nTransparenz dar\u00fcber, welche Daten wie lange gespeichert werden.\n\nQuery Parameters:\n filter: 'essential' f\u00fcr Pflicht-Daten, 'optional' f\u00fcr Opt-in Daten", + "operationId": "get_data_categories_api_consent_privacy_data_categories_get", + "parameters": [ + { + "description": "Filter: 'essential', 'optional', oder leer f\u00fcr alle", + "in": "query", + "name": "filter", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter: 'essential', 'optional', oder leer f\u00fcr alle", + "title": "Filter" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Data Categories", + "tags": [ + "gdpr-privacy" + ] + } + }, + "/api/consent/privacy/data-categories/{category}": { + "get": { + "description": "Gibt Details zu einer spezifischen Datenkategorie zur\u00fcck.", + "operationId": "get_data_category_details_api_consent_privacy_data_categories__category__get", + "parameters": [ + { + "in": "path", + "name": "category", + "required": true, + "schema": { + "title": "Category", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Data Category Details", + "tags": [ + "gdpr-privacy" + ] + } + }, + "/api/consent/privacy/delete": { + "post": { + "description": "GDPR Art. 17: Recht auf L\u00f6schung\nFordert die L\u00f6schung aller Benutzerdaten an.", + "operationId": "request_data_deletion_api_consent_privacy_delete_post", + "parameters": [ + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataDeletionRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Request Data Deletion", + "tags": [ + "consent" + ] + } + }, + "/api/consent/privacy/export": { + "post": { + "description": "GDPR Art. 20: Recht auf Daten\u00fcbertragbarkeit\nFordert einen Export aller Benutzerdaten an.", + "operationId": "request_data_export_api_consent_privacy_export_post", + "parameters": [ + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Request Data Export", + "tags": [ + "consent" + ] + } + }, + "/api/consent/privacy/export-html": { + "get": { + "description": "Generiert eine HTML-Datenauskunft (Preview oder Alternative zu PDF).\n\nReturns:\n HTML-Dokument mit allen gespeicherten Nutzerdaten", + "operationId": "export_user_data_html_api_consent_privacy_export_html_get", + "parameters": [ + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "content": { + "text/html": { + "schema": { + "type": "string" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Export User Data Html", + "tags": [ + "gdpr-privacy" + ] + } + }, + "/api/consent/privacy/export-pdf": { + "post": { + "description": "Generiert eine PDF-Datenauskunft gem\u00e4\u00df DSGVO Art. 15.\n\nReturns:\n PDF-Dokument mit allen gespeicherten Nutzerdaten", + "operationId": "export_user_data_pdf_api_consent_privacy_export_pdf_post", + "parameters": [ + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Export User Data Pdf", + "tags": [ + "gdpr-privacy" + ] + } + }, + "/api/consent/privacy/my-data": { + "get": { + "description": "GDPR Art. 15: Auskunftsrecht\nGibt alle \u00fcber den Benutzer gespeicherten Daten zur\u00fcck.", + "operationId": "get_my_data_api_consent_privacy_my_data_get", + "parameters": [ + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get My Data", + "tags": [ + "consent" + ] + } + }, + "/api/consent/privacy/request-deletion": { + "post": { + "description": "Reicht einen Antrag auf Datenl\u00f6schung ein (DSGVO Art. 17).\n\nDer Antrag wird protokolliert und innerhalb von 30 Tagen bearbeitet.\nBestimmte Daten m\u00fcssen aufgrund gesetzlicher Aufbewahrungsfristen\nm\u00f6glicherweise l\u00e4nger gespeichert werden.\n\nBody:\n reason: Optionaler Grund f\u00fcr die L\u00f6schung\n confirm: Muss true sein zur Best\u00e4tigung", + "operationId": "request_data_deletion_api_consent_privacy_request_deletion_post", + "parameters": [ + { + "in": "header", + "name": "authorization", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeletionRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Request Data Deletion", + "tags": [ + "gdpr-privacy" + ] + } + }, + "/api/consent/token/demo": { + "get": { + "description": "Generiert einen Demo-Token f\u00fcr nicht-authentifizierte Benutzer.\nDieser Token erm\u00f6glicht das Lesen von \u00f6ffentlichen Dokumenten.", + "operationId": "get_demo_token_api_consent_token_demo_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "Get Demo Token", + "tags": [ + "consent" + ] + } + }, + "/api/v1/admin/blocked-content": { + "get": { + "description": "List blocked content entries.", + "operationId": "list_blocked_content_api_v1_admin_blocked_content_get", + "parameters": [ + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 50, + "maximum": 500, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "minimum": 0, + "title": "Offset", + "type": "integer" + } + }, + { + "in": "query", + "name": "domain", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Domain" + } + }, + { + "in": "query", + "name": "from", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "From" + } + }, + { + "in": "query", + "name": "to", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "To" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Blocked Content", + "tags": [ + "source-policy" + ] + } + }, + "/api/v1/admin/compliance-report": { + "get": { + "description": "Generate a compliance report for source policies.", + "operationId": "get_compliance_report_api_v1_admin_compliance_report_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "Get Compliance Report", + "tags": [ + "source-policy" + ] + } + }, + "/api/v1/admin/operations-matrix": { + "get": { + "description": "Get the full operations matrix.", + "operationId": "get_operations_matrix_api_v1_admin_operations_matrix_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "Get Operations Matrix", + "tags": [ + "source-policy" + ] + } + }, + "/api/v1/admin/operations/{operation_id}": { + "put": { + "description": "Update an operation in the matrix.", + "operationId": "update_operation_api_v1_admin_operations__operation_id__put", + "parameters": [ + { + "in": "path", + "name": "operation_id", + "required": true, + "schema": { + "title": "Operation Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperationUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Operation", + "tags": [ + "source-policy" + ] + } + }, + "/api/v1/admin/pii-rules": { + "get": { + "description": "List all PII rules with optional category filter.", + "operationId": "list_pii_rules_api_v1_admin_pii_rules_get", + "parameters": [ + { + "in": "query", + "name": "category", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Category" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Pii Rules", + "tags": [ + "source-policy" + ] + }, + "post": { + "description": "Create a new PII rule.", + "operationId": "create_pii_rule_api_v1_admin_pii_rules_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PIIRuleCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Pii Rule", + "tags": [ + "source-policy" + ] + } + }, + "/api/v1/admin/pii-rules/{rule_id}": { + "delete": { + "description": "Delete a PII rule.", + "operationId": "delete_pii_rule_api_v1_admin_pii_rules__rule_id__delete", + "parameters": [ + { + "in": "path", + "name": "rule_id", + "required": true, + "schema": { + "title": "Rule Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Pii Rule", + "tags": [ + "source-policy" + ] + }, + "put": { + "description": "Update a PII rule.", + "operationId": "update_pii_rule_api_v1_admin_pii_rules__rule_id__put", + "parameters": [ + { + "in": "path", + "name": "rule_id", + "required": true, + "schema": { + "title": "Rule Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PIIRuleUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Pii Rule", + "tags": [ + "source-policy" + ] + } + }, + "/api/v1/admin/policy-audit": { + "get": { + "description": "Get the audit trail for source policy changes.", + "operationId": "get_policy_audit_api_v1_admin_policy_audit_get", + "parameters": [ + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 50, + "maximum": 500, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "minimum": 0, + "title": "Offset", + "type": "integer" + } + }, + { + "in": "query", + "name": "entity_type", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Entity Type" + } + }, + { + "in": "query", + "name": "from", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "From" + } + }, + { + "in": "query", + "name": "to", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "To" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Policy Audit", + "tags": [ + "source-policy" + ] + } + }, + "/api/v1/admin/policy-stats": { + "get": { + "description": "Get dashboard statistics for source policy.", + "operationId": "get_policy_stats_api_v1_admin_policy_stats_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "Get Policy Stats", + "tags": [ + "source-policy" + ] + } + }, + "/api/v1/admin/sources": { + "get": { + "description": "List all allowed sources with optional filters.", + "operationId": "list_sources_api_v1_admin_sources_get", + "parameters": [ + { + "in": "query", + "name": "active_only", + "required": false, + "schema": { + "default": false, + "title": "Active Only", + "type": "boolean" + } + }, + { + "in": "query", + "name": "source_type", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source Type" + } + }, + { + "in": "query", + "name": "license", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "License" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Sources", + "tags": [ + "source-policy" + ] + }, + "post": { + "description": "Add a new allowed source.", + "operationId": "create_source_api_v1_admin_sources_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SourceCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Create Source", + "tags": [ + "source-policy" + ] + } + }, + "/api/v1/admin/sources/{source_id}": { + "delete": { + "description": "Remove an allowed source.", + "operationId": "delete_source_api_v1_admin_sources__source_id__delete", + "parameters": [ + { + "in": "path", + "name": "source_id", + "required": true, + "schema": { + "title": "Source Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Source", + "tags": [ + "source-policy" + ] + }, + "get": { + "description": "Get a specific source.", + "operationId": "get_source_api_v1_admin_sources__source_id__get", + "parameters": [ + { + "in": "path", + "name": "source_id", + "required": true, + "schema": { + "title": "Source Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Source", + "tags": [ + "source-policy" + ] + }, + "put": { + "description": "Update an existing source.", + "operationId": "update_source_api_v1_admin_sources__source_id__put", + "parameters": [ + { + "in": "path", + "name": "source_id", + "required": true, + "schema": { + "title": "Source Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SourceUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Update Source", + "tags": [ + "source-policy" + ] + } + }, + "/api/v1/company-profile": { + "delete": { + "description": "Delete company profile for a tenant (DSGVO Recht auf Loeschung, Art. 17).", + "operationId": "delete_company_profile_api_v1_company_profile_delete", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "default": "default", + "title": "Tenant Id", + "type": "string" + } + }, + { + "in": "query", + "name": "project_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Project Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Company Profile", + "tags": [ + "company-profile" + ] + }, + "get": { + "description": "Get company profile for a tenant (optionally per project).", + "operationId": "get_company_profile_api_v1_company_profile_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "default": "default", + "title": "Tenant Id", + "type": "string" + } + }, + { + "in": "query", + "name": "project_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Project Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CompanyProfileResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Company Profile", + "tags": [ + "company-profile" + ] + }, + "patch": { + "description": "Partial update for company profile.", + "operationId": "patch_company_profile_api_v1_company_profile_patch", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "default": "default", + "title": "Tenant Id", + "type": "string" + } + }, + { + "in": "query", + "name": "project_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Project Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "title": "Updates", + "type": "object" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CompanyProfileResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Patch Company Profile", + "tags": [ + "company-profile" + ] + }, + "post": { + "description": "Create or update company profile (upsert).", + "operationId": "upsert_company_profile_api_v1_company_profile_post", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "default": "default", + "title": "Tenant Id", + "type": "string" + } + }, + { + "in": "query", + "name": "project_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Project Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CompanyProfileRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CompanyProfileResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Upsert Company Profile", + "tags": [ + "company-profile" + ] + } + }, + "/api/v1/company-profile/audit": { + "get": { + "description": "Get audit log for company profile changes.", + "operationId": "get_audit_log_api_v1_company_profile_audit_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "default": "default", + "title": "Tenant Id", + "type": "string" + } + }, + { + "in": "query", + "name": "project_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Project Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuditListResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Audit Log", + "tags": [ + "company-profile" + ] + } + }, + "/api/v1/company-profile/template-context": { + "get": { + "description": "Return flat dict for Jinja2 template substitution in document generation.", + "operationId": "get_template_context_api_v1_company_profile_template_context_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "default": "default", + "title": "Tenant Id", + "type": "string" + } + }, + { + "in": "query", + "name": "project_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Project Id" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Template Context", + "tags": [ + "company-profile" + ] + } + }, + "/api/v1/import": { + "get": { + "description": "Alias: GET /v1/import \u2192 list documents (proxy-compatible URL).", + "operationId": "list_documents_root_api_v1_import_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "default": "default", + "title": "Tenant Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentListResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Documents Root", + "tags": [ + "document-import" + ] + } + }, + "/api/v1/import/analyze": { + "post": { + "description": "Upload and analyze a compliance document.", + "operationId": "analyze_document_api_v1_import_analyze_post", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_analyze_document_api_v1_import_analyze_post" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentAnalysisResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Analyze Document", + "tags": [ + "document-import" + ] + } + }, + "/api/v1/import/documents": { + "get": { + "description": "List all imported documents for a tenant.", + "operationId": "list_documents_api_v1_import_documents_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "default": "default", + "title": "Tenant Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentListResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Documents", + "tags": [ + "document-import" + ] + } + }, + "/api/v1/import/gap-analysis/{document_id}": { + "get": { + "description": "Get gap analysis for a specific document.", + "operationId": "get_gap_analysis_api_v1_import_gap_analysis__document_id__get", + "parameters": [ + { + "in": "path", + "name": "document_id", + "required": true, + "schema": { + "title": "Document Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "default": "default", + "title": "Tenant Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Gap Analysis", + "tags": [ + "document-import" + ] + } + }, + "/api/v1/import/{document_id}": { + "delete": { + "description": "Delete an imported document and its gap analysis.", + "operationId": "delete_document_api_v1_import__document_id__delete", + "parameters": [ + { + "in": "path", + "name": "document_id", + "required": true, + "schema": { + "title": "Document Id", + "type": "string" + } + }, + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "default": "default", + "title": "Tenant Id", + "type": "string" + } + }, + { + "in": "header", + "name": "X-Tenant-ID", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Tenant-Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Delete Document", + "tags": [ + "document-import" + ] + } + }, + "/api/v1/screening": { + "get": { + "description": "List all screenings for a tenant.", + "operationId": "list_screenings_api_v1_screening_get", + "parameters": [ + { + "in": "query", + "name": "tenant_id", + "required": false, + "schema": { + "default": "default", + "title": "Tenant Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScreeningListResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "List Screenings", + "tags": [ + "system-screening" + ] + } + }, + "/api/v1/screening/scan": { + "post": { + "description": "Upload a dependency file, generate SBOM, and scan for vulnerabilities.", + "operationId": "scan_dependencies_api_v1_screening_scan_post", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_scan_dependencies_api_v1_screening_scan_post" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScreeningResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Scan Dependencies", + "tags": [ + "system-screening" + ] + } + }, + "/api/v1/screening/{screening_id}": { + "get": { + "description": "Get a screening result by ID.", + "operationId": "get_screening_api_v1_screening__screening_id__get", + "parameters": [ + { + "in": "path", + "name": "screening_id", + "required": true, + "schema": { + "title": "Screening Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScreeningResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get Screening", + "tags": [ + "system-screening" + ] + } + }, + "/health": { + "get": { + "description": "Health check endpoint for load balancers and orchestration.", + "operationId": "health_health_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + } + }, + "summary": "Health", + "tags": [ + "system" + ] + } + } + } +} diff --git a/backend-compliance/tests/contracts/regenerate_baseline.py b/backend-compliance/tests/contracts/regenerate_baseline.py new file mode 100644 index 0000000..ada4dce --- /dev/null +++ b/backend-compliance/tests/contracts/regenerate_baseline.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +"""Regenerate the OpenAPI baseline. + +Run this ONLY when you have intentionally made an additive API change and want +the contract test to pick up the new baseline. Removing or renaming anything is +a breaking change and requires updating every consumer in the same change set. + +Usage: + python tests/contracts/regenerate_baseline.py +""" +from __future__ import annotations + +import json +import sys +from pathlib import Path + +THIS_DIR = Path(__file__).parent +REPO_ROOT = THIS_DIR.parent.parent # backend-compliance/ +sys.path.insert(0, str(REPO_ROOT)) + +from main import app # type: ignore[import-not-found] # noqa: E402 + +out = THIS_DIR / "openapi.baseline.json" +out.write_text(json.dumps(app.openapi(), indent=2, sort_keys=True) + "\n") +print(f"wrote {out}") diff --git a/backend-compliance/tests/contracts/test_openapi_baseline.py b/backend-compliance/tests/contracts/test_openapi_baseline.py new file mode 100644 index 0000000..12a91d7 --- /dev/null +++ b/backend-compliance/tests/contracts/test_openapi_baseline.py @@ -0,0 +1,102 @@ +"""OpenAPI contract test. + +This test pins the public HTTP contract of backend-compliance. It loads the +FastAPI app, extracts the live OpenAPI schema, and compares it against a +checked-in baseline at ``tests/contracts/openapi.baseline.json``. + +Rules: + - Adding new paths/operations/fields → OK (additive change). + - Removing a path, changing a method, changing a status code, removing or + renaming a response/request field → FAIL. Such changes require updating + every consumer (admin-compliance, developer-portal, SDKs) in the same + change, then regenerating the baseline with: + + python tests/contracts/regenerate_baseline.py + + and explaining the contract change in the PR description. + +The baseline is missing on first run — the test prints the command to create +it and skips. This is intentional: Phase 1 step 1 generates it fresh from the +current app state before any refactoring begins. +""" + +from __future__ import annotations + +import json +from pathlib import Path +from typing import Any + +import pytest + +BASELINE_PATH = Path(__file__).parent / "openapi.baseline.json" + + +def _load_live_schema() -> dict[str, Any]: + """Import the FastAPI app and extract its OpenAPI schema. + + Kept inside the function so that test collection does not fail if the app + has import-time side effects that aren't satisfied in the test env. + """ + from main import app # type: ignore[import-not-found] + + return app.openapi() + + +def _collect_operations(schema: dict[str, Any]) -> dict[str, dict[str, Any]]: + """Return a flat {f'{METHOD} {path}': operation} map for diffing.""" + out: dict[str, dict[str, Any]] = {} + for path, methods in schema.get("paths", {}).items(): + for method, op in methods.items(): + if method.lower() in {"get", "post", "put", "patch", "delete", "options", "head"}: + out[f"{method.upper()} {path}"] = op + return out + + +@pytest.mark.contract +def test_openapi_no_breaking_changes() -> None: + if not BASELINE_PATH.exists(): + pytest.skip( + f"Baseline missing. Run: python {Path(__file__).parent}/regenerate_baseline.py" + ) + + baseline = json.loads(BASELINE_PATH.read_text()) + live = _load_live_schema() + + baseline_ops = _collect_operations(baseline) + live_ops = _collect_operations(live) + + # 1. No operation may disappear. + removed = sorted(set(baseline_ops) - set(live_ops)) + assert not removed, ( + f"Breaking change: {len(removed)} operation(s) removed from public API:\n " + + "\n ".join(removed) + ) + + # 2. For operations that exist in both, response status codes must be a superset. + for key, baseline_op in baseline_ops.items(): + live_op = live_ops[key] + baseline_codes = set((baseline_op.get("responses") or {}).keys()) + live_codes = set((live_op.get("responses") or {}).keys()) + missing = baseline_codes - live_codes + assert not missing, ( + f"Breaking change: {key} no longer returns status code(s) {sorted(missing)}" + ) + + # 3. Required request-body fields may not be added (would break existing clients). + for key, baseline_op in baseline_ops.items(): + live_op = live_ops[key] + base_req = _required_body_fields(baseline_op) + live_req = _required_body_fields(live_op) + new_required = live_req - base_req + assert not new_required, ( + f"Breaking change: {key} added required request field(s) {sorted(new_required)}" + ) + + +def _required_body_fields(op: dict[str, Any]) -> set[str]: + rb = op.get("requestBody") or {} + content = rb.get("content") or {} + for media in content.values(): + schema = media.get("schema") or {} + return set(schema.get("required") or []) + return set() diff --git a/backend-compliance/tests/test_dsfa_routes.py b/backend-compliance/tests/test_dsfa_routes.py index 6b78d78..6601ced 100644 --- a/backend-compliance/tests/test_dsfa_routes.py +++ b/backend-compliance/tests/test_dsfa_routes.py @@ -10,7 +10,7 @@ import pytest import uuid import os import sys -from datetime import datetime +from datetime import datetime, timezone from unittest.mock import MagicMock from fastapi import FastAPI @@ -51,7 +51,7 @@ _RawSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) @event.listens_for(engine, "connect") def _register_sqlite_functions(dbapi_conn, connection_record): """Register PostgreSQL-compatible functions for SQLite.""" - dbapi_conn.create_function("NOW", 0, lambda: datetime.utcnow().isoformat()) + dbapi_conn.create_function("NOW", 0, lambda: datetime.now(timezone.utc).isoformat()) TENANT_ID = "default" diff --git a/backend-compliance/tests/test_dsr_routes.py b/backend-compliance/tests/test_dsr_routes.py index ff91e9d..bd9748b 100644 --- a/backend-compliance/tests/test_dsr_routes.py +++ b/backend-compliance/tests/test_dsr_routes.py @@ -6,7 +6,7 @@ Pattern: app.dependency_overrides[get_db] for FastAPI DI. import uuid import os import sys -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone import pytest from fastapi import FastAPI @@ -75,7 +75,7 @@ def db_session(): def _create_dsr_in_db(db, **kwargs): """Helper to create a DSR directly in DB.""" - now = datetime.utcnow() + now = datetime.now(timezone.utc) defaults = { "tenant_id": uuid.UUID(TENANT_ID), "request_number": f"DSR-2026-{str(uuid.uuid4())[:6].upper()}", @@ -241,8 +241,8 @@ class TestListDSR: assert len(data["requests"]) == 2 def test_list_overdue_only(self, db_session): - _create_dsr_in_db(db_session, deadline_at=datetime.utcnow() - timedelta(days=5), status="processing") - _create_dsr_in_db(db_session, deadline_at=datetime.utcnow() + timedelta(days=20), status="processing") + _create_dsr_in_db(db_session, deadline_at=datetime.now(timezone.utc) - timedelta(days=5), status="processing") + _create_dsr_in_db(db_session, deadline_at=datetime.now(timezone.utc) + timedelta(days=20), status="processing") resp = client.get("/api/compliance/dsr?overdue_only=true", headers=HEADERS) assert resp.status_code == 200 @@ -339,7 +339,7 @@ class TestDSRStats: _create_dsr_in_db(db_session, status="intake", request_type="access") _create_dsr_in_db(db_session, status="processing", request_type="erasure") _create_dsr_in_db(db_session, status="completed", request_type="access", - completed_at=datetime.utcnow()) + completed_at=datetime.now(timezone.utc)) resp = client.get("/api/compliance/dsr/stats", headers=HEADERS) assert resp.status_code == 200 @@ -561,9 +561,9 @@ class TestDeadlineProcessing: def test_process_deadlines_with_overdue(self, db_session): _create_dsr_in_db(db_session, status="processing", - deadline_at=datetime.utcnow() - timedelta(days=5)) + deadline_at=datetime.now(timezone.utc) - timedelta(days=5)) _create_dsr_in_db(db_session, status="processing", - deadline_at=datetime.utcnow() + timedelta(days=20)) + deadline_at=datetime.now(timezone.utc) + timedelta(days=20)) resp = client.post("/api/compliance/dsr/deadlines/process", headers=HEADERS) assert resp.status_code == 200 @@ -609,7 +609,7 @@ class TestDSRTemplates: subject="Bestaetigung", body_html="

Test

", status="published", - published_at=datetime.utcnow(), + published_at=datetime.now(timezone.utc), ) db_session.add(v) db_session.commit() diff --git a/backend-compliance/tests/test_einwilligungen_routes.py b/backend-compliance/tests/test_einwilligungen_routes.py index 5af913d..ffc4c18 100644 --- a/backend-compliance/tests/test_einwilligungen_routes.py +++ b/backend-compliance/tests/test_einwilligungen_routes.py @@ -7,7 +7,7 @@ Consent widerrufen, Statistiken. import pytest from unittest.mock import MagicMock, patch -from datetime import datetime +from datetime import datetime, timezone import uuid @@ -25,7 +25,7 @@ def make_catalog(tenant_id='test-tenant'): rec.tenant_id = tenant_id rec.selected_data_point_ids = ['dp-001', 'dp-002'] rec.custom_data_points = [] - rec.updated_at = datetime.utcnow() + rec.updated_at = datetime.now(timezone.utc) return rec @@ -34,7 +34,7 @@ def make_company(tenant_id='test-tenant'): rec.id = uuid.uuid4() rec.tenant_id = tenant_id rec.data = {'company_name': 'Test GmbH', 'email': 'datenschutz@test.de'} - rec.updated_at = datetime.utcnow() + rec.updated_at = datetime.now(timezone.utc) return rec @@ -47,7 +47,7 @@ def make_cookies(tenant_id='test-tenant'): {'id': 'analytics', 'name': 'Analyse', 'isRequired': False, 'defaultEnabled': False}, ] rec.config = {'position': 'bottom', 'style': 'bar'} - rec.updated_at = datetime.utcnow() + rec.updated_at = datetime.now(timezone.utc) return rec @@ -58,13 +58,13 @@ def make_consent(tenant_id='test-tenant', user_id='user-001', data_point_id='dp- rec.user_id = user_id rec.data_point_id = data_point_id rec.granted = granted - rec.granted_at = datetime.utcnow() + rec.granted_at = datetime.now(timezone.utc) rec.revoked_at = None rec.consent_version = '1.0' rec.source = 'website' rec.ip_address = None rec.user_agent = None - rec.created_at = datetime.utcnow() + rec.created_at = datetime.now(timezone.utc) return rec @@ -263,7 +263,7 @@ class TestConsentDB: user_id='user-001', data_point_id='dp-marketing', granted=True, - granted_at=datetime.utcnow(), + granted_at=datetime.now(timezone.utc), consent_version='1.0', source='website', ) @@ -276,13 +276,13 @@ class TestConsentDB: consent = make_consent() assert consent.revoked_at is None - consent.revoked_at = datetime.utcnow() + consent.revoked_at = datetime.now(timezone.utc) assert consent.revoked_at is not None def test_cannot_revoke_already_revoked(self): """Should not be possible to revoke an already revoked consent.""" consent = make_consent() - consent.revoked_at = datetime.utcnow() + consent.revoked_at = datetime.now(timezone.utc) # Simulate the guard logic from the route already_revoked = consent.revoked_at is not None @@ -315,7 +315,7 @@ class TestConsentStats: make_consent(user_id='user-2', data_point_id='dp-1', granted=True), ] # Revoke one - consents[1].revoked_at = datetime.utcnow() + consents[1].revoked_at = datetime.now(timezone.utc) total = len(consents) active = sum(1 for c in consents if c.granted and not c.revoked_at) @@ -334,7 +334,7 @@ class TestConsentStats: make_consent(user_id='user-2', granted=True), make_consent(user_id='user-3', granted=True), ] - consents[2].revoked_at = datetime.utcnow() # user-3 revoked + consents[2].revoked_at = datetime.now(timezone.utc) # user-3 revoked unique_users = len(set(c.user_id for c in consents)) users_with_active = len(set(c.user_id for c in consents if c.granted and not c.revoked_at)) @@ -501,7 +501,7 @@ class TestConsentHistoryTracking: from compliance.db.einwilligungen_models import EinwilligungenConsentHistoryDB consent = make_consent() - consent.revoked_at = datetime.utcnow() + consent.revoked_at = datetime.now(timezone.utc) entry = EinwilligungenConsentHistoryDB( consent_id=consent.id, tenant_id=consent.tenant_id, @@ -516,7 +516,7 @@ class TestConsentHistoryTracking: entry_id = _uuid.uuid4() consent_id = _uuid.uuid4() - now = datetime.utcnow() + now = datetime.now(timezone.utc) row = { "id": str(entry_id), diff --git a/backend-compliance/tests/test_isms_routes.py b/backend-compliance/tests/test_isms_routes.py index 8eb9364..89aa7d2 100644 --- a/backend-compliance/tests/test_isms_routes.py +++ b/backend-compliance/tests/test_isms_routes.py @@ -13,7 +13,7 @@ Run with: cd backend-compliance && python3 -m pytest tests/test_isms_routes.py - import os import sys import pytest -from datetime import date, datetime +from datetime import date, datetime, timezone from fastapi import FastAPI from fastapi.testclient import TestClient @@ -40,7 +40,7 @@ def _set_sqlite_pragma(dbapi_conn, connection_record): cursor = dbapi_conn.cursor() cursor.execute("PRAGMA foreign_keys=ON") cursor.close() - dbapi_conn.create_function("NOW", 0, lambda: datetime.utcnow().isoformat()) + dbapi_conn.create_function("NOW", 0, lambda: datetime.now(timezone.utc).isoformat()) app = FastAPI() diff --git a/backend-compliance/tests/test_legal_document_routes.py b/backend-compliance/tests/test_legal_document_routes.py index e51c148..0b4e4cb 100644 --- a/backend-compliance/tests/test_legal_document_routes.py +++ b/backend-compliance/tests/test_legal_document_routes.py @@ -7,7 +7,7 @@ Rejection-Flow, approval history. import pytest from unittest.mock import MagicMock, patch -from datetime import datetime +from datetime import datetime, timezone import uuid @@ -27,7 +27,7 @@ def make_document(type='privacy_policy', name='Datenschutzerklärung', tenant_id doc.name = name doc.description = 'Test description' doc.mandatory = False - doc.created_at = datetime.utcnow() + doc.created_at = datetime.now(timezone.utc) doc.updated_at = None return doc @@ -46,7 +46,7 @@ def make_version(document_id=None, version='1.0', status='draft', title='Test Ve v.approved_by = None v.approved_at = None v.rejection_reason = None - v.created_at = datetime.utcnow() + v.created_at = datetime.now(timezone.utc) v.updated_at = None return v @@ -58,7 +58,7 @@ def make_approval(version_id=None, action='created'): a.action = action a.approver = 'admin@test.de' a.comment = None - a.created_at = datetime.utcnow() + a.created_at = datetime.now(timezone.utc) return a @@ -179,7 +179,7 @@ class TestVersionToResponse: from compliance.api.legal_document_routes import _version_to_response v = make_version(status='approved') v.approved_by = 'dpo@company.de' - v.approved_at = datetime.utcnow() + v.approved_at = datetime.now(timezone.utc) resp = _version_to_response(v) assert resp.status == 'approved' assert resp.approved_by == 'dpo@company.de' @@ -254,7 +254,7 @@ class TestApprovalWorkflow: # Step 2: Approve mock_db.reset_mock() _transition(mock_db, str(v.id), ['review'], 'approved', 'approved', 'dpo', 'Korrekt', - extra_updates={'approved_by': 'dpo', 'approved_at': datetime.utcnow()}) + extra_updates={'approved_by': 'dpo', 'approved_at': datetime.now(timezone.utc)}) assert v.status == 'approved' # Step 3: Publish diff --git a/backend-compliance/tests/test_legal_document_routes_extended.py b/backend-compliance/tests/test_legal_document_routes_extended.py index 764f72a..aad27da 100644 --- a/backend-compliance/tests/test_legal_document_routes_extended.py +++ b/backend-compliance/tests/test_legal_document_routes_extended.py @@ -5,7 +5,7 @@ Tests for Legal Document extended routes (User Consents, Audit Log, Cookie Categ import uuid import os import sys -from datetime import datetime +from datetime import datetime, timezone import pytest from fastapi import FastAPI @@ -103,7 +103,7 @@ def _publish_version(version_id): v = db.query(LegalDocumentVersionDB).filter(LegalDocumentVersionDB.id == vid).first() v.status = "published" v.approved_by = "admin" - v.approved_at = datetime.utcnow() + v.approved_at = datetime.now(timezone.utc) db.commit() db.refresh(v) result = {"id": str(v.id), "status": v.status} diff --git a/backend-compliance/tests/test_vendor_compliance_routes.py b/backend-compliance/tests/test_vendor_compliance_routes.py index 5d8b327..7a34692 100644 --- a/backend-compliance/tests/test_vendor_compliance_routes.py +++ b/backend-compliance/tests/test_vendor_compliance_routes.py @@ -15,7 +15,7 @@ import pytest import uuid import os import sys -from datetime import datetime +from datetime import datetime, timezone from fastapi import FastAPI from fastapi.testclient import TestClient @@ -40,7 +40,7 @@ TENANT_ID = "default" @event.listens_for(engine, "connect") def _register_sqlite_functions(dbapi_conn, connection_record): - dbapi_conn.create_function("NOW", 0, lambda: datetime.utcnow().isoformat()) + dbapi_conn.create_function("NOW", 0, lambda: datetime.now(timezone.utc).isoformat()) class _DictRow(dict): diff --git a/backend-compliance/tests/test_vvt_routes.py b/backend-compliance/tests/test_vvt_routes.py index c9461b3..9031016 100644 --- a/backend-compliance/tests/test_vvt_routes.py +++ b/backend-compliance/tests/test_vvt_routes.py @@ -186,7 +186,7 @@ class TestActivityToResponse: act.next_review_at = kwargs.get("next_review_at", None) act.created_by = kwargs.get("created_by", None) act.dsfa_id = kwargs.get("dsfa_id", None) - act.created_at = datetime.utcnow() + act.created_at = datetime.now(timezone.utc) act.updated_at = None return act @@ -330,7 +330,7 @@ class TestVVTConsolidationResponse: act.next_review_at = kwargs.get("next_review_at", None) act.created_by = kwargs.get("created_by", None) act.dsfa_id = kwargs.get("dsfa_id", None) - act.created_at = datetime.utcnow() + act.created_at = datetime.now(timezone.utc) act.updated_at = None return act diff --git a/backend-compliance/tests/test_vvt_tenant_isolation.py b/backend-compliance/tests/test_vvt_tenant_isolation.py index e7960d3..9167cca 100644 --- a/backend-compliance/tests/test_vvt_tenant_isolation.py +++ b/backend-compliance/tests/test_vvt_tenant_isolation.py @@ -10,7 +10,7 @@ Verifies that: import pytest import uuid from unittest.mock import MagicMock, AsyncMock, patch -from datetime import datetime +from datetime import datetime, timezone from fastapi import HTTPException from fastapi.testclient import TestClient @@ -144,8 +144,8 @@ def _make_activity(tenant_id, vvt_id="VVT-001", name="Test", **kwargs): act.next_review_at = None act.created_by = "system" act.dsfa_id = None - act.created_at = datetime.utcnow() - act.updated_at = datetime.utcnow() + act.created_at = datetime.now(timezone.utc) + act.updated_at = datetime.now(timezone.utc) return act diff --git a/breakpilot-compliance-sdk/README.md b/breakpilot-compliance-sdk/README.md new file mode 100644 index 0000000..8a653e6 --- /dev/null +++ b/breakpilot-compliance-sdk/README.md @@ -0,0 +1,37 @@ +# breakpilot-compliance-sdk + +TypeScript SDK monorepo providing React, Angular, Vue, vanilla JS, and core bindings for the BreakPilot Compliance backend. Published as npm packages. + +**Stack:** TypeScript, workspaces (`packages/core`, `packages/react`, `packages/angular`, `packages/vanilla`, `packages/types`). + +## Layout + +``` +packages/ +├── core/ # Framework-agnostic client + state +├── types/ # Shared type definitions +├── react/ # React Provider + hooks +├── angular/ # Angular service +└── vanilla/ # Vanilla-JS embed script +``` + +## Architecture + +Follow `../AGENTS.typescript.md`. No framework-specific code in `core/`. + +## Build + test + +```bash +npm install +npm run build # per-workspace build +npm test # Vitest (Phase 4 adds coverage — currently 0 tests) +``` + +## Known debt (Phase 4) + +- `packages/vanilla/src/embed.ts` (611), `packages/react/src/provider.tsx` (539), `packages/core/src/client.ts` (521), `packages/react/src/hooks.ts` (474) — split. +- **Zero test coverage.** Priority Phase 4 target. + +## Don't touch + +Public API surface of `core` without bumping package major version and updating consumers. diff --git a/compliance-tts-service/README.md b/compliance-tts-service/README.md new file mode 100644 index 0000000..856c5ec --- /dev/null +++ b/compliance-tts-service/README.md @@ -0,0 +1,30 @@ +# compliance-tts-service + +Python service generating German-language audio/video training materials using Piper TTS + FFmpeg. Outputs are stored in Hetzner Object Storage (S3-compatible). + +**Port:** `8095` (container: `bp-compliance-tts`) +**Stack:** Python 3.12, Piper TTS (`de_DE-thorsten-high.onnx`), FFmpeg, boto3. + +## Files + +- `main.py` — FastAPI entrypoint +- `tts_engine.py` — Piper wrapper +- `video_generator.py` — FFmpeg pipeline +- `storage.py` — S3 client + +## Run locally + +```bash +cd compliance-tts-service +pip install -r requirements.txt +# Piper model + ffmpeg must be available on PATH +uvicorn main:app --reload --port 8095 +``` + +## Tests + +0 test files today. Phase 4 adds unit tests for the synthesis pipeline (mocked Piper + FFmpeg) and the S3 client. + +## Architecture + +Follow `../AGENTS.python.md`. Keep the Piper model loading behind a single service instance — not loaded per request. diff --git a/developer-portal/README.md b/developer-portal/README.md new file mode 100644 index 0000000..31b789f --- /dev/null +++ b/developer-portal/README.md @@ -0,0 +1,26 @@ +# developer-portal + +Next.js 15 public API documentation portal — integration guides, SDK docs, BYOEH, development phases. Consumed by external customers. + +**Port:** `3006` (container: `bp-compliance-developer-portal`) +**Stack:** Next.js 15, React 18, TypeScript. + +## Run locally + +```bash +cd developer-portal +npm install +npm run dev +``` + +## Tests + +0 test files today. Phase 4 adds Playwright smoke tests for each top-level page and Vitest for `lib/` helpers. + +## Architecture + +Follow `../AGENTS.typescript.md`. MD/MDX content should live in a data directory, not inline in `page.tsx`. + +## Known debt + +- `app/development/docs/page.tsx` (891), `app/development/byoeh/page.tsx` (769), and others > 300 LOC — split in Phase 4. diff --git a/docs-src/README.md b/docs-src/README.md new file mode 100644 index 0000000..8081848 --- /dev/null +++ b/docs-src/README.md @@ -0,0 +1,19 @@ +# docs-src + +MkDocs-based internal documentation site — system architecture, data models, runbooks, API references. + +**Port:** `8011` (container: `bp-compliance-docs`) +**Stack:** MkDocs + Material theme, served via nginx. + +## Build + serve locally + +```bash +cd docs-src +pip install -r requirements.txt +mkdocs serve # http://localhost:8000 +mkdocs build # static output to site/ +``` + +## Known debt (Phase 4) + +- `index.md` is 9436 lines — will be split into per-topic pages with proper mkdocs nav. Target: no single markdown file >500 lines except explicit reference tables. diff --git a/document-crawler/README.md b/document-crawler/README.md new file mode 100644 index 0000000..185a796 --- /dev/null +++ b/document-crawler/README.md @@ -0,0 +1,28 @@ +# document-crawler + +Python/FastAPI service for document ingestion and compliance gap analysis. Parses PDF, DOCX, XLSX, PPTX; runs gap analysis against compliance requirements; coordinates with `ai-compliance-sdk` via the LLM gateway; archives to `dsms-gateway`. + +**Port:** `8098` (container: `bp-compliance-document-crawler`) +**Stack:** Python 3.11, FastAPI. + +## Architecture + +Small service — already well under the LOC budget. Follow `../AGENTS.python.md` for any additions. + +## Run locally + +```bash +cd document-crawler +pip install -r requirements.txt +uvicorn main:app --reload --port 8098 +``` + +## Tests + +```bash +pytest tests/ -v +``` + +## Public API surface + +`GET /health`, document upload/parse endpoints, gap-analysis endpoints. See the OpenAPI doc at `/docs` when running. diff --git a/dsms-gateway/README.md b/dsms-gateway/README.md new file mode 100644 index 0000000..62aa490 --- /dev/null +++ b/dsms-gateway/README.md @@ -0,0 +1,55 @@ +# dsms-gateway + +Python/FastAPI gateway to the IPFS-backed document archival store. Upload, retrieve, verify, and archive legal documents with content-addressed immutability. + +**Port:** `8082` (container: `bp-compliance-dsms-gateway`) +**Stack:** Python 3.11, FastAPI, IPFS (Kubo via `dsms-node`). + +## Architecture (target — Phase 4) + +`main.py` (467 LOC) will split into: + +``` +dsms_gateway/ +├── main.py # FastAPI app factory, <50 LOC +├── routers/ # /documents, /legal-documents, /verify, /node +├── ipfs/ # IPFS client wrapper +├── services/ # Business logic (archive, verify) +├── schemas/ # Pydantic models +└── config.py +``` + +See `../AGENTS.python.md`. + +## Run locally + +```bash +cd dsms-gateway +pip install -r requirements.txt +export IPFS_API_URL=http://localhost:5001 +uvicorn main:app --reload --port 8082 +``` + +## Tests + +```bash +pytest test_main.py -v +``` + +Note: the existing test file is larger than the implementation — good coverage already. Phase 4 splits both into matching module pairs. + +## Public API surface + +``` +GET /health +GET /api/v1/documents +POST /api/v1/documents +GET /api/v1/documents/{cid} +GET /api/v1/documents/{cid}/metadata +DELETE /api/v1/documents/{cid} +POST /api/v1/legal-documents/archive +GET /api/v1/verify/{cid} +GET /api/v1/node/info +``` + +Every path is a contract — updating requires synchronized updates in consumers. diff --git a/dsms-node/README.md b/dsms-node/README.md new file mode 100644 index 0000000..d8335d7 --- /dev/null +++ b/dsms-node/README.md @@ -0,0 +1,15 @@ +# dsms-node + +IPFS Kubo node container — distributed document storage backend for the compliance platform. Participates in the BreakPilot IPFS swarm and serves as the storage layer behind `dsms-gateway`. + +**Image:** `ipfs/kubo:v0.24.0` +**Ports:** `4001` (swarm), `5001` (API), `8085` (HTTP gateway) +**Container:** `bp-compliance-dsms-node` + +## Operation + +No source code — this is a thin wrapper around the upstream IPFS Kubo image. Configuration is via environment and the compose file at repo root. + +## Don't touch + +This service is out of refactor scope. Do not modify without the infrastructure owner's sign-off. diff --git a/scripts/check-loc.sh b/scripts/check-loc.sh new file mode 100755 index 0000000..f6e4ce0 --- /dev/null +++ b/scripts/check-loc.sh @@ -0,0 +1,123 @@ +#!/usr/bin/env bash +# check-loc.sh — File-size budget enforcer for breakpilot-compliance. +# +# Soft target: 300 LOC. Hard cap: 500 LOC. +# +# Usage: +# scripts/check-loc.sh # scan whole repo, respect exceptions +# scripts/check-loc.sh --changed # only files changed vs origin/main +# scripts/check-loc.sh path/to/file.py # check specific files +# scripts/check-loc.sh --json # machine-readable output +# +# Exit codes: +# 0 — clean (no hard violations) +# 1 — at least one file exceeds the hard cap (500) +# 2 — invalid invocation +# +# Behavior: +# - Skips test files, generated files, vendor dirs, node_modules, .git, dist, build, +# .next, __pycache__, migrations, and anything matching .claude/rules/loc-exceptions.txt. +# - Counts non-blank, non-comment-only lines is NOT done — we count raw lines so the +# rule is unambiguous. If you want to game it with blank lines, you're missing the point. + +set -euo pipefail + +SOFT=300 +HARD=500 +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +EXCEPTIONS_FILE="$REPO_ROOT/.claude/rules/loc-exceptions.txt" + +CHANGED_ONLY=0 +JSON=0 +TARGETS=() + +for arg in "$@"; do + case "$arg" in + --changed) CHANGED_ONLY=1 ;; + --json) JSON=1 ;; + -h|--help) + sed -n '2,18p' "$0"; exit 0 ;; + -*) echo "unknown flag: $arg" >&2; exit 2 ;; + *) TARGETS+=("$arg") ;; + esac +done + +# Patterns excluded from the budget regardless of path. +is_excluded() { + local f="$1" + case "$f" in + */node_modules/*|*/.next/*|*/.git/*|*/dist/*|*/build/*|*/__pycache__/*|*/vendor/*) return 0 ;; + */migrations/*|*/alembic/versions/*) return 0 ;; + *_test.go|*.test.ts|*.test.tsx|*.spec.ts|*.spec.tsx) return 0 ;; + */tests/*|*/test/*) return 0 ;; + *.md|*.json|*.yaml|*.yml|*.lock|*.sum|*.mod|*.toml|*.cfg|*.ini) return 0 ;; + *.svg|*.png|*.jpg|*.jpeg|*.gif|*.ico|*.pdf|*.woff|*.woff2|*.ttf) return 0 ;; + *.generated.*|*.gen.*|*_pb.go|*_pb2.py|*.pb.go) return 0 ;; + esac + return 1 +} + +is_in_exceptions() { + [[ -f "$EXCEPTIONS_FILE" ]] || return 1 + local rel="${1#$REPO_ROOT/}" + grep -Fxq "$rel" "$EXCEPTIONS_FILE" +} + +collect_targets() { + if (( ${#TARGETS[@]} > 0 )); then + printf '%s\n' "${TARGETS[@]}" + elif (( CHANGED_ONLY )); then + git -C "$REPO_ROOT" diff --name-only --diff-filter=AM origin/main...HEAD 2>/dev/null \ + || git -C "$REPO_ROOT" diff --name-only --diff-filter=AM HEAD + else + git -C "$REPO_ROOT" ls-files + fi +} + +violations_hard=() +violations_soft=() + +while IFS= read -r f; do + [[ -z "$f" ]] && continue + abs="$f" + [[ "$abs" != /* ]] && abs="$REPO_ROOT/$f" + [[ -f "$abs" ]] || continue + is_excluded "$abs" && continue + is_in_exceptions "$abs" && continue + loc=$(wc -l < "$abs" | tr -d ' ') + if (( loc > HARD )); then + violations_hard+=("$loc $f") + elif (( loc > SOFT )); then + violations_soft+=("$loc $f") + fi +done < <(collect_targets) + +if (( JSON )); then + printf '{"hard":[' + first=1; for v in "${violations_hard[@]}"; do + loc="${v%% *}"; path="${v#* }" + (( first )) || printf ','; first=0 + printf '{"loc":%s,"path":"%s"}' "$loc" "$path" + done + printf '],"soft":[' + first=1; for v in "${violations_soft[@]}"; do + loc="${v%% *}"; path="${v#* }" + (( first )) || printf ','; first=0 + printf '{"loc":%s,"path":"%s"}' "$loc" "$path" + done + printf ']}\n' +else + if (( ${#violations_soft[@]} > 0 )); then + echo "::warning:: $((${#violations_soft[@]})) file(s) exceed soft target ($SOFT lines):" + printf ' %s\n' "${violations_soft[@]}" | sort -rn + fi + if (( ${#violations_hard[@]} > 0 )); then + echo "::error:: $((${#violations_hard[@]})) file(s) exceed HARD CAP ($HARD lines) — split required:" + printf ' %s\n' "${violations_hard[@]}" | sort -rn + echo + echo "If a file legitimately must exceed $HARD lines (generated code, large data tables)," + echo "add it to .claude/rules/loc-exceptions.txt with a one-line rationale comment above it." + fi +fi + +(( ${#violations_hard[@]} == 0 )) diff --git a/scripts/githooks/pre-commit b/scripts/githooks/pre-commit new file mode 100755 index 0000000..44d0314 --- /dev/null +++ b/scripts/githooks/pre-commit @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +# pre-commit — enforces breakpilot-compliance structural guardrails. +# +# 1. Blocks commits that introduce a non-test, non-generated source file > 500 LOC. +# 2. Blocks commits that touch backend-compliance/migrations/ unless the commit message +# contains the marker [migration-approved] (last-resort escape hatch). +# 3. Blocks edits to .claude/settings.json, scripts/check-loc.sh, or +# .claude/rules/loc-exceptions.txt unless [guardrail-change] is in the commit message. +# +# Bypass with --no-verify is intentionally NOT supported by the team workflow. +# CI re-runs all of these on the server side anyway. + +set -euo pipefail +REPO_ROOT="$(git rev-parse --show-toplevel)" + +mapfile -t staged < <(git diff --cached --name-only --diff-filter=ACM) +[[ ${#staged[@]} -eq 0 ]] && exit 0 + +# 1. LOC budget on staged files. +loc_targets=() +for f in "${staged[@]}"; do + [[ -f "$REPO_ROOT/$f" ]] && loc_targets+=("$REPO_ROOT/$f") +done +if [[ ${#loc_targets[@]} -gt 0 ]]; then + if ! "$REPO_ROOT/scripts/check-loc.sh" "${loc_targets[@]}"; then + echo + echo "Commit blocked: file-size budget violated. See output above." + echo "Either split the file (preferred) or add an exception with rationale to" + echo " .claude/rules/loc-exceptions.txt" + exit 1 + fi +fi + +# 2. Migration directories are frozen unless explicitly approved. +if printf '%s\n' "${staged[@]}" | grep -qE '(^|/)(migrations|alembic/versions)/'; then + if ! git log --format=%B -n 1 HEAD 2>/dev/null | grep -q '\[migration-approved\]' \ + && ! grep -q '\[migration-approved\]' "$(git rev-parse --git-dir)/COMMIT_EDITMSG" 2>/dev/null; then + echo "Commit blocked: this change touches a migrations directory." + echo "Database schema changes require an explicit migration plan reviewed by the DB owner." + echo "If approved, add '[migration-approved]' to your commit message." + exit 1 + fi +fi + +# 3. Guardrail files are protected. +guarded='^(\.claude/settings\.json|\.claude/rules/loc-exceptions\.txt|scripts/check-loc\.sh|scripts/githooks/pre-commit|AGENTS\.(python|go|typescript)\.md)$' +if printf '%s\n' "${staged[@]}" | grep -qE "$guarded"; then + if ! grep -q '\[guardrail-change\]' "$(git rev-parse --git-dir)/COMMIT_EDITMSG" 2>/dev/null; then + echo "Commit blocked: this change modifies guardrail files." + echo "If intentional, add '[guardrail-change]' to your commit message and explain why in the body." + exit 1 + fi +fi + +exit 0 diff --git a/scripts/install-hooks.sh b/scripts/install-hooks.sh new file mode 100755 index 0000000..51cb144 --- /dev/null +++ b/scripts/install-hooks.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# install-hooks.sh — installs git hooks that enforce repo guardrails locally. +# Idempotent. Safe to re-run. + +set -euo pipefail +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +HOOKS_DIR="$REPO_ROOT/.git/hooks" +SRC_DIR="$REPO_ROOT/scripts/githooks" + +if [[ ! -d "$REPO_ROOT/.git" ]]; then + echo "Not a git repository: $REPO_ROOT" >&2 + exit 1 +fi + +mkdir -p "$HOOKS_DIR" +for hook in pre-commit; do + src="$SRC_DIR/$hook" + dst="$HOOKS_DIR/$hook" + if [[ -f "$src" ]]; then + cp "$src" "$dst" + chmod +x "$dst" + echo "installed: $dst" + fi +done + +echo "Done. Hooks active for this clone."