Skip to main content

Crate wardline_core

Crate wardline_core 

Source
Expand description

Core vocabulary and execution engine for Wardline.

Wardline evaluates guardrails inline and synchronously, in the caller’s request path: a check returns a blocking verdict before an action is taken or an LLM response is released. No queue, no separate service, no async runtime — a blocked action never happens rather than being detected shortly after it did.

TypeRole
GuardOne check. The trait you implement.
VerdictWhat a guard decided: allow, block, or modify.
GuardErrorWhy a guard reached no decision at all.
FailPolicyWhat the pipeline does about that failure.
ContextPer-request metadata and the deadline.
DeadlineA cooperative wall-clock bound.
PipelineAn ordered list of guards, run in place.
TraceThe bounded record of what each guard did.
MetricsOptional per-guard counters (allow/block/error/panic).

The key distinction: Verdict::Block means the guard said no; GuardError means it said nothing. Failures are resolved by the failing guard’s own FailPolicy, which defaults to FailPolicy::FailClosed, so a broken guard doesn’t silently stop guarding.

Pipeline::evaluate runs guards in order, stops at the first block, and returns the decision together with its Trace — so a caller can log why something was refused, not just that it was. A panic inside a guard becomes GuardError::Panicked and is resolved through that guard’s FailPolicy; it never unwinds past the caller.

Enable the tracing feature to emit a wardline.evaluate span and a wardline.guard span per check, including an error event when a guard panics. Without that feature this crate still depends on nothing outside std. See AGENTS.md for the architectural invariants.

§Example

use wardline_core::{Context, Guard, GuardError, Verdict};

struct NoProfanity;

impl Guard for NoProfanity {
    type Input = str;
    type Output = ();

    fn check(&self, input: &str, _ctx: &Context) -> Result<Verdict, GuardError> {
        if input.contains("darn") {
            return Ok(Verdict::block("profanity detected"));
        }
        Ok(Verdict::Allow)
    }

    fn name(&self) -> &'static str {
        "no_profanity"
    }
}

let ctx = Context::new();
assert_eq!(NoProfanity.check("hello there", &ctx), Ok(Verdict::Allow));
assert!(NoProfanity.check("well darn", &ctx).is_ok_and(|v| v.is_block()));

Structs§

Context
Everything a guard knows about the request beyond the input itself.
Deadline
A point in time by which work is expected to be finished.
GuardCounters
Snapshot of one guard’s counters.
InMemoryMetrics
A process-local Metrics sink, useful in tests and examples.
Pipeline
An ordered list of guards, evaluated in place on the calling thread.
PipelineResult
One evaluation: the decision, and the record of how it was reached.
Trace
Every guard the pipeline ran, in order, with a hard cap on entries.
TraceEntry
One guard’s line in the audit trail.

Enums§

FailPolicy
How the pipeline resolves a guard that errored, timed out, or panicked.
GuardError
Something went wrong while evaluating a guard.
TraceOutcome
What one guard did, as recorded for the audit trail.
Value
A typed metadata value carried in a Context.
Verdict
The outcome of a single guard evaluation.

Traits§

Guard
A single check that runs before an action is allowed to happen.
Metrics
Counts of allow / block / modify / error / panic, keyed by guard name.