Permissions — Reference
The Permissions surface is the fine-grained capability plane for SGEN. It owns the catalog of capability identifiers the platform exposes, the per-surface gate at request time, the per-action enable / disable knobs that operators can toggle without rewriting the role catalog, and the audit trace that records every grant, deny, and explicit override decision. Anything that asks "is this operator allowed to do this specific thing right now?" traces back to a record managed here.
This page is a reference for platform engineers and integrators who need to understand the surface before scripting against it, extending the capability catalog, or scoping a fine-grained access model that sits below the role layer. Customer-facing permission walkthroughs live in the customer docs set; this page describes the shape of the surface, not the steps to drive it.
Overview
Permissions live under the Settings → Permissions module in SG-Admin. The module renders three primary views — the capability catalog (every capability identifier the platform exposes, grouped by module), the per-role override matrix (the same matrix the Roles module renders, accessed from the capability side), and the audit-trace search (every grant, deny, and override decision logged across the site).
The module is paired by convention with the Roles surface. Roles define the catalog of capability sets; Permissions define the catalog of capability identifiers and the per-action gate that consults them. Engineers reading the SG-Admin source will see the Permissions view templates rendering catalog entries while the per-action gate code lives inside each module's controller action set. The Permissions module is the explorer; the gates are the consumers.
A second surface — per-operator overrides — extends the model. Beyond role-level capability assignment, individual operators can carry explicit per-capability overrides recorded against the operator record itself. Used sparingly — most access changes belong at the role tier — but valuable for narrow exceptions (a specific operator granted one extra capability without inheriting a whole role's worth).
Where it lives in SG-Admin:
- Sidebar: SG-Admin → Settings → Permissions
- URL prefix:
/sg-admin/settings/permissions/ - View templates:
application/views/Admin/Settings/Permissions/
┌──────────────────────────────────────────────────────────────────────┐│ SG-Admin → Settings → Permissions │├──────────────────────────────────────────────────────────────────────┤│ Filter: [ all modules ▾ ] Search: [_____________] [Export catalog]││ ────────────────────────────────────────────────────────────────────││ Module Capability Roles Operators ││ ────────── ───────────────────────────── ──────── ───────── ││ users users.create 1 / 6 4 ││ users users.edit_any 1 / 6 4 ││ users users.delete 1 / 6 4 ││ users users.impersonate 1 / 6 4 ││ pages pages.publish 3 / 6 14 ││ pages pages.edit 4 / 6 18 ││ pages pages.delete 2 / 6 6 ││ media media.upload 5 / 6 22 ││ settings settings.roles.edit 1 / 6 4 ││ settings settings.domains.edit 1 / 6 4 ││ ││ [⋯ View override matrix] [⋯ View audit trace] [⋯ Test gate] │└──────────────────────────────────────────────────────────────────────┘Actions
The Permissions surface exposes the following operations. Each is described by what it does to the data, not by its internal method name.
List capabilities
Returns the full catalog of capability identifiers the platform exposes. Each row carries the module the capability belongs to, the dotted slug, a human-readable description, the number of roles that currently grant the capability, and the count of operators effectively granted the capability after role resolution.
View capability
Loads a single capability identifier with its full description, the module that owns the gate, and the per-role grant / deny matrix. Useful for understanding what a specific gate guards before adjusting a role catalog.
Override role capability
Toggles a single capability for a single role between grant, deny, and inherit. Same shape as the matrix edit on the Roles surface, but invoked from the capability side — useful for sweeping a single capability across many roles in one session.
Override operator capability
Records an explicit per-operator capability override. The operator's effective capability map at request time is the role-resolved map plus any per-operator overrides on top. Used for narrow exceptions; never the default tier for access changes.
Remove override
Removes a per-role or per-operator override, re-deferring the capability to the parent (for roles) or to the role-resolved map (for operators). Symmetric with the override action.
Test gate
A diagnostic action. Given an operator identifier and a capability identifier, runs the full resolution chain (per-operator override, role override, role baseline, parent chain) and returns the grant / deny decision plus the resolution path. Useful for debugging unexpected rejections and for integration testing against the gate.
Search audit trace
Returns audit-log entries scoped to capability decisions — every grant or deny logged at request time, with the operator, capability, action, and resolution path. Filterable by operator, capability, action, time range, and decision outcome.
Export catalog
Produces a snapshot of the capability catalog (every identifier, description, and module pointer). Used for documentation generation, integration testing against a stable shape, and version comparison across platform updates.
Import override set
Loads a bundle of per-role overrides from a configuration export. Used for cloning a permissions posture across sites in a multi-site deployment. The bundle validates against the current capability catalog — overrides for retired or unknown identifiers report a per-entry skip with reason.
Bulk grant or deny
A sweep operation. Applies a single grant or deny decision to a chosen capability across a chosen set of roles in one write. Used for platform-wide policy moves (lock down a capability across every custom role, grant a new capability to a chosen role tier).
Data model
A capability identifier carries the following fields. The catalog is owned by the platform — new identifiers ship with module updates, and identifiers are never deleted (retired identifiers move to an archived state to preserve historical override records).
| Field | Type | Notes |
|---|---|---|
slug | string | Dotted capability identifier — users.create, pages.publish, settings.roles.edit. Stable across platform updates. |
module | string | The module that owns the gate this capability guards. |
display_name | string | Human-readable label rendered in the matrix and the catalog. |
description | string | One-line description of what the gate guards. |
category | enum | read, write, destructive, administrative. Drives matrix grouping and the default deny posture. |
is_archived | boolean | True for retired identifiers. Archived capabilities are no longer checked at request time but remain in the catalog so historical overrides still resolve. |
introduced_at | timestamp | Platform version when the capability shipped. |
| Field | Type | Notes |
|---|---|---|
role_id | integer | Role this override applies to. |
capability_slug | string | Capability identifier. Join key against the catalog. |
decision | enum | grant or deny. Absence of a row means inherit from parent. |
set_by | integer | Operator who recorded the override. |
set_at | timestamp | When the override was recorded. |
| Field | Type | Notes |
|---|---|---|
user_id | integer | Operator this override applies to. |
capability_slug | string | Capability identifier. |
decision | enum | grant or deny. |
expires_at | timestamp | Optional. Per-operator overrides can carry an expiration; on expiry, the override is removed and the operator re-defers to role resolution. |
set_by | integer | Operator who recorded the override. |
set_at | timestamp | When the override was recorded. |
Default deny: capabilities not granted explicitly anywhere along the chain resolve to deny. The platform never carries a global default-allow — every capability is denied until a role catalog grants it.
Category-driven defaults: the category field on a capability identifier drives the platform's recommended default posture. Built-in roles ship with read capabilities granted broadly, write capabilities granted to Editor and above, destructive capabilities granted to Administrator only, and administrative capabilities granted to Administrator only. Custom roles inherit these defaults from the chosen parent role and override per capability.
REQUEST: operator_id=88, capability=pages.delete│▼┌───────────────────────────────┐│ STEP 1 — operator override? ││ check user_id=88 + capability │└─────────────────┬─────────────┘│┌─────────────┼─────────────┐▼ ▼ ▼grant deny absent│ │ │▼ ▼ ▼allow reject STEP 2 — role override?│▼┌─────────────────────────┐│ check operator's role + ││ capability │└───────────┬─────────────┘│┌─────────────┼─────────────┐▼ ▼ ▼grant deny absent│ │ │▼ ▼ ▼allow reject STEP 3 — parentwalk│▼(resolve up chain;default deny)Permissions
Access to the Permissions surface is gated at two layers.
Layer 1 — admin gate. Every action under SG-Admin passes through the platform's standard admin access check at request entry. An unauthenticated request never reaches the Permissions surface.
Layer 2 — per-action capability. Within SG-Admin, each Permissions action checks a capability associated with the calling operator's role. The default role configuration ships with three roles — Administrator, Editor, Viewer — and the capability map is:
| Capability | Administrator | Editor | Viewer |
|---|---|---|---|
| List capabilities | ✔ | ✔ | — |
| View capability (description, matrix) | ✔ | ✔ | — |
| Override role capability | ✔ | — | — |
| Override operator capability | ✔ | — | — |
| Remove override | ✔ | — | — |
| Test gate (own capabilities) | ✔ | ✔ | ✔ |
| Test gate (any operator) | ✔ | — | — |
| Search audit trace (own) | ✔ | ✔ | ✔ |
| Search audit trace (any operator) | ✔ | — | — |
| Export catalog | ✔ | ✔ | — |
| Import override set | ✔ | — | — |
| Bulk grant or deny | ✔ | — | — |
Override decay. Per-operator overrides can carry an expires_at timestamp. On expiry, a background sweep removes the override and the operator re-defers to role resolution. The expiry mechanism is intentionally tied to the override layer, not the role layer — temporary access changes are recorded per-operator with a clock; permanent access changes belong at the role tier.
Audit. Every override write — per-role or per-operator, grant or deny, set or remove — emits an Activity Log entry. The log records the acting operator, the target (role or operator), the capability affected, and the decision shape. Per-action gate decisions themselves (every grant or deny resolved at request time) are also recorded in a higher-volume capability decision log, queryable through the audit-trace view but rotated more aggressively than the Activity Log.
Capability catalog stability. Capability identifiers, once shipped, are stable across platform updates. A capability that is retired moves to the is_archived state — the identifier remains in the catalog so historical overrides still resolve, but the gate at request time no longer checks it. Sites with overrides against archived capabilities see a flag in the catalog view recommending the override be removed.
┌──────────────────────────────────────────────────────────────────────┐│ SG-Admin → Settings → Permissions → Audit trace │├──────────────────────────────────────────────────────────────────────┤│ Filters: [operator: any ▾] [capability: pages.delete] [last 7d] ││ ────────────────────────────────────────────────────────────────────││ Timestamp Operator Capability Decision Path ││ ───────────────── ─────────────── ────────────── ──────── ──── ││ 2026-05-21 14:32 jerome@sgen.com pages.delete allow R ││ 2026-05-21 14:18 maria@sgen.com pages.delete reject R ││ 2026-05-21 13:04 james@jc.com pages.delete allow O ││ 2026-05-21 12:51 sandbox@sgen.com pages.delete reject P ││ ││ Path key: O = operator override · R = role · P = parent walk ││ Decision log retention: 30 days. Activity Log retention: 1 year. │└──────────────────────────────────────────────────────────────────────┘Related references
- Roles — Reference. Roles define the capability sets the Permissions surface explores. The matrix in the Roles edit form and the matrix in the Permissions module render the same underlying records.
- Users — Reference. Per-operator overrides attach to user records. The Permissions surface records the override; the user record carries the pointer.
- Settings — Reference. Per-module override defaults that the Permissions surface references at platform initialization (default category posture, default decision logging retention) are defined under Settings.
- Tools — Reference. The Activity Log entries for permissions writes (overrides, removals, bulk operations) are queryable from Tools alongside the rest of the audit log.
- Pages — Reference. Page lifecycle gates (
pages.publish,pages.edit,pages.delete) are defined in this catalog. - Posts — Reference. Post lifecycle gates route through the same catalog.
- Media — Reference. Media upload, edit, and delete gates are defined here.
- Subscriptions — Reference. Subscription management gates (
subscriptions.manage,subscriptions.cancel) are defined here.
/docs/permissions.