feat: Worker portal Stage 3 — promote-live-to-baseline (git-host PR generation)

Description

Land the promote-live-to-baseline mechanism: convert a jurisdiction's live overrides into a real PR against the jurisdiction's TOML baseline in git. Implementation follows the Stage 2 promote-PR ADR's decision on service ownership, signing, and supported git hosts.

This is the most novel and highest-risk piece of Stage 3.

Acceptance Criteria

  • Service/component lives where Stage 2 promote-PR ADR designates (canopy-ops, inline canopy-web, or new canopy-promotion service)
  • HTTP endpoint: POST /v1/composition/{surface}/promote — generates a PR converting the current live overrides into a TOML baseline diff
  • PR generation:
    • Diff: TOML baseline → live overrides applied (merged per Stage 2 ADR semantics)
    • Commit author: per ADR's signing identity decision
    • Commit signing: GPG/EdDSA per project convention
    • Branch naming: per ADR
    • PR title + body: per ADR template
  • Failure modes handled gracefully: git-host unreachable, auth expired, base branch moved, merge conflict, malformed TOML
  • After PR open: live override is not auto-archived (jurisdiction must explicitly archive after PR merges, per the live-override lifecycle in Stage 2 ADR)
  • Audit event emitted per ADR-014
  • Integration test: against a test git repo (sandbox), end-to-end promote produces a valid TOML diff
  • Secrets: git-host PAT loaded via EnvSecretProvider per ADR-017
  • CHANGELOG entry under === Added

Blocked by

  • Stage 2 promote-PR ADR merged
  • Stage 3 live override APIs issue merged

Context & References

Labels

type::feature, priority::medium, program::infrastructure, service::web, workflow::needs-spec