Unused permission declared
The Permissions property declares which table data operations the object performs. When an entry references a table the object never accesses, or grants broader access than the code requires, the extra declarations mislead anyone auditing the object: a reviewer reading Permissions = tabledata "G/L Entry" = rimd trusts that the object modifies and deletes general ledger entries, when in fact it only reads them. Remove unused entries and reduce overly broad chars to match actual usage.
This rule is the inverse of AC0031 . Where AC0031 detects missing permissions, AC0032 detects permissions that are declared but not backed by any code.
Example
Entire entry unused. When a Permissions entry references a table that no code in the object accesses at all:
codeunit 50100 "Post Sales Invoice"
{
Permissions = tabledata "Sales Header" = rimd; // Unused permission declared [AC0032]
procedure Post()
begin
// No code accesses "Sales Header"
end;
}Remove the unused entry:
codeunit 50100 "Post Sales Invoice"
{
procedure Post()
begin
end;
}Partial chars unused. When the declared permission chars exceed what the code actually needs:
codeunit 50100 "Post Sales Invoice"
{
Permissions = tabledata "Sales Header" = rimd; // Unused permission declared [AC0032]
procedure Post()
var
SalesHeader: Record "Sales Header";
begin
SalesHeader.FindFirst();
end;
}Reduce the permission to match actual usage:
codeunit 50100 "Post Sales Invoice"
{
Permissions = tabledata "Sales Header" = r;
procedure Post()
var
SalesHeader: Record "Sales Header";
begin
SalesHeader.FindFirst();
end;
}Code fix
The ALCops: Remove unused permission code fix handles both variants:
- Entire entry unused: removes the entry from the list. If it is the last entry, the entire
Permissionsproperty is removed. - Partial chars unused: reduces the permission string to only the chars that are actually used, in canonical
rimdorder.
Exception
The diagnostic is suppressed when any of the following conditions apply:
- The target table is a system table (ID > 2,000,000,000)
- The containing symbol is obsolete
- The codeunit is a test codeunit with
TestPermissions = Disabled - The containing object is a
permissionsetorpermissionsetextension(these declare permissions structurally, not for access control)
Temporary tables
Access through a temporary table does not count as using a permission. Temporary tables never touch the database, so a Permissions entry for a table that is accessed only through temporary records is dead code and is reported as unused. This applies to every way a temporary table can be implemented: the temporary keyword on a record variable, a table object with TableType = Temporary, a page with SourceTableTemporary = true, and report data items or XMLPort table elements with UseTemporary = true.
Temporary tables don’t require the user to have permissions on the underlying table. Because temporary table data is held only in memory and never read from or written to the database, the permission system doesn’t apply. […] This behavior applies regardless of how the temporary table is implemented—whether by using the
TableTypeproperty, a temporary record variable, or theSourceTableTemporaryproperty on a page.
— Temporary tables on Microsoft Learn
See also
- Permissions on database objects on Microsoft Learn