- Integrate ABAC policies into apply_visibility_filter() (allow/deny with priority)
- Add field whitelist (ABAC_ALLOWED_FIELDS) for build_sql_condition() security
- Add request-level ContextVar for user principals (group_ids, role_id)
- Set principals in deps.py (session + bearer auth)
- Use ContextVar in visibility.py and permission_resolver.py (N+1 fix)
- Add version validation to get_cached_visible_ids() (cache strategy unification)
- Deactivate delegation route (parked — not integrated into resolve_permissions)
- Add 7 ABAC integration tests
All 70 tests pass (7 ABAC + 63 existing). No regressions.
Problem 1: Remove legacy role bypass
- Remove role="admin" string bypass in permissions.py resolve_permissions()
- Remove role="admin"/"editor" bypass in auth.py check_permission()
- Remove legacy role string fallback in deps.py require_admin/require_write
- Add migration 0112: Create Role records for built-in roles and link role_id
- KI-Kommentar: Legacy Role Bypass entfernt — alle Admins müssen echte role_id haben
Problem 2: Enforce API token scopes
- Add _token_scopes check in require_permission() in deps.py
- When _token_scopes is set (API token auth), required permission must be in scopes
- When _token_scopes not set (session auth), normal permission check applies
Problem 3: Migration chain verification
- Chain is already linear: 0027→0028_rls_force→0028_user_preferences→0029
- user_preferences table confirmed exists in DB
- No duplicate revision IDs found
Problem 4: RLS for remaining tenant tables
- Add migration 0111: Dynamic RLS activation for any remaining tables with tenant_id
- Login tables and global tables explicitly excluded
- DB check shows 0 tables currently missing RLS (safety net migration)
Problem 5: Permission cache invalidation on tenant switch
- Add invalidate_permission_cache() call in switch_tenant() for old tenant
- Stale cached permissions from old tenant no longer leak
Problem 6+7: Guest system removal
- Remove get_current_guest() from deps.py
- Remove guest_auth.py router from main.py and routes/__init__.py
- Rewrite guests.py to use regular User/UserTenant with role=guest
- Remove GuestUser/GuestInvitation from models/__init__.py
- Add migration 0113: Migrate guest_users to regular users, drop guest tables
- Update frontend GuestLogin/GuestContacts to redirect to normal pages
- KI-Kommentar: Guest-System umgebaut — Guests sind jetzt reguläre User mit role=guest
- app/core/resilience.py: CircuitBreaker (CLOSED/OPEN/HALF_OPEN), retry_db,
redis_call_with_fallback, InMemoryRateLimiter, CircuitBreakerMiddleware
- app/core/auth.py: get_session_data now falls back to PostgreSQL sessions
table when Redis is unavailable
- app/core/permissions.py: get_cached_permissions falls back to direct DB
resolution when Redis circuit is open
- app/core/rate_limit.py: check_rate_limit falls back to in-memory limiter
when Redis is down; reset_rate_limit clears both Redis and in-memory
- app/core/middleware.py: CSRF validation uses get_session_data (Redis+DB
fallback); sliding session TTL is best-effort during outage
- app/core/db/__init__.py: get_db() wraps session creation with retry_db
for transient connection errors; records circuit breaker success/failure
- app/deps.py: refresh_session_ttl wrapped in try/except for Redis outage
- app/main.py: CircuitBreakerMiddleware registered (returns 503 when DB
circuit is OPEN, skips health/metrics endpoints)
- app/config.py: Added resilience settings (thresholds, cooldown, retries)
- tests/test_resilience.py: 30 tests covering all patterns
30/30 resilience tests pass. No regressions in plugin lifecycle tests.
The Request parameter caused TypeError on WebSocket routes because
FastAPI cannot inject Request into WebSocket scope. Reverted to
parameterless _check(). WebSocket 403 is handled by CSRF middleware
which already skips WebSocket upgrade requests.
Simpler approach: require_active_plugin._check() now accepts Request
parameter and returns early for WebSocket upgrade requests.
No route splitting needed — all routes stay in their original router.
- Create call_crm_api tool: single tool that can call ANY CRM API endpoint
- Inject OpenAPI spec into system prompt so AI knows all available endpoints
- Always include call_crm_api in agent tools (not just via tool_ids)
- Extend get_current_user to support internal header-based auth (X-Internal-Call,
X-Tenant-Id, X-User-Id) for AI tool API access
- No more manual tool-per-endpoint registration needed