feat(04-rbac-01): RBAC guards + invite token + email + invitation API

- rbac.py: PortalCaller dataclass + get_portal_caller dependency (header-based)
- rbac.py: require_platform_admin (403 for non-platform_admin)
- rbac.py: require_tenant_admin (platform_admin bypasses; customer_admin
  checks UserTenantRole; operator always rejected)
- rbac.py: require_tenant_member (platform_admin bypasses; all roles
  checked against UserTenantRole)
- invite_token.py: generate_invite_token (HMAC-SHA256, base64url, 48h TTL)
- invite_token.py: validate_invite_token (timing-safe compare_digest, TTL check)
- invite_token.py: token_to_hash (SHA-256 for DB storage)
- email.py: send_invite_email (sync smtplib, skips if smtp_host empty)
- invitations.py: POST /api/portal/invitations (create, requires tenant admin)
- invitations.py: POST /api/portal/invitations/accept (accept invitation)
- invitations.py: POST /api/portal/invitations/{id}/resend (regenerate token)
- invitations.py: GET /api/portal/invitations (list pending)
- portal.py: AuthVerifyResponse now returns role+tenant_ids+active_tenant_id
- portal.py: auth/register gated behind require_platform_admin
- tasks.py: send_invite_email_task Celery task (fire-and-forget)
- gateway/main.py: invitations_router mounted
This commit is contained in:
2026-03-24 13:52:45 -06:00
parent f710c9c5fe
commit d59f85cd87
8 changed files with 831 additions and 7 deletions

View File

@@ -43,6 +43,7 @@ from gateway.channels.whatsapp import whatsapp_router
from shared.api import (
billing_router,
channels_router,
invitations_router,
llm_keys_router,
portal_router,
usage_router,
@@ -134,6 +135,11 @@ app.include_router(llm_keys_router)
app.include_router(usage_router)
app.include_router(webhook_router)
# ---------------------------------------------------------------------------
# Register Phase 4 RBAC routers
# ---------------------------------------------------------------------------
app.include_router(invitations_router)
# ---------------------------------------------------------------------------
# Routes