AgentStack
SKILL verified MIT Self-run

Controlling Al Access

skill-emgreppi-business-central-ai-skill-controlling-al-access · by emgreppi

Controls visibility of AL objects and fields using Access property (Public, Internal, Protected, Local), hides internal helpers from external apps, exposes public API surfaces, and configures internalsVisibleTo for multi-app scenarios. Use when making codeunits private, hiding staging tables, protecting fields from partners, or sharing internals between companion apps.

No reviews yet
0 installs
10 views
0.0% view→install

Install

$ agentstack add skill-emgreppi-business-central-ai-skill-controlling-al-access

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Controlling Al Access? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Skill: AL Access Modifiers

Validation Gates

  1. After Step 1: Internal objects compile, external apps get "not accessible" compile error
  2. After Step 2: Field access levels work (test: Local field inaccessible outside table)
  3. Final: internalsVisibleTo apps can access internal objects

Note: BC 2019 Wave 2+ (Runtime 4.0). Compile-time only - RecordRef/FieldRef bypass at runtime.

Output: Objects with correct Access property, app.json with internalsVisibleTo (if multi-app).

Supported objects: Codeunit, Table, Table field, Query, Enum, Interface, PermissionSet

Procedure

Step 1: Set Object Access

// Internal table - hidden from external apps
table  " Internal Staging"
{
    Access = Internal;
    // ... fields
}

// Internal codeunit - helper not exposed to partners
codeunit  " Internal Helper"
{
    Access = Internal;
    // ... procedures
}

Step 2: Set Field Access

table  " Order Extension"
{
    Access = Public;
    fields
    {
        field(1; "Order No."; Code[20]) { Access = Public; }      // Stable API
        field(2; "Processing Flags"; Integer) { Access = Internal; } // Same app only
        field(3; "Extension Point"; Code[50]) { Access = Protected; } // Table extensions
        field(4; "Internal Counter"; Integer) { Access = Local; }    // This table only
    }
}

Access Level Summary

| Level | Same Table | Table Extension | Same App | Other Apps | |-------------|------------|-----------------|----------|------------| | Local | ✓ | | | | | Protected | ✓ | ✓ | | | | Internal | ✓ | ✓ | ✓ | | | Public | ✓ | ✓ | ✓ | ✓ |

Designer note: Only Public fields appear in in-client Designer.

Step 3: Configure internalsVisibleTo (Multi-App)

In app.json of the core app:

{
    "internalsVisibleTo": [
        { "id": "", "name": "Companion App", "publisher": "My Publisher" },
        { "id": "", "name": "Test App", "publisher": "My Publisher" }
    ]
}

Use cases: Core + Companion apps, Test apps accessing internals, Modular architecture.

Important Notes

⚠️ NOT a security boundary: Access is compile-time only. RecordRef/FieldRef bypass at runtime. Use permission sets for data security.

Design Patterns

Public API + Internal Implementation

codeunit  " Public API"
{
    Access = Public;
    procedure ProcessOperation(InputData: Text): Boolean
    begin
        exit(InternalProcessor.DoProcess(InputData));
    end;
    var
        InternalProcessor: Codeunit " Internal Processor";
}

codeunit  " Internal Processor"
{
    Access = Internal;
    procedure DoProcess(InputData: Text): Boolean
    begin
        // Can be refactored freely - not exposed
    end;
}

Secret Management

codeunit  " Secret Manager"
{
    Access = Internal;
    [NonDebuggable]
    procedure GetClientSecret(): Text
    begin
        // Use IsolatedStorage with DataScope::Module
    end;
}

Quick Reference

| Scenario | Recommended Access | |----------|-------------------| | Stable API for partners | Public | | Helper codeunits | Internal | | Staging/buffer tables | Internal | | Fields for table extensions | Protected | | Fields in table triggers only | Local | | Secret management | Internal + [NonDebuggable] |

Guidelines: Default to Internal • Public = supported contract • Changing Public → Internal is breaking

Limitations: Cannot set on Pages, Reports, XMLports, Control add-ins.

External Documentation

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.