Skip to main content

Deponent

deponent: GAK self-evaluated  ·  CI  ·  Apache-2.0  ·  check the mark yourself: python3 -m deponent.badge verify --kernel deponent

A deny-by-default gate, macOS Seatbelt jail, and tamper-evident ledger for local agent tool calls. Standard-library only: zero third-party runtime dependencies.

Install: pip install deponent

import tempfile
from deponent import Cell

cell = Cell(tempfile.mkdtemp(), use_jail=False)
print(cell.act("write_file", {"path": "notes.txt", "content": "hello"}).output)
print(cell.act("run_cmd", {"cmd": "rm -rf ./blocked-example"}).output)
print(cell.act("exfiltrate", {"to": "evil.example"}).output)

Refuses: unknown tools, out-of-sandbox paths, destructive commands; in gate-only mode, interpreters and command chains unless you opt them in.

Why it exists: docs/WHY.md. Limits: docs/BOUNDARIES.md.


Quickstart

import tempfile
from deponent import Cell

cell = Cell(tempfile.mkdtemp(), use_jail=False)   # use_jail=True on macOS adds the Seatbelt jail
print(cell.act("write_file", {"path": "notes.txt", "content": "hello"}).output)  # ALLOW
print(cell.act("read_file",  {"path": "notes.txt"}).output)                      # ALLOW
print(cell.act("run_cmd",    {"cmd": "rm -rf ./blocked-example"}).output)        # BLOCK (destructive)
print(cell.act("exfiltrate", {"to": "evil.example"}).output)                     # BLOCK (deny-by-default)

ok, msg = cell.verify()
print(f"chain intact: {ok} — {msg}")

That is examples/minimal.py. Run it (python3 examples/minimal.py). No model. No network.


Containment

Containment boundary: the live-verified jail is macOS Seatbelt (OS confinement) only. Cell() defaults to use_jail=True; when the jail is unavailable it fail-closes (records ALLOW, refuses execution) rather than silently switching to gate-only. On other hosts you supply confinement or opt into gate-only (use_jail=False): the deny-by-default gate and the ledger still run, but there is no OS confinement; argument paths are containment-checked whether spaced, glued to a flag (-o/tmp/x, --output=/tmp/x), dash-prefixed after -- (cat -- -secret), or reached through a symlink that already exists inside the sandbox. In gate-only mode only a small safe set of heads runs by default; other heads need allow_unjailed_heads on both the Cell and its Gate (the Cell heads kwarg alone does not opt in a foreign gate). Interpreters need both knobs: membership in allow_unjailed_heads and allow_unjailed_interpreters=True on both the Cell and its Gate (the Cell interpreter kwarg alone does not opt in a foreign gate, and an interpreter listed only in allow_unjailed_heads is still refused), and gate-only commands run without a shell, one command at a time. Playground ClassifyCell is gate-only, so a chain such as echo a && echo b is chain-unjailed BLOCK (jail-mode would ALLOW). Gate-only runs are policy evidence, not sandbox evidence. The ledger is tamper-evident for edits, deletions and reordering; truncation and re-chaining are caught only against a head published outside the ledger (Ledger.head() / receipt ledger_head).

The live-verified jail is macOS Seatbelt (OS confinement). jail.py also contains a DRAFT Docker backend; do not read DRAFT as proven. On other hosts you supply confinement or opt into gate-only (use_jail=False). In gate-only mode only a small safe set of heads runs by default; other heads need allow_unjailed_heads on both the Cell and its Gate (the Cell heads kwarg alone does not opt in a foreign gate). Interpreters need both knobs: membership in allow_unjailed_heads and allow_unjailed_interpreters=True on both the Cell and its Gate (the Cell interpreter kwarg alone does not opt in a foreign gate, and an interpreter listed only in allow_unjailed_heads is still refused), and gate-only commands run without a shell, one command at a time. Playground ClassifyCell is gate-only, so a chain such as echo a && echo b is chain-unjailed BLOCK (jail-mode would ALLOW). The gate and ledger are platform-independent.

deny-by-default gate  ->  Seatbelt jail  ->  tamper-evident ledger  ->  verifiable evidence record
  • The Gate checks which programs may run, which paths may be touched, and whether a command chains or substitutes its way out of policy. Deny-by-default and fail-closed. Optional ReachOracle: a write can be checked on its reverse-dependency closure.
  • The Jail confines the code inside an allowed command. On macOS the native primitive is sandbox-exec (Seatbelt).
  • The Ledger is an append-only sha256 hash chain. Mutating or reordering any past entry breaks the re-link.
  • The evidence record (deponent.receipts) recomputes the chain from genesis and recomputes its own content hash. persist() runs that check as a write-time round-trip and raises on failure.

Subclass Cell and override _execute to wrap your own tool surface — gate + jail + ledger wrapping is inherited.


What it does NOT do

Full text: docs/BOUNDARIES.md.

  • Reference kernel, not a certified security product.
  • Live-verified jail is macOS Seatbelt only. Docker in jail.py is DRAFT.
  • Tamper-evident, not tamper-proof. Keyless sha256 chain; optional verification-only ed25519 overlay (operator_attest.py, extra deponent[attest]) checks a maintainer's out-of-band signature over a run and signs nothing the agent does.
  • Default policy is a coding-agent sandbox. Override with deny= / allow_heads=.

