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
29pub(super) fn create_encoded(
30    layout: &BackupLayoutGuard,
31    bytes: &[u8],
32) -> Result<(), OperationPlanPersistenceError> {
33    immutable_record::create_encoded_record(layout, "operation-plan.json", bytes)
34}
35
36/// Admit bounded validated local plan under its exact original expected intent digest.
37///
38/// Lost creation responses reconcile through this exact local read. This observes
39/// no remote authority, does not create/reset journals and grants no dispatch permit.
40///
41/// # Errors
42/// Rejects unsafe/missing/oversized/invalid declarations, digest mismatch and ownership failures.
43pub fn read_operation_plan(
44    layout: &BackupLayoutGuard,
45    expected: &ArtifactChecksumRecord,
46) -> Result<OperationPlanRecord, OperationPlanPersistenceError> {
47    immutable_record::read(
48        layout,
49        "operation-plan.json",
50        MAX_OPERATION_PLAN_BYTES,
51        |record: &OperationPlanRecord| &record.digest() == expected,
52        || OperationPlanPersistenceError::DigestMismatch,
53    )
54}
55
56/// Typed original operation-plan identity or bounded immutable local admission failure.
57#[derive(Debug, Error)]
58pub enum OperationPlanPersistenceError {
59    /// Retained declaration differs from the exact original selected intent digest.
60    #[error("operation plan digest mismatch")]
61    DigestMismatch,
62    /// Cooperating layout/journal ownership failed.
63    #[error(transparent)]
64    Lock(#[from] JournalLockError),
65    /// Bounded JSON, model admission or durable filesystem access failed.
66    #[error(transparent)]
67    Persistence(#[from] PersistenceError),
68}
69
70#[cfg(all(test, unix))]
71mod tests;