# Controlling Al Access

> 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.

- **Type:** Skill
- **Install:** `agentstack add skill-emgreppi-business-central-ai-skill-controlling-al-access`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [emgreppi](https://agentstack.voostack.com/s/emgreppi)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [emgreppi](https://github.com/emgreppi)
- **Source:** https://github.com/emgreppi/Business-Central-AI-Skill/tree/main/controlling-al-access

## Install

```sh
agentstack add skill-emgreppi-business-central-ai-skill-controlling-al-access
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## 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

```al
// 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

```al
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:

```json
{
    "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

```al
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

```al
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

- [Access Property](https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/developer/properties/devenv-access-property)
- [Access Modifiers](https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/developer/devenv-using-access-modifiers)
- [internalsVisibleTo](https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/developer/devenv-json-files#appjson-file)

## Source & license

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

- **Author:** [emgreppi](https://github.com/emgreppi)
- **Source:** [emgreppi/Business-Central-AI-Skill](https://github.com/emgreppi/Business-Central-AI-Skill)
- **License:** MIT

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

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-emgreppi-business-central-ai-skill-controlling-al-access
- Seller: https://agentstack.voostack.com/s/emgreppi
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
