/* deployment authority — certification gate authority evaluation for deployment operations. Do not deploy — this module only evaluates gate authority. RFC-1097: sweep — werkstatt-engine clean Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics. */ import type { Sha256Digest } from "@warpgogol/werkstatt-shared/fingerprint"; import { byteHash } from "@warpgogol/werkstatt-shared/fingerprint"; import type { GateChannel } from "../contracts/identifiers.ts"; import type { GateDecisionV1, MainVerificationDecisionV1 } from "../contracts/decisions.ts"; import type { DeploymentOperationState } from "../state-machine.ts"; import { validateDeploymentTransition, validateArtifactTransition } from "../state-machine.ts"; import type { ReleaseArtifactState } from "@warpgogol/werkstatt-shared/ontology/operations"; export type CertificationGate = "dev-deploy" | "propagate-alt" | "promote-main"; export interface DeploymentGateRequirementV1 { gate: CertificationGate; channel: GateChannel; requiresDurableSync: boolean; requiresMainVerification: boolean; allowsForce: boolean; allowsSkip: boolean; allowsWaiver: boolean; allowsGrace: boolean; } export const DEPLOYMENT_GATE_REQUIREMENTS: readonly DeploymentGateRequirementV1[] = [ { gate: "dev-deploy", channel: "dev", requiresDurableSync: false, requiresMainVerification: false, allowsForce: false, allowsSkip: false, allowsWaiver: false, allowsGrace: false, }, { gate: "propagate-alt", channel: "alt", requiresDurableSync: true, requiresMainVerification: false, allowsForce: false, allowsSkip: false, allowsWaiver: false, allowsGrace: false, }, { gate: "promote-main", channel: "main", requiresDurableSync: true, requiresMainVerification: true, allowsForce: false, allowsSkip: false, allowsWaiver: false, allowsGrace: false, }, ]; export interface DeploymentAuthorizationInputV1 { candidateId: string; gate: CertificationGate; gateDecision: GateDecisionV1; durableSyncVerified: boolean; artifactReadinessVerified: boolean; artifactHash: Sha256Digest; forceRequested: boolean; skipRequested: boolean; waiverRequested: boolean; graceRequested: boolean; } export interface DeploymentAuthorizationResultV1 { ok: true; authorized: boolean; gate: CertificationGate; channel: GateChannel; candidateId: string; decisionId: string; requiresMainVerification: boolean; requiresDurableSync: boolean; } export interface DeploymentAuthorizationFailureV1 { ok: false; ruleId: string; message: string; gate: CertificationGate; } export type DeploymentAuthorizationOutcomeV1 = DeploymentAuthorizationResultV1 | DeploymentAuthorizationFailureV1; export function authorizeDeployment( input: DeploymentAuthorizationInputV1, ): DeploymentAuthorizationOutcomeV1 { const req = DEPLOYMENT_GATE_REQUIREMENTS.find((r) => r.gate === input.gate); if (!req) { return { ok: false, ruleId: "CERT-DEPLOY-01", message: `unknown deployment gate "${input.gate}"`, gate: input.gate, }; } if (input.forceRequested && !req.allowsForce) { return { ok: false, ruleId: "CERT-DEPLOY-02", message: `force flag is not permitted for gate "${input.gate}"`, gate: input.gate, }; } if (input.skipRequested && !req.allowsSkip) { return { ok: false, ruleId: "CERT-DEPLOY-03", message: `skip flag is not permitted for gate "${input.gate}"`, gate: input.gate, }; } if (input.waiverRequested && !req.allowsWaiver) { return { ok: false, ruleId: "CERT-DEPLOY-04", message: `waiver flag is not permitted for gate "${input.gate}"`, gate: input.gate, }; } if (input.graceRequested && !req.allowsGrace) { return { ok: false, ruleId: "CERT-DEPLOY-05", message: `grace flag is not permitted for gate "${input.gate}"`, gate: input.gate, }; } if (input.gateDecision.candidateId !== input.candidateId) { return { ok: false, ruleId: "CERT-DEPLOY-06", message: `gate decision candidate "${input.gateDecision.candidateId}" does not match requested candidate "${input.candidateId}"`, gate: input.gate, }; } if (input.gateDecision.status !== "pass") { return { ok: false, ruleId: "CERT-DEPLOY-07", message: `gate "${input.gate}" decision is "${input.gateDecision.status}", not "pass" — deployment denied`, gate: input.gate, }; } if (!input.artifactReadinessVerified) { return { ok: false, ruleId: "CERT-DEPLOY-08", message: `artifact readiness not verified for candidate "${input.candidateId}"`, gate: input.gate, }; } if (req.requiresDurableSync && !input.durableSyncVerified) { return { ok: false, ruleId: "CERT-DEPLOY-09", message: `durable sync not verified for gate "${input.gate}" — deployment denied`, gate: input.gate, }; } return { ok: true, authorized: true, gate: input.gate, channel: req.channel, candidateId: input.candidateId, decisionId: input.gateDecision.decisionId, requiresMainVerification: req.requiresMainVerification, requiresDurableSync: req.requiresDurableSync, }; } export interface MainVerificationInputV1 { candidateId: string; mainVerificationDecision: MainVerificationDecisionV1; durableSyncVerified: boolean; artifactHash: Sha256Digest; priorOperationRef: Sha256Digest | null; } export interface MainVerificationResultV1 { ok: true; certified: boolean; candidateId: string; decisionId: string; rootDossierRef: Sha256Digest; } export interface MainVerificationFailureV1 { ok: false; ruleId: string; message: string; } export type MainVerificationOutcomeV1 = MainVerificationResultV1 | MainVerificationFailureV1; export function verifyMainPromotion(input: MainVerificationInputV1): MainVerificationOutcomeV1 { if (input.mainVerificationDecision.candidateId !== input.candidateId) { return { ok: false, ruleId: "CERT-DEPLOY-10", message: `main verification decision candidate "${input.mainVerificationDecision.candidateId}" does not match "${input.candidateId}"`, }; } if (input.mainVerificationDecision.status !== "pass") { return { ok: false, ruleId: "CERT-DEPLOY-11", message: `main verification status is "${input.mainVerificationDecision.status}", not "pass" — promotion denied`, }; } if (!input.durableSyncVerified) { return { ok: false, ruleId: "CERT-DEPLOY-12", message: `durable sync not verified after main verification — certification denied`, }; } return { ok: true, certified: true, candidateId: input.candidateId, decisionId: input.mainVerificationDecision.decisionId, rootDossierRef: input.mainVerificationDecision.rootDossierRef, }; } export interface RollbackEvaluationInputV1 { candidateId: string; failedGate: CertificationGate; rollbackCandidateId: string; rollbackArtifactHash: Sha256Digest; rollbackArtifactReadinessVerified: boolean; sharedOutageDetected: boolean; } export interface RollbackEvaluationResultV1 { ok: true; rollbackAuthorized: boolean; reason: string; rollbackCandidateId: string; } export interface RollbackEvaluationFailureV1 { ok: false; ruleId: string; message: string; } export type RollbackEvaluationOutcomeV1 = RollbackEvaluationResultV1 | RollbackEvaluationFailureV1; export function evaluateRollback(input: RollbackEvaluationInputV1): RollbackEvaluationOutcomeV1 { if (input.sharedOutageDetected) { return { ok: true, rollbackAuthorized: false, reason: "shared infrastructure outage detected — rollback to equally affected candidate is not useful", rollbackCandidateId: input.rollbackCandidateId, }; } if (!input.rollbackArtifactReadinessVerified) { return { ok: true, rollbackAuthorized: false, reason: `rollback candidate "${input.rollbackCandidateId}" artifact is not ready — cannot restore`, rollbackCandidateId: input.rollbackCandidateId, }; } if (input.rollbackCandidateId === input.candidateId) { return { ok: true, rollbackAuthorized: false, reason: "rollback target is the same as the failed candidate — nothing to restore", rollbackCandidateId: input.rollbackCandidateId, }; } return { ok: true, rollbackAuthorized: true, reason: `rollback from failed gate "${input.failedGate}" to verified candidate "${input.rollbackCandidateId}"`, rollbackCandidateId: input.rollbackCandidateId, }; } export interface CrashRecoveryStateV1 { operationId: string; candidateId: string; channel: GateChannel; lastPersistedState: DeploymentOperationState; artifactPersisted: boolean; trafficSwitched: boolean; verificationStarted: boolean; verificationCompleted: boolean; statePersisted: boolean; } export interface CrashRecoveryResultV1 { ok: true; resumeFrom: DeploymentOperationState; action: "resume-verification" | "resume-rollback" | "restart-deployment" | "quarantine"; reason: string; } export interface CrashRecoveryFailureV1 { ok: false; ruleId: string; message: string; } export type CrashRecoveryOutcomeV1 = CrashRecoveryResultV1 | CrashRecoveryFailureV1; export function evaluateCrashRecovery(state: CrashRecoveryStateV1): CrashRecoveryOutcomeV1 { if (state.verificationCompleted && !state.statePersisted) { return { ok: true, resumeFrom: "verifying", action: "resume-verification", reason: "verification completed but state not persisted — re-verify and persist", }; } if (state.trafficSwitched && !state.verificationStarted) { return { ok: true, resumeFrom: "deployed", action: "resume-verification", reason: "traffic switched but verification not started — start verification", }; } if (state.trafficSwitched && state.verificationStarted && !state.verificationCompleted) { return { ok: true, resumeFrom: "verifying", action: "resume-verification", reason: "verification started but not completed — resume verification", }; } if (state.artifactPersisted && !state.trafficSwitched) { return { ok: true, resumeFrom: "deployed", action: "resume-verification", reason: "artifact deployed but traffic not switched — proceed to verification", }; } if (!state.artifactPersisted) { return { ok: true, resumeFrom: "authorized", action: "restart-deployment", reason: "artifact not persisted — restart deployment from authorized state", }; } if (state.lastPersistedState === "rolled-back") { return { ok: true, resumeFrom: "rolled-back", action: "quarantine", reason: "rollback completed — quarantine and open incident", }; } return { ok: false, ruleId: "CERT-DEPLOY-13", message: `crash recovery state is ambiguous — cannot determine resume point from state "${state.lastPersistedState}"`, }; } export interface DeploymentEffectRecordV1 { schema: "werkstatt/deployment-effect-record@1"; effectHash: Sha256Digest; operationId: string; candidateId: string; gate: CertificationGate; channel: GateChannel; artifactHash: Sha256Digest; decisionId: string; durableSyncVerified: boolean; mainVerificationDecisionId: string | null; state: DeploymentOperationState; timestamp: string; workerVersionId?: string; releaseId?: string; } export function buildDeploymentEffectRecord( operationId: string, candidateId: string, gate: CertificationGate, channel: GateChannel, artifactHash: Sha256Digest, decisionId: string, durableSyncVerified: boolean, mainVerificationDecisionId: string | null, state: DeploymentOperationState, timestamp: string, workerVersionId?: string, releaseId?: string, ): DeploymentEffectRecordV1 { const recordData = { operationId, candidateId, gate, channel, artifactHash, decisionId, durableSyncVerified, mainVerificationDecisionId, state, timestamp, workerVersionId, releaseId, }; const effectHash = byteHash(JSON.stringify(recordData)) as Sha256Digest; return { schema: "werkstatt/deployment-effect-record@1", effectHash, ...recordData, }; } export function gateFromChannel(channel: GateChannel): CertificationGate { switch (channel) { case "dev": return "dev-deploy"; case "alt": return "propagate-alt"; case "main": return "promote-main"; } } export function isForceBypassRequested(input: { forceRequested: boolean; skipRequested: boolean; waiverRequested: boolean; graceRequested: boolean; }): boolean { return ( input.forceRequested || input.skipRequested || input.waiverRequested || input.graceRequested ); } export { validateDeploymentTransition, validateArtifactTransition }; export type { ReleaseArtifactState };