fix: recover and fence atomic activation

This commit is contained in:
2026-09-02 11:49:49 +03:00
parent 79e5d04395
commit a8fa09e21e
12 changed files with 1733 additions and 543 deletions

View File

@@ -1,34 +1,79 @@
export interface TransactionInput {
root: string;
archivePath: string;
transactionId: string;
verifierModulePath: string;
trustPolicyPath: string;
uid: number;
gid: number;
now?: string;
clock?: () => string;
verifySignedReleaseEnvelope?: (input: any) => any;
smokeCheck?: (input: { releaseDir: string; manifestDigest: string }) => Promise<Uint8Array>;
smokeCommand?: string;
expectedCurrentManifestDigest?: string | null;
expectedFence?: number;
crashPoint?: 'before-swap' | 'after-swap';
targetReleaseId?: string;
}
export interface ControlState {
schema: 'portfolio-release-control-state/v1';
export interface ProtectedControlState {
schema: "portfolio-release-control-state/v1";
currentManifestDigest: string | null;
currentReleaseId: string | null;
publisherFence: number;
latestLedgerHeadHash: string;
latestLedgerRevision: number;
releaseTrustPolicyDigest: string;
activeTransaction: null | Record<string, unknown>;
}
export function readControlState(root: string): Promise<ControlState>;
export function prepareRelease(input: TransactionInput): Promise<Record<string, unknown>>;
export function activateRelease(input: TransactionInput): Promise<Record<string, any>>;
export function rollbackRelease(input: TransactionInput): Promise<Record<string, any>>;
export interface ProductionPrepareInput {
root: string;
archivePath: string;
transactionId: string;
smokeCommand: string;
}
export interface ProductionActivateInput {
root: string;
transactionId: string;
expectedCurrentManifestDigest: string | null;
expectedFence: number;
}
export interface ProductionRollbackInput
extends ProductionPrepareInput, ProductionActivateInput {
targetReleaseId: string;
}
export interface TestTransactionInput {
root: string;
archivePath: string;
transactionId: string;
testOnlyVerification: {
trustPolicyPath: string;
verifySignedReleaseEnvelope: (input: any) => any;
};
testClock?: () => string;
smokeCheck?: (input: {
releaseDir: string;
manifestDigest: string;
}) => Promise<Uint8Array>;
smokeCommand?: string;
expectedCurrentManifestDigest?: string | null;
expectedFence?: number;
crashPoint?: "before-swap" | "after-swap";
testPreparationCrashPoint?:
| "after-intent"
| "after-extract"
| "after-immutable"
| "after-release-rename"
| "after-receipt";
testBeforeCommit?: () => Promise<void>;
testBeforePointerSwap?: () => Promise<void>;
targetReleaseId?: string;
lock?: boolean;
}
export function readControlState(root: string): Promise<ProtectedControlState>;
export function prepareRelease(
input: ProductionPrepareInput,
): Promise<Record<string, unknown>>;
export function prepareReleaseForTest(
input: TestTransactionInput,
): Promise<Record<string, unknown>>;
export function activateRelease(
input: ProductionActivateInput,
): Promise<Record<string, any>>;
export function activateReleaseForTest(
input: TestTransactionInput,
): Promise<Record<string, any>>;
export function rollbackRelease(
input: ProductionRollbackInput,
): Promise<Record<string, any>>;
export function rollbackReleaseForTest(
input: TestTransactionInput,
): Promise<Record<string, any>>;
export function cleanupOrphanStages(root: string): Promise<string[]>;