Blowing the “Single Profile” approach out of the water
When you install a package from AppExchange via the browser you get to choose whether to Install it for All Users, Only Admins, Specific Profiles or no-one. This really means if you want to grant full access to Classes, Pages, Fields (and more) to your users. See here for more details of exactly what users get granted access to. You can install any package this way so long as you know the Package Version Id (the “04t” Id).
If you want to install or upgrade a package via the Salesforce CLI e.g. in automated pipelines like GitHub Workflows (which you always do in any sort of bigger project) you only have 2 of the choices available to you in the equivalent --security-type
parameter: AllUsers or AdminsOnly. Notice the lack of a “NoAccess” option.
We have been very good in our project and all our permissions (and I mean all) are done via Permission Sets organised into Permission Set Groups. We only have a single profile for everyone, users are provisioned via API and we have some automation to pick the right Permission Set Groups. Beautiful solution.
Ok, Page Layout assignments or Flexi page assignments. But they are not really permissions.
Until we found the supposedly empty profile full of permissions no-one had set on it. That’s when we realised this sentence in the documentation is not 100% accurate:
Install for Admins Only
Specifies the following settings on the installing administrator’s profile and any profile with the Customize Application permission.
What it really should say is “Specifies the following settings on the installing user’s profile and any profile with the Customize Application permission“. Our user had the Customize Application permission, but via a Permission Set.
The only solution to this is having a different profile for the “deployment user” and accept that they will have many unintended permissions. Or clean it up after every upgrade.
Salesforce say (via Support) that the CLI is intended to automate deployment of metadata changes. It is not intended to manage permissions (yet). I’d say that the lack of a “NoAccess” option is actually having quite the effect on your permission management. Both “No profile” and “Package delivery” are examples of best practices IMO, but you have to muddy them a bit to use both at the same time.
Other Traps
LWC in Purgatory
If you are delivering your SFDX projects using packaging you are likely aware of the challenges with moving metadata artefacts from one package to another. Particularly when moving up the dependency hierarchy. There is this very neat “trick” for Unlocked Packages where you can temporarily remove metadata from a package…