Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

requisite

requisite makes data-handling requirements part of Rust function signatures. Values carry the state required by the next operation, and APIs state that requirement in their parameter types.

use requisite::prelude::*;

fn db_lookup(id: Tainted<u64, Trusted>) -> String { /* ... */ }

let body = Tainted::<_, Untrusted>::from_input(request_body);
let customer_id = sanitize(body, clean_customer_id);
db_lookup(customer_id);

The receiving function states its requirement in its parameter type. The compiler then verifies that callers perform the required transition.

module role
trust routes external input through a named sanitizer before trusted use
confidence converts a probability into an action tier and issues proof for the highest tier
fresh checks TTLs at read time and binds scoped values to their use site

Installation

cargo add requisite

requisite supports Rust 1.70 and later.

Guides

guide use it to
Getting started add requisite and build an end-to-end flow
Trust transitions route external input through infallible or fallible policies
Confidence gates validate probabilities and authorize high-confidence actions
Freshness enforce TTLs, recover stale values, and scope live data
Integration patterns place wrappers at application boundaries and design typed APIs

Trust

use requisite::prelude::*;

fn db_lookup(id: Tainted<u64, Trusted>) -> String { /* ... */ }

let raw = Tainted::<_, Untrusted>::from_input("42; DROP TABLE customers".into());

println!("{:?}", raw.as_ref());

let clean = try_sanitize(raw, |s| {
    s.chars()
        .filter(char::is_ascii_digit)
        .collect::<String>()
        .parse::<u64>()
})?;
db_lookup(clean);

Tainted<T, Untrusted> marks data at an input boundary. sanitize handles infallible transformations, while try_sanitize returns validation errors to the caller. Successful transitions produce Tainted<U, Trusted>, which trusted sinks accept directly.

The sanitizer closure defines what “trusted” means for a specific sink. Keep the destination's cleaning policy in that closure. widen() supports APIs that accept a lower trust requirement.

See Trust transitions for validation, type-changing policies, and sink design.

Confidence

Confident<T> carries a value and a validated probability. gate() applies the default thresholds, and gate_with() accepts application-defined thresholds.

let aurora = Confident::new(forecast(kp_index), 0.97)?;

let plan = match aurora.gate() {
    Gate::HighConfidence(proof, _) => {
        wake_slepp(proof);
        "woke him up"
    }
    Gate::Likely(_) => {
        buzz_phone();
        "sent a buzz"
    }
    Gate::Unsure(_) => "logged it",
};

The highest tier includes a Certain token. Functions such as wake_slepp can require that token, making a successful confidence check part of their call contract. Lower tiers remain available for proportionate actions such as a notification or log entry.

let forecast = Confident::new(predicted_event, 0.99)?;
let thresholds = Thresholds::new(0.70, 0.98)?;
match forecast.gate_with(thresholds) {
    Gate::HighConfidence(proof, value) => act(proof, value),
    Gate::Likely(value) => notify(value),
    Gate::Unsure(value) => record(value),
}

Custom thresholds may raise the Certain boundary above 0.95. The lower bound keeps every Certain token consistent for functions that require one.

See Confidence gates for threshold configuration and typed action authorization.

Freshness

let quote = Fresh::fetch(price, Duration::from_secs(30));

match quote.get() {
    Ok(price) => charge(customer, *price),
    Err(stale) => println!("price is {} old, refetching", stale.age.as_secs()),
}

Fresh::get compares the value's age with its TTL and returns either the value or a Stale error containing both durations. into_inner performs the same check while consuming the wrapper, allowing ownership of a fresh non-Clone value to move into the next operation. A stale result returns the value in StaleValue<T>. fetched_at supports deterministic tests and rejects timestamps ahead of the current monotonic clock.

with_live handles values whose validity is tied to one operation:

with_live(price, |live| {
    let total = live.get().cents + tax;
    total
});

The branded Live value stays within the closure while derived owned values can be returned. The closure’s return type is independent of the private lifetime brand, so retaining Live produces a lifetime error at the return site.

See Freshness for cache access, stale-value recovery, and deterministic tests.

Enforcement model

requirement enforcement
trusted sink arguments Tainted<T, Trusted> parameter types
confidence-based action tiers Confident::gate(), gate_with(), and Gate<T>
high-confidence action authorization private Certain construction
operation-scoped values branded Live<'id, T> lifetimes
TTL validity Fresh::get() or into_inner() at read time
sanitization policy the closure passed to sanitize or try_sanitize

Runtime checks produce types that carry their result into the next operation. For example, gate() converts a probability into a Gate<T>, and the highest tier carries the Certain token required by sensitive actions.

Compile-time guarantees

tests/ui/ contains compile-fail cases for each type-level contract. trybuild compares the compiler output with checked-in snapshots, so CI detects changes that weaken a contract.

test contract
untrusted_to_sink.rs trusted sinks require sanitized input
widen_upward.rs trust promotion goes through sanitize
confidence_as_bool.rs confidence values go through gate
forge_certain.rs Certain originates from the highest gate tier
escape_live.rs scoped values remain inside their closure

Regenerate snapshots after an intentional compiler diagnostic change:

TRYBUILD=overwrite cargo test --test compile_fail

Review the resulting diff to confirm that each failure still exercises its documented contract.

Try it

cargo run --example payment_flow
cargo test

Layout

src/trust.rs             Tainted<T, Tr>, sanitize, widen
src/confidence.rs        Confident<T>, gate() -> Gate, Certain
src/fresh.rs             Fresh<T> with a TTL; scoped::with_live
examples/payment_flow.rs   payment and alerting example
tests/runtime.rs            behavior tests
tests/ui/*.rs + .stderr     compile-fail tests
docs/                       user guides

License

Licensed under either of

at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

About

Typed validated values, explicit trust transitions, exhaustive confidence levels, and per-value TTL freshness for Rust.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages