"""Synchronise the permission catalog. Model-derived permissions (``{app}.{verb}_{model}``) plus permissions registered by apps through ``PermissionRegistry`` are upserted into the ``security_permission`` table. Imported permissions are marked inactive, never deleted, so existing role assignments survive. """ from __future__ import annotations from django.core.management.base import BaseCommand from infrasynth.security.catalog import sync_permissions class Command(BaseCommand): help = "Synchronise the permission catalog from models and registered custom permissions." def add_arguments(self, parser): parser.add_argument( "--no-deactivate", action="store_true", help="Do not deactivate catalog entries that are no longer derived/registered.", ) def handle(self, *args, **options): summary = sync_permissions(deactivate_missing=not options["no_deactivate"]) self.stdout.write( self.style.SUCCESS( "Permission catalog synced: " f"{summary['created']} created, {summary['updated']} updated, " f"{summary['reactivated']} reactivated, {summary['deactivated']} deactivated " f"({summary['total']} total)." ) )