uniac.yaml declares an application’s infrastructure in YAML: resources
holds reusable service definitions and the deployment declarations that
instantiate them, and a workspace combines package directories.
File format
The document is a mapping with these top-level fields:
Resource names match
^[a-z0-9]+(?:(?:__?|-+)[a-z0-9]+)*$ and are unique
within the file. A deployment declaration’s name is also its service’s name,
so it is one DNS label: lowercase letters, digits and dashes, starting and
ending with a letter or digit, at most 63 characters. Every resource requires
type; unknown fields are rejected at every level.
Workspaces and packages
A workspace owns its containing directory and subtree. Its root resources and each included directory’suniac.yaml contribute to one local project.
A directory containing uniac.yaml is a package; the root’s resources
have their own package scope.
Paths are relative to the workspace root and must name directories below it.
Missing manifests, duplicate canonical directories, paths escaping the root,
globs, and nested workspaces are rejected. Inclusion loads exactly the listed
manifests. Root-local
resources can accompany workspace directly.
A manifest outside any workspace owns a standalone project. Inside a
workspace, every manifest below the root is listed in includes.
Resource names, from lookups and environment references are local to each
package: a reference addresses the services declared in its own package, and
the root’s resources form their own package. Different packages may reuse
definition names; service names are unique across the project.
Definitions and deployments
type: service and type: singleton create reusable service definitions
for stateless and singleton execution. A definition holds the OCI image or
Dockerfile build source, environment, startup command, and storage needs. The
image platform is linux/amd64.
A deployment declaration turns it into a running service. Complete field
contracts are in Service and Volume.
A type: deployment resource instantiates one definition as a service.
The declaration’s name is the service’s name: its identity in the target
project and its private hostname. Several declarations can instantiate the
same definition, each as its own service.
The service’s replicas are the containers running it;
deployment versions
describes how each deployment applies the count. A definition and a
deployment declaration in the same file have different names. Renaming a
declaration names a different service, with its own hostname, reference
target and volume names; the service deployed under the earlier name, and its
data, stay in the project.
Deploying a project includes every deployment declaration in its root and
included packages. Each resulting service has its own deployment versions.
The target project’s identity is supplied separately from this file.
Example composition
This application has an API and a private Redis service with durable storage. It assumesapi/Dockerfile builds an application listening on port 8080 that
uses CACHE_URL to connect to Redis.
api declaration instantiates api_definition as the service api,
running two replicas; cache instantiates cache_definition as the service
cache. Both services are included in the project deployment. The API can
reference cache because both declarations belong to this package.
The reference names the cache service, which gives its volume the
project-scoped name cache.data. The API is publicly exposed; Redis is
reachable within the project’s private network.
Environment and references explains
resolution between services in the same package.
Validation
Local validation checks ownership, included manifests, each file’s schema, resource names, deployment declarations, replica counts, endpoint ports, volume sizes and mount paths, environment variable counts and lengths, and package-localfrom references. Composition checks all service names,
build-source paths on disk, composed volume names, reference visibility,
referenced variables, and ungrounded value-reference cycles. Unknown or cross-package service
references fail locally. At least one deployment is required to produce a
deployable description.
Generated description
The generated description is JSON withkind: deployable and a services
array. Each entry contains a service name, normalized source declaration,
environment templates, and runtime configuration, including a declared
replicas count. The remote project binding lives in .uniac/deploy.json,
and environment values remain templates until deployment.
Build paths are authored relative to the defining manifest’s directory and
normalized relative to the project root in the generated description. Thus
build: . in api/uniac.yaml and jobs/uniac.yaml describes distinct sources.
The digest identifies that description. Equivalent path spellings, omitted
build defaults, YAML formatting, and mapping or exposure-list ordering leave it
unchanged. Reordering workspace includes or moving an identical checkout to
another absolute path also preserves the digest. A declared replicas count
is part of the description; omitting it and null produce the same
description. An explicit build target remains part of the description even
when it names the Dockerfile’s last stage. The digest excludes source-file and
image contents and remotely resolved environment values.
