Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>mse AL Object ID ManagerNew to Visual Studio Code? Get it now.
mse AL Object ID Manager

mse AL Object ID Manager

mse-Business-Consulting

|
2 installs
| (0) | Free
Branch-aware AL object IDs with optional GitHub or shared Excel allocation registers.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

mse AL Object ID Manager

Manage numbered Microsoft Dynamics 365 Business Central AL objects across Git branches. By mse Business Consulting.

Find unused IDs, investigate conflicts and optionally coordinate reservations through your own private Git registry or shared Excel workbook. No publisher-hosted allocation service is required.

Features

  • Scan local branches and fetched remote-tracking branches without checkout.
  • Include saved tracked and untracked AL files and each app's ID ranges.
  • Show conflicts as warnings with branch names and navigation to pinned Git snapshots.
  • Find the lowest unused ID per object type within app.json and optional setup ranges.
  • Read customer license Object Assignment ranges from a text export in your private Git registry.
  • Scan table/tableextension fields, show field conflicts by branch, and find/reserve/release field IDs per underlying table.
  • Support different customer registers and setup in each workspace folder.
  • Import used objects into a shared register, preserving historical IDs.
  • Reserve IDs using Git fast-forward transactions or a shared-folder lock.
  • Release unused reservations with developer, timestamp and reason history.
  • Reuse immutable scan results and show progress during scanning and register operations.

Quick start

  1. Install the extension, open a trusted AL Git repository and save your editors.
  2. Open AL Object IDs in the activity bar.
  3. Run Fetch Remote Branches and Scan to refresh remote-tracking refs, or Scan All Branches to use locally cached refs.
  4. Run Find Next Free ID and choose the app and object type.

Standalone mode is the default when no shared register is configured. A suggested ID is not reserved. Two developers can receive the same suggestion until they coordinate through a shared register.

Requires VS Code 1.90 or newer and Git on the extension host. Normal use does not require a separate Node server.

Customer-specific workspace setup

Store customer-specific settings in that project's .vscode/settings.json. Folder settings in multi-root workspaces are resolved for the selected app. Remove customer-specific defaults from global User Settings if they could select the wrong register. AL IDs: Open Setup opens Workspace Settings JSON.

Optional multiple ranges per object type:

{
  "alIds.objectTypeRanges": {
    "table": [{ "from": 50010, "to": 50049 }],
    "codeunit": [{ "from": 50000, "to": 50049 }, { "from": 50100, "to": 50149 }],
    "page": [{ "from": 50100, "to": 50199 }]
  }
}

Use lowercase singular AL types. Type-specific ranges override general alIds.idRanges; omitted types fall back to the general ranges, then app.json. An explicit empty or invalid type list fails instead of broadening the search. Every result remains restricted by app.json. The numbers in this document are illustrative, not customer license entitlements.

Alternatively put .al-id-setup.json beside the selected app.json:

{
  "objects": {
    "table": [{ "from": 50010, "to": 50049 }],
    "codeunit": [{ "from": 50000, "to": 50099 }]
  }
}

File entries override matching type settings. alIds.setupFile accepts another relative/absolute path; an empty string disables file lookup. If the default .al-id-setup.json is missing, the legacy .al-id-license.json filename is accepted as a fallback. Legacy kind/customer/source/validUntil metadata is ignored. JSON setup ranges are configuration, not license evidence. Git schema 3 can read Object Assignment from a text export as described below; it does not decode license binaries or authenticate an export.

Additional related repositories may be listed in alIds.repositories. Include every relevant customer app. Different customer register targets are kept separate; do not deliberately add another customer's source repository to a customer's setup.

GitHub or Git registry

Use a private registry repository separate from normal AL development branches. One JSON file per customer is sufficient when access permissions are shared:

customers/customer/registry.json
customers/customer/license.txt
customers/another-customer/registry.json
customers/another-customer/license.txt

Create the branch/files yourself using examples/registry.json. Replace the Customer label and place the actual customer license text export beside the registry as license.txt. examples/license.txt is fictional demonstration data and must be replaced. Configure the actual URL, existing branch and customer file:

{
  "alIds.storageBackend": "github",
  "alIds.githubRepository": "https://github.com/your-organization/al-object-id-registry.git",
  "alIds.githubBranch": "master",
  "alIds.githubRegistryFile": "customers/customer/registry.json"
}

