Skip to main content

ic_memory/
lib.rs

1#![forbid(unsafe_code)]
2#![deny(rustdoc::broken_intra_doc_links)]
3#![doc = include_str!("../README.md")]
4
5//! Stable-memory allocation-governance primitives for Internet Computer
6//! canister upgrades.
7//!
8//! `ic-memory` prevents stable-memory slot drift.
9//!
10//! Once a stable key is committed to a physical allocation slot, future binaries
11//! must either reopen that same stable key on that same slot or declare a new
12//! stable key.
13//!
14//! The crate records and validates durable ownership in both directions: an
15//! active stable key cannot move to a different physical slot, and an active
16//! physical slot cannot be reused by a different stable key.
17//!
18//! The intended integration flow is:
19//!
20//! 1. Recover the persisted allocation ledger.
21//! 2. Declare the stable stores expected by the current binary.
22//! 3. Validate those declarations against ledger history and any framework
23//!    policy.
24//! 4. Commit the next generation.
25//! 5. Only then open stable-memory handles through a validated allocation
26//!    session.
27//!
28//! This crate owns allocation invariants, not framework policy. Namespace
29//! rules, range ownership, controller authorization, endpoint lifecycle, schema
30//! migrations, and application validation belong to the framework or
31//! application.
32//!
33//! Use these primitives before opening stable-memory handles. Integrations
34//! should recover the historical ledger, declare the stores expected by the
35//! current binary, validate declarations against history and policy, commit a
36//! new generation, and only then publish a validated allocation session that can
37//! open slots through a storage substrate.
38//!
39//! [`AllocationBootstrap`] is the golden path for whichever layer owns a given
40//! ledger store. Canic may own bootstrap for a framework canister and compose
41//! IcyDB/application declarations through its registry; IcyDB may own bootstrap
42//! directly for generated database stores; or a standalone application canister
43//! may own bootstrap itself. Exactly one owner should bootstrap one ledger
44//! store. Multiple layers in the same canister must either compose declarations
45//! into that owner or use distinct ledger stores and allocation domains.
46//!
47//! `ic-stable-structures` `MemoryManager` IDs are the first-class supported
48//! physical slot substrate. The crate still keeps narrow internal abstractions
49//! for storage adapters and diagnostics, but the native IC path is
50//! `MemoryManager` ID 0 -> `ic-stable-structures::Cell<StableCellLedgerRecord,
51//! _>` -> [`LedgerCommitStore`] -> committed [`AllocationLedger`] payloads.
52//!
53//! `ic-memory` is not a replacement for `ic-stable-structures` collections and
54//! does not wrap typed stores such as `StableBTreeMap`.
55
56pub mod bootstrap;
57pub mod declaration;
58pub mod diagnostics;
59pub mod key;
60pub mod ledger;
61pub mod physical;
62pub mod policy;
63pub mod schema;
64pub mod session;
65pub mod slot;
66pub mod stable_cell;
67pub mod substrate;
68pub mod validation;
69
70pub use ic_stable_structures as stable_structures;
71
72pub use bootstrap::{
73    AllocationBootstrap, BootstrapCommit, BootstrapError, BootstrapReservationError,
74    BootstrapRetirementError,
75};
76pub use declaration::{
77    AllocationDeclaration, DeclarationCollector, DeclarationSnapshot, DeclarationSnapshotError,
78};
79pub use diagnostics::{DiagnosticExport, DiagnosticGeneration, DiagnosticRecord};
80pub use key::{StableKey, StableKeyError};
81pub use ledger::{
82    AllocationHistory, AllocationLedger, AllocationRecord, AllocationReservationError,
83    AllocationRetirement, AllocationRetirementError, AllocationStageError, AllocationState,
84    CURRENT_LEDGER_SCHEMA_VERSION, CURRENT_PHYSICAL_FORMAT_ID, CborLedgerCodec, GenerationRecord,
85    LedgerCodec, LedgerCommitError, LedgerCommitStore, LedgerCompatibility,
86    LedgerCompatibilityError, LedgerIntegrityError, SchemaMetadataRecord,
87};
88pub use physical::{
89    AuthoritativeSlot, CommitRecoveryError, CommitSlotDiagnostic, CommitSlotIndex,
90    CommitStoreDiagnostic, CommittedGenerationBytes, DualCommitStore, DualProtectedCommitStore,
91    ProtectedGenerationSlot, select_authoritative_slot,
92};
93pub use policy::AllocationPolicy;
94pub use schema::{SchemaMetadata, SchemaMetadataError};
95pub use session::{AllocationSession, AllocationSessionError, ValidatedAllocations};
96pub use slot::{
97    AllocationSlot, AllocationSlotDescriptor, IC_MEMORY_AUTHORITY_OWNER,
98    IC_MEMORY_AUTHORITY_PURPOSE, IC_MEMORY_LEDGER_LABEL, IC_MEMORY_LEDGER_STABLE_KEY,
99    IC_MEMORY_STABLE_KEY_PREFIX, MEMORY_MANAGER_DESCRIPTOR_VERSION,
100    MEMORY_MANAGER_GOVERNANCE_MAX_ID, MEMORY_MANAGER_INVALID_ID, MEMORY_MANAGER_LEDGER_ID,
101    MEMORY_MANAGER_MAX_ID, MEMORY_MANAGER_MIN_ID, MEMORY_MANAGER_SUBSTRATE,
102    MemoryManagerAuthorityRecord, MemoryManagerIdRange, MemoryManagerRangeAuthority,
103    MemoryManagerRangeAuthorityError, MemoryManagerRangeError, MemoryManagerRangeMode,
104    MemoryManagerSlotError, is_ic_memory_stable_key, memory_manager_governance_range,
105    validate_memory_manager_id,
106};
107pub use stable_cell::{
108    STABLE_CELL_HEADER_SIZE, STABLE_CELL_LAYOUT_VERSION, STABLE_CELL_MAGIC,
109    STABLE_CELL_VALUE_OFFSET, StableCellLedgerRecord, StableCellPayloadError,
110    decode_stable_cell_ledger_record, decode_stable_cell_payload,
111};
112pub use substrate::{LedgerAnchor, StorageSubstrate};
113pub use validation::{AllocationValidationError, validate_allocations};