Security Readiness Checklist
Every new model, screen, action, report or API endpoint must pass this checklist before it is considered finished. An element that is not catalogued and assigned cannot be granted, and only superusers can reach it.
1. App configuration
- Declare
menu_verbose_name,app_icon,app_entry_menu,menu_positionandmenusin the app'sAppConfig. - Declare dashboards in
dashboardswhen the app ships dashboard data sources. - Add a module-entry view and protect it:
python
from enezarbac.registry import rbac_protected
from enezarbac.services.menus import module_menu_code
@rbac_protected(module_menu_code("humanresource"), kind="menu")
def humanresource_module_entry(request):
return redirect("enezadashboard:module_entry", module="humanresource")
- Every URL referenced by a menu must exist. A dead menu link cannot be granted safely.
2. Models
- Inherit the correct framework base model and include the
entityfield when the data is entity-scoped. - Do not add the model to
RBAC_EXEMPT_MODELSorRBAC_INTERNAL_MODEL_LABELSunless it is genuinely internal. - Create and apply the migration.
- Confirm the model appears in Access Control → Catalogue after
rbac_sync.
3. CRUD views
- Inherit
BaseListView,BaseDetailView,BaseCreateViewandBaseDeleteView(or the inline/setup/journal equivalents). - Do not override
dispatchin a way that skips the framework mixins. - If a view uses a non-standard
view_type, setrbac_operationexplicitly. An unmapped model view is denied.
4. Custom views, actions and APIs
- Use
@rbac_action("action.<app>.<task>", name="...")for class-based or function-based actions. - For a function view wrapped by
@login_required, put@rbac_actionabove@login_requiredso the attribute survives. - Use
@rbac_protected(code, kind="menu" | "output")for bespoke menu or output endpoints. - Use
@rbac_publiconly for login, registration, health checks and other genuinely public endpoints. Never mark an entire business app public. - WebSocket consumers must call
has_action_permission(scope["user"], code)before joining a group or mutating data.
5. Menus and navigation
- Add menu items in
AppConfig.menus; the menu URL becomes a target automatically. - Grant the parent fasttab and the item to the task. Parent menus have no URL, so a task spec uses
menu_codesfor them. - Module menus use
menu.<app>.__module__. This is also the code used by dashboard access. - Never use an unqualified short URL name in a selector; include the namespace (
app:url_name).
6. Reports and outputs
- Decorate the report view with
@rbac_output("output.<app>.<slug>.view", "..."). - Add the output code to the task that should read it.
- A dashboard is visible only when the module menu is granted and, when set, its
access_codeis granted. - Report data sources must keep their entity and module checks; the output permission is not a substitute for data scoping.
7. Inline and autocomplete views
- Inherit
BaseInlineListView,BaseInlineDetailView,BaseInlineCreateView,BaseInlineDeleteVieworBaseAutocompleteView. - These classes use the parent model's RBAC verbs. Do not replace them with a plain Django view without an explicit action code.
8. Django admin
Business models registered in Django admin bypass the request middleware because admin is an exempt namespace.
Choose one policy for the app:
- do not register business models in Django admin, or
- inherit
RbacAdminModelAdminMixinin everyModelAdminso view/add/change/delete checks callhas_model_permission.
python
from django.contrib import admin
from enezarbac.admin import RbacAdminModelAdminMixin
@admin.register(Employee)
class EmployeeAdmin(RbacAdminModelAdminMixin, admin.ModelAdmin):
...
9. Create the task privilege
- Add a
TaskPrivilegeSpecinenezarbac/task_catalog.pyfor a framework app, or create the privilege in Access Control → Security configuration for a project-specific request. - Use
task.<app>.<object>.<operation>. - Grant the minimum verbs:
viewfor read,create/updatefor data entry,deleteonly for a separately named delete task,correct/invokeonly with a stated reason. - Include only the menus, actions and outputs the task needs.
- Do not link the task to a role automatically.
- Do not use
app_labelson a user-facing specification. - Do not rely on a broad
function.*.usebundle to grant a task target. The seeder deactivates task targets found in a.usebundle;rbac_auditreports any that remain.
10. Verify before handoff
Run these steps yourself or ask the user to run them:
powershell
python manage.py rbac_sync
python manage.py rbac_audit --strict --list
Then check:
- The new targets appear in the Catalogue.
- The task privilege appears with the expected elements and verbs.
- A role with only
NORMAL_USERis denied the new screen. - A test role with the new task is allowed only the requested operations.
python manage.py rbac_explain --user <test-user>shows the expected source.- No new target appears only under
function.unclassified.admin.
The user is solely responsible for testing and validation.