Both main and master are supported; choose the actual branch. All developers of one customer must use the same file. Related apps that must avoid ID collisions must share that file. Separate private repositories are appropriate when access permissions differ.

Authenticate command-line Git using your approved credential manager or SSH agent. Do not embed tokens in URLs. Configure Git user.name and user.email for commit attribution. Run Check GitHub Registry, then Import Scanned Objects to Register before allocating new IDs. Preserve any existing real reservations during migration; importing source alone cannot recover unpublished reservations from a different store.

Reserve Object ID creates and pushes an allocation metadata commit. Competing writers use ordinary fast-forward pushes; a rejected writer refetches and recalculates, with up to six attempts. No force-push or AL source checkout/commit/push occurs. Each operation uses an isolated temporary bare cache. An uncertain push is checked against stable operation keys; if it cannot be confirmed, the extension reports uncertainty rather than claiming success. There is no offline shared allocation fallback.

The selected branch must permit the intended ordinary metadata commits under your organization's policy. This implementation uses unsigned commit-tree commits; PR-only or signed-commit requirements may reject writes and are not bypassed. Protect registry history against unauthorized edits, deletions and force-pushes.

Registry sections:

Section Purpose
licenseFile Relative customer license text path, required by schema 3
objects Optional additional restrictions; explicit ranges for types absent from the license export
inventory Imported existing declarations and branch evidence
reservations Active and released claims with stable keys
operations Audit and push-confirmation history

Customer license text in the Git registry

In each private customer directory, commit license.txt beside registry.json. In the existing registry, change schemaVersion to 3 and add licenseFile. Preserve customer, reservations, inventory and operations:

{
  "schemaVersion": 3,
  "customer": "Customer",
  "licenseFile": "license.txt",
  "objects": {
    "tableextension": [{ "from": 5000, "to": 99999 }],
    "pageextension": [{ "from": 5000, "to": 99999 }]
  },
  "reservations": [],
  "inventory": [],
  "operations": []
}

The empty lists above are for a NEW register only. Never replace existing history with them. All developers must install version 2.1.0 or newer before switching to schema 3. Older clients reject this schema instead of ignoring the license policy. Legacy schemas 1/2 remain JSON-only; merely adding a text file to a legacy register does not enable license checks.

licenseFile is resolved relative to registry.json, on the same branch and exact fetched commit. It must be a .txt path inside that customer directory, without parent traversal. Normal Git authentication is sufficient; there is no extra server or token setting. License text support applies to the Git backend; standalone and Excel retain their existing setup behavior.

Only the single Object Assignment section is read. Earlier and later Module Objects and Permissions sections are ignored. The parser accepts whitespace including pasted non-breaking spaces, CRLF/LF and UTF-8 BOM; the export must be UTF-8 text. Rows must contain type, numeric quantity, from, to and RIMDX permission letters. Quantity must match the inclusive range. TableData maps to table; multiple ranges per type are retained. Unknown or malformed assignment rows, missing/duplicate/empty sections and unreadable files block the registry operation with a clear error. No fallback to copied JSON ranges occurs in schema 3.

For table, page, report, codeunit, xmlport and query, a missing assignment row blocks allocation. For other AL types absent from the export, supply explicit per-type ranges in registry.objects or the selected app's objectTypeRanges/setup file. These are identified as configured ranges, never Object Assignment evidence. The sample tableextension/pageextension ranges 5000–99999 are configuration only. All results still intersect app.json and local setup restrictions, and exclude scanned declarations, active reservations and retained imported inventory. Existing objects entries for assigned types may be kept as extra restrictions, or removed to rely on the text ranges alone. objects may be empty in schema 3.

Run Check GitHub Registry to validate the export and populate Customer license checks in the dashboard. It shows the file, SHA-256, parsed ranges/permissions and configured types. It warns about active reservations, imported inventory and already-scanned source occurrences outside Object Assignment; records remain intact. Source validation covers the latest completed local scan, not unscanned repositories. The dashboard labels the checked commit and must be refreshed after changes; allocation itself always fetches fresh registry/license data. At most 200 out-of-range occurrences are displayed; the total is shown.

