Implement verified OCI prepared-lower lifecycle

This commit is contained in:
ms2k 2026-07-15 15:22:02 +09:00
commit 5458460717

View file

@ -8,7 +8,9 @@ use lazaret_core::identity::{
DeviceId, DomainId, GenerationId, HostPath, IdMapDigest, InodeId, PolicyId, PrepareOperationId,
PreparedArtifactId, SelectedManifestDigest, SourceIdentity,
};
use lazaret_core::records::{ArtifactLease, ArtifactState, PrepareOperation, PreparedArtifact};
use lazaret_core::records::{
ArtifactLease, ArtifactState, PrepareOperation, PrepareStageState, PreparedArtifact,
};
use lazaret_linux::filesystem::try_exclusive_flock;
use lazaret_storage_catalog::{Catalog, CatalogError, CatalogRow};
use redb::{Database, TableDefinition};
@ -52,16 +54,29 @@ impl Fixture {
operation_id: PrepareOperationId::new([seed; 32]),
expected_artifact_id: artifact.prepared_artifact_id,
source_identity: artifact.source_identity.clone(),
selected_manifest_digest: artifact.selected_manifest_digest,
policy_id: artifact.policy_id,
id_map_digest: artifact.id_map_digest,
stage_path: HostPath::new(format!("stages/{seed}").into_bytes()),
device: DeviceId::new(u64::from(seed) + 200),
inode: InodeId::new(u64::from(seed) + 300),
stage_state: PrepareStageState::Owned,
device: Some(artifact.device),
inode: Some(artifact.inode),
}
}
fn publish(&self, seed: u8) -> PreparedArtifact {
let artifact = Self::artifact(seed);
let operation = Self::prepare(&artifact, seed);
self.catalog.record_prepare(&operation).unwrap();
let intent = PrepareOperation {
stage_state: PrepareStageState::Intent,
device: None,
inode: None,
..operation.clone()
};
self.catalog.record_prepare(&intent).unwrap();
self.catalog
.bind_prepare_stage(&intent, &operation)
.unwrap();
self.catalog.publish(&operation, &artifact).unwrap();
artifact
}
@ -97,10 +112,20 @@ fn publication_is_one_exact_transaction() {
let fixture = Fixture::new();
let artifact = Fixture::artifact(2);
let operation = Fixture::prepare(&artifact, 2);
fixture.catalog.record_prepare(&operation).unwrap();
let intent = PrepareOperation {
stage_state: PrepareStageState::Intent,
device: None,
inode: None,
..operation.clone()
};
fixture.catalog.record_prepare(&intent).unwrap();
fixture
.catalog
.bind_prepare_stage(&intent, &operation)
.unwrap();
let mut forged = operation.clone();
forged.inode = InodeId::new(999);
forged.inode = Some(InodeId::new(999));
assert!(matches!(
fixture.catalog.publish(&forged, &artifact),
Err(CatalogError::OwnershipMismatch {