In this video, I take a look at the new AL-based permission system we got with version 18 of Microsoft Dynamics 365 Business Central. The permission system, behind the scene, is changed to use AL objects for permissions instead of maintaining permissions as data.

In this video, Erik walks through the brand new AL-based permission system introduced in Business Central version 18 (wave 1). While the user interface looks nearly identical to the old one, the underlying architecture has fundamentally changed: permissions can now be expressed as AL objects rather than being purely data-driven entries sitting in permission tables. Erik demonstrates how to create permission sets, organize them using includes, and touches on a PowerShell conversion tool for migrating existing permissions.
What Changed in Version 18?
For roughly 20 years, permissions in Business Central (and NAV before it) were entirely data-driven — they were stored as rows in permission tables. Starting with version 18, permissions can now be defined as AL objects. This is a major architectural shift, even though the end-user experience looks remarkably similar.
When you open the Permission Sets page in Business Central, you’ll notice a new Extension column. This tells you which extension (app) provided each permission set. For example, the Base Application provides a “Setup” permission set, the System Application provides a “Snapshot Debug” permission set, and the Company Hub app provides its own permission set — all defined as AL objects within their respective extensions.
Creating Permission Sets in AL
Erik demonstrates building permissions for a simple Point of Sale app (from a previous video in the series) that has just a single table: POS Setup.
Two New Object Types
AL now includes two new object types related to permissions:
- Permission Set — defines a set of permissions
- Permission Set Extension — extends an existing permission set from another app
Note that these new object types still require object numbers, even though recent AL object types have trended away from them.
A Basic Permission Set
Here’s a simple permission set that grants full access (Read, Insert, Modify, Delete) to the POS Setup table:
permissionset 50100 "POS Admin"
{
Access = Public;
Assignable = true;
Caption = 'Point of Sale Admin';
IncludedPermissionSets = "POS Setup Admin";
}
The Access Property: Public vs. Internal
Permission sets have an Access property with two options:
- Public — combined with
Assignable = true, this means the permission set can be assigned to users - Internal — the permission set cannot be assigned directly to users, but can be included in other permission sets
This lets you create a modular structure: internal permission sets handle specific areas, and public-facing permission sets compose them together.
permissionset 50101 "POS Setup Admin"
{
Access = Internal;
Caption = 'POS Setup Admin';
Permissions = tabledata "POS Setup" = RIMD,
tabledata "General Ledger Setup" = RIMD;
}
Understanding the RIMD Permission Mask
In the broader development world, people talk about CRUD operations (Create, Read, Update, Delete). In Business Central, the equivalent is RIMD — Read, Insert, Modify, Delete — plus X for Execute (used on codeunits, reports, pages, etc.).
The case of the letters matters:
- Uppercase (R, I, M, D, X) — direct access: the user can access the object directly
- Lowercase (r, i, m, d, x) — indirect access: the user can only access the object through another object
For example, a user might have indirect insert access (i) to G/L Entry, meaning they can’t open the table and type entries directly, but Codeunit 12 (the posting codeunit) can insert entries on their behalf. In most typical scenarios, you’ll use uppercase for direct access.
Composing Permission Sets with Includes
One of the most powerful aspects of this new system is the ability to compose permission sets. You can create focused, internal permission sets and then include them in broader, user-facing ones:
permissionset 50103 "POS GL"
{
Access = Internal;
Caption = 'POS GL';
Permissions = tabledata "General Ledger Setup" = RIMD;
}
permissionset 50102 "POS User"
{
Access = Public;
Assignable = true;
Caption = 'Point of Sale User';
IncludedPermissionSets = "POS GL";
Permissions = tabledata "POS Setup" = R;
}
Even though “POS User” is composed of multiple permission sets, when you view it in Business Central, all the permissions are flattened and displayed together — the user sees exactly what access they have.
Cross-Extension Permissions
Your permission sets aren’t limited to objects within your own extension. You can grant access to tables, pages, codeunits, and other objects from other extensions as well.
A Warning About Wildcards
There is a wildcard syntax available — for example, tabledata * = RIMD — but Erik strongly warns against using it. It does not mean “all objects in my extension.” It means all objects in the entire system. This is equivalent to the old tabledata 0 = RIMD pattern. Be very reluctant to use the asterisk.
Permission Set Extensions
The permissionsetextension object type lets you extend permission sets defined by other apps. This is useful when your app needs to be part of an existing permission structure — you can add your objects to an existing permission set so that users with that set automatically get access to your app’s objects.
The Easy Copy-Paste Advantage
Because permissions are now code, you get all the benefits of working in a code editor: copy-paste, find-and-replace, version control, code review, and more. Creating a “User” variant of an “Admin” permission set is just a few keystrokes — change RIMD to R and update the name. Compare this to the old XML-based approach:
<PermissionSet>
<Permission>
<ObjectType>8</ObjectType>
...
</Permission>
</PermissionSet>
Who can remember what object type 8 is? The old XML format was terrible to work with on many levels.
Converting Existing Permission Sets
If you already have permission sets that users have hand-crafted and curated over time, there’s a PowerShell tool available to convert them into AL objects. It’s located on the BCTech GitHub repository under the samples folder, in a project called Permission Set Conversion.
The module connects to a SQL Server database, extracts your current permission sets, and saves them as .permissionset.al files that you can then incorporate into your AL projects.
Using the Conversion Tool
First, you’ll need the SQL Server PowerShell module installed:
Install-Module SqlServer
Note: the required module is called SqlServer, not SQLPS — that would be too easy!
Then you can run the conversion:
Convert-PermissionSets -DatabaseServer localhost -DatabaseName W1 -Destination ".\NewPermissionSets"
How the Conversion Tool Works
The PowerShell module handles several key tasks:
- Downloads symbols from the “Published Application” table to resolve object IDs to names and types
- Queries permissions from both the
PermissionandTenant Permissiontables - Converts numeric permission masks to symbolic ones (e.g., permission value
1becomes uppercase for direct access,2becomes lowercase for indirect access) - Generates proper AL files with the
.permissionset.alextension
Here’s a look at the core of the permission mask conversion logic from the module:
function GetPermissionMask
{
param(
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
$Permission
)
$PermissionMask = ''
if ($Permission.'Read Permission' -eq 1)
{
$PermissionMask += 'R'
} elseif ($Permission.'Read Permission' -eq 2)
{
$PermissionMask += 'r'
}
if ($Permission.'Insert Permission' -eq 1)
{
$PermissionMask += 'I'
} elseif ($Permission.'Insert Permission' -eq 2)
{
$PermissionMask += 'i'
}
if ($Permission.'Modify Permission' -eq 1)
{
$PermissionMask += 'M'
} elseif ($Permission.'Modify Permission' -eq 2)
{
$PermissionMask += 'm'
}
if ($Permission.'Delete Permission' -eq 1)
{
$PermissionMask += 'D'
} elseif ($Permission.'Delete Permission' -eq 2)
{
$PermissionMask += 'd'
}
if ($Permission.'Execute Permission' -eq 1)
{
$PermissionMask += 'X'
} elseif ($Permission.'Execute Permission' -eq 2)
{
$PermissionMask += 'x'
}
return $PermissionMask
}
The generated AL files include the proper Access, Assignable, and Caption properties, making them ready to incorporate into your projects with minimal editing.
Summary
The new AL-based permission system in Business Central version 18 is a significant improvement:
- Permissions as code — defined in AL objects, versioned with your extension, and easy to manage
- Composable — use
IncludedPermissionSetsto build modular, maintainable permission structures - Public vs. Internal — control which permission sets are user-assignable and which are building blocks
- Extensible — use permission set extensions to add your objects to existing permission sets
- Backward compatible — the user experience in the client is virtually unchanged
- Migration path — the PowerShell conversion tool on BCTech helps you convert existing data-driven permission sets to AL objects
The result is something genuinely new and powerful that doesn’t break existing workflows — users can look at permissions with the same interface they’re used to, while developers finally have a proper, code-based way to define and ship permissions with their apps.