road-runner-common 0.12.1

Shared Rust utilities for exchange ecosystem backend services.
Documentation
use road_runner_common::authz::model::{
    grant_matches, BindingEntry, CompiledBinding, CompiledSnapshot, GrantEntry, PermissionEntry,
    RoleEntry, SnapshotPayload,
};

fn payload() -> SnapshotPayload {
    SnapshotPayload {
        schema: "cex.authz.snapshot.v1".to_string(),
        policy_version: 7,
        issued_at: Some("2026-07-08T00:00:00Z".to_string()),
        permissions: vec![PermissionEntry {
            permission: "finance:write".to_string(),
            declaring_service: Some("finance".to_string()),
            min_acr: Some("aal2".to_string()),
            requires_quorum: true,
        }],
        roles: vec![RoleEntry {
            id: "r1".to_string(),
            name: "Risk".to_string(),
            description: Some("Risk admin".to_string()),
        }],
        grants: vec![
            GrantEntry {
                role_id: "r1".to_string(),
                permission: "finance:*".to_string(),
                effect: "ALLOW".to_string(),
            },
            GrantEntry {
                role_id: "r1".to_string(),
                permission: "finance:delete".to_string(),
                effect: "DENY".to_string(),
            },
        ],
        bindings: vec![
            BindingEntry {
                id: Some("b1".to_string()),
                principal_sub: "sub-1".to_string(),
                binding_type: "ROLE".to_string(),
                role_id: Some("r1".to_string()),
                expires_at: None,
            },
            BindingEntry {
                id: Some("b2".to_string()),
                principal_sub: "sub-1".to_string(),
                binding_type: "EMERGENCY_DENY".to_string(),
                role_id: None,
                expires_at: Some(99),
            },
        ],
    }
}

#[test]
fn compiled_binding_active_respects_expiry() {
    // Arrange
    let permanent = CompiledBinding { is_emergency_deny: false, role_id: Some("r1".to_string()), expires_at: None };
    let expiring = CompiledBinding { is_emergency_deny: false, role_id: None, expires_at: Some(10) };

    // Act / Assert
    assert!(permanent.active(i64::MAX));
    assert!(expiring.active(9));
    assert!(!expiring.active(10));
}

#[test]
fn compiled_snapshot_indexes_bindings_grants_and_permission_metadata() {
    // Arrange
    let payload = payload();

    // Act
    let snapshot = CompiledSnapshot::from_payload(payload);

    // Assert
    assert_eq!(snapshot.version, 7);
    assert_eq!(snapshot.bindings_for("sub-1").len(), 2);
    assert!(snapshot.bindings_for("missing").is_empty());
    assert_eq!(snapshot.grants_for_role("r1").len(), 2);
    assert!(snapshot.grants_for_role("missing").is_empty());
    let meta = snapshot.perm_meta("finance:write").unwrap();
    assert_eq!(meta.min_acr.as_deref(), Some("aal2"));
    assert!(meta.requires_quorum);
}

#[test]
fn grant_matches_supports_exact_domain_wildcard_and_global_wildcard_only() {
    // Arrange / Act / Assert
    assert!(grant_matches("finance:read", "finance:read"));
    assert!(grant_matches("finance:*", "finance:write"));
    assert!(grant_matches("*:*", "risk:write"));
    assert!(!grant_matches("finance:*", "risk:write"));
    assert!(!grant_matches("finance*", "finance:write"));
    assert!(!grant_matches("finance:*", "finance"));
}