--- title: "Registry Specifications" order: 4 ---

A Universal Package Registry consists of two components: a registry file and an ephemeral lock file. A package cache can also be added, but it's optional. The structure on disk is as follows:

`‹registry-root›\ .lock installedPackages.json packageCache\ ‹group$packageName›\ ‹packageName.version›.upack`

As with universal packages, you can add any number of files or directories outside of these minimum requirements. However, we strongly recommend that you prefix these files and folders with an underscore (_) to avoid overlap with files or folders that are added in a future version of the specification.

## Interacting with a Universal Package Registry and the Lock File

The lack of a registry root directory or installedPackages.json file is not an error condition, but implies that no packages are registered (i.e. have been installed). An invalid `installedPackages.json` file (i.e. not readable as JSON or invalid data) is an error condition and should not be automatically remediated.

The .lock file is used to indicate that another process is currently interacting with the registry. It should only be used when atomically reading/writing the metadata file; changing the package cache should not cause the repository to be locked.

If a .lock file exists, its modification date should be checked against the current system time. If the difference is more than ten seconds, the other process is assumed to have crashed, and the lock file should be deleted. Otherwise, the file should be checked again in this way until the lock is removed.

If no .lock file exists, a process should create a lock file with two lines (\r or \r\n): a human-readable description of the lock (generally the process name) and a lock token (generally a GUID). If, when the operation is complete, the lock token matches, the file should be deleted.

No operation should take longer than one second (let alone ten), and the user should be notified of any exceptions (locked registry, unmatched token).

## Installed Packages JSON Format

The registry file (installedPackages.json) is a JSON-based array of objects with the following properties:

Property | Format
--- | ---
`group` | see package metadata specs
`name`R | see package metadata specs
`version`R | see package metadata specs
`path` | A string of the absolute path on disk where the package was installed to
`feedUrl` | A string of an absolute URL of the universal feed where the package was installed from
`installationDate` | A string representing the UTC date when the package was installed, in ISO 8601 format (yyyy-MM-ddThh:mm:ss)
`installationReason` | A string describing the reason or purpose of the installation For example, BuildMaster uses `{Application Name}` `v{Release Number}` `#{Package Number}` `(ID{Execution-Number})`
`installationUsing` | A string describing the mechanism the package was installed with; there are no format restrictions, but we recommend treating it like a User Agent string and including the tool name and version For example, BuildMaster uses `BuildMaster/5.6.11`
`installationBy` | A string describing the person or service that performed the installation For example, BuildMaster uses the user who triggered the deployment or SYSTEM if it was a triggered/scheduled deployment

An `R` denotes a required property, and the object may contain additional properties as needed.

We strongly recommended that you prefix these properties with an underscore (_) so as to not clash with property names that may be added to the specification later.

## Package Uniqueness and Data Constraints

Only one version of a package can be registered at a time. Uniqueness is determined by a combination of the group (or lack thereof) and the package name. A future version of this specification may allow multiple versions of a package, but that will be an "opt-in" setting, likely defined in a (yet to be specified) registry configuration file.

## Package Cache

The package cache is simply a directory containing package files that may currently be installed. It must be named `packageCache`, and contain package files (`packageName.version.upack`) stored in subdirectories comprised of the group name (with $ replacing the /), a $, and the package name. For example:

`‹registry-root›\ packageCache\ $hdars\ hdars.1.2.3.upack hdars.1.2.4.upack hdars.2.0.0.upack accounting$apps$accounts\ accounts.1.0.2-beta.upack`

We strongly recommend that the use of caching be explicitly enabled (both when downloading and installing packages). Caching packages by default generally causes more problems than it helps, and can take up a lot of memory if not monitored.