# Multi-Tenancy & Access Reference (Current State)

## Purpose
Authoritative map of tenant isolation, role access, and payment/API-key handling across the stack. Built from code as of Dec 2025.

## Core Enforcement Points (backend)
- Middleware:
  - `backend/igny8_core/auth/middleware.py` (`AccountContextMiddleware`, ~L1-L220): resolves `request.account` from JWT/API key; blocks inactive/suspended accounts.
  - `backend/igny8_core/middleware/request_id.py` (~L1-L70): request ID (not tenancy).
  - `backend/igny8_core/middleware/resource_tracker.py` (~L1-L170): metrics (not tenancy).
- Base viewsets:
  - `backend/igny8_core/api/base.py` (`AccountModelViewSet`, ~L1-L240): filters by `request.account`; admin/developer/system overrides; sets account on create.
  - `backend/igny8_core/api/base.py` (`SiteSectorModelViewSet`, ~L238-L430): additionally filters by site/sector and user’s accessible sites (SiteUserAccess) unless admin/developer/system.
- Permissions:
  - `backend/igny8_core/api/permissions.py`:
    - `IsAuthenticatedAndActive`, `HasTenantAccess` (default in settings).
    - `IsViewerOrAbove`, `IsEditorOrAbove`, `IsAdminOrOwner`.
    - `IsSystemAccountOrDeveloper` (system/admin for integrations).
  - Module-specific permissions also appear in `backend/igny8_core/auth/permissions.py` (legacy IsOwnerOrAdmin, IsEditorOrAbove, IsViewerOrAbove, AccountPermission).
- Settings defaults:
  - `backend/igny8_core/settings.py` REST_FRAMEWORK `DEFAULT_PERMISSION_CLASSES` = `IsAuthenticatedAndActive` + `HasTenantAccess`.
  - Auth order: APIKeyAuthentication → JWTAuthentication → CSRFExemptSessionAuthentication → BasicAuth.
  - Throttling: `DebugScopedRateThrottle` bypasses throttles for authenticated users/system/debug.
- Models with enforced account/site/sector:
  - Base models `AccountBaseModel`, `SiteSectorBaseModel` in `backend/igny8_core/auth/models.py` (top of file).

## Flow (text flowchart)
```
Request
  -> Middleware: AccountContextMiddleware sets request.account (JWT/API key), validates account status/plan
  -> DRF Auth: APIKey/JWT/Session
  -> Permissions: IsAuthenticatedAndActive + HasTenantAccess (+ role-specific)
  -> ViewSet:
       AccountModelViewSet filters by account
       SiteSectorModelViewSet filters by account + site/sector + SiteUserAccess
  -> Action-specific role checks (IsEditorOrAbove, IsAdminOrOwner, IsSystemAccountOrDeveloper)
  -> Business logic (services) + credit checks (billing)
  -> Response
```

## Module Access (backend ViewSets & guards)
- Accounts/Users/Plans/Subscriptions:
  - `auth/views.py`: `UsersViewSet`, `AccountsViewSet`, `SubscriptionsViewSet`, `SiteUserAccessViewSet` (account-scoped via AccountModelViewSet + role guards).
  - Roles: owner/admin (or developer/system) can manage; others limited to self (UsersViewSet get_queryset).
- Sites/Sectors:
  - `auth/views.py` (`SiteViewSet`, `Sector` actions): SiteSectorModelViewSet enforces account + site/sector + SiteUserAccess; public slug read is AllowAny for active site slug only.
- Planner:
  - `modules/planner/views.py` (KeywordViewSet, ClusterViewSet, ContentIdeasViewSet) inherit SiteSectorModelViewSet; require site_id/sector_id; role: typically editor+ for writes.
- Writer:
  - `modules/writer/views.py` (TasksViewSet, ContentViewSet, ImagesViewSet, ContentTaxonomyViewSet) inherit SiteSectorModelViewSet; site/sector scoping; editor+ for writes.
