import logging from django.apps import AppConfig from django.db.models.signals import post_migrate logger = logging.getLogger(__name__) # Explicit (non model-derived) codenames the kit enforces or documents. _KIT_PERMISSIONS: list[tuple[str, str, str, str]] = [ # (codename, name, group, description) ("security.manage_api_keys", "Manage API keys", "Security", "Create/rotate/delete tenant API keys."), ("security.manage_roles", "Manage roles", "Security", "Create and assign tenant roles."), ("security.manage_grants", "Manage grants", "Security", "Grant/revoke permissions directly."), ("security.view_permissions", "View permissions", "Security", "Read the permission catalog."), ("platform.roles.manage", "Manage platform roles", "Platform", "Create and assign global roles."), ("platform.tenants.view", "View any tenant", "Platform", "Read tenants across the platform."), ("platform.tenants.manage", "Manage tenants", "Platform", "Edit tenant metadata across the platform."), ("platform.tenants.suspend", "Suspend tenants", "Platform", "Suspend a tenant."), ("platform.tenants.reinstate", "Reinstate tenants", "Platform", "Reinstate a suspended tenant."), ("platform.tenants.delete", "Delete tenants", "Platform", "Archive/delete a tenant."), ("platform.tenants.impersonate", "Impersonate tenants", "Platform", "Open a support session into a tenant."), ("platform.users.view_any", "View any user", "Platform", "Read users/members across tenants."), ("platform.users.manage_email", "Change any user email", "Platform", "Update a user's email across tenants."), ("platform.users.deactivate", "Deactivate any user", "Platform", "Disable accounts across tenants."), ("platform.users.manage_roles", "Assign roles anywhere", "Platform", "Assign roles in any tenant."), ("platform.audit.view_all", "View all audit", "Platform", "Read audit records across tenants."), ("audit.view_model_changes", "View model changes", "Audit", "Read the model change log."), ("audit.view_api_logs", "View API logs", "Audit", "Read API interaction logs."), ("audit.view_security_events", "View security events", "Audit", "Read security events."), ("tenancy.manage_tenant", "Manage tenant", "Tenancy", "Edit the current tenant."), ("tenancy.manage_members", "Manage members", "Tenancy", "Invite/remove tenant members."), ("configs.manage", "Manage configuration", "Configs", "Write tenant configuration values."), ("configs.manage_global", "Manage global configuration", "Configs", "Write platform configuration defaults."), ] def register_builtin_permissions() -> None: from .registry import PermissionRegistry for codename, name, group, description in _KIT_PERMISSIONS: PermissionRegistry.register(codename, name=name, group=group, description=description) def _sync_permissions_on_migrate(sender, **kwargs) -> None: from .catalog import sync_permissions try: summary = sync_permissions() except Exception: # noqa: BLE001 - migrate must never fail because of the catalog logger.exception("Permission catalog sync failed during post_migrate") return logger.info("Permission catalog synced: %s", summary) class SecurityConfig(AppConfig): default_auto_field = "django.db.models.BigAutoField" name = "infrasynth.security" label = "infrasynth_security" def ready(self): from infrasynth.features.registry import FeatureRegistry register_builtin_permissions() FeatureRegistry.register( "security", name="Security & Access", description="Authentication, authorization, 2FA, API keys, ALTCHA", default=True, category="system", ) post_migrate.connect( _sync_permissions_on_migrate, sender=self, dispatch_uid="infrasynth_security.sync_permissions", )