/** * Approval Completion Service — Story A (PRI-408) * * Formal production service that orchestrates activation AFTER an owner * approves an approval record. Replaces the demo "approve → direct writer" * pattern with a structured, idempotent, validated completion path. * * Product Contract B requirements: * - Reads the approved approval record * - Validates artifact/version/channel consistency * - Prevents unapproved, rejected, or expired records from activating * - Idempotent activation (duplicate submissions = no duplicate activation) * - Calls the ActivationDispatcher with rolloutDecision='approved' * - Records activation state (via dispatcher) * - Returns structured decision/reason/nextAction * * ERR checklist: * - ERR-001: Approval record fields validated at runtime, not via `as` * - ERR-002: Every failure path carries reason + nextAction * - ERR-009: Required fields fail loud when missing * - ERR-015: Idempotency state distinguished from current dispatch state * - ERR-025: Production-path service, not demo helper */ import type { ActivationActor, ActivationDecision, ActivationStateReadModel, ApprovalQueueStore } from './activation-types.js'; import type { ActivationDispatcher } from './activation-dispatcher.js'; export interface ApprovalCompletionInput { approvalId: string; actor: ActivationActor; now: string; } export type ApprovalCompletionResult = { ok: true; decision: ActivationDecision; activationId?: string; approvalId: string; } | { ok: false; error: 'not_found' | 'not_approved' | 'already_activated'; reason: string; nextAction: string; approvalId: string; }; export declare class ApprovalCompletionService { private readonly approvalStore; private readonly dispatcher; private readonly stateReadModel; constructor(approvalStore: ApprovalQueueStore, dispatcher: ActivationDispatcher, stateReadModel: ActivationStateReadModel); completeApproval(input: ApprovalCompletionInput): Promise; } //# sourceMappingURL=approval-completion-service.d.ts.map