Security
How the CMS respects all four Quickback security layers — firewall, CRUD access, guards, and masking.
Security
The CMS respects all four Quickback security layers. Every UI element — buttons, form fields, table columns, action menus — adapts based on the current user's role and the security rules defined in your feature files.
The Four Layers
Quickback enforces security through four complementary layers:
| Layer | Purpose | CMS Behavior |
|---|---|---|
| Firewall | Tenant isolation (org-scoped data) | Handled server-side. CMS cannot bypass it. |
| CRUD Access | Per-operation role requirements | Buttons hidden when role lacks permission |
| Guards | Field-level create/update control | Form fields enabled/disabled per guard rules |
| Masking | Sensitive field redaction | Masked values with lock icons per role |
Role-Based Access
The CMS header includes a role switcher (in demo mode) or reads the user's actual role from their organization membership (in live mode). The three roles are:
- owner — Full access to all operations and data
- admin — Elevated access, typically all CRUD and most actions
- member — Standard access with restrictions on sensitive data and destructive actions
CRUD Button Visibility
CRUD operation buttons are shown or hidden based on the current role's access:
crud: {
create: { access: { roles: ['admin', 'owner'] } },
read: { access: { roles: ['member', 'admin', 'owner'] } },
update: { access: { roles: ['admin', 'owner'] } },
delete: { access: { roles: ['owner'] } },
}With the config above:
- Members see the table (read) but no Create, Edit, or Delete buttons
- Admins see Create and Edit buttons but no Delete
- Owners see all buttons
The row action menu also adapts — Edit and Delete entries only appear when the role has the corresponding permission.
Guards
Guards control which fields appear in create and edit forms, and which cells are editable in Data Table mode.
Createable Fields
Fields listed in guards.createable appear in the create form. Fields not in this list are hidden from the form entirely:
guards: {
createable: ['name', 'email', 'phone', 'status'],
}Updatable Fields
Fields listed in guards.updatable are editable in the edit form and in Data Table inline editing:
guards: {
updatable: ['name', 'email', 'phone'],
}Immutable Fields
Fields in guards.immutable can be set during creation but cannot be changed afterward. In edit mode, they appear as disabled inputs with a lock icon:
guards: {
immutable: ['accountCode', 'type'],
}Protected Fields
Fields in guards.protected can only be updated via specific actions. They appear as disabled inputs with the message "Updated via actions only":
guards: {
protected: {
status: ['approve', 'void'], // Updated by approve or void actions
balance: ['applyPayment'], // Updated by applyPayment action
},
}Masking
Masking rules redact sensitive data based on the user's role. The CMS applies masking client-side for display and the API enforces it server-side in responses.
Masking Types
| Type | Example Input | Masked Output |
|---|---|---|
email | john@acme.com | j***@acme.com |
phone | (555) 123-4567 | ***-***-4567 |
ssn | 123-45-6789 | ***-**-6789 |
redact | Confidential notes | ------ |
Configuration
masking: {
email: { type: 'email', show: { roles: ['admin', 'owner'] } },
phone: { type: 'phone', show: { roles: ['admin', 'owner'] } },
ssn: { type: 'ssn', show: { roles: ['owner'] } },
}With the above config:
- Members see masked values for email, phone, and SSN
- Admins see unmasked email and phone, but masked SSN
- Owners see all values unmasked
Visual Indicator
Masked fields display a lock icon next to the redacted value, making it clear that the field contains hidden data:
Email: [lock] j***@acme.com
SSN: [lock] ***-**-6789Views
Views provide column-level projections per role. Only authorized views appear in the toolbar dropdown.
views: {
summary: {
fields: ['id', 'name', 'status'],
access: { roles: ['member', 'admin', 'owner'] },
},
financial: {
fields: ['id', 'name', 'balance', 'creditLimit', 'paymentTerms'],
access: { roles: ['admin', 'owner'] },
},
}Members only see the "summary" view option. Admins and owners see both "summary" and "financial". The "All Fields" option is always available.
Firewall
The firewall layer handles tenant isolation — ensuring users can only access data within their organization. This is enforced entirely server-side:
organization_idcolumns are filtered automatically by the APIownermode restricts records to the creating user- The CMS never sees data outside the user's organization scope
The CMS does not display firewall config in its UI because there is nothing for the user to control. Tenant isolation is transparent and automatic.
Actions
Action visibility is controlled by access conditions on each action:
actions: {
approve: {
access: {
roles: ['admin', 'owner'],
record: { status: { equals: 'pending' } },
},
cms: { destructive: true, confirm: true },
},
}The CMS evaluates both the role requirement and the record condition. In this example, the "Approve" action only appears for admins and owners, and only on records where status === "pending".
Destructive actions (cms.destructive: true, or named void/delete) receive special warning styling with red text and an alert icon. Actions with cms.hidden: true are hidden from the CMS entirely (API-only).
Next Steps
- Actions — Action dialogs and input forms
- Table Views — View projections and toolbar
- Inline Editing — How guards affect editability