# ADR 0005: Unified Portable Deployment Bundle

**Status:** Retired as release authority; materialization helpers remain as
migration dependencies

Current signed-BOM D3 Test, Staging, and Prod do not use this Candidate bundle
as release authority. The historical decision below is retained because
`scripts/deployment_bundle.py` still supplies bounded validation and
materialization helpers to migration/runtime support code.

**Decision date:** 2026-07-31

## Decision

Fixed-slot Test and Formal Staging use one policy-neutral immutable payload
contract: `deployment-bundle/v1`. The canonical implementation is
`scripts/deployment_bundle.py`.

The bundle owns byte identity and portable layout only. It contains relative
paths, exact source refs, final-pack identity, executable and frontend bytes,
source snapshots, Connect artifacts, optional named runtime extras, and a
complete per-file SHA-256 inventory. It contains no absolute build paths and no
`releasable` flag.

Environment authority remains outside the bundle:

- Test emits `test-deployment-authority/v1`, permanently binds
  `authority=non_release_test`, and has no release-eligibility field. The
  workflow carries the exact Candidate ID across jobs as the trust anchor.
- Formal Staging emits the existing release manifest and annotated release tag.
  Only that trusted workflow evidence may assert `prod_release_eligible=true`
  and bind a bundle for Prod promotion.
- A Test authority record or an unattested bundle is never a release-tag input.

Consumers execute through a trusted operator checkout. Test creates an
exact-SHA, run-scoped operator worktree before Candidate sealing so concurrent
environment workflows cannot replace its executor. The operator verifies
its own revision and cleanliness, validates the authority record, verifies the
outer archive hash, internal manifest hash, exact refs, final-pack hash,
per-file hashes, modes, and file set, then atomically materializes the bundle.
Candidate-owned source is payload, not validator code.

## Interface

The deployment-bundle module presents one build/materialization seam:

1. `build_deployment_bundle(...)` creates deterministic archive, manifest, and
   receipt bytes.
2. `materialize_deployment_bundle(...)` validates and atomically materializes
   those bytes at any normal target directory, or fully rehashes an existing
   exact materialization for replay.
3. `materialize_official_app_packs_checkout(...)` derives the exact pristine
   checkout from the manifest-hashed offline Git bundle.

Formal Staging and Test are policy adapters at this seam. They do not implement
separate archive or hash logic.

## Portability And Replay

Candidate identity never includes an absolute build or materialization path.
A Candidate directory may be copied to another root and validated there without
rewriting its manifest. Runtime environment files may record local materialized
paths as deployment state, but those paths are not bundle identity.

An existing materialization is reusable only after a complete file-set, size,
and SHA-256 recheck. Any archive, manifest, undeclared member, executable mode,
or retained-file mismatch blocks before lifecycle mutation. Replay consumes the
same archive and Candidate ID; it does not fetch, checkout, compile, rebuild the
frontend, regenerate the final pack, or rebuild Connect artifacts.

## Contract Migration

`deployment-bundle/v1` replaces `release-candidate-bundle/v3` and the local
absolute-path `candidate-deployment/v1` manifest. Existing release tags and
Test manifests are not reinterpreted. A release created before this decision
requires a fresh Formal Staging run and tag before Prod promotion.

## Consequences

- Test and Formal Staging share one deep module for deterministic packaging,
  tamper detection, portable materialization, and exact replay.
- Test runtime-only helpers and optional patch content are named bundle extras;
  release eligibility does not depend on whether an extra exists.
- Test remains permanently non-promotable even when its payload bytes happen to
  equal a Formal Staging bundle.
- Prod continues to consume only a Formal-Staging-attested bundle and performs
  no rebuild.
- Runtime-generated logs, environment files, systemd units, object-store copies,
  and derived checkouts remain deployment state outside immutable bundle bytes.
