Ingest Azure DevOps deployments into Production QA
## Gap
Epic 12247 item 1 asked for deploy ingestion on GitHub "and each supported forge's equivalent". Only GitHub shipped (architecture AC-6 deferred the others to Finish). `apps/api/app/triggers.py:16-45` has no Azure DevOps source kind and `apps/api/app/production_qa/deployments.py` reads GitHub events only, so an Azure DevOps project gets no Deployments rows, `deployed` edge or `deploy_failed` incident.
## Fix
Add a record-only `azure_devops` deploy recorder mapping Azure DevOps service hooks (`ms.vss-pipelines.run-state-changed-event`, `ms.vss-pipelines.stage-state-changed-event`, release deployment-completed; authenticated by the service hook's basic-auth or custom header secret, constant-time compare — confirm from Microsoft's service-hook docs, never memory) onto the same `deployments` rows, range/PR mapping, `deployed` edges and `deploy_failed` incidents the GitHub `reconcile` path writes. Connect deploys (Project › Production QA) gets an Azure DevOps variant. No new table.
## Acceptance
- A succeeded production stage → one Deployments row with range and merged PRs' tasks — fixture test with documented samples.
- A failed production stage → one `deploy_failed` incident; repeat updates it — test.
- Missing/wrong secret → 401, nothing written — test.
- Gate OFF: rows written, nothing filed — test.
- Connect deploys UI checked at 448 px and desktop.
Out of scope: GitLab and Bitbucket (own tasks); the GitHub path; filing logic; any scoring.
Done means:
- Tests above green; UI screenshots in the PR.
- Required checks: ./dc check quick, changed-area tests, merge lane full gate.
Activity
- Ready
- Runner started