Protect Custom Metadata Types and Records

Learning Objectives

After completing this unit, you’ll be able to:
  • Identify the options for protecting custom metadata types.
  • Control the editability of a field.
  • Protect custom metadata records.

Protect Custom Metadata Types

When you create a custom metadata type, you can determine who can access and change the type. 

  • Public — Regardless of the type of package (managed or unmanaged), the following have access:
    • Apex
    • Formulas
    • Flows
    • API for users with Customize Application or permissions granted through profiles or permission sets. The custom metadata type, fields, and unprotected records are visible in setup.
  • Protected — When in a managed package, only Apex code in the same namespace can see the type. The name of the type and the record are visible if they’re referenced in a formula.
  • PackageProtected — When in a second-generation managed package, only Apex code in the same managed package can see the type. The name of the type and the record are visible if they’re referenced in a formula.
Note

Note

If a custom metadata type is protected, it can only be accessed by other components that are in the same namespace. However, with second-generation packaging, you can create multiple packages in the same namespace, and this adds another level of protection, which is called package protection. So now we can control how components that are in the same package, or in the same namespace can access custom metadata types.

There are a few more things you need to know about custom metadata types and protection.

  • Protected custom metadata types can only be created in developer and scratch orgs.
  • By default API read access is restricted, even for types set to Public. This is set through the Schema Setting, Restricted access to custom metadata types. Restricting access is recommended. Access can be granted to users through profiles and permission sets by admins with Customize Application permission. When not enabled, users without the Customize Application permission can read custom metadata types using different Salesforce APIs that are provided by Salesforce.
  • Apex code that is run in system mode ignores user permissions and your Apex code is given access to all objects and fields. Functionality that runs in system mode, such as Apex, is not affected by the Restrict access to custom metadata types org preference.
  • In user mode, functionality such as Visualforce Components, Visualforce Email templates, and Aura, is run with respect to the user's permissions and sharing of records.
You set the visibility of custom metadata types to public, protected, or package protected in your scratch or developer org where you're designing your app and creating custom metadata types that you will use in an application. Then you bundle your app and your custom metadata types into a package. Once the package is installed in a subscriber org, the access is public or restricted by either being protected (namespace protected), or package protected.

Protect Custom Metadata Records

Instead of protecting an entire metadata type, you can protect individual records within a public type. If a developer releases protected records in a managed package, access to them is limited in specific ways.

  • Code that’s in the same namespace as custom metadata records can read the records.
  • Code that’s in the same namespace as custom metadata types can read the records that belong to that type.
  • Code that’s in a namespace that doesn’t contain either the type or the protected record can’t read the protected records.
  • Code that the subscriber creates and code that’s in an unmanaged package can’t read the protected records.

You can also protect custom metadata types, providing the same access protection as protected records. If you change a type from protected to public, its protected records remain protected, and all other records become public. If you use Setup to create a record on a protected type, Protected Component is selected by default.

When a type is public, you can’t convert it to protected. The subscriber can’t create records of a protected type.

Field Manageability

When it comes to protecting fields on custom metadata types, you have three options.

  • The package developer can use package upgrades to edit the field after release. Subscriber orgs can’t change the field.
  • The subscriber org can edit the field after installing the package. Package upgrades don’t override the subscriber’s changes.
  • Neither the package developer nor the subscriber can edit the field after the package is released.

These options seem fairly simple, but let’s take some time to dig into how everything works together.

Put It All Together

Let’s say we’re putting our Support Tier type in a managed package. For legal reasons, we don’t want package subscribers to change the Default Discount field. As the package developer, you still want to be able to change it in later package releases if the legal requirements change. So, you want the Default Discount field to be upgradeable.

The values on the Minimum Spending field vary depending on the org, though. Sometimes orgs change the minimum spending amounts based on local factors. To account for this need, make the Minimum Spending field subscriber editable.

Review this table to see who can edit the fields on both public and protected records in a managed package.

Developer Name Label Support Tier (upgradeable) Support Level Mapping (subscriber editable)
Public record Developer Developer Subscriber
Protected record Developer Developer
In a managed package, the package developer can always edit upgradeable fields. Subscribers can edit subscriber editable fields on public records but not on protected records. Subscriber editable fields on protected records are locked after release.

If we look at the same custom metadata type and its associated records in an unmanaged package, it’s easier to see who can edit what.


Developer Name Label Support Tier (upgradeable) Support Level Mapping (subscriber editable)
Public record Subscriber Subscriber Subscriber Subscriber
Protected record Subscriber Subscriber Subscriber Subscriber

An unmanaged package gives the subscriber freedom to edit records and fields on custom metadata types.

The moral of this unit is that field management can get complicated quickly. It’s important to plan how you want to manage your custom metadata types, fields, and records before you package your app and release it into the wild.
When you want Use
Subscribers to be able to change anything within the metadata type. For example, your subscribers can add more custom fields to your type.
Public type, or any type outside of a managed package
To protect sensitive data, like application secrets, include custom metadata types in a managed package.
When contained in a managed package and set to package protected, types are not visible to subscribing organizations through Apex or the API and only accessible by Apex code in the same package or namespace, making it a good place for storing API keys or other secret keys.
Package protected within 2G managed package
or
Namespace protected within the managed package
A subscriber org or extension package to add its own records to the type.
A protected record is only accessible to code in the same namespace as the record or its associated custom metadata type. For example, perhaps you want subsidiaries at Acme to be able to add another tier record, such as Platinum.
The visibility for the type is set to public and records set to protected.
Speaking of packaging, we’ll start that adventure next!