To update a license, replace the same license.txt with the new export, review the Object Assignment changes, then commit and push using your normal review process. No registry reset or re-import is needed. New allocations use the new ranges; removed ranges block future allocations while existing records remain visible for review. A concurrent registry or license update rejects a stale allocation push and forces recomputation. New reservations retain the source file, full-text SHA-256 and source commit, with an evidence kind distinguishing Object Assignment from configured ranges. The hash traces the supplied text; it does not establish authenticity, customer identity or license currency. Permission letters are displayed as evidence and do not establish deployment-specific access rights.

Field IDs for tables and table extensions

Use Find and Reserve Next Field ID, Reserve Field ID, Release Reserved Field ID, and Import Scanned Fields to Git Registry in the activity-bar dashboard or Command Palette. Choose the app and the saved table/tableextension declaration. Save editors and refresh AL remotes before an availability check. The parser scans fields on every local and fetched remote branch plus saved working files; page controls, modify clauses, comments, strings and trigger code are excluded. A malformed table/field body blocks field commands until corrected, without disabling ordinary object lookup.

Field IDs are scoped to the underlying table. A base table and all its table extensions share the same field ID space; the same field number on another table is independent. Conflicts appear as warnings (ALID003), with branch names and navigation to source or pinned snapshots in Field conflicts. Unchanged declarations repeated across branches do not create a warning. Ambiguous source table names block lookup; use qualified names/include the correct source or symbols. Unresolved external names are conservatively grouped by their simple name in source conflict warnings, which can over-report names shared across namespaces.

Tableextension fields use the selected app.json idRanges. Fields declared directly in a custom table also allow the low range 1–49999, so a table with fields 1 and 2 can suggest 3. Optional field restrictions are independent of object ranges and Object Assignment. See Microsoft's field-ID guidance. The helper checks numbering/inventory, not deployment-specific field licensing or AppSource certification.

Configure field lookup per customer workspace, for example:

{
  "alIds.fieldIdRanges": {
    "table": [{ "from": 1, "to": 99999 }],
    "tableextension": [{ "from": 50000, "to": 99999 }]
  },
  "alIds.fieldSymbolFiles": [
    ".alpackages/your-downloaded-base-application.app",
    "symbols/related-extension-SymbolReference.json"
  ]
}

Both settings are optional. An empty fieldIdRanges uses the defaults above. A typed fieldIdRanges map selects table or tableextension ranges for the declaring object; a legacy array restricts both types. Empty type ranges, unknown keys and a missing entry for the selected type fail instead of broadening the search. Configure real paths; example filenames are placeholders. fieldSymbolFiles accepts downloaded ZIP-readable .app packages containing SymbolReference.json, or exported UTF-8 symbol JSON with Tables/TableExtensions metadata. Paths are relative to the selected app.json directory or absolute. Files are read afresh for each field command; malformed, inaccessible, encrypted or unsupported packages block the operation. No automatic package download, extraction to the customer project, or upload of package binaries occurs.

A base table must be identified from scanned source or configured symbols before lookup/reservation. For a standard table such as Customer, supply current base-application symbols and the symbols/source of every related extension that adds fields. Include related customer repositories using alIds.repositories. An identified base table is not proof that all installed extensions are covered: missing, stale or unpublished dependency fields cannot be detected automatically. Results are explicitly limited to the scanned source, supplied symbols and selected registry. The source conflict dashboard covers AL source; configured symbols supplement command lookup/import/release checks, not navigable AL source diagnostics.

Starting with 2.4.0, Find and Reserve Next Field ID (command ID alIds.nextField) immediately reserves the next available field ID in the Git registry after app/table selection. It makes one atomic reserve request, not a preview followed by a separate reservation. The success notification contains only Next available field ID : , using the confirmed reserved ID. A failed or uncertain push produces an error, not a success notification.

Automatic claims record the current developer, branch, declaring table/extension and a label Pending field in , with an empty task reference. No field name or task prompt is required. Use Reserve Field ID when a known field name and task should be recorded. Both flows keep normal owner/usage/release protections; each successful click reserves another ID. Cancelling app/table selection creates no claim. The command does not insert or modify AL code.

The next-field command now requires the Git backend; it does not silently return an unreserved number in standalone or Excel mode. Ordinary object-ID lookup remains available in standalone mode, and the Excel workbook format remains for object IDs. The first successful field write upgrades the existing registry to schema 4, preserving objects, licenseFile, inventory, reservations and operations, and adding separate fieldReservations/fieldInventory arrays. All developers must install 2.2.0 or newer before any field write. Older clients reject schema 4 rather than ignoring field reservations. Existing schemas 1–3 remain readable; do not reset or replace the register to enable fields.

