## Why
Phase 1 of progressive delivery needs an explicit eligibility boundary
before deployment automation can safely consume relay artifacts. Today
the canonical Docker workflow can publish independently of the same-SHA
CI result, the relay does not expose its source/build identity, and the
Helm chart only renders mutable tags.
The existing `ghcr.io/block/buzz-staging-dev` workflow in #6709 remains
a manual pre-merge preview lane. It is deliberately not a canonical
promotion input.
## What changed
- Compile the full source SHA and GitHub Actions build identity into
canonical relay binaries and expose it at `/_status`.
- Gate creation of tagged multi-architecture manifests on the latest
exact-SHA `CI` push run succeeding on `main` or `release`.
- Preserve the signed SLSA provenance and add a signed, release-only
deployment-eligibility predicate with source, build run, qualifying CI
run, and exact compatible Buzz chart version.
- Keep failed or pending builds untagged and without an eligibility
predicate; preview-package artifacts are excluded by package and signer
contract.
- Add optional `image.digest` support to Buzz chart `0.1.8`, retaining
the existing tag fallback.
- Document verification and the intentional boundary between image/chart
compatibility and backwards-compatible database migrations.
## Risk and rollout
Canonical tag publication now waits for same-SHA CI and fails closed
when the newest matching run fails. Per-architecture blobs may remain
untagged after a failed qualification; they are not promotion inputs.
Debug manifests are also CI-gated but do not receive the release
eligibility predicate.
There are no migration or schema-orchestration changes. The companion
BuilderBot infrastructure PR will pin a separately verified canonical
main digest and expose a read-only running-deployment inspection
command. Signed eligibility is available only for artifacts published
after this workflow lands.
## Verification
- Blox: workflow contract fixtures, including stale-green rejection and
predicate structure
- Blox: `actionlint` for `ci.yml` and `docker.yml`
- Blox: 46 Helm unit tests, chart lint, and production/quickstart render
fixtures
- Blox: relay status unit test, workspace Rust formatting, and workspace
all-target clippy
- Live evidence: exact-SHA CI selector chose successful run
`32857345153` for source `9d1e4b257657f382d3111ce748f3da8d063b7671`
- Existing canonical digest provenance verified with `gh attestation
verify`
## References
- #6709 — developer-preview precursor; intentionally separate from
canonical eligibility
- `docs/deployment-identity.md`
*Generated with Codex*
---------
Signed-off-by: Luke Tornquist <tornquist@squareup.com>
## Why
Native profilers such as `ddprof` need symbols to resolve optimized Buzz
relay stacks, while ordinary deployments should keep the current compact
stripped image.
## What
- Build optimized relay binaries with line-table debug information and
derive the stripped release binaries from the same ELF files
- Publish matching multi-arch `debug-*` tags while preserving existing
stripped tags and runtime behavior
- Document the debug image as an optimized symbol-bearing release, not a
debug-mode build
## Risk Assessment
Medium — this changes the relay image release workflow and adds a second
image variant, but existing tags remain stripped and use the same
runtime base, user, entrypoint, and optimized machine code.
## References
- Follows Envoy's optimized unstripped `debug-*` image pattern:
https://github.com/envoyproxy/envoy/blob/main/distribution/binary/BUILD
- Built both Docker targets locally; verified matching GNU build IDs and
`.text` hashes, with DWARF and symbol sections present only in the debug
variant
- Pre-push checks passed: branch skew, org policy, desktop checks/tests,
Rust tests, mobile tests, Tauri tests, and workspace tests
Generated with Amp
Signed-off-by: David Grochowski <dgrochowski@squareup.com>
Co-authored-by: Amp <amp@ampcode.com>
## Problem
A fresh `deploy/compose` install never starts. The relay exits during
config
validation and crash-loops under `restart: unless-stopped`:
```
Error: Configuration error: invalid config: BUZZ_GIT_PACK_CACHE_PATH=/data/git/.pack-cache could not be created: Permission denied (os error 13)
```
## Cause
The image runs as `buzz:buzz`. Docker seeds a volume's ownership from
the image
**only when the mount point already exists there** — otherwise it
creates the
mount point as `root:root`. `compose.yml` mounts `buzz-git-data` at
`/data/git`,
which the image doesn't create, so the relay can't write the pack cache.
`USER buzz:buzz` and `BUZZ_GIT_REPO_PATH=/data/git` arrived in the same
commit
(426497a), so there was never a working state to regress from.
The other deployment paths are unaffected, which is probably why this
went
unnoticed: the code default (`./repos`, under the `buzz`-owned home)
works
unmounted, and the Helm chart gets volume ownership from `fsGroup:
65532`.
## Fix
Create `/data/git` as `buzz:buzz` in the image, the way the official
`postgres`
image prepares `$PGDATA`.
`compose.yml`, `run.sh` and the volume layout are untouched, so existing
deployments need no migration and the `run.sh backup-hint` output stays
accurate.
## Testing
`ghcr.io/block/buzz@sha256:ec96e029` on arm64 with this change applied
as a
derived layer, running **unmodified** `deploy/compose/compose.yml`
against clean
volumes:
| Image | `/data/git` owner | Result |
|---|---|---|
| upstream | `root:root` | `Permission denied` — crash loop |
| patched | `buzz:buzz` | relay healthy |
```
relay health: healthy
/data/git = buzz:buzz (contains .pack-cache)
/_readiness -> 200
WS upgrade -> 101
```
Relay log shows migrations applied, the A3 git object-store conformance
probe
passing, and `buzz-relay TCP listening`.
I have not run `just ci` / `just test` — this touches no Rust, JS, or
mobile
code. Happy to run them if you'd like.
## Alternatives
- A `git-init` one-shot in `compose.yml` that chowns the volume. Works,
but adds
a container to every `up` and doesn't help `docker run` or Kubernetes
without
an `fsGroup`.
- Moving `BUZZ_GIT_REPO_PATH` to the code default `/var/lib/buzz/repos`
and
pre-creating that instead. Arguably tidier, since `/data/git` then only
lives
in the compose bundle — but it moves the volume mount point, so existing
installs would have to relocate their git data. Happy to do it that way
if you
prefer; it seemed the wrong trade for a bug fix.
Signed-off-by: Onno Klein Hofmeijer <onnokh@hotmail.com>