Metadata-Version: 2.5
Name: rag-security-protocol
Version: 0.1.1rc1
Summary: RAG Security Protocol — where security tools hook into a RAG pipeline, and what they return
Project-URL: Homepage, https://github.com/PCBZ/rsp
Project-URL: Specification, https://github.com/PCBZ/rsp/blob/main/SPEC.md
Project-URL: Issues, https://github.com/PCBZ/rsp/issues
Project-URL: Changelog, https://github.com/PCBZ/rsp/releases
Author: PCBZ
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: conformance,llm,protocol,rag,redaction,security
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Security
Classifier: Typing :: Typed
Requires-Python: >=3.11
Provides-Extra: llamaindex
Requires-Dist: llama-index-core<0.15,>=0.14; extra == 'llamaindex'
Description-Content-Type: text/markdown

# RSP

A protocol for scanning content **before** it reaches a vector store.

Everything that ships today scans after storage, where an embedding already
exists and the text is recoverable from it. RSP puts the scanner at the
ingest hook instead, so that blocked means it was never there.

```console
$ rsp ingest demo/sample-docs --config demo/rsp.toml
scanned 11 chunks
  REDACT aws-access-token   demo/sample-docs/deploy-notes.md:1-14
  REDACT private-key        demo/sample-docs/runbook-backups.md:1-18
11 chunks indexed, 0 blocked, 2 redacted
```

Nothing in that run is ours except the wiring: the detector is
[gitleaks](https://github.com/gitleaks/gitleaks), unmodified, and the pipeline
is LlamaIndex.

## What it is

`SPEC.md` is the deliverable — twenty-eight clauses, each with the reasoning
that produced it, twenty-three of them settled by a conformance case rather
than by assertion. The code in `rsp/` is one host implementation, and exists
to prove the clauses are implementable.

A plugin is a command. It reads one JSON object on stdin, writes one on
stdout, and exits:

```console
$ echo '{"rsp_version":"0.1","hook":"on_chunk","content":"key: AKIA47CQZHT2MVPF3JXB"}' | my-scanner
{"verdict":"REDACT","spans":[{"start":5,"end":25,"type":"aws"}],"replacement":"[REDACTED]"}
```

Offsets are bytes into UTF-8, half-open. The host applies them; a plugin never
sees the content again. [Writing a plugin](https://github.com/PCBZ/rsp/blob/main/WRITING-A-PLUGIN.md) is the page to
start from — the four messages, and the three things that bite.

## Try it

```bash
uv sync --extra llamaindex
uv run rsp ingest demo/sample-docs --config demo/rsp.toml   # needs gitleaks and node
```

## Use it

```python
from rsp.config import load
from rsp.guards import RSPIngestGuard, RSPRetrieveGuard
from rsp.runtime import Runtime

runtime = Runtime(load("rsp.toml"))  # every plugin handshakes here, or this raises

indexed = IngestionPipeline(
    transformations=[SentenceSplitter(), RSPIngestGuard(runtime=runtime), embedding]
).run(documents=documents)

kept = RSPRetrieveGuard(runtime=runtime).postprocess_nodes(retrieved, query_str=query)
```

The ingest guard goes after the splitter and before the embedding, which is
the whole point: a blocked chunk is never embedded and never stored. The
retrieve guard catches what an index already held.

[`examples/host`](https://github.com/PCBZ/rsp/tree/main/examples/host) is that, whole and runnable: four documents
through one pipeline, judged by a Python plugin and a Go one at the same time.
The host code does not know which is which.

## Check your own plugin

```console
$ python conformance/run.py -- my-scanner
```

Copy `conformance/` and `plugins/` next to your plugin — they are not in the
installed package, on purpose: you are checking against the protocol, not
against a version of it that shipped with a host. Standard library only, and
nothing in it imports this host. `conformance/README.md` explains roles
and the host cases.

## Where things are

| | |
|---|---|
| `SPEC.md` | the protocol |
| `WRITING-A-PLUGIN.md` | the on-ramp, quoting a plugin under test |
| `conformance/` | cases, a runner, and a plugin that misbehaves on request |
| `rsp/` | the reference host — five layers, one-way imports, zero dependencies |
| `plugins/rsp-echo` | the reference plugin, whose verdicts are chosen by markers |
| `examples/host` | a whole host in one file, judged by a Python plugin and a Go one |
| `examples/gitleaks-{ts,go,rs,py,c,java,swift}` | the same real scanner wrapped seven times, in seven languages |
| `demo/` | eight documents, two of them with fabricated credentials |

Decisions (D1–D9) and open questions live in the
[wiki](https://github.com/PCBZ/rsp/wiki). Clause IDs — `S1`, `E4` — resolve
inside a clone; issue numbers do not, so the spec never cites one.

## Status

v0.1 is the first freeze. Four clauses have no conformance case and
`SPEC.md` §10 says which and why. Two of them — blocked content never reaching
storage, and a dropped retrieval hit — are the ones a host case cannot observe
without the host offering somewhere to look, and they are the two the protocol
is most about. That is the honest state of it.
