shinkan-jinkendo/backend/scripts/check_access_layer_hints.py
Lars 286c36e9d7
Some checks failed
Deploy Development / deploy (push) Successful in 38s
Test Suite / pytest-backend (push) Successful in 43s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 12s
Test Suite / k6 /health Baseline (push) Successful in 33s
Test Suite / playwright-tests (push) Has been cancelled
Document Superadmin API for AI Skill Retrieval Profiles and Update Access Layer
- Added documentation for the new Superadmin CRUD endpoints for managing AI Skill Retrieval Profiles (`/api/admin/ai-skill-retrieval-profiles*`).
- Updated the ACCESS_LAYER_ENDPOINT_AUDIT.md to include the new Superadmin API and its exempt status.
- Registered the ai_skill_retrieval_admin router in the backend and updated versioning to reflect the changes.
- Enhanced the frontend with a new Admin page for AI Skill Retrieval, including navigation and API integration for profile management.
2026-05-22 09:57:39 +02:00

80 lines
2.7 KiB
Python

#!/usr/bin/env python3
"""
Heuristik-Check: Router mit FastAPI-Routen und Auth sollten bei mandantenrelevanten APIs
get_tenant_context nutzen — siehe ACCESS_LAYER_AND_GOVERNANCE_PLAN.md.
Lauf aus Repo-Root:
python backend/scripts/check_access_layer_hints.py
Mit Fehler-Exit bei Verstößen (z. B. CI):
set ACCESS_LAYER_STRICT=1 # Windows: set ACCESS_LAYER_STRICT=1
"""
from __future__ import annotations
import os
import sys
from pathlib import Path
# Router, die bewusst keinen TenantContext verwenden (global / Auth-only / Admin-Tools).
# Neuen Eintrag nur mit kurzer Begründung im Commit/Audit ergänzen.
EXEMPT_ROUTERS: frozenset[str] = frozenset(
{
"auth.py",
"admin_users.py",
"platform_media_storage.py",
"legal_documents.py", # ACCESS_LAYER exempt: Plattform-Rechtstexte ohne Vereinsbezug; öffentlicher Endpoint ohne Auth, Admin-Endpoints require_auth + is_superadmin()
"ai_skill_retrieval_admin.py", # Superadmin-Plattform-Konfiguration Skill-KI-Retrieval; require_auth + is_superadmin — kein Vereinsmandant
"catalogs.py",
"skills.py",
"maturity_models.py",
"matrix_stack_bundle.py",
"import_wiki.py",
"import_wiki_admin.py",
}
)
def main() -> int:
strict = os.environ.get("ACCESS_LAYER_STRICT", "").strip().lower() in ("1", "true", "yes")
root = Path(__file__).resolve().parents[1]
routers = root / "routers"
if not routers.is_dir():
print("check_access_layer_hints: routers/ nicht gefunden", file=sys.stderr)
return 1
issues: list[str] = []
for path in sorted(routers.glob("*.py")):
name = path.name
text = path.read_text(encoding="utf-8")
if "@router." not in text:
continue
if name in EXEMPT_ROUTERS:
continue
if "get_tenant_context" in text:
continue
if "require_auth" not in text:
continue
issues.append(
f" {path.relative_to(root.parent)}: Routen + require_auth, "
f"aber kein get_tenant_context — TenantContext ergänzen oder in EXEMPT_ROUTERS eintragen "
f"(mit Begründung / Audit)."
)
if not issues:
print("check_access_layer_hints: OK (keine auffälligen Router außerhalb EXEMPT).")
return 0
print("check_access_layer_hints: mögliche ACCESS_LAYER-Abweichungen:\n", file=sys.stderr)
for line in issues:
print(line, file=sys.stderr)
print(
"\nHinweis: Heuristik — false positives möglich. "
"Bei echter Ausnahme Datei zu EXEMPT_ROUTERS hinzufügen.",
file=sys.stderr,
)
return 1 if strict else 0
if __name__ == "__main__":
raise SystemExit(main())