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.2.0.tar.gz (302.2 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.2.0-py3-none-any.whl (71.2 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for chancel-0.2.0.tar.gz
Algorithm Hash digest
SHA256 09603071304c2b2b8d16e0836f8dcd6317368a7706dc5fb0e755510a7f03773d
MD5 4365b685ef328ddcfe210f16889f194e
BLAKE2b-256 406e6f9b6464525c87a0235d46fb72fd8f2cfd309fb4e82259f377f58c4cace2

See more details on using hashes here.

Provenance

The following attestation bundles were made for chancel-0.2.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.2.0-py3-none-any.whl.

File metadata

  • Download URL: chancel-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 71.2 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.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3a689295773ab50bb6ad15fdaf9f08fe9fc4a7d6dd0483d8f33b8aa010a83357
MD5 025b19eb0cd1a96ef1d76796f7659472
BLAKE2b-256 cffa415741d3c74ca269af59f407ca7483c77a10676c696fdafd41bf2287f32f

See more details on using hashes here.

Provenance

The following attestation bundles were made for chancel-0.2.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.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 files

0.1.0

2 files

Supported by

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