Git field writes use the same fresh snapshot, fast-forward push and concurrency retry as object reservations. Optional registry.fieldRanges supplies shared restrictions, intersected with the selected app's field rules and local fieldIdRanges. Version 2.3.0 adds this top-level format (beside objects, never inside it):

"fieldRanges": {
  "table": [{ "from": 1, "to": 99999 }],
  "tableextension": [{ "from": 50000, "to": 99999 }]
}

Use version 2.3.0 or newer on every developer machine when using this typed format. Older clients reject this configuration instead of ignoring its restrictions. A legacy shared array remains supported, for example fieldRanges: [{from:50000,to:99999}]. The existing schema number and history do not need resetting; a first field write still upgrades to schema 4 automatically. If a local shared fieldIdRanges array starts at 50000, it still restricts table fields: remove it or change it to the same typed map to allow low table-field IDs. The allowed table range is still limited to low IDs 1–49999 plus app.json ranges, while extensions always stay within app.json. All fields on the same underlying table remain mutually exclusive, regardless of which declaring-type range selected them. Unlike table object IDs, field numbers are not restricted by the license's TableData object ID ranges. License-backed registries still require a readable valid license export when loading the snapshot.

Import Scanned Fields to Git Registry imports the selected customer's scanned fields and configured symbol fields (across all tables, not just the chosen table). Repeated imports merge branch evidence; retained imported IDs remain used after source deletion. Import only the intended customer/dependencies. Reservations record the base table, declaring table/extension, field name, developer, task, branch and timestamp. Field ID 50000 on Customer does not occupy 50000 on Vendor.

Release chooses the developer's reservation on the selected table, requires a reason, fetches configured AL remotes and performs another field selection/scan. Select the same customer and target table to finish. A field found in source, symbols, imported history or another active claim cannot be released. Releases retain actor/date/reason; a new reservation receives a new key so stale release requests cannot free it. Git permissions are the authorization boundary; developer labels are not authenticated identities.

Remove imported field metadata

Run AL IDs: Remove Imported Field Metadata from the Command Palette or dashboard. Choose the customer workspace if more than one is open. The extension fetches that customer's Git register, shows the imported-record count, asks for a reason, and requires an explicit confirmation identifying the repository, branch and registry file. No AL scan or base-table selection is required just to remove imported metadata.

This command empties only fieldInventory for the selected customer. It preserves fieldReservations (active and released), object inventory/reservations, ranges, the license reference and earlier operation history. Future availability/release checks still use current source, supplied symbols and central reservations. A historical field absent from all of those checks can become available again. This does not disable Import Scanned Fields: importing later can repopulate the inventory.

The confirmed inventory is fingerprinted. A concurrent import or refresh changes that fingerprint and blocks removal until you review again; unrelated reservation commits can be preserved during a retry. The cleanup is committed through the existing fast-forward transaction and records developer label, timestamp, reason, count and inventory fingerprint in operations. Failed/unconfirmed writes do not report success. Empty registers and cancelled dialogs create no cleanup commit.

Everyone using a register after this cleanup must install 2.5.0 or newer: the new clearFieldInventory audit operation is rejected by older clients. The schema stays unchanged; do not replace the registry or delete its history to enable the command. Previous imported content remains in normal Git history for review/recovery, and this feature does not rewrite or erase old commits. Git write access remains the authorization boundary.

Shared Excel registry

Copy examples/AL-ID-Allocation.xlsx to one consistent SMB share and configure:

{
  "alIds.storageBackend": "excel",
  "alIds.sharedWorkbook": "\\\\file-server\\share\\ObjectAllocation\\AL-ID-Allocation.xlsx"
}

Every developer needs folder Modify permission and the identical UNC path. Keep the workbook closed during writes. If VS Code blocks the UNC hostname, add that specific hostname to security.allowedUNCHosts in User Settings; Windows permissions still apply. A remote extension host must itself be able to access the path.

The Ranges sheet is shared setup. The original Allocations sheet can hold manual rows; delete the clearly labeled sample entries before real use. The extension writes Shared allocations and Git inventory separately. Keep required headers and keys unchanged. Task references accept your team's work-item format; legacy workbook task headings remain readable.

