crates.io ↗

iet-core

core contract official

Defines the shared vocabulary: errors, validation, call context, sessions, transactions, queries, persistence metadata.

CoreFeaturesIntegrationsStacksTooling
Used byiet-appiet-authiet-auth-acliet-auth-acl-timescaleiet-auth-basiciet-auth-basic-axumiet-auth-basic-timescaleiet-auth-identity-timescale+28 more
iet-corecontractContracts and neutral primitives
Depends onnothing — it stands alone

How to use it

iet-core holds the implementation-neutral primitives every feature builds on: AppError/ErrorKind, Principal/CallContext, Session/CallScope, Validate, Operation/Access, Authorizer, transactions, and pagination. Inputs declare the access they require, and operation::check enforces access before validation identically at every boundary.

rust
// examples/handbook-notes/src/note.rs (+ src/service.rs)
use iet_core::operation::{Access, Operation, check};
use iet_core::{AppError, AppResult, CallContext, ErrorKind, FieldError, Validate};

impl Validate for CreateNote {
    fn validate(&self) -> AppResult<()> {
        if self.text.trim().is_empty() {
            let mut error = AppError::new(
                ErrorKind::Validation, "note.text_required", "A note needs some text",
            );
            error.fields.push(FieldError { path: "text".into(), code: "required".into() });
            return Err(error);
        }
        Ok(())
    }
}
impl Operation for CreateNote {
    type Input = Self;
    const ACCESS: Access = Access::Public; // or Authenticated / Permission("...")
}

// In the service; runs the access check first, then validates.
check::<CreateNote, _>(&authorizer, &CallContext::default(), &input).await?;
  • check performs access control before validate, so unauthorized input is never validated.
  • CallScope::require_resource guards against a session for the wrong ResourceId.

Core contract

This page is the crate reference. For the framework-wide runtime and trait model, read Architecture.

What it implements

  • Defines the traits other crates implement: UseCase, SessionFactory, Validate, Session, Authorizer, TransactionSession, Permission, Event, Operation, Persistent, QueryField.

What's inside

Modules

  • src/lib.rs
  • src/module.rs
  • src/operation.rs
  • src/persistence.rs
  • src/query.rs

Public API

(root)

  • trait UseCase — A statically wired single-operation application contract.
rust
pub trait UseCase<I, O, S: Session>: Send + Sync {
    fn execute(
        &self,
        input: I,
        scope: &mut CallScope<'_, S>,
    ) -> impl Future<Output = AppResult<O>> + Send;
}
  • trait SessionFactory — Factory implementations decide how to acquire the execution resource.
rust
pub trait SessionFactory: Send + Sync {
    type Session: Session;
    fn open(&self) -> impl Future<Output = AppResult<Self::Session>> + Send;
}
  • type AppResult — Application operation result.
  • enum ErrorKind
  • struct FieldError
  • struct AppError
  • struct ErrorDiagnostic
  • pub fn new(kind: ErrorKind, code: impl Into<String>, message: impl Into<String>) -> Self
  • pub fn with_diagnostic( mut self, component: impl Into<String>, cause_code: impl Into<String>, ) -> Self — Supply a safe classification/SQLSTATE, not raw payloads or credential-bearing URLs.
  • pub fn diagnostic(&self) -> Option<&ErrorDiagnostic>
  • trait Validate — Pure input validation, invoked by guarded service entrypoints.
rust
pub trait Validate {
    fn validate(&self) -> AppResult<()>;
}
  • struct Principal
  • struct CallContext
  • struct ResourceId
  • trait Session — Per-invocation execution session, implemented by a feature.
rust
pub trait Session: Send {
    fn resource_id(&self) -> &ResourceId;
}
  • struct CallScope — Exclusive session borrow propagated across feature port calls.
  • pub fn new(context: &'a CallContext, session: &'a mut S) -> Self
  • pub fn context(&self) -> &CallContext
  • pub fn session(&mut self) -> &mut S
  • pub fn require_resource(&self, expected: &ResourceId) -> AppResult<()>
  • trait Authorizer — Typed policy implementation; core does not assume RBAC or ACL semantics.
