Quickstart¶
Install¶
pip install umbra-core # or: uv pip install umbra-core
umbra completion zsh >> ~/.zshrc # optional: shell completion (bash | zsh | fish)
Scaffold a contract¶
umbra init # writes a conservative starter .umbra/admission.yaml
Edit the scope it generates, then govern a change. (Without any contract a conservative default applies.)
Govern a change from Python¶
from pathlib import Path
from umbra_core import get_executor, run_admission, build_receipt, verify_receipt, public_key_b64
agent = get_executor("claude-code") # or "codex-cli", or "none" for an existing diff
report = run_admission(
repo_path=Path("checkout"),
repo_label="acme/app",
mission="update the vulnerable dependency; change only manifests",
executor=agent,
)
print(report.authority_level, report.authority) # e.g. 2 branch_pr
print(report.outcome)
envelope = build_receipt(
repo=report.repo, base_commit=report.base_commit, contract=report.contract,
contract_result=report.contract_result, verifier=report.verifier,
trust_boundary=report.trust_boundary, proposed_change=report.proposed_change,
providers=report.providers, authority_level=report.authority_level,
authority=report.authority, executor=report.executor, diff=report.diff,
checks=report.checks, model_identity=report.model_identity, outcome=report.outcome,
)
# Verify against a PINNED key. In production set UMBRA_SIGNING_KEY and pin the
# published key; the dev-fallback key is refused unless pinned explicitly.
assert verify_receipt(envelope, expected_public_key=public_key_b64())["verified"]
Govern from the CLI¶
umbra admit . --agent none --mission "review the pending change" --min-authority 1
umbra verify receipt.json --public-key <base64-pubkey>
umbra gates receipt.json # G1/G2/G3 proof-gate summary (non-zero unless all pass)
umbra comment report.json # canonical PR-comment markdown from the pack
umbra provenance receipt.json # in-toto / SLSA statement
umbra admit-extension ./my-skill # govern a skill / MCP extension (+ --asbom)
umbra brake acme app --store passports.json --reason "incident-42"
umbra admit exits non-zero unless the change earns at least --min-authority,
so it gates a git pre-push hook or CI.
Declare a contract¶
Add .umbra/admission.yaml to the repo:
version: 2
allowed_paths:
- "src/**"
- "package.json"
forbidden_paths:
- "**/deploy.y*ml"
- ".github/workflows/**"
- "**/.env*"
- "**/*secret*"
max_files_changed: 10
required_checks:
- "pytest"
# Capability graph (v2, optional — omit any line for no extra restriction):
allowed_tools: [Read, Edit, Bash]
denied_bash: ["docker\\s+run", "kubectl"]
allowed_mcp: ["github:search"]
allowed_skills: ["web-search"]
policy_owner: platform-team
policy_version: "1.0"
Without one, a conservative default applies. See Capabilities & Proof for what each v2 field enforces.