Config
NAME
App::Ariza::Config - the per-app ariza.toml manifest
SYNOPSIS
use App::Ariza::Config;
my $cfg = App::Ariza::Config.load('/path/to/App-Moneymoor'.IO);
say $cfg.app-name; # App::Moneymoor
say $cfg.app-exec; # moneymoor
say $cfg.app-display; # Moneymoor
say $cfg.bundle-platforms; # (macos-arm64 linux-x86_64-glibc windows-x86_64)
say $cfg.bundle-native; # (notcurses sqlcipher)
say $cfg.installer-repo; # m-doughty/App-Moneymoor
say $cfg.updates-enabled; # False unless [updates] opts in
say $cfg.ci-ariza-source; # fez (or a URL zef can install from)
say $cfg.smoke-command; # moneymoor --version
say $cfg.licensing-strict; # False
say $cfg.licensing-third-party; # ({name => Inter, spdx-license => OFL-1.1})
# Every smoke command as argv, with paths substituted in:
.say for $cfg.smoke-commands(:exec($launcher), :raku($raku), :tmp($scratch));
# (/ā¦/bin/moneymoor --version)
# (/ā¦/rakudo/bin/raku -e use App::Moneymoor::DB; ⦠/ā¦/scratch)
.note for $cfg.warnings; # unrecognised keys, if any
DESCRIPTION
ariza.toml lives in the app's repository, not in ariza's. It is
how an application declares what it is and what a bundle of it needs,
so that ariza stays a general tool rather than a list of special cases
about specific apps.
THE V1 SCHEMA
[app]
name = "App::Moneymoor" # dist name
exec = "moneymoor" # launcher/binary name
display = "Moneymoor"
[bundle]
platforms = ["macos-arm64", "linux-x86_64-glibc", "windows-x86_64"]
native = ["notcurses", "sqlcipher"]
smoke = "{exec} --version" # command template run by ariza smoke
[installer]
repo = "m-doughty/App-Moneymoor" # where the releases live
warm = "--version" # run once at install time; false skips it
[updates]
enabled = true # weekly managed-install prompt
[ci]
ariza-source = "fez" # how the scaffolded workflows install ariza
[licensing]
strict = false # an unattributed native pack fails the build
[app]
All three keys are required; a manifest missing any of them dies at load time naming the key and the file.
nameā the distribution name aszefknows it (App::Moneymoor, colons and all), not the repository directory name.execā the launcher name: the command a user types, the basename of the binary inside a bundle, and the{exec}expansion inbundle.smoke.displayā the human-facing name, for window titles, desktop entries and Start Menu shortcuts. Required rather than derived, because the correct capitalisation of a product name is not something a tool should be guessing at.
[bundle]
Every key optional.
platformsā which App::Ariza::Platform slugs to build for. Each entry must be a slug ariza knows; an unknown one is a hard error (see below). Absent means an empty list.nativeā names of native libraries the bundle has to carry beyond the Raku runtime itself. Free-form strings in v1; a later phase gives them meaning.smokeā whatariza smokeruns against a freshly built bundle to prove it works. See below.
bundle.smoke
Three shapes, in increasing order of how much you need:
# One command:
smoke = "{exec} --version"
# Several:
smoke = ["{exec} --version", "{exec} --help"]
# Commands that must not go anywhere near a shell:
smoke = [
["{exec}", "--version"],
["{raku}", "-e", '''
use App::Moneymoor::DB;
ā¦
''', "{tmp}"],
]
A string entry is split on whitespace. An array entry is taken word for word, verbatim ā which is the only way to express a command containing spaces, quotes, or an entire program, and the reason the schema grew an array form at all. Nothing is ever passed through a shell, in either form, so there is no quoting layer to get wrong.
The two entry shapes cannot be mixed in one file: Config::TOML
enforces the pre-1.0 rule that an array's elements are all of one type,
so a list is either all strings or all arrays. That is a limitation of
the parser rather than of this schema ā smoke-argvs is happy to
accept either ā and the workaround is to write the whole list as argv
arrays, which is the better form anyway.
[installer]
repoā the GitHubowner/namewhose releases the generated end-user installers download from. App::Ariza::Installer builds three URLs out of it: thereleases/latestredirect it reads a tag from, the bundle asset, and that asset's.sha256sibling.
Optional in the schema ā an app that is not published anywhere has no
repository to name ā but required by ariza installers, which says so
rather than rendering a script that 404s.
The value must be exactly owner/name. A full URL, a trailing
.git, or a stray space is a hard error for the same reason an unknown
platform slug is: the shape is closed, so a typo cannot be a future
feature, and the resulting 404 lands on a stranger's machine rather than
on the author's.
warmā the arguments the generated installers run the freshly installed launcher with, once, before they print the parting message. Defaults to--version.
Whatever a first launch has to do that later ones do not ā paging a few hundred megabytes off a cold disk, building a per-user state directory, touching a keychain ā is done there, while the installer is on screen saying so, rather than the first time the user actually wants the application.
Four spellings:
[installer]
warm = "--version" # arguments, whitespace-split
warm = ["--check", "--quiet"] # the same, word for word
warm = true # the default arguments, said out loud
warm = false # no warm-up step at all
An empty string or array is an error rather than either of the two
things it might mean. Running the launcher with no arguments starts the
application, and a full-screen application does not return ā the
installers deliberately impose no timeout, so that spelling would be a
hang. false is how you say "skip it", and arguments the app returns
from are how you say anything else.
The warm-up never fails an install. See App::Ariza::Installer.
Placeholders
{exec} is expanded by smoke-command against app.exec.
App::Ariza::Smoke expands rather more, against a bundle it has just
unpacked:
{exec}ā the launcher,< <bundle>/bin/<exec> >{raku}ā the bundled interpreter{site}ā the bundle's module repository{native}ā the staged native libraries{bundle}ā the bundle root{tmp}ā a writable scratch directory, created per run
A placeholder that nothing supplies is an error, not an empty string: a smoke command with a hole in it does not fail, it silently runs something else.
[updates]
enabled is a boolean and defaults to false. When true, bundles carry the
managed-install update coordinator and trusted local installer snapshot
described by App::Ariza::Update. The coordinator checks at most weekly and
offers the user install-now, ask-next-time and ignore-this-version choices.
Enabling updates requires installer.repo. The repository is not duplicated
in this table: discovery and the private exact-candidate installer must use the
same GitHub release identity as the public generated installers.
[ci]
One key, optional, read only by App::Ariza::CI when it scaffolds an app's GitHub Actions workflows.
ariza-sourceā where the generatedrelease.ymlinstalls ariza itself from."fez"(the default) renderszef install --/test 'App::Ariza:ver<0.2.2+>:auth<zef:apogee>'; the version floor prevents an older bundler from silently rebuilding a release and the author qualifier prevents a same-named distribution from satisfying it. Anything else is passed tozefverbatim, which is how a repository URL gets used before ariza is published, or while a release is being tested:
[ci]
ariza-source = "https://github.com/m-doughty/App-Ariza.git"
Whichever is chosen, the other is rendered beside it as a comment, so switching between them in a hurry is an uncomment rather than a remembering exercise.
Unlike a platform slug this is not a closed set ā anything zef
install accepts is legitimate, and enumerating those here would date
badly ā so only an empty value is an error, because it renders a
workflow step that installs nothing and succeeds.
[licensing]
Everything about what a bundle redistributes is read out of the bundle
itself ā a native pack's own licensing kit, each installed
distribution's META6.json license, ariza's record of the vendored
runtime. This table is for the two things that are not readable from
anywhere: how strict to be about a payload nobody attributed, and what
the app ships that ariza cannot see.
Every key is optional, and an app that writes none of it still gets a
complete THIRD-PARTY.md.
[licensing]
# A native pack with no licensing manifest is a warning and a visible
# "unattributed" row by default. `true` makes it a failed build.
strict = true
# The application's own row. Every field defaults from the app's
# META6.json (and its LICENSE file), so most apps need none of this.
[licensing.app]
copyright = "Copyright 2026 A Person"
project-url = "https://example.org/moneymoor"
notes = "The bundled build enables the encrypted-store feature."
# Anything the app ships that ariza cannot see: fonts, datasets,
# artwork, a vendored C library of its own.
[[licensing.third-party]]
name = "Inter"
version = "4.0"
spdx-license = "OFL-1.1" # a text ariza ships
copyright = "Copyright 2016 The Inter Project Authors"
project-url = "https://rsms.me/inter/"
files = ["resources/fonts/Inter-*.ttf"]
[[licensing.third-party]]
name = "The cover artwork"
spdx-license = "CC-BY-4.0" # one it does not: name a file
license-files = ["licenses/CC-BY-4.0.txt"] # path in THIS repository
files = ["resources/art/*.png"]
# A distribution in the closure whose own metadata is wrong or absent.
[[licensing.dists]]
name = "Some::Ancient::Module"
spdx-license = "Artistic-2.0"
notes = "Its META6 has no license field; confirmed from its LICENSE."
The three row tables share one vocabulary ā id, name, version,
spdx-license, conveyed-under, copyright, project-url,
source, notes, license-files, files ā and it is deliberately
the same vocabulary a native pack's third-party.json uses, so an app
describes a bundled font in the words a pack describes FFmpeg in.
licensing.app takes neither id (there is one application) nor
files (the bundle is the file); licensing.dists corrects a
distribution ariza already found, so it takes neither id, source
nor files.
license-files entries are paths inside the app's repository, never
absolute: a licence text belongs to the repository that declares it, and
an absolute path in a committed config file is a path that exists on one
machine. Where a row omits them, ariza uses the text it ships for the
row's SPDX identifier ā it ships Artistic-2.0, MIT, Apache-2.0,
BSD-2-Clause, BSD-3-Clause, LGPL-2.1, LGPL-3.0, GPL-2.0,
GPL-3.0, AGPL-3.0, Zlib, ISC, X11, OFL-1.1,
Unlicense and a public-domain statement ā and an identifier it has no
text for is a hard error naming this key as the fix.
NOASSERTION
spdx-license = "NOASSERTION" is SPDX's own spelling for "somebody
looked and could not determine the licensing", and it is accepted in a
[[licensing.dists]] or [[licensing.third-party]] row ā after
looking, as a declaration on the record. No licence text is looked up
for it, since there is none, and the generated document says in words
that licensing was not asserted and points at the component's own
repository.
It is available nowhere else. A distribution whose own metadata says
NOASSERTION fails like any other missing licence (nobody has looked
yet), [licensing.app] may not say it about the application itself
(there is nobody to look on its behalf), and licensing.strict refuses
a bundle that contains one ā strict means every component names a
licence, and "we could not find one" is not a name.
name and spdx-license are required in a [[licensing.third-party]]
row, name in a [[licensing.dists]] one; anything else is optional.
See App::Ariza::Licensing for what is done with them.
UNKNOWN KEYS WARN; WRONG TYPES DIE
The house rule, shared with App::Ariza::Versions and
App::Shigur::Config: unrecognised keys at any level go into
warnings and loading continues, so one manifest can serve several
ariza versions. Wrong types die immediately, naming the dotted path
and the expected shape:
ariza: app.name must be a string
ariza: bundle.platforms must be an array of strings
ariza: bundle.native must be an array of strings
Keys beginning with // are ignored silently, at any level, matching
every other ariza config file.
The one value that is not forward-compatible
An unknown platform slug in bundle.platforms dies rather than
warning:
ariza: bundle.platforms contains unknown platform 'macos-aarch64'
(expected one of: linux-aarch64-glibc, ..., windows-x86_64)
installer.repo is the same kind of value and dies the same way:
ariza: installer.repo must look like 'owner/name'
(got 'https://github.com/m-doughty/App-Moneymoor')
The reasoning is asymmetric on purpose. An unknown key costs
nothing to ignore ā some future ariza understands it. An unknown
slug is a closed-set value: the set is exactly what ariza can build
for, so a typo cannot be a future feature, and ignoring it would
produce a release quietly missing a platform the author asked for.
macos-aarch64 for macos-arm64 is the exact mistake this catches.
METHODS
load(IO() $dir = $*CWD --> App::Ariza::Config)
Load $dir/ariza.toml.
load-file(IO() $path --> App::Ariza::Config)
Load a manifest from an exact path.
Both die ā with distinct messages ā on a missing file, an unreadable
file, malformed TOML, a document that is not a table, a wrongly-typed
value, or a missing required [app] key.
An empty file is a valid, empty TOML document, so it fails on the
honest complaint ā "app.name is required" ā rather than as
"malformed". (Config::TOML rejects an empty document outright, so
load-file short-circuits before handing it over.)
smoke-argvs(--> List)
Every configured smoke command as raw argv, in order: string entries split on whitespace, array entries verbatim. Empty entries are dropped.
smoke-commands(*%vars --> List)
The same, with {placeholder} substitutions applied. {exec} defaults
to app.exec and can be overridden; every other name comes from
%vars. A surviving {...} dies naming the known placeholders.
smoke-command(--> Str)
The first smoke command as one display string with {exec}
expanded, or the undefined Str when none is configured. For showing a
human what will run ā smoke-commands is for running it.
licensing-strict(--> Bool) / licensing-app(--> Hash) / licensing-third-party(--> List) / licensing-dists(--> List)
The [licensing] table: whether an unattributed native pack fails the
build, the app's own row, the rows it declared for what ariza cannot
see, and the corrections it declared for distributions whose metadata is
wrong. All four are empty-but-defined for a config that omits the
table, so a caller never has to test for it.
warnings(--> List) / path(--> IO::Path)
The unrecognised keys found while loading, and the file loaded from.
AUTHOR
Matt Doughty
COPYRIGHT AND LICENSE
Copyright 2026 Matt Doughty
This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.