rust
pub trait Authorizer: Send + Sync {
    fn authorize(
        &self,
        context: &CallContext,
        permission: &str,
    ) -> impl Future<Output = AppResult<()>> + Send;
}
  • enum Patch
  • enum TransactionState
  • trait TransactionSession — Database feature lifecycle. Cancellation cleanup remains a driver obligation.
rust
pub trait TransactionSession: Session {
    fn state(&self) -> TransactionState;
    fn mark_rollback_only(&mut self);
    fn begin(&mut self) -> impl Future<Output = AppResult<()>> + Send;
    fn commit(&mut self) -> impl Future<Output = AppResult<()>> + Send;
    fn rollback(&mut self) -> impl Future<Output = AppResult<()>> + Send;
}
  • trait Permission — Contract metadata consumed by transport/policy adapters, not an access grant.
rust
pub trait Permission {
    const NAME: &'static str;
}
  • trait Event
rust
pub trait Event {
    const NAME: &'static str;
}
  • struct TransactionScope — Borrowed ownership token. Dropping unfinished work poisons the transaction; asynchronous rollback is performed by the outer owner or database driver.
  • pub fn session(&mut self) -> &mut S

module

  • struct ModuleDescriptor
  • pub fn order_modules(modules: &[ModuleDescriptor]) -> AppResult<Vec<&ModuleDescriptor>> — Deterministic dependency-first ordering with strict missing/cycle checks.

operation

  • enum Access
  • trait Operation
rust
pub trait Operation {
    type Input: Validate + Sync;
    const ACCESS: Access;
}

persistence

  • struct Hypertable
  • trait Persistent
rust
pub trait Persistent {
    const TABLE: &'static str;
    const SOFT_DELETE_COLUMN: Option<&'static str> = Some("deleted_at");
    const HYPERTABLE: Option<Hypertable> = None;
    const COLUMNS: &'static [Column] = &[];
    const IDENTITY_COLUMNS: &'static [&'static str] = &[];
    const DEFAULTS: &'static [(&'static str, &'static str)] = &[];
    const PRIMARY_KEY: &'static [&'static str] = &[];
    const CHECKS: &'static [&'static str] = &[];
    const INDEXES: &'static [Index] = &[];
    const FOREIGN_KEYS: &'static [ForeignKey] = &[];
}
  • struct ForeignKey — Stable-key relationship. Soft deletion does not remove referenced rows.
  • struct Index
  • enum ColumnType
  • struct Column

query

  • trait QueryField — Explicit transport field allowlist, independent of SQL column mappings.
rust
pub trait QueryField: Sized {
    fn resolve(name: &str) -> Option<Self>;
    fn name(&self) -> &'static str;
}
  • struct Pagination
  • pub fn new(page: u64, limit: u32, max_limit: u32, max_offset: u64) -> AppResult<Self>
  • pub fn page(self) -> u64
  • pub fn limit(self) -> u32
  • pub fn offset(self) -> u64
  • enum Direction
  • struct Sort
  • pub fn parse_sort<F: PartialEq>( input: &str, max_fields: usize, resolve: impl Fn(&str) -> Option<F>, ) -> AppResult<Vec<Sort<F>>> — The caller supplies the allowlisted typed field resolver, never SQL identifiers.
  • struct ListQuery
  • struct Page
  • struct CursorPagination
  • pub fn new( after: Option<String>, before: Option<String>, limit: u32, max_limit: u32, max_cursor_bytes: usize, ) -> AppResult<Self>

Impl map

  • std::fmt::Display for AppError
  • std::error::Error for AppError
  • Drop for TransactionScope<'_, S>
  • Wake for ThreadWake
  • Session for FakeSession
  • TransactionSession for FakeSession
  • Authorizer for Deny
  • Validate for MustNotValidate
  • Validate for Input
  • Operation for Public
  • Operation for Authenticated
  • Operation for Restricted

Depends on

  • No other framework crate: it stands alone.

Used by

In this repository

  • examples/handbook-notes
  • examples/htmx-starter
  • examples/reusable-notes
  • examples/skills-only-app
  • examples/skills-only-app-task-tracker

Source: crates/core/iet-core