- Automation:
  - `business/automation/views.py` (AutomationViewSet) inherits AccountModelViewSet/SiteSectorModelViewSet patterns; requires site_id for run/config; role: editor+ for mutate.
- System settings (non-integrations):
  - `modules/system/views.py` / `settings_views.py`: AccountModelViewSet; role usually admin/owner; authenticated + tenant required.
- Integrations (OpenAI/Runware API keys):
  - `modules/system/integration_views.py`: guarded by `IsSystemAccountOrDeveloper` (system account or developer only); tenant-scoped but effectively system-only for keys.
- Billing:
  - `modules/billing/views.py`: AccountModelViewSet; `IsAdminOrOwner` for credit transactions/payment methods; balance/usage requires auth + tenant.
- Payments/Payment Methods:
  - Payment methods: `AccountPaymentMethodViewSet` account-scoped; IsAuthenticated; default selection per account; admin/owner should manage.
  - Payments: `PaymentViewSet` account-scoped; IsAuthenticated; list/available_methods/manual payment for current account only.

## Frontend Guards
- Route protection: `ProtectedRoute` (auth required, checks account/plan/payment methods), `ModuleGuard` (module enabled), `AdminGuard` (integration/admin pages only for system account or developer).
- Sidebar hides Integration for non-system/developer; admin section shown only for system/developer.

## AI Key Resolution
- `ai/ai_core.py` `_load_account_settings`: tries tenant IntegrationSettings → system account IntegrationSettings (`aws-admin`/`default-account`/`default`) → Django settings (`OPENAI_API_KEY`, `RUNWARE_API_KEY`). All users run AI with shared keys if tenant keys absent.

## Throttling
- `api/throttles.py` `DebugScopedRateThrottle`: bypass for authenticated users/system/debug; per-scope rates in `settings.py`. Prevents 429s for normal users.

## Payment / Billing Workflow (happy path)
1) User authenticates (JWT) → request.account set.
2) Payment methods (account-scoped) fetched via `/v1/billing/payment-methods/available/`; admin/owner can CRUD `/v1/billing/payment-methods/`.
3) Invoices/Payments via billing endpoints (account-scoped; admin/owner).
4) Credits used via CreditService on AI/automation calls (backend).

## Access Summary by Role (runtime enforcement)
- Viewer: read-only where viewsets allow `IsViewerOrAbove`; no writes.
- Editor: can write planner/writer/automation; cannot manage billing/integration.
- Admin/Owner: manage account/team/billing/payment methods; full module writes.
- Developer/System account: cross-tenant overrides in some base filters; integration settings and admin menus.

## Key Files (with line bands)
- Middleware: `auth/middleware.py` (~L1-220)
- Base viewsets: `api/base.py` (~L1-430)
- Permissions: `api/permissions.py` (~L1-200), `auth/permissions.py` (~L1-120)
- Settings (REST/Throttle): `settings.py` (REST_FRAMEWORK block, ~L200-360)
- AI core key loading: `ai/ai_core.py` (~L1-120)
- Integration settings views: `modules/system/integration_views.py` (~L1-300 main guards; actions throughout)
- Planner views: `modules/planner/views.py` (all ViewSets inherit SiteSectorModelViewSet)
- Writer views: `modules/writer/views.py`
- Automation: `business/automation/views.py`, `services/automation_service.py`
- Billing: `modules/billing/views.py`, `business/billing/services/credit_service.py`
- Payment methods: `modules/billing/views.py` AccountPaymentMethodViewSet
- Frontend guards: `src/components/auth/ProtectedRoute.tsx`, `src/components/auth/AdminGuard.tsx`, `src/components/common/ModuleGuard.tsx`
- Sidebar gating: `src/layout/AppSidebar.tsx`

## Open Items / Risks
- Ensure public endpoints explicitly override default permissions (e.g., auth register/login, site slug read).
- Validate all viewsets still inherit AccountModelViewSet/SiteSectorModelViewSet after future changes.
- Add automated tests for cross-tenant denial, role gates, plan limits, and integration access.***

