Skip to main content

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;