TYPO3 backend rights
Build one complete editor group from the live project. Treat permissions as a verified model, not a copied backend record.
Contract
- Identify the TYPO3 installation selected by the user before writing. If several projects could be meant, ask which one to use. Apply the approved group model, User TSconfig, and user settings to that installation; a permission plan without the requested live/local integration is incomplete.
- Inventory the current group topology and obtain the explicit group-model decision below before consolidating anything. If approved, create or maintain exactly one user-facing main editor group with four required leaf subgroups: Base, Content, Site access, and Extensions. If declined, preserve the existing user-facing role separation and audit each intended group independently. Never interpret “one group” as permission to delete group rows or replace user memberships.
- Derive rights from installed TCA, existing records, backend modules, configured sites, pages
marked
is_siteroot, file mounts, and file storages. Never clone a legacy group without auditing every field. - Add every configured site root and every non-deleted page marked Use as Root Page
(
pages.is_siteroot = 1) as a database mount. Use all site languages; in TYPO3 v14 an emptyallowed_languagesvalue means unrestricted access to all current and future site languages. - Allow every content type currently used for editorial content. Record every exception with its CType and reason.
- Keep infrastructure content elements such as list/detail renderers, login endpoints, or system integration plugins admin-only when editors manage their underlying records instead. Decide from the actual record, FlexForm, page purpose, and workflow—not from the CType name alone.
- For every table in
tables_modify, grant every runtime editor-accessible exclude field. Never grant fields hidden withHIDE_FOR_NON_ADMINS, a table'sctrl.editlockfield, or read-only, passthrough, generated, or otherwise system-managed fields. Do not present a read-only form as successful editing. Plugin placement and domain-record rights remain separate. - Make
tables_selecta superset oftables_modify. A table used in an editing workflow belongs in both lists; select-only access is reserved for a documented lookup or reporting use case. - Include every required web mount and every active file mount. Ensure every online, browsable file storage is covered by an active file mount and works in Media and record selectors. Do not replace real mounts with hard-coded example paths.
- Allow exactly the installed editor modules defined below, including Forms, Visual Editor, and
Solr only when present. Allow the MFA providers
totpandrecovery-codes. - Verify page ownership and permission bits throughout every mounted site tree; DB mounts alone
do not grant access. Resolve one explicit default owner user and the intended page-owner group.
In the single-main-group model, use the main group. In the preserved-role model, retain or
explicitly select the appropriate existing owner group per Site tree without broadening other
roles. Apply the complete baseline
31/27/1: owner user31, owner group27, and everybody view-only1. Never switch ownership before an enabled non-admin member of that owner group passes a login test. - Preserve a different enabled, login-capable administrator. Never demote the administrator used for the current work or the last remaining administrator. Ask whether each target user's existing groups should be appended to or replaced; do not infer a bulk membership cutover.
- Apply customer branding and the actual TYPO3 application context before and after login using supported Core configuration and a small sitepackage stylesheet. Keep it version-controlled.
- When
typo3/cms-workspacesis installed, add the safe basic Workspace setup below. Do not write stale Workspace permissions or module identifiers when it is absent.
Decide the group model first
Before proposing a topology, inventory active be_groups, direct memberships in
be_users.usergroup, inheritance in be_groups.subgroup, and material differences in mounts,
languages, modules, tables, fields, Workspaces, and site scope. Show which groups are duplicates,
which encode a real authorization boundary, and which enabled users depend on each group.
Then ask exactly this project-level question and record the answer as evidence:
Can this project live with one user-facing, non-admin editor group for all normal editors? This means one directly assigned main role, with inherited internal Base, Content, Site, and Extensions leaves. It is simpler to maintain, but all included editors share the same authorization boundary.
- Recommend yes only when normal editors genuinely have the same site, language, module, table, field, Workspace, and file scope. A yes answer authorizes building the single-main-group topology; it does not authorize deleting legacy groups or changing any user's membership.
- Recommend no when the installation has meaningful role separation, limited-site editors, translators, publishers, form-only users, agency/customer boundaries, or other least-privilege differences. Preserve those roles and repair their rights independently.
- If the user has not answered, stop before group creation, consolidation, membership replacement, or page-owner changes. Do not turn convenience into implied authorization.
TYPO3 stores all groups—including the internal leaves—in be_groups. Direct group assignments are
stored in be_users.usergroup; there is no be_user_group table. Therefore “one group” in this
decision means one user-facing main membership, not literally one database row.
The topology decision and the later per-user cutover are separate approvals. Even after a yes, show every target user's current memberships and ask append-versus-replace for that user.
Approved single-main-group model
Use this model only after the user answered yes to the project-level question above. Use one flat inheritance level:
| Group | Owns |
|---|---|
<main> · Base |
Core editor modules, page types, all languages, MFA, file operations, User TSconfig |
<main> · Content |
Editorial CTypes, Core content/FAL/category tables, and their editor fields |
<main> · Site |
Database mounts and file mounts |
<main> · Extensions |
Installed extension modules, domain tables, editor fields, and conditional Workspace access |
The main group contains only those subgroup references and remains the page group owner. To add a
website later, attach one new leaf such as <main> · Site: Example; to add a separately maintained
extension capability, attach <main> · Extension: Example. Do not nest leaves. Preserve additional
leaf groups when regenerating the four required groups. This is a baseline of four, not a permanent
limit of four.
Report the selected installation's DDEV/project name, root, TYPO3 version, and affected group/user UIDs. Never apply one installation's audited permissions to another installation.
Preserved-role model
When the answer is no, keep the existing user-facing groups, direct membership intent, and meaningful inheritance boundaries. Apply the same least-privilege rules in this skill to every intended role, but evaluate CTypes, fields, tables, modules, mounts, languages, Workspaces, file operations, page ACLs, and Redirects separately for each group. Do not broaden a narrow group just because a broader group already has the capability.
Run the read-only audit once per target title and produce a role matrix showing effective and
missing permissions. Do not use apply-backend-rights.php to pretend it supports a multi-role
consolidation: that script implements only the approved single-main-group model. Make preserved-role
changes through reviewed TYPO3/DataHandler operations, retain existing UIDs and inheritance unless
an exact change is approved, and verify each materially different role with its own non-admin user.
Every later instruction that says “main group” describes the single-main-group mode. In the preserved-role mode, apply it only to the selected role when the capability belongs there. Page ownership still needs one explicit owner group per Site tree; it is never granted to every role.
Separate permission creation from the live cutover
Treat group configuration, user membership, and page ownership as three distinct operations:
- Create/update the main group and leaves, then audit their effective permissions.
- For every named target user, show the current membership and ask whether the main group should be appended or should replace the existing non-admin groups. Preserve unrelated groups until the user answers. Set the group-mount inheritance option bits without clearing other bits.
- Resolve and report the default owner user. Log in as an enabled non-admin target and verify
modules, page tree, content editing, Media/FAL, language, and selectors. Only then assign that
user and the main group as owners with the
31/27/1baseline. - Re-audit page ownership and repeat the non-admin test. Keep the prior owner group recoverable until the cutover is accepted.
If no enabled non-admin user belongs to the main group, page ownership remediation is blocked even when the permission model itself is valid. Do not create a temporary editor or guess membership to make the audit green.
Audit first
Run the bundled read-only audit inside the project container:
ddev exec php /dev/stdin --pretty \
< /absolute/path/to/typo3-backend-rights/scripts/audit-backend-rights.php
Add --group-title='Editorial Main' to check a target group,
--owner-username='default-owner' to verify the resolved page owner, and --strict to return
non-zero for blocking findings. Add --exceptions-plan=/container/path/to/permission-plan.json to
load the documented exception map used by the group. Read
permission-model.md before changing a group or user.
Treat this result as a blocking defect:
tt_content.CType authMode = explicitAllow
be_groups.explicit_allowdeny has no tt_content:CType:* entries
An empty list does not mean “allow every CType.” It prevents non-admin users from using the
explicitly protected types. Require each used editorial CType to appear as
tt_content:CType:<value>.
Build the permission plan
- Inventory enabled backend users, their groups, and enabled administrators. Identify the current working administrator and the separate administrator that will remain.
- Inventory distinct non-deleted
tt_content.CTypevalues, including hidden records. Compare them with registered TCA types and the target group's explicit allow-list. - Classify each used CType:
- editorial: add it to
explicit_allowdeny; - infrastructure: omit it and record the specific reason and owner.
- editorial: add it to
- Inventory editable tables. Make
tables_selecta superset oftables_modify. Include content, FAL relations/metadata, categories, and the project's editorial domain tables. Require the registered Core setpages,tt_content,sys_category,sys_file,sys_file_collection,sys_file_metadata, andsys_file_reference. When EXT:news is installed, also require its registered news, link, and tag tables in both lists. - Add every runtime TCA column marked
excludethat is genuinely editor-editable tonon_exclude_fields. Exclude Core-enforced admin-only and system-managed fields. Report unexpected read-only fields instead of overriding them. For editorial records such as news, expose the complete editing form apart from those verified exceptions. - Use every configured Site root and every page with
is_siteroot = 1asdb_mountpoints. Include extra storage folders only when the workflow requires them. Use every activesys_filemounts.uidasfile_mountpoints, validate each identifier's storage UID againstsys_file_storage, ensure every online browsable storage has an active mount, and grant the file operations required by the workflow. - Set
allowed_languagesto an empty value for all languages and setmfa_providerstototp,recovery-codes. Recommend TOTP in User TSconfig; requiring MFA is a separate security policy and needs an explicit decision. - Add the installed minimum modules listed below. Do not grant administration, system configuration, Powermail reporting/marketing, Solr index mutation, or infrastructure modules.
- Include every page type already used below the editor's web mounts. Add unused types only when the workflow explicitly needs editors to create them.
- Audit every page in the deduplicated union of all configured Site trees and every tree marked
is_siteroot. Ensure the approved default user owns it with bits31, the main group owns it with bits27, and everybody has view-only bit1. Remediate through the Permissions module or DataHandler after the membership/login cutover gate above passes. Configure new pages to inherit both owners and the same31/27/1baseline. Never grant everybody write rights.
Minimum installed modules
Resolve identifiers from the runtime ModuleRegistry; never write identifiers for absent modules.
- Always when installed:
web_layout,records,page_preview,content_status,web_info_overview,web_info_translations,recycler,media_management, anduser_setup. - Visual Editor:
web_edit. - Core Form:
web_FormFormbuilder,form_manager, andform_editor. - Core Redirects:
redirects. Grant only to named trusted editor groups; it manages redirects across the entire installation. Do not grantqrcodesorshort_urlsunless separately requested. - Solr:
searchbackendand the read-onlysearchbackend_infoentry. Keepsearchbackend_coreoptimization,searchbackend_indexqueue, andsearchbackend_indexadministrationadmin-only. - Workspaces:
workspaces_publishand Live access bitworkspace_perms = 1in the Extensions subgroup.
When typo3/cms-form is installed, grant read/write access to form_definition; TYPO3 v14.3's
Form persistence permission checker requires both lists even though its TCA display fields are
read-only and the Form modules perform the controlled writes.
When typo3/cms-redirects is installed, grant the intended trusted editor group or groups
read/write access to sys_redirect and its runtime editor-editable exclude fields. Keep read-only
and system-managed fields excluded. Users inherit this through groups; never write direct per-user
rights.
When Powermail is installed, grant read/write access and every editor-accessible field for
tx_powermail_domain_model_form, tx_powermail_domain_model_page, and
tx_powermail_domain_model_field. Do not grant Powermail mail/answer/marketing tables or any
web_powermail / powermail_* reporting module by default. Keep the powermail_pi1 CType as a
documented infrastructure exception so normal editors build forms but do not place or reconfigure
the frontend plugin.
Use basic Workspaces settings when installed
First confirm that typo3/cms-workspaces and its runtime module workspaces_publish are installed.
If they are absent, keep workspace_perms = 0, do not add the module, and do not create Workspace
records. If present, read the Workspaces skill and use this baseline:
- Put
workspaces_publishand Live access bitworkspace_perms = 1in the Extensions leaf. - Keep the Core default stages. Do not invent review stages, notifications, or scheduled publishing for a basic editor role.
- Add the main editor group—not individual users—as a member of the intended custom Workspace. Do not make it an owner. Ask who should own and publish before creating a missing Workspace.
- Set
publish_access = 2so only approved Workspace owners can publish. Do not expose publishing controls to normal editors. - Use the group's audited database and file mounts for the Workspace. Do not grant
sys_workspacetable access; its TCA is administrator-only. - Set
options.workspaces.previewLinkTTLHours = 48in User TSconfig.
Create or update a custom Workspace through DataHandler, not raw SQL. Adding the group permission alone does not make the group a custom-Workspace member. Physical FAL files are not versioned: editors must upload replacements under new unique filenames instead of overwriting a shared file, and unpublished page content must never be treated as protection for a directly accessible file.
Configure TSconfig
Keep User TSconfig in the sitepackage and import it from the Base subgroup. Copy one bundled profile:
- basic.tsconfig: page-cache clearing and safe preview access.
- optimized.tsconfig: the basic rights plus useful Admin Panel sections, file-list actions, resource view, and live-search destinations.
Use the optimized profile by default for trusted content editors. Keep debug, tsdebug, and
publish disabled. Verify the frontend TypoScript has config.admPanel = 1; User TSconfig alone
cannot display the Admin Panel.
Both profiles recommend TOTP and make new pages inherit their parent owner user and owner group.
They set owner user show,edit,delete,new,editcontent (31), owner group
show,edit,new,editcontent (27), and everybody show (1). Group page deletion remains off;
the profiles do not force MFA.
Both profiles set options.workspaces.previewLinkTTLHours = 48. TYPO3 ignores the option when
Workspaces is absent; it does not grant Workspace access by itself.
When friendsoftypo3/visual-editor is installed, include its registered web_edit module and set:
options.pageTree.showPageIdWithTitle = 1
The Visual Editor consumes this option when building its editing context. In multi-site projects,
also enable options.pageTree.showDomainNameWithTitle = 1 to make destinations unambiguous.
These options improve the editor context but do not grant write access. Visual editing additionally
requires the page mount, language, tables_modify, non_exclude_fields, and explicit CType rights
for each rendered record. admPanel.enable.edit controls the Admin Panel and is not a substitute
for the web_edit backend module.
Prefer a group import over duplicated inline TSconfig:
@import 'EXT:sitepackage/Configuration/TsConfig/User/BackendEditor/optimized.tsconfig'
Brand the login and backend
Read backend-branding.md, derive an accessible action color from
the customer's design tokens/CSS/logo, and configure the Core login logo, logo alt text, highlight,
background, footnote, backend logo, and favicon. Use the plain-text Core footnote for
Website by webconsulting.at; TYPO3 already places it at the lower right on wide screens.
Show the exact value of Environment::getContext() before login and in the logged-in backend by
adding it to the instance sitename and login footnote. Do not infer the context from the hostname
and do not try to set TYPO3_CONTEXT from additional.php; it is read earlier during bootstrap.
Use $GLOBALS['TYPO3_CONF_VARS']['BE']['stylesheets'] for a small sitepackage stylesheet. Do not
override TYPO3's danger/success colors, focus indicators, or structural layout.
Create the group structure
This section applies only to the approved single-main-group model. Create or update the four
required leaf groups first, then create or update the main group with
their UIDs in subgroup. Keep the main group's permission fields empty and each leaf's subgroup
empty. Set a descriptive main title such as Editorial Main and document:
- the allowed editorial CTypes;
- every excluded infrastructure CType with its reason;
- editable/selectable tables and non-exclude fields;
- backend modules and page types;
- database/file mounts and file operations;
- all-languages mode and both MFA providers;
- page group ownership and permission bits;
- the selected TSconfig profile.
Create the complete structure before changing any user. Do not delete or repurpose old groups until the main group and all inherited rights have passed verification.
For a repeatable local/DDEV setup, prepare a reviewed JSON plan following permission-plan.example.json, then apply only the group:
ddev exec php /dev/stdin --dry-run \
--plan=/var/www/html/var/transient/backend-rights-plan.json \
< /absolute/path/to/typo3-backend-rights/scripts/apply-backend-rights.php
ddev exec php /dev/stdin --plan=/var/www/html/var/transient/backend-rights-plan.json \
< /absolute/path/to/typo3-backend-rights/scripts/apply-backend-rights.php
The command validates live CTypes, exception reasons, tables, mounts, and admin presence before a transactional insert/update of the main group and four required leaves. It preserves additional leaf references and never changes users or deletes old groups.
Change user membership safely
This is a per-user decision, separate from approval of the project-level group model. Ask the user this explicit question before replacing memberships:
Should
<main group>be this backend user's only group?
- If yes, replace that user's group list with the main group.
- If no, append the main group and preserve existing memberships.
- Never assign a user directly to Base, Content, Site, Extensions, or later capability leaves.
- Enable both Inherit page mounts from groups and Inherit file mounts from groups while
preserving other user options (
be_users.options |= 3). Otherwise the Site leaf has no effect. - If the target user is an administrator, set
admin = 0only after proving a different enabled, login-capable administrator remains. - Never demote the current working administrator. Use a second account for the editor test.
Changing one user's memberships does not authorize bulk changes to other users.
After the approved membership/login gate, use the bundled DataHandler cutover script to apply the
same default owner and 31/27/1 matrix to every configured or flagged Site tree. Start with a dry
run and name the default owner explicitly; the script never guesses it:
ddev exec php /dev/stdin --dry-run \
--group-title='Editorial Main' --owner-username='default-owner' \
--usernames='editor-one,editor-two' --membership-mode=replace \
--replace-group-title='Legacy Editors' --apply-pages \
< /absolute/path/to/scripts/apply-page-permissions.php
Run without --dry-run only after review. Use membership-mode=append for the pre-cutover login
test, then replace only when the user approved replacement. The script preserves unrelated group
memberships, sets the two group-mount inheritance bits, deduplicates nested Site roots, and writes
users/pages through DataHandler.
Verify as a non-admin
Use a real non-admin session and verify all of these:
- The page tree covers every required web mount.
- Every used editorial CType can be opened, changed, saved, hidden/unhidden, copied, and created.
- Each documented infrastructure CType is unavailable for creation and cannot be reconfigured.
- Editorial records such as news open with every required field and can be saved.
- Every Site tree is mounted and has the same default owner plus
31/27/1page baseline, every configured site language can be edited, and newly created pages inherit both owners and those permissions. - Core Forms can be created, edited, duplicated, and saved when installed. Powermail forms, pages, and fields can be created and changed when installed, while marketing/reporting modules and the frontend plugin remain unavailable.
- All active file mounts appear in Media and in file selectors; upload, replace, metadata edit, move/copy, and delete behave according to the plan.
- If installed, the Visual Editor module opens and every allowed rendered field can be changed and saved; page IDs are present in its editing context and multi-site destinations are clear.
- If installed, Redirects opens for the named trusted non-admin, who can list, create, follow,
edit, disable and delete a DDEV-only redirect; cleanup and
redirects:checkintegritypass. - Preview, Status, Recycler, Media, and the Admin Panel work; page cache clearing is available, while debugging, page deletion, Solr index mutation, and publishing controls remain unavailable.
- When Workspaces is installed, the main group can enter the intended custom Workspace, edit and preview versioned content, and create a 48-hour preview link, but cannot publish. Confirm the group is a member rather than an owner and test file replacement with a new unique filename.
- TOTP and recovery codes can be configured in User Settings; MFA enforcement matches the separately approved policy.
- Login, password reset, MFA, and the logged-in top bar show the customer identity and exact application context with accessible contrast.
- The separate administrator can still log in.
Re-run the audit with --group-title and --strict. Report the main and leaf group UIDs, target
user, remaining administrator, allowed/missing CTypes, exceptions, tables, fields, mounts,
TSconfig profile, and the non-admin verification evidence.
Resources
- permission-model.md: database field mapping, classification rules, and verification queries.
- backend-branding.md: supported login/backend branding, accessible color selection, application-context display, and verification.
- typo3-workspaces: Workspace versioning, DataHandler setup, preview, publishing, and the physical-file limitation.
scripts/audit-backend-rights.php: read-only runtime TCA/database audit.scripts/apply-backend-rights.php: validate and transactionally create/update the main group and four required leaves from a reviewed plan; never changes users.scripts/apply-page-permissions.php: dry-run/apply the approved membership cutover and complete default-owner/main-group/everybody31/27/1baseline across all configured Site trees via DataHandler.assets/tsconfig/: basic and optimized User TSconfig templates.