blindplane-access 0.1.0

Signed enterprise access grants, capability policies, revocation and encrypted audit events for Blindplane
Documentation
//! User-scoped access with tenant-administrator visibility.

use blindplane_access::{
    AccessGrant, AccessIssuer, AuditContext, AuditEvent, AuditEventKind, CapabilityKind,
    CapabilityRule, Decision, Effect, GrantSpec, Permissions, PolicySpec, PrincipalKeypair,
    PrincipalKind, RevocationSpec, RevocationState, RoleKeypair, TenantPolicy, open_audit_event,
    seal_audit_event,
};
use blindplane_core::{Author, fastest_payload_suite};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let issuer = AccessIssuer::generate("acme-admin")?;
    let alice = PrincipalKeypair::generate("acme", "alice", PrincipalKind::User, 1)?;
    let admin = PrincipalKeypair::generate("acme", "admin", PrincipalKind::Administrator, 1)?;

    let alice_audit = RoleKeypair::generate("acme", "audit", "alice-audit", 1)?;
    let tenant_audit = RoleKeypair::generate("acme", "audit", "tenant-audit", 1)?;

    let alice_grant = AccessGrant::issue(
        &issuer,
        alice.principal(),
        &alice_audit,
        GrantSpec {
            grant_id: "alice-audit-v1".into(),
            scope: "audit".into(),
            permissions: Permissions::READ | Permissions::WRITE,
            authorization_epoch: 1,
            not_before: 1,
            not_after: u64::MAX,
        },
    )?;
    let admin_grant = AccessGrant::issue(
        &issuer,
        admin.principal(),
        &tenant_audit,
        GrantSpec {
            grant_id: "admin-audit-v1".into(),
            scope: "audit".into(),
            permissions: Permissions::READ | Permissions::OBSERVE,
            authorization_epoch: 1,
            not_before: 1,
            not_after: u64::MAX,
        },
    )?;

    let alice_state = RevocationState::issue(
        &issuer,
        "acme",
        "alice",
        "audit",
        RevocationSpec {
            revision: 1,
            minimum_authorization_epoch: 1,
            minimum_role_key_epoch: 1,
            issued_at: 1,
        },
    )?;
    let admin_state = RevocationState::issue(
        &issuer,
        "acme",
        "admin",
        "audit",
        RevocationSpec {
            revision: 1,
            minimum_authorization_epoch: 1,
            minimum_role_key_epoch: 1,
            issued_at: 1,
        },
    )?;
    let trusted = issuer.trusted();
    let alice_role = alice_grant.open_role(
        &alice,
        &trusted,
        100,
        &alice_state.verify(&trusted, "acme", "alice", "audit")?,
    )?;
    let admin_role = admin_grant.open_role(
        &admin,
        &trusted,
        100,
        &admin_state.verify(&trusted, "acme", "admin", "audit")?,
    )?;

    let policy = TenantPolicy::issue(
        &issuer,
        alice.principal(),
        PolicySpec {
            revision: 1,
            previous_hash: [0; 32],
            authorization_epoch: 1,
            issued_at: 1,
            not_before: 1,
            not_after: u64::MAX,
            rules: vec![CapabilityRule::new(
                CapabilityKind::Mcp,
                "github",
                Effect::Allow,
            )?],
        },
    )?;
    let verified = policy.verify(&trusted, "acme", "alice", 100, 1, 1)?;
    assert_eq!(
        verified.decision(CapabilityKind::Mcp, "github"),
        Decision::Allow
    );
    assert_eq!(
        verified.decision(CapabilityKind::Skill, "deploy"),
        Decision::Deny
    );

    let author = Author::generate()?;
    let event = AuditEvent {
        tenant_id: "acme".into(),
        subject_id: "alice".into(),
        session_id: "session-42".into(),
        sequence: 1,
        timestamp: 100,
        kind: AuditEventKind::Request,
        media_type: "application/json".into(),
        body: br#"{"tool":"github.search","query":"private"}"#.to_vec(),
    };
    let record = seal_audit_event(
        &author,
        AuditContext {
            tenant_id: "acme".into(),
            subject_id: "alice".into(),
            stream_id: "session-42".into(),
            epoch: 1,
            sequence: 1,
        },
        &event,
        &alice_role,
        &admin_role,
        fastest_payload_suite(),
    )?;

    assert_eq!(
        open_audit_event(&record, &alice_role, author.public_key())?,
        event
    );
    assert_eq!(
        open_audit_event(&record, &admin_role, author.public_key())?,
        event
    );
    println!("user and tenant administrator opened the encrypted audit event");
    Ok(())
}