Skip to main content

ic_backup/ops/persistence/
mod.rs

1//! Durable publication, journal/layout exclusion and retained local dependencies.
2
3mod artifact_commit;
4mod attempt_journal;
5mod command_lifetime_lock;
6mod consistency;
7mod directory_custody;
8mod download_journal;
9mod effect_graph;
10mod execution_progress;
11mod execution_settlement;
12mod execution_workflow;
13mod fence_obligation;
14mod file_lock;
15mod immutable_record;
16mod inventory;
17mod journal_lock;
18mod json;
19mod layout_lifetime;
20mod operation_plan;
21mod publication_error;
22mod restore_reference_release;
23mod restore_safety;
24
25pub use artifact_commit::{ArtifactCommitOutcome, commit_artifact_directory};
26pub use attempt_journal::{AttemptJournalError, AttemptJournalGuard};
27pub use command_lifetime_lock::{
28    COMMAND_CUSTODY_DESCRIPTOR_ENV, CommandLifetimeLock, CommandLifetimeLockError,
29    CommandQuiescenceGuard,
30};
31pub use consistency::{
32    ConsistencyPersistenceError, create_consistency_requirement, read_consistency_requirement,
33};
34pub use download_journal::{
35    DownloadIntegrityError, DownloadJournalError, DownloadJournalGuard, DownloadManifestError,
36    LocalRestoreArtifactError, LocalRestoreArtifactPublicationError, LocalRestoreArtifactView,
37    LocalRestoreSourceError, read_download_manifest,
38};
39#[cfg(unix)]
40pub use download_journal::{
41    IcSnapshotArtifactError, IcSnapshotArtifactWriter, IcSnapshotDataUploadPreparationError,
42    IcSnapshotLocalMetrics, IcSnapshotUploadArtifactError, MeasurementAggregate,
43    MeasurementHistogram, MeasurementSummary,
44};
45pub use effect_graph::{EffectGraphPersistenceError, create_effect_graph, read_effect_graph};
46pub use execution_progress::{ExecutionProgressPersistenceError, read_execution_progress};
47pub use execution_settlement::{
48    ExecutionSettlementCheckpointError, ExecutionSettlementPersistenceError,
49    checkpoint_execution_settlement, create_execution_settlement, read_execution_settlement,
50    reconcile_execution_settlement, replay_execution_settlement,
51};
52pub(crate) use execution_workflow::read_execution_stage_occupancy;
53pub use execution_workflow::{
54    ExecutionStageCheckpointError, ExecutionStageGuard, ExecutionStagePreparationError,
55    ExecutionStageResumeError, ExecutionStageSettlementView, ExecutionWorkflowPersistenceError,
56    ExecutionWorkflowSettlementView, create_execution_workflow, read_complete_execution_workflow,
57    read_execution_workflow,
58};
59pub use fence_obligation::{
60    FenceObligationPersistenceError, FenceObligationRequirement, create_fence_obligation,
61    read_fence_obligation,
62};
63pub use inventory::{InventoryError, create_inventory, read_inventory};
64pub use journal_lock::{JournalLock, JournalLockError};
65pub use json::{create_json_durable, read_json, write_json_durable};
66pub use layout_lifetime::{BackupLayoutGuard, MAX_RESTORE_REFERENCE_BYTES};
67pub use operation_plan::{
68    OperationPlanPersistenceError, create_operation_plan, read_operation_plan,
69};
70pub use publication_error::PublicationError;
71pub use restore_reference_release::{
72    MAX_RESTORE_TERMINAL_BYTES, RestoreReferenceReleaseError, RestoreReferenceReleaseOutcome,
73    RestoreTerminalEvidenceProvider,
74};
75pub use restore_safety::{
76    RestoreSafetyPersistenceError, create_restore_safety_requirement,
77    read_restore_safety_requirement,
78};
79
80use crate::{model::artifacts::ChecksumError, ops::artifacts::ArtifactError};
81use std::io;
82use thiserror::Error;
83
84/// Typed local persistence failure.
85#[derive(Debug, Error)]
86pub enum PersistenceError {
87    /// An existing layout path no longer denotes the held directory.
88    #[error("backup layout changed while held: {path:?}")]
89    LayoutChanged {
90        /// Resolved layout location.
91        path: std::path::PathBuf,
92    },
93    /// A retained dependency document or journal location has an unsafe entry type.
94    #[error("unsafe restore reference entry: {path:?}")]
95    InvalidRestoreReferences {
96        /// Rejected local path.
97        path: std::path::PathBuf,
98    },
99    /// Restore dependency validation or an immutable retention transition failed.
100    #[error(transparent)]
101    RestoreReference(#[from] crate::model::restore_references::RestoreReferenceError),
102    /// Parent preparation, record reads or other local filesystem IO failed.
103    /// Shared JSON publication failures retain their separate structured boundary.
104    #[error(transparent)]
105    Io(#[from] io::Error),
106    /// File publication failed, retaining producer/cleanup causes and visibility.
107    /// An after-publication failure leaves output visible and requires reconciliation.
108    #[error(transparent)]
109    Publication(#[from] PublicationError),
110    /// JSON encoding or decoding failed.
111    #[error(transparent)]
112    Json(#[from] serde_json::Error),
113    /// A machine record exceeds its caller-selected byte bound.
114    #[error("record exceeds byte limit {limit}")]
115    RecordTooLarge {
116        /// Maximum accepted bytes.
117        limit: u64,
118    },
119    /// Artifact traversal or streaming failed.
120    #[error(transparent)]
121    Artifact(#[from] ArtifactError),
122    /// Verified bytes do not match the expected checksum.
123    #[error(transparent)]
124    Checksum(#[from] ChecksumError),
125    /// Publication requires distinct siblings in one directory.
126    #[error("artifact commit paths must be distinct siblings: {temporary}, {canonical}")]
127    ArtifactCommitPathMismatch {
128        /// Retained staging path.
129        temporary: String,
130        /// Canonical destination.
131        canonical: String,
132    },
133    /// Both staging and canonical trees exist; neither is overwritten.
134    #[error("artifact commit has conflicting paths: {temporary}, {canonical}")]
135    ArtifactCommitPathConflict {
136        /// Retained staging path.
137        temporary: String,
138        /// Existing canonical destination.
139        canonical: String,
140    },
141    /// Neither expected tree exists.
142    #[error("artifact commit is missing both paths: {temporary}, {canonical}")]
143    ArtifactCommitPathMissing {
144        /// Missing staging path.
145        temporary: String,
146        /// Missing canonical destination.
147        canonical: String,
148    },
149    /// Atomic no-replace directory publication is unsupported.
150    #[error("durable artifact publication is unsupported on {platform}")]
151    ArtifactCommitUnsupportedPlatform {
152        /// Host platform name.
153        platform: &'static str,
154    },
155    /// Publication found an unsafe tree entry.
156    #[error("unsupported artifact entry at {path}: {kind}")]
157    UnsupportedArtifactEntry {
158        /// Entry path.
159        path: String,
160        /// Observed entry kind.
161        kind: String,
162    },
163}