-
1
Inventory objects, fields, and the actions that need gating
You cannot write a permissions model until you know what is being permitted. Start with a flat inventory: every object, every field on every object, and every action a user might take on each (view, create, edit, delete, export, merge, reassign owner, mass update). Mark which fields carry restricted data (contract value, commission, SSN, health info) and which actions carry blast-radius risk (export, delete, mass update, owner reassignment). This spreadsheet becomes the control surface for everything that follows. If an object or action is not on the list, you cannot gate it, and you cannot audit it later.
- List every standard and custom object with its approximate record count and growth rate
- List every field per object and tag each as public, internal, sensitive, or regulated
- List every action a user can take per object and tag each as read, write, destructive, or export
- Flag the fields and actions that already live under a compliance obligation (SOC 2, HIPAA, GDPR)
Tip: Export this inventory as a CSV and keep it in the same repo as your admin config. If a new field or action lands outside this inventory, it is unpermissioned by definition.
-
2
Define the record-scope ladder: own, team, region, all
Record scope answers the question 'which rows can this user see?' and is the single most important decision in the model. Pick a small ladder and apply it consistently across objects. The default ladder is own records, team records (direct reports plus peers who share a manager), region or territory records, and all records. Each role on the next step gets exactly one scope per object. Resist the urge to invent a fifth custom scope for a VP who wants 'everyone except the Boston team'; one-off scopes are how permission models rot. If a request does not fit the ladder, change the ladder once, not the exception set forever.
- Decide the ladder: own, team, region, all is a safe default for most B2B CRMs
- Decide how team is computed: direct manager, manager hierarchy BFS, or an explicit team membership table
- Decide how region is computed: territory assignment, account country, or an explicit region field
- Write one sentence per rung describing what a user with that scope on Accounts can and cannot do
Tip: Strkr's own forecast permissions follow this pattern: scope is a knob (own, direct reports, manager hierarchy BFS, all), and it is set per role rather than per user. Copy that shape; it survives reorgs.
-
3
Draft the role catalog following least privilege
Now map people to scopes. Keep the role catalog small: 8 to 15 roles covers almost every B2B CRM. Start from the least privileged role (rep, SDR, intern, read-only auditor) and only widen a permission when a documented workflow requires it. Senior roles inherit from junior ones, not the other way around. Every role gets a one-sentence job description, a scope per object, an action set per object, and a named owner on the business side. If no business owner will sign for a role, that role should not exist. Keep every custom-user override out of the role catalog itself; those belong on a separate exception list reviewed quarterly.
- Sketch 8 to 15 roles maximum, from least to most privileged
- Give each role a single-sentence purpose: who sits in this seat and what do they ship
- Assign scope per object (own, team, region, all) and action set (view, edit, export, delete) per role
- Name a business owner per role: Sales Ops owns reps, Marketing Ops owns MDRs, Security owns auditors
Tip: If two roles differ by only one permission, they are probably the same role with a per-user override, or you have an undocumented split in the business. Collapse or clarify before shipping.
-
4
Separate read from edit, and gate export and delete explicitly
The two most common permission failures are 'reps can edit records they can see' and 'anyone with view can export the whole book.' Treat view, edit, export, and delete as four separate switches on every object, not as a single tier. A rep might view team pipeline for context but only edit their own records. A manager might edit the team's records but only export anonymized summaries. Delete is almost always its own gate, scoped to admins and governed by a soft-delete archive pattern rather than a hard destroy. Export is the single gate that most often shows up in a breach post-mortem, so it gets the strictest default: off, unless the role has a business reason to pull data out of the system.
- On every object, split the permission into view, edit, export, delete, and merge as separate switches
- Default export to off for every role except explicit data-handling roles with written approval
- Default delete to off for every role except admins, and prefer archive over hard-delete in the model
- Document, per role, which fields can be edited inline versus which require a workflow or approval
Tip: Export is where the breach happens. If a role has export on an object, write the business reason in the role catalog or revoke it the same day.
-
5
Add field-level rules for sensitive data
Record scope controls which rows a user sees. Field-level rules control which columns. Contract value, commission rate, source-of-truth revenue, SSN, DOB, and health or payment data all need field-level gating on top of record-level gating. A sales rep might see every column on their own accounts but only a redacted subset on peer accounts. A finance analyst might see financial columns on every record but no contact PII. Design these as a short overlay on the role catalog: a role has record scope A on an object plus a sensitive-field policy B. Keep the overlay small so admins can reason about it; a role with 40 field-level exceptions is really a new role.
- List the fields that carry sensitive or regulated data from step 1 and group them into 3 to 5 policies
- Attach a field-level policy to each role per object: full, redacted, or none
- Make sure masked fields stay masked in exports, reports, and API responses, not only in the UI
- Document which fields are editable only by a named service role, never by any human role
Tip: A field that is masked in the UI but visible in the API or exported CSV is unmasked. The gate has to live at the data layer or it is theatre.
-
6
Pin ownership, delegation, and reassignment rules
Record ownership is a permission by itself. Decide up front who can own records, who can reassign them, and what happens when an owner leaves. Reps own records in their scope. Managers can reassign within the team. Admins can reassign across teams. Never allow a user to reassign a record out of their own visibility, because the result is a record they cannot audit. For departures, build a routine: suspend the user, transfer owned records to the manager or a holding queue, archive personal activities, and only then disable the account. Strkr's own rule is to never hard-delete an active user; the same discipline applies here. Document the delegation chain so a rep going on leave can hand off cleanly without an admin ticket every time.
- Define who can own records per object: usually the roles that actually work the records day to day
- Define who can reassign ownership and within what scope: manager within team, admin across teams
- Build a Leaver workflow: suspend, transfer, archive, disable, in that order, as a documented runbook
- Allow temporary delegation for leave or coverage without transferring permanent ownership
Tip: A record owned by a disabled user is a landmine for reports, routing, and automations. Transfer first, disable second, every time.
-
7
Design admin and service-account permissions as their own tier
Admin is not just 'all permissions on.' Split admin into named sub-roles with the smallest scope that still gets the job done: user admin, security admin, data admin, integrations admin, billing admin. Service accounts (API users, integration bots, Strkr AI jobs) get their own role tier with narrow, documented scopes and no interactive login. Rotate service-account credentials on a schedule, scope their write access to the specific objects and actions they need, and never let a service account inherit a human admin role. Every admin and service action lands in the audit log, and every admin role has a named human owner on the Security side.
- Break admin into 4 or 5 named sub-roles rather than one god role
- Create a separate service-account tier with no interactive login and scoped write access per integration
- Rotate service-account secrets on a schedule and alert on long-lived credentials
- Require two humans to grant any admin role, and log the grant with the business reason
Tip: The second someone asks for 'temporary full admin to debug a thing,' create a scoped break-glass role with a 24-hour timer instead. Full admin for an afternoon is full admin forever.
-
8
Turn on audit logs and build the review cadence
A permissions model is only as good as the audit trail behind it. Turn on logs for every permission change, every role grant and revoke, every export, every mass update, every delete or archive, and every ownership reassignment. Ship these to a system Security owns, not to the CRM's own UI only. Then build the review cadence: a weekly report of new role grants, a monthly report of exports by role and user, a quarterly review of exception overrides, and an annual full re-approval of every role and every exception. The weekly and monthly reports catch drift. The annual review is the audit artifact that satisfies SOC 2, ISO 27001, and most customer security reviews.
- Log every permission grant, revoke, export, mass update, delete, and ownership change
- Ship logs to a Security-owned store with retention that meets your compliance obligations
- Build weekly new-grant and export-by-user reports and route them to a named reviewer
- Schedule a full annual review of every role, every exception, and every service account on the calendar
Tip: An audit log nobody reads is not an audit log. Assign a named reviewer per report, with a 30-minute weekly ritual to walk the deltas, or it decays within a quarter.
-
9
Dry-run in sandbox, roll out in waves, and schedule the annual review
Never ship a permissions model straight to production. Dry-run every role in a sandbox against production-shaped data: log in as a sample user per role and walk the real workflows. Spot checks catch the surprises (a report that silently filters out team data, a dashboard that breaks because a field is now masked, an integration that fails because a service role lost export). Roll out in waves: internal admins first, then a pilot team, then the long tail. Communicate the model in writing, publish the role catalog where every manager can read it, and put the next annual review on the calendar before you declare rollout done. The model is a living document; the calendar entry is what keeps it alive.
- Dry-run each role in sandbox by logging in as a sample user and walking real workflows end to end
- Roll out in waves: admins, then one pilot team, then the rest, with a feedback loop at each wave
- Publish the role catalog, exception list, and audit cadence in the admin wiki, not a one-off deck
- Put the annual review on the calendar now, with RevOps and Security co-chairing, before you call it done
Tip: The role catalog is a product. It has owners, a changelog, a review cadence, and a sunset policy for every exception. Treat it that way or you will be rewriting it from scratch in 18 months.