Skip to main content

chancel

Provable scope isolation for AI retrieval. Firm-level instructions travel everywhere; a client matter's data provably never crosses a matter boundary — and the boundary is enforced below the model boundary, so it survives swapping the AI provider.

CI coverage PyPI license

Demo matrix — regenerated by CI on every push. The table below is the literal output of chancel demo --no-llm. CI runs it on every push and fails the build if a single cell diverges from what this repo claims. (The badges 404 until the repo is public; that is expected.)

The proof, in one table

finding                 backend   provider      expected  actual  ok
----------------------  --------  ------------  --------  ------  --
canary-leak             isolated  echo          clean     clean   ✓
canary-leak             isolated  hostile_echo  clean     clean   ✓
unrepresentable-call    isolated  n/a           denied    denied  ✓
deletion-verifiability  isolated  n/a           clean     clean   ✓
canary-leak             filtered  echo          clean     clean   ✓
canary-leak             filtered  hostile_echo  clean     clean   ✓
unrepresentable-call    filtered  n/a           leaked    leaked  ✓
deletion-verifiability  filtered  n/a           leaked    leaked  ✓
canary-leak             shared    echo          leaked    leaked  ✓
canary-leak             shared    hostile_echo  leaked    leaked  ✓
unrepresentable-call    shared    n/a           leaked    leaked  ✓
deletion-verifiability  shared    n/a           leaked    leaked  ✓

PASS: 12/12 cells matched their predicted color

This is the literal output of chancel demo --no-llm. It runs from a cold clone with no API key and no Docker — the demo uses an in-memory store and a deterministic offline embedder. "Green" does not mean "no leak." It means every cell behaved as predicted: isolated clean, shared leaking as designed, filtered red exactly where it is supposed to be red. A would be the alarm — a backend no longer behaving the way this repo says it does.

Quickstart

git clone https://github.com/Nobel-Co/chancel && cd chancel
uv sync
just demo          # or: uv run chancel demo --no-llm

The three backends

Each backend implements the same logical vocabulary — one firm collection plus one collection per matter — and differs only in how that maps onto physical storage and whether the boundary is a structural fact or a runtime decision.

backend layout what it is the finding it must face
isolated one physical collection per space + a firm collection the claim being defended holds all four findings — a cross-space read has no signature to express
filtered one shared collection, space_id payload, must-filter every query the vendor-default multitenancy pattern leaks the unrepresentable-call and deletion-verifiability findings; the sparse-IDF side channel shifts one matter's scores by another's vocabulary
shared one shared collection, no filter, system prompt says "don't cross matters" what much shipped software actually does leaks everything, starting with a direct canary read

The shared backend is deliberately weak and is asserted red in CI: fixing it would delete the negative example the suite needs. See architecture.md for the full module contract.

Why collection-per-space when the vendor recommends against it

The vector-store vendor's own guidance is to prefer a single shared collection over collection-per-tenant, and it is right — but that is a scaling recommendation, not a security one. Its exact words:

"Creating a separate collection for each tenant is rarely the most efficient approach… Only create multiple collections when you have a limited number of tenants that need strict isolation."

A law firm's matters are exactly that named exception: a bounded number of tenants that need strict isolation, where the isolation benefit outweighs the operational cost of extra collections. chancel occupies the exception on purpose. See ADR 0003.

Fork in five minutes

The base install runs the unit and conformance suites green in under a minute, with no API keys and no Docker — the reference inmemory store and hash_stub embedder carry the whole default path.

uv sync
just test          # unit + integration + conformance
just demo          # the leak matrix above

Adding a provider or a store is implementing one protocol and passing tests/conformance/ — there is a test that proves a fresh adapter drops in with zero edits to the suite. See adding-a-provider.md and adding-a-store.md.

This is a demonstration, not a product

chancel demonstrates exactly one idea end to end: a provider-neutral policy gate that makes a cross-matter read structurally unrepresentable, with a red/green test suite proving it against the two architectures the industry actually ships. It carries zero real data — the corpus is synthetic and generated by a script.

Out of scope (named here so their omission is not mistaken for oversight): authentication, RBAC, multi-user sessions, key management, retention, egress DLP, answer-quality evaluation, any UI, and any hosted deployment.

Documentation

  • Why — the migration argument, the memory tiers, and why the wall belongs below the provider boundary.
  • Architecture — the request path, the three backends side by side, the memory-promotion gate, and the module-by-module contract.
  • Threat model — what it defends, what it does not, and the trust boundaries.
  • Architecture Decision Records — the name gate, the enforcement boundary, the vendor departure, and the audit hash chain.

MIT licensed. See LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

chancel-0.1.0.tar.gz (292.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

chancel-0.1.0-py3-none-any.whl (70.3 kB view details)

Uploaded Python 3

File details

Details for the file chancel-0.1.0.tar.gz.

File metadata

  • Download URL: chancel-0.1.0.tar.gz
  • Upload date:
  • Size: 292.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for chancel-0.1.0.tar.gz
Algorithm Hash digest
SHA256 01058df7452f5f7a6d795a135d3f885cfb412f69f1e1418cef9e766ec18685be
MD5 c378381b711c6e97221407be7c1b5fbb
BLAKE2b-256 980353d7895d9c8fc8024496add0913d7929fae50dc914fd74a8f16ef21b88ed

See more details on using hashes here.

Provenance

The following attestation bundles were made for chancel-0.1.0.tar.gz:

Publisher: release.yml on Nobel-Co/chancel

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file chancel-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: chancel-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 70.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for chancel-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1d9b0606a8015c74a6a3d1f8b099ea8a82798da6f061a2d9781444d3c04070ad
MD5 681848a67541c649d15f91347b59c3e1
BLAKE2b-256 36d18a3a5ffb0d851060289a2ad82ef9c2940a5455e1b01b2ab5180c96ce5d43

See more details on using hashes here.

Provenance

The following attestation bundles were made for chancel-0.1.0-py3-none-any.whl:

Publisher: release.yml on Nobel-Co/chancel

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page