ic_backup/ops/persistence/operation_plan/mod.rs
1//! Immutable bounded operation plan publication and original local intent admission.
2
3use super::{BackupLayoutGuard, JournalLockError, PersistenceError, immutable_record};
4use crate::model::{
5 artifacts::ArtifactChecksumRecord,
6 operation_plan::{MAX_OPERATION_PLAN_BYTES, OperationPlanRecord},
7};
8use thiserror::Error;
9
10/// Durably create fixed `operation-plan.json` without replacing prior evidence.
11///
12/// The embedded inventory/graph are the declaration's original bindings; separate
13/// retained inventory/graph files are not adopted or rewritten by this operation.
14///
15/// # Errors
16/// Rejects excessive canonical bytes, unsafe/existing entries, replaced roots and IO/locks.
17pub fn create_operation_plan(
18 layout: &BackupLayoutGuard,
19 record: &OperationPlanRecord,
20) -> Result<(), OperationPlanPersistenceError> {
21 immutable_record::create(
22 layout,
23 "operation-plan.json",
24 MAX_OPERATION_PLAN_BYTES,
25 record,
26 )
27}
28
29/// Admit bounded validated local plan under its exact original expected intent digest.
30///
31/// Lost creation responses reconcile through this exact local read. This observes
32/// no remote authority, does not create/reset journals and grants no dispatch permit.
33///
34/// # Errors
35/// Rejects unsafe/missing/oversized/invalid declarations, digest mismatch and ownership failures.
36pub fn read_operation_plan(
37 layout: &BackupLayoutGuard,
38 expected: &ArtifactChecksumRecord,
39) -> Result<OperationPlanRecord, OperationPlanPersistenceError> {
40 immutable_record::read(
41 layout,
42 "operation-plan.json",
43 MAX_OPERATION_PLAN_BYTES,
44 |record: &OperationPlanRecord| &record.digest() == expected,
45 || OperationPlanPersistenceError::DigestMismatch,
46 )
47}
48
49/// Typed original operation-plan identity or bounded immutable local admission failure.
50#[derive(Debug, Error)]
51pub enum OperationPlanPersistenceError {
52 /// Retained declaration differs from the exact original selected intent digest.
53 #[error("operation plan digest mismatch")]
54 DigestMismatch,
55 /// Cooperating layout/journal ownership failed.
56 #[error(transparent)]
57 Lock(#[from] JournalLockError),
58 /// Bounded JSON, model admission or durable filesystem access failed.
59 #[error(transparent)]
60 Persistence(#[from] PersistenceError),
61}
62
63#[cfg(all(test, unix))]
64mod tests;