aontu

Packages reference

Rendered from docs/reference-packages.md in the engine repository, where a correction belongs, and where the test suite executes every example on this page.

A module is a document another document imports. A package is a module that was published: a tree of aontu source with a path, a version, a signed manifest, and an archive whose bytes one digest names. The language reference states how an import routes to one; this page states what the package system keeps on disk while it does so.

This page is normative for the artefacts: the files the package system reads and writes, every field pkg.aon declares, the name and version rules, the caps every consumer applies, what an archive may hold, and every code a package operation refuses with. It states no verb’s options and no verb’s exit codes.

The verbs are the API reference: aontu sync for the one that makes a project correct, aontu add, aontu get, aontu remove for changing what a project depends on, aontu publish for sending one out, and aontu pkg for the remaining steps. Modules in the language reference states how a reference routes, and tutorial-package.md walks the whole path once with a real package.

Contents


The files

Everything the package system keeps in a project is a file in it, and every one of those is ordinary text: nothing is hidden in a database, and nothing outside this table is consulted. The two stores outside a project are not text alone. The user cache and a repository directory hold the archives themselves, which are zips, beside the manifest and proof that travel with them.

pathwritten byread bycommit it
pkg.aonthe author, and add, get, remove by the smallest text changeevery package verb, and module resolutionyes
aontu_meta/pkg-lock.aonsync, pkg tidy, pkg refreezesync --frozen, pkg verify, pkg tree, why, and resolution for a pinned importyes
aontu_meta/vendor/<package-path>/sync, pkg vendorresolution, first of the storesyes
aontu_meta/vendor/<package-path>/aontu_meta/sync, holding the manifest and proof as servedpkg verifyyes
the user cachesync, add, getresolution, when the expected canon-hash is knownit is outside the project
a repository directorypublish --to <dir>pkg serve, and any consumer whose repo.base names itit is not part of a project
the signing keypkg keygen, oncepublish --keynever

A project that has been synced evaluates from its own directory with no cache and no network, because the vendor tree is a real copy rather than a link. The lockfile and the vendor tree are written together and belong in one commit: a lockfile without the tree it pins names bytes the project does not have.

What pkg.aon declares

pkg.aon is an ordinary aontu document, evaluated as any other. The tools read the fields below and nothing else, so a field of the author’s own is carried rather than refused.

fieldvaluedefaultread by
pkg.paththis package’s pathnoneresolution, publish, why
pkg.versionthis package’s own versionnonepublish, pkg manifest
pkg.mainthe entry document, a path inside the treemain.aonresolution, publish
dep."<path>".vthe minimum version of a dependencynonesync, and every verb that resolves
dep."alias:<name>".pkgthe package an alias namesnoneresolution of an alias: import
dep."alias:<name>".vthe minimum version taken under that aliasnonesync
publishpublic, to allow publication at allprivatepublish
movedthe package path that replaces this oneabsentresolution, publish
retractversions withdrawn, as a list of stringsemptypublish --to, which derives the advisory
repo.baserepositories to read from, in ordernoneevery verb that fetches
repo.writethe write path a publish sends tononepublish
repo.privatepatterns never sent to a public basenoneevery verb that fetches
repo.private_baserepositories for a name on the private listnoneevery verb that fetches
repo.trust."<pattern>".signerforge, or ed25519: and a public keythe entry for *, which names the forge signeracquisition
repo.trust."<pattern>".inclusionnone, to accept a key proof that carries no log inclusioninclusion is requiredacquisition

A consuming project declares what it depends on, and where those packages are read from:

pkg: { path:"corp.example/checkout" main:"main.aon" }

dep: "corp.example/schemas/service": v: "1.4.2"
dep: "alias:legacy": { pkg:"corp.example/schemas/service" v:"1.2.0" }

repo: base: ["https://pkg.aontu.dev"]
repo: private: ["corp.example/*"]
repo: private_base: ["https://pkg.corp.example"]
repo: trust: "corp.example/*": { signer:"ed25519:q520" inclusion:none }

A package that is published declares its own version and says so out loud, and the last version of a path that has been superseded points at its replacement:

pkg: { path:"corp.example/schemas/service" version:"1.4.2" main:"service.aon" }
publish: public
retract: ["1.4.1"]
moved: "corp.example/schemas/service2"

Both fields are shown together above for the field’s sake. A package declares moved when its path is finished, and a path that is finished gains no further versions.

Names and versions

A package path is a domain-shaped path: the first element contains a dot, and no element is a major version, because compatibility is computed when a package is published rather than declared in its name. A path that routes to a package becomes a directory on every platform the toolchain runs on, so the shape is bounded before anything is built from it.

  • At most 512 characters, and at most 32 elements.
  • No element is empty, and none begins or ends with ..
  • The part of an element before its first . is not a reserved device name. The set, matched without regard to case: con, prn, aux, nul, com1 to com9, and lpt1 to lpt9.
  • An uppercase letter is written as ! and its lowercase form in every store, so two paths differing only in case stay two identities on a filesystem that would fold them into one.

A version is three parts separated by ., each either 0 or a digit string with no leading zero. That is what a publish mints and what a manifest carries. The comparator reads a part a version omits as 0, so 1.2 and 1.2.0 are one version to it, and a lockfile rewritten from either says the same thing.

An alias key is alias: followed by the name the imports use. A local import carries ./, ../ or /; a bare relative path whose last segment has an extension the include table knows is refused with module_local rather than read as a package.

