think
16px
820px

Deploy runbook — commitment traceability (Channel WC)

Branch: feat/commitment-channel-wc. This feature spans three deploy artifacts that must ship
together, because they share the stego.proto contract: the stego sidecar (Python), the
obscura Go server, and the web SPA. deploy/update.sh rebuilds obscura + web but NOT the
sidecar
(sidecars keep running across an update). So the sidecar must be rebuilt separately, or the
Go server will send the new issue_day / issuance_ordinal / commit_* fields to a stale sidecar
that ignores them and commitment traceability silently never applies.

Pre-flight

  • No concurrent deploy. As of this writing another party was mid-deploy on valbox
    (deploy-web-1 / deploy-obscura-1 had just restarted). Do not overlap deploys on the shared host.
  • The working tree co-mingles this feature with an in-flight photo/channel_d change from another
    agent. Decide whether to deploy the merged working tree (dirty deploy — this project's norm) or to
    land feat/commitment-channel-wc on its own first. Prefer merging the branch to the deploy checkout
    cleanly.
  • PROTECTION_ENGINE=grpc and STEGO_MASTER_KEY must be set in the deploy env (see
    deploy/docker-compose.yml). The master key is env-only (never a DB row) — keep it that way.

Steps (on valbox, in the obscura deploy checkout)

# 1. Get the code onto the deploy checkout (branch or merge to the deployed ref).
git fetch && git checkout feat/commitment-channel-wc   # or merge it into the deployed branch

# 2. Rebuild + recreate the stego sidecar FIRST (update.sh will not touch it).
#    Build context is ../stego (repo-root .dockerignore excludes stego/).
docker compose -f deploy/docker-compose.yml build stego-sidecar
docker compose -f deploy/docker-compose.yml up -d --no-deps stego-sidecar
docker compose -f deploy/docker-compose.yml ps stego-sidecar   # wait for (healthy)

# 3. Deploy obscura + web (snapshot → build → migrate → health-gate → auto-rollback).
./deploy/update.sh

# 4. If not already, enable the engine (env), then verify.

Verify (post-deploy)

  1. Capabilities: sidecar advertises channels incl. w; engine reachable
    (GET /api/v1/protection/capabilities → non-empty).
  2. Mark a real doc: download a Google-Docs-exported PDF for a recipient with the mode set to
    Traceability (or Both). Diag should report traceability_channel: wc, applied: true.
  3. Forensic verify (/verify forensic, protection.investigate): upload the marked PDF or a
    one-paragraph screenshot → result card shows the recipient with the “Survivable · no DB” tag,
    the issue day, and the copy ordinal.
  4. Screenshot excerpt: a ~one-paragraph crop still resolves the recipient.

Rollback

  • obscura/web: update.sh auto-rolls-back its images if the health-gate fails; the pre-update DB
    snapshot path is printed for a manual restore if a migration misbehaves.
  • stego sidecar: docker compose ... up -d --no-deps stego-sidecar from the previous image tag. The
    proto change is backward-compatible (a rolled-back Go server simply omits the new fields → the
    sidecar falls back to the legacy seq path), so a sidecar-only rollback is safe.

Still deploy-time wiring (optional, not blocking)

  • Roster-export admin endpoint: the crypto (go/internal/protection/export) is built + tested;
    a live GET endpoint that lists issuance identities, BuildRoster + Signs them with an
    in-house-CA-issued key, and streams the bundle to WORM/offsite is the remaining wiring.
  • HSM/KMS for the master key (today an env secret) is a prod-hardening swap, not a code change.