Audit & Error

AuditSink Trait

Pluggable audit interface for recording access decisions.

#![allow(unused)]
fn main() {
use schubert::audit::{AuditSink, DecisionRecord};

struct DatabaseAudit { pool: PgPool }

impl AuditSink for DatabaseAudit {
    fn record(&self, record: &DecisionRecord) -> schubert::Result<()> {
        // Write to database, file, log, etc.
        Ok(())
    }
}

acl.set_audit_sink(Box::new(DatabaseAudit { pool }));
}

InMemoryAudit

Built-in audit sink that stores records in memory:

#![allow(unused)]
fn main() {
use schubert::audit::InMemoryAudit;

let sink = InMemoryAudit::new();
acl.set_audit_sink(Box::new(sink));

// After checks...
let records = sink.records();
let filtered = sink.records_for_principal(&alice);
sink.clear();
}

Audit Design

  • Fire-and-forget: Failing sinks never block access decisions
  • Feature-gated: AuditSink requires the std feature
  • No_std: InMemoryAudit uses RefCell, no thread safety

SchubertError

All errors use SchubertError with 11 variants:

VariantWhen
InvalidGrassmanniank ≥ n or k = 0
CapabilityNotFoundReferenced capability not registered
PrincipalNotFoundReferenced principal doesn't exist
AlreadyHoldsDuplicate grant
DoesNotHoldRevoke on unheld capability
InvalidPartitionPartition not weakly decreasing
ImpossibleCompositionGeometric incompatibility
UnderconstrainedToo few conditions
OverconstrainedToo many conditions
SerializationErrorserde I/O failure
VerificationErrorKarpal proof obligation failed