shinkan-jinkendo/.cursor/rules/access-layer.mdc

37 lines
1.8 KiB
Plaintext
Raw Permalink Normal View History

---
description: Mandanten & Governance — TenantContext, Sichtbarkeit, keine Schnellpfade
globs: backend/routers/*.py
alwaysApply: false
---
# Zugriffsschicht (Shinkan)
Vor neuen oder geänderten Endpoints in `backend/routers/` kurz prüfen:
1. **Pflichtlektüre** (bei inhaltsbezogenen APIs): `.claude/docs/technical/ACCESS_LAYER_AND_GOVERNANCE_PLAN.md` und `.claude/docs/working/ACCESS_LAYER_ENDPOINT_AUDIT.md`.
2. **Auth**: kein geschützter Endpoint ohne `Depends(require_auth)` bzw. eingebettet in `Depends(get_tenant_context)` (der holt die Session bereits).
3. **Verein / Sichtbarkeit** (`visibility`, `club_id`, Mitglieder-Inhalte):
`tenant: TenantContext = Depends(get_tenant_context)` verwenden; Profile-ID aus `tenant.profile_id`, Rolle aus `tenant.global_role`.
4. **Bibliothekslisten** (Übungen, Vorlagen, Rahmenprogramme, Progressionsgraphen, gleiche Semantik): Filter über `library_content_visibility_sql(...)` bzw. gleiche Leseregel wie bestehende Module — nicht „alle Zeilen aus SELECT“.
5. **Schreiben mit Governance**: bei `visibility`/`club_id`-Änderungen `assert_valid_governance_visibility`; bei `club` ohne `club_id` im Body → `tenant.effective_club_id` oder klare 400-Hinweise (wie bei Übungen).
6. **Ausnahmen** nur mit kurzem Kommentar im Code: `# ACCESS_LAYER exempt: …` und Eintrag im Audit oder in `backend/scripts/check_access_layer_hints.py` (EXEMPT-Liste).
7. **Nach Merge**: eine Zeile `.claude/docs/working/ACCESS_LAYER_ENDPOINT_AUDIT.md` anpassen, wenn sich Tenant oder Governance ändert.
```python
# ❌ Schnellpfad: nur Session, obwohl Vereinsdaten betroffen
@router.get("/foo")
def foo(session=Depends(require_auth)):
...
# ✅ Konsistent zu clubs/exercises/planning
@router.get("/foo")
def foo(tenant: TenantContext = Depends(get_tenant_context)):
...
```