Case study · Access audit for a residential developer
Another business's sales team could open their deals.
Nobody could see it on a screen. A count found it.
A residential developer selling apartments, storage rooms and parking spaces shares one Salesforce org with other businesses in its group. Everyone believed each business's deals were closed to the others. They were not: a sales team in the same org could open another business's deals and payments, with every client name, amount and stage on them. I worked on the audit and the fix with the client's team, and the separation went live on development, staging and production on the same day.
This is for you if more than one company, brand or team works in your Salesforce org, and nobody has ever counted what one team can open of another's.
August 2026, remote, delivered with the client's team. The client is not named and none of its record counts are published: a client's data stays the client's. Reviewed 29 October 2026.
The risk
What was at risk, and why did nobody see it?
The risk was plain: one business's pipeline, its clients and what they pay, open to the sales staff of another. Nothing was broken, so nothing warned anyone. Salesforce shows each user the records they can open and says nothing about the ones they should not, and no setup screen shows how many people can reach a record. The separation looked done because each business had its own record types, and record types do not decide who can see a record.
That is why the audit counts instead of looking. The check behind it is one working day, read only against your own exports, delivered within three working days.
What changed
What changed for the developer?
Before, another team could open the developer's deals and payments and nobody knew. After, both leaks were closed, the same way on all three orgs, and the queries that prove it are written into a runbook the client's team keeps.
1 count
instead of one more look at the configuration. The first check read the setup and said the other team could not see the deals. The count said it could
2 leaks, 2 causes.
Deals were open through one permission on a profile, payments through an org wide setting. Closing the first would have left the second open
3 of 3
orgs, development, staging and production, changed the same way on the same day, so the rehearsal matched the real thing
1 runbook
with every change, the queries that verify it and the way back, so the next admin does not have to rediscover any of it
Before
What was going wrong before?
Each business in the group had its own record types for accounts, deals and contracts, so the separation was assumed. A record type decides which layout and which picklist values a user gets when creating a record. Who can open the record afterwards is decided by the org wide default, the sharing rules and the View All and Modify All permissions, and on this org two of those three were open. The business whose deals were exposed believed its data was closed.
What was built
Four changes, each one replacing an assumption.
Deals: the View All permission removed from the sales profile.
The sales profile now reaches deals through ownership and sharing, like every other user. The permissions came off in the only order the platform accepts: Modify All on quotes, View All on quotes, then View All on opportunities.
Payments: the org wide default moved from public read and write to private.
Payments are now visible to their owners and to whoever a sharing rule names. changed nothing while the default stayed open.*
Sharing rules deployed only once the recalculation had finished.
The state of the org is read with a query before the rules go in. `ALREADY_IN_PROCESS` and rolled back, leaving payments on private with no rules at all. Everyone saw only their own.*
A runbook instead of memory.
The full list of changes, the queries that verify them, the traps, and the way back, with a "checked on" date updated after every later change.
The decisions that mattered
Which decisions are usually made the other way?
Three choices that are often made the other way, and what goes wrong when they are.
Separating businesses by record type.
It is the obvious move in a shared org, and it looks complete: each team sees its own layout, its own stages, its own picklists. It separates nothing. Anyone with a View All permission or an open org wide default still opens every record of every type. So every request to separate access here starts with the org wide default for each object, not with record types.
One fix for one symptom.
The symptom was the same on deals and on payments: the other team could see them. The causes were not. On deals it was a profile permission; on payments it was the org wide default, and taking permissions off payments did nothing while the default was public. Fixing the first cause everywhere would have closed deals, left payments open, and produced a report saying the work was finished.
Trusting the deploy report.
Changing the org wide default on a large object starts a recalculation of sharing in the background. Salesforce's guide to deferred sharing calculations warns that a recalculation can take a significant amount of time, and deferring it is something only Customer Support can enable. On this org a sharing rule deployed during the recalculation failed with `ALREADY_IN_PROCESS`, and because a Salesforce deploy is all or nothing, the whole package rolled back with it. The org was left private with no rules, which on a working day means staff opening a record they used yesterday and getting nothing. The rules go in only after a query shows the recalculation is done, and the result is checked with a query, not from the command's output.
Lessons
What would I do differently next time?
Three things this work taught, now part of every access audit.
Count first, read the setup second.
The first check here read the configuration and concluded the other team could not see the deals. It would have been signed off. Now the first step is a count of the other team's records one user can open; the reading of profiles and sharing comes after, to explain the number.
Ask which fields are required before promising read only.
A field the platform requires, such as the name of a record or the stage and close date of a deal, cannot be made read only on a layout. The deploy refuses it: `Field:Name must not be Readonly`. Where a team must not change those, the answer is a validation rule, and that belongs in the estimate from the start.
Check who holds Edit Read Only Fields.
That permission lets a user edit fields a layout marks read only. On this org two profiles held it at the time, System Administrator and API User. A layout is not a lock for anyone who holds it, so the list of holders is read before relying on layouts.
What buyers ask first
Three questions before you start
Will our people lose access while this is changed?
That is the real risk, and it is why the order matters. The change is made on development and staging first, in the same order as production; the default changes before the rules; the rules go in only after the recalculation is confirmed by a query; and the runbook holds the way back. The one failure seen here, the rolled back rule deploy, is caught by that query rather than by a user calling.
We separated teams with record types and separate apps. Is that not enough?
No. Record types and apps decide what a user is shown, not what a user can open. A record of another team's type is one search or one list view away for anyone whose profile, permission set or org wide default allows it. The only way to know is to count.
Do you need admin access to our production org?
Not for the audit. It runs read only against exports your own admin sends, and nothing in your org is modified. Changing access is a separate, quoted piece of work, rehearsed in your sandbox before production.
For your business
Which parts carry over to any shared org?
Any org where two companies, brands or teams work side by side needs the same four answers per object: the org wide default, every profile and permission set with View All or Modify All on it, the sharing rules, and a count of what one user of team A can open of team B. Who holds which grant and why is covered in the nine risks of a Salesforce permissions audit; this case is the other half, which records those grants open.
A quick test before anything else: log in as one user of team A, run a report on deals filtered to team B's record type, and read the row count. A report lists only the records its user can open, so that number is what team A can open today. If it is not zero and should be, record types were never the separation.
The access audit is one fixed day, €650, read only against your own exports, delivered within three working days, with a verdict and a costed order of work.
Serhii Skrypnyk · Senior Salesforce Administrator · 7 Salesforce certifications · on the platform since 2018. Reviewed 29 October 2026.
Read next
The question that usually comes after this one.
Salesforce Permissions Audit: Fixed €650
Nine access risks a Salesforce permissions audit finds and why agents inherit them all. Check them yourself, or one fixed day at €650 against your exports.
Slack and Salesforce: Six Governance Gaps
What changes when the conversation about a record lives somewhere the record does not, and the six decisions to write down before connecting the two.
Case: Group of companies, second rollout
A holding and its operating companies came back to Salesforce after a first rollout stalled: tenders as leads, one customer record in either alphabet, access proved as the users.