Skip to main content

Module secure

Module secure 

Source
Expand description

Secure ORM layer for scoped database access.

This module provides a type-safe wrapper around SeaORM that enforces access control scoping at compile time using the typestate pattern.

§Basic Example

Creating and using access scopes:

use modkit_db::secure::{AccessScope, pep_properties};
use uuid::Uuid;

// Create an empty scope (deny-all)
let deny_scope = AccessScope::default();
assert!(deny_scope.is_deny_all());

// Create a tenant-scoped access
let tenant_id = Uuid::new_v4();
let scope = AccessScope::for_tenant(tenant_id);
assert!(scope.has_property(pep_properties::OWNER_TENANT_ID));
assert!(!scope.is_deny_all());

// Create a resource-scoped access
let resource_id = Uuid::new_v4();
let resource_scope = AccessScope::for_resource(resource_id);
assert!(resource_scope.has_property(pep_properties::RESOURCE_ID));

§Quick Start with SeaORM

use modkit_db::secure::{AccessScope, SecureEntityExt, Scopable};
use sea_orm::entity::prelude::*;

// 1. Derive Scopable for your entity (or implement manually)
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Scopable)]
#[sea_orm(table_name = "users")]
#[secure(
    tenant_col = "tenant_id",
    resource_col = "id",
    no_owner,
    no_type
)]
pub struct Model {
    #[sea_orm(primary_key)]
    pub id: Uuid,
    pub tenant_id: Uuid,
    pub email: String,
}

// 2. Create an access scope
let scope = AccessScope::for_tenants(vec![tenant_id]);

// 3. Execute scoped queries
let users = Entity::find()
    .secure()
    .scope_with(&scope)?
    .all(conn)
    .await?;

§Manual Implementation

If you prefer not to use the derive macro:

use modkit_db::secure::ScopableEntity;

impl ScopableEntity for Entity {
    fn tenant_col() -> Option<Self::Column> {
        Some(Column::TenantId)
    }
    fn resource_col() -> Option<Self::Column> {
        Some(Column::Id)
    }
    fn owner_col() -> Option<Self::Column> {
        None
    }
    fn type_col() -> Option<Self::Column> {
        None
    }
}

§Features

  • Typestate enforcement: Prevents unscoped queries at compile time
  • Implicit policy: Automatic deny-all for empty scopes
  • Multi-tenant support: Enforces tenant isolation when applicable
  • Resource-level access: Fine-grained control via explicit IDs
  • Zero runtime overhead: All checks at compile/build time

§Policy

ScopeBehavior
EmptyDeny all (WHERE 1=0)
Tenants onlyFilter by tenant column
Resources onlyFilter by ID column
BothAND them together

See the docs module for comprehensive examples and usage patterns.

Re-exports§

pub use provider::SimpleTenantFilter;
pub use provider::TenantFilterProvider;

Modules§

docs
Secure ORM Layer Documentation
pep_properties
Well-known authorization property names.
provider

Structs§

AccessScope
A disjunction (OR) of scope constraints defining what data is accessible.
Db
Database handle for secure operations.
DbConn
Non-transactional database runner.
DbTx
Transactional database runner.
EqScopeFilter
Equality scope filter: property = value.
InScopeFilter
Set membership scope filter: property IN (values).
InfraError
Infrastructure error representing a database-level failure.
ScopeConstraint
A conjunction (AND) of scope filters — one access path.
Scoped
Typestate marker: query has been scoped with access control. Can now execute queries safely.
SecureConn
Secure database connection wrapper.
SecureDeleteMany
A type-safe wrapper around SeaORM’s DeleteMany that enforces scoping.
SecureInsertOne
A type-safe wrapper around SeaORM’s Insert that enforces scoping.
SecureOnConflict
A secure builder for ON CONFLICT DO UPDATE clauses that enforces tenant immutability.
SecureSelect
A type-safe wrapper around SeaORM’s Select that enforces scoping.
SecureSelectTwo
A type-safe wrapper around SeaORM’s SelectTwo that enforces scoping.
SecureSelectTwoMany
A type-safe wrapper around SeaORM’s SelectTwoMany that enforces scoping.
SecureTx
Secure transaction wrapper (capability).
SecureUpdateMany
A type-safe wrapper around SeaORM’s UpdateMany that enforces scoping.
TxConfig
Configuration for database transactions.
Unscoped
Typestate marker: query has not yet been scoped. Cannot execute queries in this state.

Enums§

ScopeError
Errors that can occur during scoped query execution.
ScopeFilter
A single scope filter — a typed predicate on a named resource property.
ScopeValue
A scalar value for scope filtering.
TxAccessMode
Transaction access mode.
TxError
Transaction error that distinguishes domain errors from infrastructure errors.
TxIsolationLevel
Transaction isolation level.

Constants§

DEFAULT_TX_RETRY_ATTEMPTS
Default attempt budget for Db::transaction_with_retry.

Traits§

ScopableEntity
Defines the contract for entities that can be scoped by tenant, resource, owner, and type.
SecureDeleteExt
Extension trait to convert a regular SeaORM DeleteMany into a SecureDeleteMany.
SecureEntityExt
Extension trait to convert a regular SeaORM Select into a SecureSelect.
SecureFindRelatedExt
Extension trait to perform secure find_related queries from a model instance.
SecureInsertExt
Extension trait to convert a regular SeaORM Insert into a SecureInsertOne.
SecureUpdateExt
Extension trait to convert a regular SeaORM UpdateMany into a SecureUpdateMany.

Functions§

is_unique_violation
Check whether a sea_orm::DbErr represents a unique-constraint violation.
secure_insert
Secure insert helper for Scopable entities.
secure_update_with_scope
Secure update helper for updating a single entity by ID inside a scope.
validate_tenant_in_scope
Helper to validate a tenant ID is in the scope.

Derive Macros§

Scopable
Derive macro for implementing ScopableEntity.