angee.platform.permissions
Reconcile the REBAC permission schema to the composed addon set.
When an addon is uninstalled it leaves INSTALLED_APPS, but rebac sync only ever revisits composed apps (apps.get_app_configs()) — so the uninstalled addon's Schema* rows orphan, and the library's rebac.E009 system check then fails for every checked command (makemigrations, migrate, rebac sync), breaking the very rebuild the uninstall triggers.
:func:reconcile_permission_schema is the global counterpart to the library's per-package prune: it removes every Schema* row owned by a package no longer in the composed app set. platform owns the addon lifecycle (install / uninstall / reconcile), so it owns this cleanup; the reconcile_permissions management command runs it check-free, before the gated DB steps (see that command and the build lifecycle). The composed set is apps.get_app_configs() — the same source rebac sync keys its packages on — not the addon-only rollups: a package is orphaned only when its app is not loaded at all.
The same check-gated deadlock happens when a composed package removes or renames one definition: rebac sync would prune the stale package-managed rows, but it cannot start while the old row still fails system checks. The reconcile step therefore compares package-managed schema rows with the current permissions.zed declarations and prunes stale rows inside still-composed packages too.
PermissionSchemaReconcileError
class PermissionSchemaReconcileError(RuntimeError)Raised when current REBAC schema declarations cannot be reconciled safely.
reconcile_permission_schema
def reconcile_permission_schema() -> intPrune stale package-managed Schema* rows.
Idempotent and best-effort: returns the number of stale managed rows pruned, and is a no-op on a fresh/unmigrated database (no Schema* tables yet). Runs under system_context in one transaction.