A .al-id-manager directory beside the workbook stores authoritative immutable claim files, release events, locks and workbook backups. Do not delete it. Cooperating clients use exclusive directory creation and exclusive claim writes. Locks are never automatically stolen; an administrator must confirm no operation is active before removing an abandoned allocation.lock directory. Never delete reservation files to clear a lock.

If Excel publication fails, a confirmed claim/release remains in the durable files. Close Excel and run Sync Shared Excel. Stable keys prevent duplicate report rows. Back up the workbook and complete state directory together and manage backup retention. Use one consistent SMB backing directory; OneDrive replicas, Offline Files and divergent copies are not a coordination backend. Validate real two-machine SMB behavior before operational rollout.

Import existing objects

Refresh source remotes, close Excel if applicable, then run Import Scanned Objects to Register. A fresh complete scan is required. In a multi-customer workspace select the intended register target. Imports consolidate repeated declarations, add new ones and retain historical IDs and branch evidence. Imported IDs remain occupied even if absent from a later scan. No allocating developer/task/date is invented for existing source objects.

Release unused reservations

Run Release Reserved ID, choose your reservation and enter a reason. The extension refreshes configured source remotes, rescans and checks the latest register. It blocks release if the ID exists in scanned source, imported history, a Used allocation or another occupied entry. Save editors first. Failed fetches and incomplete scans block release.

Release is limited to the recorded developer label. Names are audit labels, not authenticated identities: Git/share permissions remain the authorization boundary. No administrator bypass or automatic expiry is provided. A released number gets a new key when reserved again; an old release request cannot free that newer claim. Audit history records actor, timestamp and reason. Releasing a claim does not delete AL source objects or historical inventory.

Shared Git schema 2 and Excel format 2 support release history. Everyone sharing a release-capable register must use a compatible version. Older Git schema 1 and legacy shared claim filenames are read and upgraded by successful writes; never downgrade the format or remove its guard to accommodate an old client.

Settings overview

Setting Default / meaning
alIds.storageBackend auto; chooses the single configured register, or standalone
alIds.githubRepository Git repository URL; empty by default
alIds.githubBranch main; set to the existing branch
alIds.githubRegistryFile al-id-registry.json; set your customer path
alIds.sharedWorkbook Absolute .xlsx path; empty by default
alIds.setupFile .al-id-setup.json, with legacy filename fallback
alIds.objectTypeRanges Optional per-type overrides
alIds.idRanges Optional general lookup ranges
alIds.repositories Additional related local repositories
alIds.fieldIdRanges Optional field ranges, separate from object ranges
alIds.fieldSymbolFiles Explicit .app or symbol JSON files for field checks

All AL IDs settings support workspace/folder scope. If both Git and Excel are configured, choose the backend explicitly; they are not automatically synchronized.

Scope and limits

The scanner covers numbered AL objects and table/tableextension field declarations. Named-only objects remain outside object inventory. Configured symbol packages supplement field commands only; they are not automatically discovered or used for object-ID scanning. Both sides of conditional compilation are conservatively included. Only fetched remote-tracking branches and saved local files are visible; other developers' unpublished work and repositories you have not included remain unknown. Renames can produce conservative conflict warnings.

The first scan builds bounded in-memory caches; repeated scans reuse immutable commit snapshots and content hashes while rereading current ref tips and saved AL/app.json files. Shared register checks remain live. Network latency, cold scans, changed branches and Excel serialization still take time. Progress notifications show the current phase.

Upgrading from internal builds

The current extension ID is mse-Business-Consulting.mse-al-object-id-manager. Uninstall earlier internal copies al-object-tools.al-object-id-manager, mse-business-consulting.al-object-id-manager and mseBusinessConsulting.al-object-id-manager before installing this build to avoid duplicate commands. Existing alIds settings and external registers are retained. Do not overwrite a real registry with an empty example or rename a shared store during active allocations. Review the publishing/migration checklist in the source release.

Development and license

Run node --test test/*.test.js with a current Node installation. The source includes generic test fixtures. The installable VSIX excludes development tests and authoring scripts. Packaging uses the official @vscode/vsce tool. No customer repository is required to run the tests.

Copyright 2026 mse Business Consulting. MIT license. Bundled ExcelJS and JSZip licenses and integrity provenance are included under vendor. See PRIVACY.md for the data-handling statement.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft