Give everyone full CMS access and eventually someone publishes the wrong thing to the wrong place — we've watched it happen, including to ourselves. Lock everything down and your writers spend their days waiting for someone with permissions. Role-based access for content teams is the art of avoiding both failure modes, and it's worth designing deliberately. Here's the model AgenticWebTeam uses and the patterns that work.
Rules, not tiers
Most CMS permission systems offer tiers: viewer, editor, admin. Real content teams don't work in tiers — they work in territories. The blog team owns /insights, the services team owns its section, the developer owns the code, and nobody should own everything. So instead of tiers, roles here are sets of rules. Each rule combines an environment (production, staging or both), a match — path pattern, page type, slug pattern, in any combination — and the actions allowed: create, read, update, delete, publish.
A write is allowed if any rule grants that action with every part of the match satisfied. That one sentence expresses surprisingly rich policies: "can edit blog posts on staging but publish nothing", "can do anything under /services except delete", "developer access to src/** on the staging branch only".
Publish is the gate that matters
The action to think hardest about is publish, because it controls what reaches the live site — and it gates more than the publish button. Editing an already-published page directly, or creating a page as published, changes live content just as surely as promoting a draft, so all three require publish permission. Users without it aren't blocked from working; their changes simply stay drafts.
This is what makes an edit-only role genuinely safe to hand out. A junior writer scoped to update on /insights can research, draft, revise and perfect — and structurally cannot put a word live. The publish decision belongs to whoever you gave it to, every time, by construction rather than by convention.
Approvals make the gate humane
A gate that dead-ends is a gate people route around, so denial flows into an approval workflow instead. When a drafter's work is ready, the assistant looks up which colleagues' roles can actually publish that specific page, lets the drafter choose who to ask, and emails those reviewers a link to a preview of exactly what would change — current live version versus draft, field by field. Approve executes the publish under the approver's name; decline sends it back; either way the requester is told, and the audit log ties the whole story together.
The result is a review step with no process overhead. Nobody maintains a checklist; the workflow is the checklist.
Patterns that work
Start with territory roles that mirror how your team already divides the site: an Insights Editor with update and publish on /insights, a Junior Writer with update only on the same paths, a Services Manager owning /services and /case-studies, a Developer with code paths and no content at all. These defaults exist out of the box and are worth keeping — rename them, adjust the paths, and you're most of the way there.
Use environments for the riskier grants. An agency preparing a campaign gets full freedom on staging and nothing on production; your in-house editor promotes what passes review. Use page-type matches for precision — a role that can edit any document of type faqItem regardless of path is often more honest than a path glob. And resist the everything role: admins exist, but every one you add is a person whose bad Tuesday can reach the whole site.
Rolling it out without a fight
Access changes fail socially before they fail technically, so sequence matters. Start by writing down who owns what today — usually five minutes on a whiteboard — and build roles that match that reality rather than an aspirational org chart. Grant slightly generously on update, strictly on publish and delete. Then tell the team the honest framing: nobody is losing the ability to work; a few people are gaining the explicit responsibility for what goes live.
Expect one week of friction while muscle memory adjusts — someone will hit a publish denial and grumble. That moment is the system working: their draft is intact, the approval request takes seconds to send, and the reviewer sees exactly what would change before agreeing. After the first few cycles, teams generally report the opposite complaint — that they wish other tools made review this cheap.
Revisit quarterly. Territories drift, people change teams, and a role that made sense in spring is someone's obstacle by autumn. Because roles are rules rather than code, adjusting one is an edit in the team screen, not a ticket to engineering.
The two roles people forget
Two roles deserve explicit design rather than emerging by accident. The developer role should have no content permissions at all — not because developers aren't trusted, but because separating the code and content territories keeps each audit trail clean. And the admin role should be held by fewer people than feels comfortable: admin is for managing the team, not for daily publishing, and the fewer holders it has, the more meaningful every entry in the log becomes.
Audit everything, trust more
The counterintuitive effect of good scoping plus a full audit trail — who did what, to which page, on which environment, when — is that you end up granting more access, not less, because the cost of a mistake drops. Writers draft freely, publishers publish confidently, and when something does go wrong, the log answers "what happened?" in seconds instead of a meeting. Access control done well isn't about restriction; it's about making trust cheap.