Add the lock-owned transactional Domain Store

This commit is contained in:
ms2k 2026-07-15 14:01:46 +09:00
commit e4d9cc2dc9
5 changed files with 1197 additions and 292 deletions

View file

@ -206,32 +206,6 @@ impl PidfsProcessIdentityV1 {
}
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct LegacyUnverifiedProcessIdentityV1 {
host_pid: HostPidLocator,
start_time_ticks: ProcessStartTimeTicks,
}
impl LegacyUnverifiedProcessIdentityV1 {
#[must_use]
pub const fn new(host_pid: HostPidLocator, start_time_ticks: ProcessStartTimeTicks) -> Self {
Self {
host_pid,
start_time_ticks,
}
}
#[must_use]
pub const fn host_pid(&self) -> HostPidLocator {
self.host_pid
}
#[must_use]
pub const fn start_time_ticks(&self) -> ProcessStartTimeTicks {
self.start_time_ticks
}
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct NamespaceIdentity {
pub device: DeviceId,
@ -252,10 +226,10 @@ mod tests {
use super::{
BootId, ContainerId, CoordinatorId, DeviceId, DomainId, GenerationId, GuestProcessId,
GuestProcessStartTimeTicks, HostPidLocator, LegacyUnverifiedProcessIdentityV1,
MountIdentity, NamespaceIdentity, NetworkSidecarId, PidfsDeviceId, PidfsInodeId,
PidfsProcessAuthorityV1, PidfsProcessIdentityV1, PreparedArtifactId, ProcessStartTimeTicks,
RequestId, SandboxId, SessionId,
GuestProcessStartTimeTicks, HostPidLocator, MountIdentity, NamespaceIdentity,
NetworkSidecarId, PidfsDeviceId, PidfsInodeId, PidfsProcessAuthorityV1,
PidfsProcessIdentityV1, PreparedArtifactId, ProcessStartTimeTicks, RequestId, SandboxId,
SessionId,
};
#[test]
@ -273,7 +247,6 @@ mod tests {
TypeId::of::<BootId>(),
TypeId::of::<PidfsProcessAuthorityV1>(),
TypeId::of::<PidfsProcessIdentityV1>(),
TypeId::of::<LegacyUnverifiedProcessIdentityV1>(),
TypeId::of::<HostPidLocator>(),
TypeId::of::<ProcessStartTimeTicks>(),
TypeId::of::<GuestProcessId>(),

View file

@ -8,11 +8,10 @@ use crate::identity::{
BundleDigest, CapabilityId, CertificateDigest, ClientId, ConfigurationFingerprint, ContainerId,
CoordinatorId, DerivedPolicyDigest, DeviceId, DomainId, FileDescriptor, GenerationId,
GuestProcessGroupId, GuestProcessId, GuestProcessStartTimeTicks, HostPath, IdMapDigest,
InodeId, LegacyUnverifiedProcessIdentityV1, MountIdentity, NamespaceIdentity, NetworkSidecarId,
PidfsProcessAuthorityV1, PidfsProcessIdentityV1, PolicyId, PrepareOperationId,
PreparedArtifactId, ProtocolCredentialId, ReadinessFingerprint, RequestDigest, RequestId,
SandboxId, SelectedManifestDigest, SessionAnchorId, SessionId, SourceIdentity, StreamDigest,
TrustManifestDigest,
InodeId, MountIdentity, NamespaceIdentity, NetworkSidecarId, PidfsProcessAuthorityV1,
PidfsProcessIdentityV1, PolicyId, PrepareOperationId, PreparedArtifactId, ProtocolCredentialId,
ReadinessFingerprint, RequestDigest, RequestId, SandboxId, SelectedManifestDigest,
SessionAnchorId, SessionId, SourceIdentity, StreamDigest, TrustManifestDigest,
};
mod configuration;

View file

@ -1,10 +1,8 @@
use super::{BTreeMap, Deserialize, HostPath, Serialize};
pub const DOMAIN_STORE_SCHEMA_ID: &str = "lazaret-domain-store-v2";
pub const LEGACY_DOMAIN_STORE_SCHEMA_ID: &str = "lazaret-domain-store-v1";
pub const DOMAIN_STORE_SCHEMA_ID: &str = "lazaret-domain-store-v1";
pub const STORAGE_CATALOG_SCHEMA_ID: &str = "lazaret-storage-catalog-v1";
pub const DOMAIN_STORE_SCHEMA_VERSION: u32 = 2;
pub const LEGACY_DOMAIN_STORE_SCHEMA_VERSION: u32 = 1;
pub const DOMAIN_STORE_SCHEMA_VERSION: u32 = 1;
pub const STORAGE_CATALOG_SCHEMA_VERSION: u32 = 1;
pub const TRUSTED_HOST_CONFIGURATION_SCHEMA_ID: &str = "lazaret-trusted-host-config-v1";

View file

@ -2,11 +2,10 @@ use super::{
BundleDigest, ClientId, ConfigurationFingerprint, ContainerId, CoordinatorId,
DOMAIN_STORE_SCHEMA_ID, DOMAIN_STORE_SCHEMA_VERSION, DerivedPolicyDigest, Deserialize,
DeviceId, DomainId, FileDescriptor, GenerationId, GuestProcessGroupId, GuestProcessId,
GuestProcessStartTimeTicks, HostPath, InodeId, LEGACY_DOMAIN_STORE_SCHEMA_ID,
LEGACY_DOMAIN_STORE_SCHEMA_VERSION, LegacyUnverifiedProcessIdentityV1, MountIdentity,
NamespaceIdentity, NetworkReadinessEvidence, NetworkSidecarId, PidfsProcessIdentityV1,
PreparedArtifactId, ReadinessFingerprint, RecordInvariantError, RecordTransitionError,
RequestId, STORAGE_CATALOG_SCHEMA_ID, STORAGE_CATALOG_SCHEMA_VERSION, SandboxId, Serialize,
GuestProcessStartTimeTicks, HostPath, InodeId, MountIdentity, NamespaceIdentity,
NetworkReadinessEvidence, NetworkSidecarId, PidfsProcessIdentityV1, PreparedArtifactId,
ReadinessFingerprint, RecordInvariantError, RecordTransitionError, RequestId,
STORAGE_CATALOG_SCHEMA_ID, STORAGE_CATALOG_SCHEMA_VERSION, SandboxId, Serialize,
SessionAnchorId, SessionId, SourceIdentity, fmt,
};
@ -18,21 +17,13 @@ pub struct StoreMetadata {
impl StoreMetadata {
#[must_use]
pub fn domain_store_v2() -> Self {
pub fn domain_store_v1() -> Self {
Self {
schema_id: DOMAIN_STORE_SCHEMA_ID.into(),
schema_version: DOMAIN_STORE_SCHEMA_VERSION,
}
}
#[must_use]
pub fn legacy_domain_store_v1() -> Self {
Self {
schema_id: LEGACY_DOMAIN_STORE_SCHEMA_ID.into(),
schema_version: LEGACY_DOMAIN_STORE_SCHEMA_VERSION,
}
}
#[must_use]
pub fn storage_catalog_v1() -> Self {
Self {
@ -56,11 +47,6 @@ impl StoreMetadata {
&& self.schema_version == DOMAIN_STORE_SCHEMA_VERSION
}
fn is_legacy_domain_store(&self) -> bool {
self.schema_id == LEGACY_DOMAIN_STORE_SCHEMA_ID
&& self.schema_version == LEGACY_DOMAIN_STORE_SCHEMA_VERSION
}
fn is_storage_catalog(&self) -> bool {
self.schema_id == STORAGE_CATALOG_SCHEMA_ID
&& self.schema_version == STORAGE_CATALOG_SCHEMA_VERSION
@ -83,10 +69,7 @@ impl<'de> Deserialize<'de> for StoreMetadata {
schema_id: fields.schema_id,
schema_version: fields.schema_version,
};
if metadata.is_domain_store()
|| metadata.is_legacy_domain_store()
|| metadata.is_storage_catalog()
{
if metadata.is_domain_store() || metadata.is_storage_catalog() {
Ok(metadata)
} else {
Err(serde::de::Error::custom(
@ -100,24 +83,9 @@ impl<'de> Deserialize<'de> for StoreMetadata {
pub struct DomainStoreMetadata(StoreMetadata);
impl DomainStoreMetadata {
#[must_use]
pub fn v2() -> Self {
Self(StoreMetadata::domain_store_v2())
}
#[must_use]
pub const fn as_metadata(&self) -> &StoreMetadata {
&self.0
}
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
pub struct LegacyDomainStoreMetadata(StoreMetadata);
impl LegacyDomainStoreMetadata {
#[must_use]
pub fn v1() -> Self {
Self(StoreMetadata::legacy_domain_store_v1())
Self(StoreMetadata::domain_store_v1())
}
#[must_use]
@ -126,22 +94,6 @@ impl LegacyDomainStoreMetadata {
}
}
impl<'de> Deserialize<'de> for LegacyDomainStoreMetadata {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let metadata = StoreMetadata::deserialize(deserializer)?;
if metadata.is_legacy_domain_store() {
Ok(Self(metadata))
} else {
Err(serde::de::Error::custom(
"expected legacy Domain Store v1 metadata",
))
}
}
}
impl<'de> Deserialize<'de> for DomainStoreMetadata {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
@ -235,42 +187,17 @@ pub enum ParticipantState {
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub enum HostProcessIdentity {
PidfsV1(PidfsProcessIdentityV1),
LegacyUnverifiedV1(LegacyUnverifiedProcessIdentityV1),
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct LegacyProcessIdentityRefusal;
impl fmt::Display for LegacyProcessIdentityRefusal {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("legacy PID/start-only process identity has no positive authority")
}
}
impl std::error::Error for LegacyProcessIdentityRefusal {}
pub struct HostProcessIdentity(PidfsProcessIdentityV1);
impl HostProcessIdentity {
#[must_use]
pub const fn pidfs_v1(identity: PidfsProcessIdentityV1) -> Self {
Self::PidfsV1(identity)
Self(identity)
}
#[must_use]
pub const fn legacy_unverified_v1(identity: LegacyUnverifiedProcessIdentityV1) -> Self {
Self::LegacyUnverifiedV1(identity)
}
/// # Errors
/// Legacy PID/start-only data has no positive authority.
pub const fn verified_pidfs(
&self,
) -> Result<&PidfsProcessIdentityV1, LegacyProcessIdentityRefusal> {
match self {
Self::PidfsV1(identity) => Ok(identity),
Self::LegacyUnverifiedV1(_) => Err(LegacyProcessIdentityRefusal),
}
pub const fn pidfs(&self) -> &PidfsProcessIdentityV1 {
&self.0
}
}
@ -297,11 +224,6 @@ impl PersistedHostProcessOwnership {
Self::Committed(HostProcessIdentity::pidfs_v1(identity))
}
#[must_use]
pub const fn legacy_unverified(identity: LegacyUnverifiedProcessIdentityV1) -> Self {
Self::Committed(HostProcessIdentity::legacy_unverified_v1(identity))
}
#[must_use]
pub const fn is_staged(&self) -> bool {
matches!(self, Self::Staged(_))
@ -314,7 +236,7 @@ impl PersistedHostProcessOwnership {
#[must_use]
pub const fn is_current_committed(&self) -> bool {
matches!(self, Self::Committed(HostProcessIdentity::PidfsV1(_)))
matches!(self, Self::Committed(_))
}
const fn is_initial_acquisition(&self) -> bool {
@ -326,29 +248,22 @@ impl PersistedHostProcessOwnership {
}
/// # Errors
/// Unassigned or legacy-unverified ownership has no positive authority.
/// Unassigned ownership has no positive authority.
pub fn authoritative_pidfs(&self) -> Result<&PidfsProcessIdentityV1, ProcessAuthorityRefusal> {
match self {
Self::Unassigned => Err(ProcessAuthorityRefusal::Unassigned),
Self::Staged(identity) | Self::Committed(HostProcessIdentity::PidfsV1(identity)) => {
Ok(identity)
}
Self::Committed(HostProcessIdentity::LegacyUnverifiedV1(_)) => {
Err(ProcessAuthorityRefusal::LegacyUnverified)
}
Self::Staged(identity) => Ok(identity),
Self::Committed(identity) => Ok(identity.pidfs()),
}
}
/// # Errors
/// Unassigned, staged, or legacy-unverified ownership is not serviceable.
/// Unassigned or staged ownership is not serviceable.
pub fn serviceable_pidfs(&self) -> Result<&PidfsProcessIdentityV1, ProcessOwnershipRefusal> {
match self {
Self::Unassigned => Err(ProcessOwnershipRefusal::Unassigned),
Self::Staged(_) => Err(ProcessOwnershipRefusal::Staged),
Self::Committed(HostProcessIdentity::PidfsV1(identity)) => Ok(identity),
Self::Committed(HostProcessIdentity::LegacyUnverifiedV1(_)) => {
Err(ProcessOwnershipRefusal::LegacyUnverified)
}
Self::Committed(identity) => Ok(identity.pidfs()),
}
}
}
@ -357,7 +272,6 @@ impl PersistedHostProcessOwnership {
pub enum ProcessOwnershipRefusal {
Unassigned,
Staged,
LegacyUnverified,
}
impl fmt::Display for ProcessOwnershipRefusal {
@ -365,8 +279,6 @@ impl fmt::Display for ProcessOwnershipRefusal {
match self {
Self::Unassigned => formatter.write_str("process ownership is unassigned"),
Self::Staged => formatter.write_str("process ownership is staged, not committed"),
Self::LegacyUnverified => formatter
.write_str("legacy PID/start-only process ownership has no positive authority"),
}
}
}
@ -376,15 +288,12 @@ impl std::error::Error for ProcessOwnershipRefusal {}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ProcessAuthorityRefusal {
Unassigned,
LegacyUnverified,
}
impl fmt::Display for ProcessAuthorityRefusal {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Unassigned => formatter.write_str("process ownership is unassigned"),
Self::LegacyUnverified => formatter
.write_str("legacy PID/start-only process ownership has no positive authority"),
}
}
}
@ -1507,8 +1416,8 @@ fn validate_process_progress(
) if old == next => Ok(()),
(
PersistedHostProcessOwnership::Staged(old),
PersistedHostProcessOwnership::Committed(HostProcessIdentity::PidfsV1(next)),
) if old == next => Ok(()),
PersistedHostProcessOwnership::Committed(next),
) if old == next.pidfs() => Ok(()),
(
PersistedHostProcessOwnership::Committed(old),
PersistedHostProcessOwnership::Committed(next),
@ -1525,7 +1434,7 @@ fn validate_existing_process_progress(
(old, next),
(
PersistedHostProcessOwnership::Unassigned,
PersistedHostProcessOwnership::Committed(HostProcessIdentity::PidfsV1(_))
PersistedHostProcessOwnership::Committed(_)
)
) {
Ok(())

View file

@ -4,20 +4,20 @@ use super::{
DerivedNetworkPolicy, DeveloperDecision, DeveloperDecisionKind, DnsObservation, Domain,
DomainStore, EnvironmentReference, EscalationOutcome, Generation, GenerationIdentity,
GitRoutingOwnership, GuestProcessIdentity, HelperOwnership, HostProcessIdentity,
HostProcessOwnershipSlot, LegacyUnverifiedProcessIdentityV1, Mailbox, MailboxCancellation,
MailboxRequest, MailboxResult, MailboxResultAck, MailboxResultChunk, MountIdentity,
NamespaceIdentity, NetworkObservation, NetworkOwnership, NetworkReachabilityProbe,
NetworkReadinessAttestation, NetworkReadinessEvidence, NetworkReadinessIdentity, Participant,
ParticipantOwnership, ParticipantState, PermittedDestinationObservation,
PersistedHostProcessOwnership, PidfsProcessAuthorityV1, PidfsProcessIdentityV1, PolicyAction,
PolicyDelivery, PrefixRule, PrepareOperation, PreparedArtifact, PreparedLowerOwnership,
ProcessOwnershipCommitAck, ProcessOwnershipMessageVersion, ProtocolCredential,
ProtocolCredentialRole, ProtocolPublicationIdentity, PtyIdentity, PublicationOwnership,
ResolvedAutoApprovalRule, ResolvedVolume, Resolver, ResultStream, SandboxCredentialBundle,
SandboxOwnership, Session, SessionBinding, SessionClose, SessionExit, SessionExitOutcome,
SessionRequestCapability, SessionTerminal, SessionTerminalEvent, SessionTerminalMessage,
SessionTerminalState, SignedProtocolRecord, StagedProcessOwnership, StateAnchorOwnership,
StorageCatalog, StoreMetadata, TerminalInput, TerminalOutput, TerminalResize, TerminalSignal,
HostProcessOwnershipSlot, Mailbox, MailboxCancellation, MailboxRequest, MailboxResult,
MailboxResultAck, MailboxResultChunk, MountIdentity, NamespaceIdentity, NetworkObservation,
NetworkOwnership, NetworkReachabilityProbe, NetworkReadinessAttestation,
NetworkReadinessEvidence, NetworkReadinessIdentity, Participant, ParticipantOwnership,
ParticipantState, PermittedDestinationObservation, PersistedHostProcessOwnership,
PidfsProcessAuthorityV1, PidfsProcessIdentityV1, PolicyAction, PolicyDelivery, PrefixRule,
PrepareOperation, PreparedArtifact, PreparedLowerOwnership, ProcessOwnershipCommitAck,
ProcessOwnershipMessageVersion, ProtocolCredential, ProtocolCredentialRole,
ProtocolPublicationIdentity, PtyIdentity, PublicationOwnership, ResolvedAutoApprovalRule,
ResolvedVolume, Resolver, ResultStream, SandboxCredentialBundle, SandboxOwnership, Session,
SessionBinding, SessionClose, SessionExit, SessionExitOutcome, SessionRequestCapability,
SessionTerminal, SessionTerminalEvent, SessionTerminalMessage, SessionTerminalState,
SignedProtocolRecord, StagedProcessOwnership, StateAnchorOwnership, StorageCatalog,
StoreMetadata, TerminalInput, TerminalOutput, TerminalResize, TerminalSignal,
TerminalSignalKind, TlsCredential, TlsRole, TrustManifest, TrustedHostConfigurationV1,
};
@ -55,7 +55,6 @@ schema_types!(
"PtyIdentity" => PtyIdentity,
"PidfsProcessAuthorityV1" => PidfsProcessAuthorityV1,
"PidfsProcessIdentityV1" => PidfsProcessIdentityV1,
"LegacyUnverifiedProcessIdentityV1" => LegacyUnverifiedProcessIdentityV1,
"HostProcessIdentity" => HostProcessIdentity,
"PersistedHostProcessOwnership" => PersistedHostProcessOwnership,
"HostProcessOwnershipSlot" => HostProcessOwnershipSlot,