chio-store-sqlite 0.1.2

SQLite-backed persistence, query, and report implementations for Chio
Documentation
use super::*;

impl SqliteBudgetStore {
    pub(super) fn require_standalone_mutation(
        &self,
        operation: &str,
    ) -> Result<(), BudgetStoreError> {
        if self.serving_owner.is_none() {
            return Ok(());
        }
        let mut connection = self.connection()?;
        let transaction = connection.transaction_with_behavior(TransactionBehavior::Deferred)?;
        crate::serving_owner::verify_budget_fence(&transaction, self.serving_owner.as_deref())?;
        if let Some(owner) = self.serving_owner.as_ref() {
            owner
                .verify_authority_anchor(&transaction)
                .map_err(crate::budget_store::store::map_serving_owner_error)?;
        }
        transaction.rollback()?;
        Err(BudgetStoreError::Invariant(format!(
            "joint sqlite authority rejects legacy {operation} mutation"
        )))
    }

    pub(super) fn reject_structured_hold_from_legacy_writer(
        transaction: &rusqlite::Transaction<'_>,
        hold_id: Option<&str>,
        operation: &str,
    ) -> Result<(), BudgetStoreError> {
        let Some(hold_id) = hold_id else {
            return Ok(());
        };
        type Row = (
            String,
            Option<String>,
            Option<String>,
            Option<i64>,
            Option<i64>,
            Option<bool>,
            Option<bool>,
            Option<i64>,
            Option<i64>,
            bool,
            bool,
            bool,
            bool,
            bool,
        );
        let row: Option<Row> = transaction
            .query_row(
                r#"
                SELECT projection_kind, operation_id, revocation_set_digest,
                       expected_quota_count, expected_artifact_count,
                       has_cumulative_approval, has_revocation_commit,
                       expected_revocation_count, trusted_capture_time,
                       EXISTS(SELECT 1 FROM budget_hold_revocation_members
                              WHERE hold_id = parent.hold_id),
                       EXISTS(SELECT 1 FROM budget_hold_quota_members
                              WHERE hold_id = parent.hold_id),
                       EXISTS(SELECT 1 FROM budget_hold_authorization_artifacts
                              WHERE hold_id = parent.hold_id),
                       EXISTS(SELECT 1 FROM budget_cumulative_approval_operations
                              WHERE hold_id = parent.hold_id),
                       EXISTS(SELECT 1 FROM budget_hold_revocation_commits
                              WHERE hold_id = parent.hold_id)
                FROM budget_authorization_holds AS parent WHERE hold_id = ?1
                "#,
                rusqlite::params![hold_id],
                |row| {
                    Ok((
                        row.get(0)?,
                        row.get(1)?,
                        row.get(2)?,
                        row.get(3)?,
                        row.get(4)?,
                        row.get(5)?,
                        row.get(6)?,
                        row.get(7)?,
                        row.get(8)?,
                        row.get(9)?,
                        row.get(10)?,
                        row.get(11)?,
                        row.get(12)?,
                        row.get(13)?,
                    ))
                },
            )
            .optional()?;
        match row {
            None => Ok(()),
            Some(row) if row.0 == "composite_v1" => Err(BudgetStoreError::Invariant(format!(
                "legacy {operation} cannot mutate structured budget hold `{hold_id}`"
            ))),
            Some(row)
                if row.0 == "legacy"
                    && row.1.is_none()
                    && row.2.is_none()
                    && row.3.is_none()
                    && row.4.is_none()
                    && row.5.is_none()
                    && row.6.is_none()
                    && row.7.is_none()
                    && row.8.is_none()
                    && !row.9
                    && !row.10
                    && !row.11
                    && !row.12
                    && !row.13 =>
            {
                Ok(())
            }
            Some(_) => Err(BudgetStoreError::Invariant(format!(
                "budget hold `{hold_id}` has an inconsistent projection discriminator"
            ))),
        }
    }

    pub(super) fn reject_legacy_admission_after_composite_history(
        transaction: &rusqlite::Transaction<'_>,
        capability_id: &str,
        grant_index: usize,
    ) -> Result<(), BudgetStoreError> {
        let exists = transaction.query_row(
            r#"
            SELECT EXISTS(
                SELECT 1 FROM budget_mutation_events
                WHERE capability_id = ?1 AND grant_index = ?2
                  AND projection_kind = 'composite_v1'
            )
            "#,
            rusqlite::params![capability_id, grant_index as i64],
            |row| row.get::<_, bool>(0),
        )?;
        if exists {
            return Err(BudgetStoreError::Invariant(format!(
                "legacy budget admission is disabled after structured history for `{capability_id}` grant {grant_index}"
            )));
        }
        Ok(())
    }
}