# Bundles and Manifests
A compiled app carries its metadata in three places, each with a
different job. They overlap by design — one is authoritative at run
time, one is the distribution descriptor, one exists for discovery.
| Artifact | Format | Written by | Read by |
|---|---|---|---|
| `*.dftc` image manifest | binary `DFTC` payload | `deft compile` | hosts/app loader (identity, capabilities) |
| `bundle.dft` | Deft data (`%DeftApp{…}`) | `deft compile --app` | installers/launchers (today: nothing at runtime) |
| `package.dft` | Deft data (`%Package{…}`) | copied from the package | launcher/app-selector package discovery |
## The Image Manifest
The image is self-describing. Its `DFTC` header (magic, version, flags,
payload length) is followed by the manifest — `entry`, `requires`,
`created-by`, prelude policy, and, for `--app` images, the app identity:
`app-owner`, `app-name`, `app-version`, `app-description`, `app-entry`,
`app-platforms`. The rest of the payload carries the macro registry,
the module table, and the compiled bodies.
That manifest is what the runtime actually consults: `retro app` and
friends can peek it before decoding, and the capability check reads
`requires` from it. When in doubt, the image is the source of truth.
## `bundle.dft`
Generated by `deft compile --app`, it is the distribution descriptor —
everything an installer or launcher needs in human-readable form:
```
%DeftApp{
owner "deft"
name "editor"
version "0.1.0"
description "Code editor"
main "src/editor.dft"
image "editor.dftc"
sha256 "1c21ac2b…d896d2"
platforms @{ "retro" "retra" }
requires @{ }
}
````
| Field | Meaning |
|---|---|
| `owner`, `name`, `version`, `description` | App identity, from the package manifest |
| `main` | The package's original source entry (may not exist in the bundle) |
| `image` | Image filename, relative to the bundle directory |
| `sha256` | Lowercase hex SHA-256 of the image file's bytes |
| `platforms` | Intended hosts, from the package's `capabilities.platform` (advisory) |
| `requires` | Runtime capabilities recorded by `--requires` (enforced by hosts) |
Every field is always written; absent values are empty strings/lists.
Nothing in the runtime reads `bundle.dft` today — the image manifest
carries the authoritative copy. Treat it as the hand-off format for
your installer: verify `sha256`, copy `image` + `assets/` + `icon.svg`,
and read `requires`/`platforms` for placement decisions. If you repack
or replace the image, regenerate the file (recompile) or recompute the
digest, or the two artifacts disagree.
## `package.dft`
The original package manifest is copied into the bundle verbatim. The
launcher and app selector identify a package by its `package.dft` (plus
an entry), so the copy is what makes the bundle directory discoverable
under a `:pkgs` root. It keeps the authoring fields the image does not
need — `tags`, `author`, `license`, `deps`, `capabilities` — and its
`main` still names the source path, which the discovery probes handle
when only the `.dftc` exists.
## Verifying a Bundle
`sha256` is a plain checksum over the image bytes:
```sh
sha256sum /opt/vendor/packages/acme/pos/pos.dftc
# compare with the sha256 field in bundle.dft
grep sha256 /opt/vendor/packages/acme/pos/bundle.dft
````
`bundle.dft` parses as ordinary Deft data, so tooling can read it with
`[fs/read]` + `[deft/parse]` rather than string matching.