# Audit Rules Reference

> Complete codification of all audit rules used by /apex-verify.
> Each rule has a unique ID, severity, description, detection method, and fix pattern.

---

## Navigation Rules (NAV-xxx)

| ID | Severity | Description | Detection | Fix |
|----|----------|-------------|-----------|-----|
| NAV-001 | BLOCKING | Reserved section code (detail/create/edit) seeded as visible menu item | Grep NavigationSeedData for `Code = "detail"` / `"create"` / `"edit"` without `IsActive = false` | Remove section from seed data, or set `IsActive = false` |
| NAV-002 | BLOCKING | Section code contains "-detail" seeded as menu item | Grep for codes matching `*-detail` pattern | Remove section entry — detail is resolved as /:id under parent section |
| NAV-003 | BLOCKING | Route contains forbidden segment (/detail/, /create/, /edit/) | Grep seed data routes for `/detail/`, `/create/`, `/edit/` segments | Use convention routes: /:id, /create, /:id/edit (no explicit segments) |
| NAV-004 | WARNING | Reserved section code with IsActive = false | Code is reserved but hidden from menu | Acceptable — remove if unnecessary |
| NAV-005 | WARNING | Section code not in kebab-case | Regex check: `^[a-z][a-z0-9]*(-[a-z0-9]+)*$` | Rename to kebab-case |

## CRUD Rules (CRUD-xxx)

| ID | Severity | Description | Detection | Fix |
|----|----------|-------------|-----------|-----|
| CRUD-001 | BLOCKING | ListPage missing for entity | Glob for `*ListPage.tsx` matching entity | Generate via `/ui-components` |
| CRUD-002 | BLOCKING | DetailPage missing for entity | Glob for `*DetailPage.tsx` matching entity | Generate via `/ui-components` |
| CRUD-003 | BLOCKING | Create/Edit page missing for entity | Glob for `*CreatePage.tsx`, `*EditPage.tsx`, `*FormPage.tsx` | Generate via `/ui-components` |
| CRUD-004 | BLOCKING | ListPage has no Create/New button | Grep for `navigate.*create` or `Link.*create` | Add navigate('create') button in page header |
| CRUD-005 | BLOCKING | Page exists but not registered in componentRegistry | Read registry, check for matching key | Add `PageRegistry.register()` call or run `scaffold_routes` |
| CRUD-006 | WARNING | Registry entry has no matching page file | Read registry, check file existence | Remove orphan registry entry or create the page |
| CRUD-007 | WARNING | Form page has no submit handler | Grep for `onSubmit`, `handleSubmit`, `api.create`, `api.post` | Implement form submission logic |

## Permission Rules (PERM-xxx)

| ID | Severity | Description | Detection | Fix |
|----|----------|-------------|-----------|-----|
| PERM-001 | BLOCKING | Controller uses permission not defined in Permissions.cs | Cross-ref `[RequirePermission]` vs `Permissions.cs` | Add missing constant to Permissions.cs |
| PERM-002 | BLOCKING | Permissions.cs constant not seeded in PermissionsSeedData | Cross-ref Permissions.cs paths vs seed data | Add `HasData()` entry in PermissionsSeedData |
| PERM-003 | CRITICAL | Seeded permission has no role mapping | Cross-ref seed data vs RolesSeedData | Add role-permission mapping in RolesSeedData |
| PERM-004 | CRITICAL | Admin role missing wildcard for module | Check admin role has `*.module.*` wildcard | Add wildcard permission for admin role |
| PERM-005 | WARNING | Permission path segments not in kebab-case | Regex check on permission paths | Rename to kebab-case |
| PERM-006 | WARNING | Viewer role has write permission | Check viewer role permissions | Remove write permissions from viewer role |
| PERM-007 | WARNING | Permission defined but unused by any controller | Cross-ref Permissions.cs vs controllers | Remove dead permission or add controller usage |

## Route Rules (ROUTE-xxx)

| ID | Severity | Description | Detection | Fix |
|----|----------|-------------|-----------|-----|
| ROUTE-001 | BLOCKING | Seed data route has no matching PageRegistry entry | Cross-ref seed routes vs registry keys | Add PageRegistry.register() or run scaffold_routes |
| ROUTE-002 | WARNING | Controller NavRoute has no matching seed data entry | Cross-ref NavRoute attrs vs seed routes | Add navigation seed data entry |
| ROUTE-003 | BLOCKING | PageRegistry references non-existent page file | Read registry imports, check file existence | Create page or fix import path |
| ROUTE-004 | WARNING | Orphan page — exists on disk but not registered | Cross-ref page files vs registry | Register page or delete orphan |
| ROUTE-005 | WARNING | Implicit route (detail/create/edit) not resolvable | Check registry + DynamicRouter conventions | Register in componentRegistry |
