AileronControlPlane

Freezing a Flight Plan

Freeze is the author-time step that seals an installed Aileron skill into a Flight Plan (ADR-0027). A skill before freeze names its execution environment by a movable tag. A Flight Plan after freeze pins every image to a content-addressed digest, records a lockfile, content-addresses the whole unit, and carries a detached signature. The frozen version is written immutably into the canonical skill store. This guide walks through running freeze and explains the guarantees it produces.

What freeze does

Freeze runs a fixed sequence over one SKILL.md document.

  1. It parses and lints the manifest. The lint rejects any step that could reach an LLM outside the marked llm-seam (see the manifest spec).
  2. It resolves the declared environment to exactly one image digest. Declared environment.tools are resolved to their catalog devcontainer Features and composed onto the Aileron-provided runner base, and the built image is pinned by its sha256: digest. A custom environment.image is resolved to its sha256: digest; when tools are declared alongside it, they compose onto that custom base. The plan runs in one container, so this resolves to a single pin. A plan that declares no environment pins nothing.
  3. It builds the lockfile. The lockfile records the single resolved image pin, the resolved capability set, the step-keyed sealed trust reach for each tool step that declared a trust contract, the content hash, and the semver label.
  4. It content-addresses the unit. The content hash is a sha256 over the canonical frozen manifest bytes plus the lockfile bytes.
  5. It signs the content with a detached ed25519 signature.
  6. It writes the frozen version into the store as an immutable directory.

Freeze pins by digest, never by tag. A resolver that returns a tag rather than a digest is a hard error.

Running freeze

Freeze takes the name of an installed skill or a path to a SKILL.md.

aileron skill freeze weekly-metrics-digest \
  --signing-key ~/.aileron/keys/author.pem \
  --version 1.0.0

The signing key is a PEM-encoded ed25519 private key. Pass it with --signing-key or set AILERON_SIGNING_KEY to the key path. The key is read for signing only. It is never copied into the frozen artifact or the store.

The --version flag records a human-facing semver label in the lock. It is optional.

Freeze prints the skill name, the version label, the content hash, and the on-disk location of the frozen version.

The frozen version

A frozen version lives under the skill in the store at ~/.aileron/skills/<name>/versions/<id>/. The version id is a short content-derived slug of the content hash. Each version directory holds four files.

FileContents
SKILL.mdThe frozen manifest with the populated lock block injected.
aileron.lockThe standalone lockfile, the durable pin record.
signature.sigThe detached ed25519 signature over the content bytes.
signing-key.pubThe author public key the signature verifies against.

The pre-freeze installed SKILL.md at the skill name root is never touched. Freeze adds versions beside it.

Guarantees

Freeze is reproducible. Running freeze twice over byte-identical input with the same key produces the same content hash, the same frozen bytes, and the same signature. ed25519 is deterministic for a fixed key and message.

Frozen versions are immutable. Re-freezing changed content writes a new version directory and leaves every prior version byte-identical. Re-freezing identical content to an existing version id is a verified no-op. Writing different content to an existing version id is rejected.

The signature is verifiable at launch. A verifier needs only the signature and the public key, both stored beside the version. The launch-time runtime (#1511) verifies the signature before it runs a Flight Plan.

The signing private key never enters the store. Only the public key and the detached signature are persisted.

A frozen version is multi-identity. The seal carries no credential binding and no identity. The identical frozen version launches under different vault-bound identities with different authorizations, and the audit trail records who ran it. The credential binding lives on the launching operator’s machine, so the same signed bytes serve many operators without carrying any one operator’s identity.