Emit deployment-lifecycle audit events
Summary
- Record the deployment lifecycle into the persisted Event audit stream: started, resumed, manual-intervention raised/submitted, guided-failure raised, succeeded, failed, timed-out, canceled.
- Emission is generic and centralized — a single auto-discovered
IDeploymentLifecycleHandler(DeploymentAuditEventHandler) subscribes to the lifecycle events the pipeline already emits and maps each milestone to oneEventCategory. No scatteredRecordAsynccalls; no producer changes. - Audit writes run in a fresh DI scope (
ILifetimeScope.BeginLifetimeScope) so they persist independently of the deployment transaction. The lifecycle publisher already isolates handler exceptions, so an audit-write failure can never fail a deployment. - Pure
DeploymentAuditEventFactoryprojects the sharedDeploymentTaskContext→RecordEventRequest(document FKs + display-name references), kept side-effect-free for unit testing. - Dispatch the previously-dropped
DeploymentTimedOutEventin the lifecycle base (additive no-op hook) so timed-out deployments are audited as failures.
Purely additive — no existing signature or behavior changed. Builds on the Event foundation from #411.
Test plan
-
Unit (16): DeploymentAuditEventFactoryprojection across all categories + null-context/no-deployment guards; lifecycle base dispatch including the new timeout hook. -
Integration (real Postgres, 7): handler → DB via the real fresh-scope path; full ordered lifecycle trail; failed/timed-out → DeploymentFailed; cross-document feed visibility; pre-deployment-data no-op; real IDeploymentLifecyclepublisher dispatches to the auto-registered handler. -
E2E (full ProcessAsync, no Kind, 2): successful pipeline records Started→Succeeded with references; failed pipeline records DeploymentFailed. -
Regression: full solution build clean; 268 lifecycle/activity-logger/events/pipeline unit tests green; verified in isolation (PR builds + passes on clean main).