Proven

The suite exercises the gate, live macOS Seatbelt confinement, ledger integrity, evidence records, reconciliation, claims, build profiles, the public playground, and the conformance harness. Platform- or optional-capability checks skip explicitly when their real backend is unavailable; they are never replaced with a passing mock.

Run python3 -m pytest -q to get the current count and host-specific skip set. make self-gate-live drives a real local build through the same gate, jail, and ledger path and emits evidence records for inspection.

The GAK-conformant mark (self-evaluated). The mark is self-evaluated against GAK v0.x: deponent.badge certify scores the kernel against a standard its own author wrote, and it stays self-evaluated until a second, independent implementer passes the same harness. python3 -m deponent.badge certify --kernel deponent emits a self-contained badge (the SVG above), a markdown snippet, and a JSON record carrying a sha256 clauses_digest over the per-clause results. Re-derive it yourself, fail-closed:

python3 -m deponent.badge verify --kernel deponent   # exit 0 only when the mark is earned

Any kernel that implements the small adapter and passes the clause set earns the same mark; a kernel that fails gets a red "not conformant" badge and a non-zero exit. The badge is generated locally — no shields.io, no network.

Seatbelt escape-proofs — two kinds, kept separate so the claim is exactly as strong as the evidence. (1) Committed live canaries (canaries/CANARIES.md, J1–J8): network exfil, raw-socket egress, writes outside the sandbox, child-process escape, memory-bomb, and wall-clock runaway — each a real test run against the live macOS sandbox, 0 through; if a canary stops holding, the suite goes red. (2) Manual development review — during development Seatbelt bypasses (osascript 'do shell script', launchctl submit, loopback /dev/tcp, DNS, symlink/hardlink/rename writes-out) were hand-run and blocked; these shaped the gate denylist and the Seatbelt profile but are not committed tests — take them as reported, not reproducible from the repo.

Recompute-not-trust evidence records: the verifier does not read a stored boolean. It re-links the chain from genesis and recomputes the record's content hash over its canonical body. persist() runs that verifier on write and raises on failure. Self-reported health is never the evidence.


Example agent team

examples/governed_team.py shows an Architect, a gated Builder, and an advisory Reviewer sharing one ledger. The example is model-agnostic through examples/backends.py; use an Ollama or MLX backend, or add your own. Closure is an out-of-band test run plus an intact ledger—not the Builder saying “done.”

# Ollama (any tool-capable coder)
python3 examples/governed_team.py --backend ollama --model qwen3-coder:30b \
  --goal "Implement reverse_words(s): reverse word order, collapse runs of spaces."

# Local MLX North Mini Code (Apple Silicon)
DEPONENT_MLX_MODEL=mlx-community/North-Mini-Code-1.0-4bit \
  python3 examples/governed_team.py --backend mlx --goal "..."

Install + run the tests

git clone <repo> deponent && cd deponent
python3 -m pip install -e .        # or just run from the repo — the core needs no install

make test                          # current suite; real-backend skips are host-dependent
make demo                          # the minimal demo, no model needed

The kernel has zero third-party dependencies. Only the example team needs a model runtime; the kernel does not.

Run it in Docker (any platform)

docker build -t deponent .
docker run --rm deponent             # scores the kernel against its own GAK standard -> CONFORMANT
docker run --rm deponent make test   # run the suite in-container

The gate, ledger, and evidence records are platform-independent. Live-verified OS confinement is macOS Seatbelt. The Docker backend in jail.py is DRAFT; tests/test_jail_backends.py gates those tests. Do not read DRAFT as proven.


Stewardship

Deponent is an open-source project from Centennial Defense Systems, maintained by Christopher “CJ” Chanhnourack. The repository is the complete public reference kernel; its claims are limited to behavior you can reproduce from the source.


Support

Report vulnerabilities through SECURITY.md. General support and contributions are best-effort; no response-time SLA is offered.


License

Apache-2.0 — including the patent grant.

The license applies to the public source and includes the Apache 2.0 patent grant.

Metadata

Release files for deponent 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for deponent 0.1.2
File Size Uploaded
deponent-0.1.2.tar.gz 174.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for deponent 0.1.2
File Interpreter ABI Platform
deponent-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 248.5 kB

Release files / deponent-0.1.2.tar.gz

Download URL deponent-0.1.2.tar.gz
Size 174.8 kB
Tags Source
SHA-256 checksum
How to use checksums
03fa9303a15c18ba1c51f4329e5009a1ccd38a7d703a27ad3a47df6a0348a5f4
BLAKE2b-256 checksum
How to use checksums
21c867257367a4c58f98f0d0f33830fbc65d6dabe3252ede5045ac334e8b3fe6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.7

Release files / deponent-0.1.2-py3-none-any.whl

Download URL deponent-0.1.2-py3-none-any.whl
Size 73.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
906817b9afd93907223a7788df31062feb32fd55e68637efed61b3afd58c5587
BLAKE2b-256 checksum
How to use checksums
69aa9c1fdf0d2e132c87e6a3937c74af60e3a1791ed5f22166786869230da148
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.7

Release history Release notifications | RSS feed

0.1.3

2 release files

This release

0.1.2 This release

2 release files

0.1.1

2 release files

0.1.0

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page