enlil 0.1.1

Vendor-neutral open-source control and audit plane for AI agent actions. Sits inline between your agents and any model or tool: enforce what each agent may do, and prove what it did.
Documentation
# Contributing to Enlil

Thanks for looking. Enlil is a security tool, so the bar for changes on the
request path is "demonstrated with a test", not "looks right".

## The most valuable contribution: a new detection

If you know a technique Enlil misses — a prompt-injection phrasing, an
exfiltration pattern, a tool-poisoning vector, an encoding trick — that is the
most useful thing you can send.

**Send it as a failing test first.** A test that fails before your change and
passes after is worth more than a long explanation:

```rust
#[test]
fn test_my_bypass_is_caught() {
    let v = analyze(&serde_json::json!({
        "messages": [{"role": "user", "content": "<the payload that gets through>"}]
    }));
    assert_eq!(v.action, GuardAction::Block, "findings {:?}", v.findings);
}
```

If you'd rather not open a public issue for a bypass, email **security@samji.in**
and we'll handle it privately and credit you in the release notes.

## Ground rules for the hot path

Enforcement runs synchronously on every request, so:

1. **Don't re-parse the body.** The request is parsed once into a
   `serde_json::Value` and shared across every analyzer. Take the parsed value.
2. **Bound your work.** Anything that recurses needs a depth cap; anything that
   scans needs a byte budget. A hostile payload will find an unbounded loop.
3. **Watch the budget.** `tests/proxy_overhead_bench.rs` asserts a per-request
   overhead budget and runs in CI. If your change makes it fail, that's a real
   signal, not a flaky test.
4. **Scan structurally, not per-vendor.** Do not add a detection that only works
   for one provider's field names. Enlil walks the whole payload precisely so it
   isn't playing catch-up with every new API shape.

## False positives matter as much as false negatives

A control plane that blocks legitimate traffic gets turned off, and then it
protects nothing. Any new detection should come with a benign case proving it
doesn't fire on ordinary traffic. See
`test_benign_multivendor_payloads_still_allowed`.

## Before you open a PR

```bash
cargo test                          # unit + integration
cargo clippy --all-targets -- -D warnings
cargo fmt --all
cargo test --release --test proxy_overhead_bench -- --nocapture
```

Clippy is a hard gate in CI. Formatting is checked but non-blocking.

## Scope

Enlil is deliberately single-tenant with no auth layer — it assumes the operator
owns the process. Multi-tenancy, SSO/RBAC, and long-term retention are out of
scope here by design; they live in the commercial build. PRs adding them will be
declined, not because they're bad ideas, but because they'd change what this
crate is.

Bug fixes, detections, performance, protocol coverage, docs, and packaging are
all in scope and welcome.

## Licence

Contributions are accepted under the repository's [BSL 1.1](LICENSE), which
converts to Apache 2.0 on the Change Date. By opening a PR you agree your
contribution ships under those terms.