Where a module resolves from

Resolution reads local stores only, in this order, and stops at the first that holds the module:

  1. aontu_meta/vendor/ of the project whose directory holds pkg.aon.
  2. aontu_meta/vendor/ of each project enclosing that one, outward, so a vendored module resolves its own dependencies from the tree that vendored it.
  3. The user cache, which is keyed by canon-hash and so is consulted only where the expected hash is already known.

The cache directory is the first of these that applies:

conditiondirectory
XDG_CACHE_HOME is set$XDG_CACHE_HOME/aontu/pkg
HOME is set$HOME/.cache/aontu/pkg
Windows, and LOCALAPPDATA is set%LOCALAPPDATA%\aontu\pkg
none of thosethere is no cache, and the vendor tree is the only store

The caps

Every cap is a fixed number, the same in both implementations, and each is refused by name so a report says which one was reached.

capvaluerefused as
a module path, in characters512module_path
elements in a module path32module_path
dependency nesting, in levels16module_depth
packages in one closure1024closure_too_large
an archive, compressed16777216 bytesarchive_too_large
an archive, extracted67108864 bytesarchive_bomb
files in an archive4096archive_too_many_files
one file in an archive8388608 bytesarchive_bomb

The four archive caps are applied twice. A consumer applies them while acquiring, before a byte of the archive is parsed. A publish applies the same four before anything is minted, so a package that every consumer would refuse never leaves the machine; there the reasons are reported as what stopped the mint rather than as a refusal code.

What an archive may hold

The archive of a package holds source and the text that travels with it. The list is enumerated and refused by default, so a new extension is admitted by a change to the engine and never by a package.

groupadmitted
aontu sourceaon, aontu
data the include table readsjson, jsonld, jsonc, json5, jsonic, jsc, toml, yaml, yml, ini
textmd, txt
by name, with no extensionLICENSE, NOTICE

No path element may begin with ., and nothing under aontu_meta/ is sent: a lockfile and a vendor tree are the consuming project’s, and a package that carried them would ship one project’s resolution to another. Anything else in the tree is refused with archive_entry_forbidden, which names the file.

Refusals

A package operation refuses with a code, a message, and the package it was about. There are thirty codes.

Six of them are also engine codes, raised while a document is evaluated, and those six are in the registry with a class and a registered-at version: see the codes for module_path, module_local, module_missing, module_moved, module_integrity and module_depth. The other twenty-four name a refusal by a verb. They are not findings, carry no class, and arrive under refusal in a verb’s --format json report.

The step each code is raised at: resolution reads the local stores while a document is evaluated; configuration reads repo and the signing key; acquisition reads a repository, in the order version list, manifest, proof, archive; publication mints and sends.

coderaised atwhat it means
archive_bombacquisitiona file, or the running total, is over the size cap once extracted
archive_digest_mismatchacquisitionthe archive’s digest is not the one the manifest declares
archive_entry_forbiddenacquisitionthe archive carries a file the allowlist does not admit
archive_not_canonicalacquisitionthe zip is not in the canonical form one tree has one digest under
archive_path_invalidacquisitiona path in the archive breaks the element rules
archive_too_largeacquisitionthe archive is over the compressed cap
archive_too_many_filesacquisitionthe archive is over the file-count cap
base_not_httpsconfigurationa repository base is neither https nor http on a loopback host
closure_too_largeacquisitionthe closure is over the package cap
config_invalidconfigurationa repo.trust entry is not a pattern, or names no signer
fetch_failedacquisitionno repository answered, or answered with a status, for a list, manifest or archive
file_manifest_mismatchacquisitionthe archive holds a file the manifest does not list, or lacks one it does
inclusion_missingacquisitionthe trust entry requires log inclusion, which a key proof does not carry
key_invalidconfigurationthe key file is not a PEM private key, or is not Ed25519
list_rollbackacquisitiona version seen before is absent from the list now served
manifest_invalidacquisitionthe manifest is malformed, names another package or version, or declares a dependency without the package it names
module_depthresolution, acquisitiondependency nesting is past the level cap
module_integrityresolution, acquisitionthe module’s meaning is not the canon-hash that was pinned
module_localresolutiona local file was written without a ./ prefix
module_missingresolutionno store holds the module, or an alias is not declared
module_movedresolution, acquisitionthe package declares moved, and nothing follows a move
module_pathresolutionthe path breaks a name rule or a length cap
not_publicpublicationthe package does not declare publish: public
path_movedpublicationthe path is frozen by a moved declaration
private_name_public_pathconfigurationthe name is on the private list and repo.private_base names no repository
proof_missingacquisitionno proof is served for the version
proof_signer_untrustedacquisitionthe proof’s signer is not the one the trust entry accepts for that name
response_mismatchacquisitiona served document is malformed, or names something other than what was asked for
tombstonedacquisitionthe version was withdrawn by the repository
version_existspublicationthe version was published before, and a version is never reusable
  • aontu sync for the verb that makes a project correct, its report, and the order the checks run in.
  • aontu publish for what a publish sends, the compatibility gate, and the proof.
  • aontu pkg for the individual operations, including verify, vendor, tree and serve.
  • Modules in the language reference for how a reference routes to a package, a file or an alias.
  • The codes in the errors reference for the six codes that are also engine codes, with their classes.
  • Vendor a dependency closure and publish a package for the two jobs in recipe form.