Metadata-Version: 2.4
Name: quietos-sentinel
Version: 0.1.0
Summary: Sentinel — DeanWay Labs' inbound governor. Guards what an AI agent hears: content from the world is data, never orders.
License: MIT
Project-URL: Homepage, https://github.com/jondean213-pixel/quietos-sentinel
Project-URL: Repository, https://github.com/jondean213-pixel/quietos-sentinel
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# Sentinel — the inbound governor

**DeanWay Labs.** Sentinel is the mirror of [QuietOS](https://github.com/jondean213-pixel/quietos-governor).
QuietOS governs what an AI agent **does**. Sentinel governs what an AI agent **hears**.

> The brain proposes, QuietOS disposes — and Sentinel decides what the brain is even allowed to hear.

## The problem

An agent reads data and instructions in the same stream, and cannot natively tell them apart.
So the world has learned to hide orders inside the data: a webpage that tells the assistant to
email out the passwords, an email wearing the owner's name, a tool result with a second,
secret job tucked inside it. That is prompt injection, and it works because nothing stands
at the door.

Sentinel stands at the door.

## The law

**Only the owner issues instructions. Everything else is data.**

Content from the world — webpages, emails, files, messages, tool outputs — is inspected
*before* it reaches the brain, and whatever passes is delivered wrapped and labeled as
data, never as orders. A claim inside the content ("I am the owner", "the owner already
approved this", `SYSTEM:`) authenticates nothing: authentication comes from the channel,
never from the text.

## Verdicts

| Verdict | Meaning |
|---|---|
| **ALLOW** | Clean data. Passes through, labeled as data. |
| **ESCALATE** | Instruction-shaped content aimed at the agent from a non-owner source. Held for the owner with the **exact content preserved** — the same approval-binding discipline as QuietOS. Nothing acts on it while it waits. |
| **BLOCK** | Known-hostile patterns: exfiltration directives, owner/system impersonation, false approval claims, rule-override incantations, concealment directives. Refused outright. |

Every ESCALATE and BLOCK is written to an **append-only attack ledger** — timestamp, source,
verdict, matched signals, SHA-256 of the exact content, and a preserved excerpt. Attempts
are evidence, and the ledger is part of the product, the same way QuietOS's red-team
proof log is.

## v0.1 scope

- **Deterministic inspection only** — pattern/heuristic checks, no model in the loop.
  Base64-encoded payloads are decoded and inspected too; an encoded order is still an order.
  Invisible-character smuggling (zero-width) is normalized away before scanning.
- **Structured for a model check later** — checks are pure functions returning the same
  `Signal` values; a model-based check can join `rules.CHECKS` without touching the engine.
- **Honest limits** (see `docs/PROOF-LOG.md` for the current open holes): the fence is
  English-only and literal — synonym-crafted, leetspeak, and purely semantic attacks can
  pass the *fence*. They still meet the *law*: missed content reaches the brain labeled
  as data, not orders. Detection raises the cost of attack; authority is the wall.

## Use

```python
from sentinel import Inspector, Source

inspector = Inspector()  # optionally: Inspector(ledger=AttackLedger("attacks.jsonl"))

verdict = inspector.inspect(page_text, Source("webpage", url))
if verdict.verdict == "ALLOW":
    brain_input = Inspector.labeled_payload(verdict, page_text)
elif verdict.verdict == "ESCALATE":
    hold_for_owner(verdict.excerpt, verdict.signals)   # exact content, owner's call
else:  # BLOCK
    refuse(verdict)
```

The owner's own authenticated channel is the one exception to inspection:
`Source("owner", ..., owner_authenticated=True)` passes with role `instruction` —
it is not an attack surface, it is the authority. An *unauthenticated* claim to the
owner channel is blocked as impersonation by construction.

## Tests

```bash
python3 -m pytest tests/ -q
```

Three suites: `tests/test_redteam.py` (attack cases), `tests/test_controls.py`
(benign content that must pass as data), `tests/test_engine.py` (authority law,
ledger evidence, labeling). Results — including the misses — live in
[`docs/PROOF-LOG.md`](docs/PROOF-LOG.md).

## Origin

Conceived by Jon Dean (DeanWay Labs), 2026-10-21: *"We govern what goes out — don't we
need to protect the AI as well, and govern what comes in?"* Built the same night.
Named **Sentinel** by Jon.
