Coditation Sentinel
Local-first git commit guardrails. Sentinel installs a global git hook that runs on
every git commit, in every repository on the machine, and blocks the commit
before anything leaves the laptop when it finds:
- 🔑 Secrets — API keys, tokens, private keys (via gitleaks)
- 📄 Forbidden files —
.env,*.pem,*.key, keystores, dumps, … - 🧑💻 Disallowed git identity — commits authored with a personal email
It is built for a services company: developers commit to customer repositories
whose remotes and CI we may not control, so enforcement lives on the developer's
machine and never writes anything into the customer's repo. It is host-agnostic —
GitHub, GitLab, Bitbucket, Azure DevOps, or no remote at all are all protected the same,
because the check runs at git commit, before anything is pushed anywhere.
Secret scanning is fail-closed: if gitleaks can't run, the commit is blocked
rather than silently allowed, so no change is ever committed unscanned (override with
secrets.require_gitleaks: false).
How it works
git commit
│ git runs the global hook → sentinel scan --staged
▼ (scans only the staged diff, so commits stay fast)
secrets? · forbidden file? · git identity?
│
clean → commit proceeds problem → friendly message + fix, commit aborted
The hook is wired via git config --global core.hooksPath, so a single install
covers every repo automatically — nothing per-project, nothing added to customer code.
Git identity — three tiers
| Identity | Example | Behavior |
|---|---|---|
| Company | you@coditation.com |
✅ silent pass |
| Customer / corporate | you@acme-client.com |
⚠️ allowed — "assuming valid identity" notice on every commit, recorded locally |
| Personal | @gmail.com, @outlook.com, … |
❌ always blocked |
We don't allow-list customer domains (impossible to maintain). Instead policy.yaml
keeps a deny-list of personal providers; the company domain passes, personal is
blocked, and everything else is treated as a legitimate customer identity.
Because tier 2 is "everything not on either list", an unrecognised address like
abc@email.com is allowed — Sentinel can't tell a real client domain from a typo,
so it says so explicitly: on every commit it prints a notice that it is assuming a
legitimate customer identity and shows how to correct it if that's wrong. (Set
reporting.fyi_once_per_repo: true to show it only once per repo instead.) To make a
domain a hard block, add it to personal_providers; to make it a silent pass, add it
to company_domains.
Install
Quick install (recommended) — one-shot scripts
Hand a developer the script for their OS from runner/. It ensures
Python 3.11, installs Sentinel into an isolated virtualenv, installs gitleaks,
and wires the global git hook — no manual steps.
| OS | Run |
|---|---|
| macOS | bash runner/run-macos.sh |
| Ubuntu / Debian | bash runner/run-ubuntu.sh |
| Windows | powershell -ExecutionPolicy Bypass -File runner/run-windows.ps1 |
Open a new terminal afterwards so the PATH change applies. Override the install
source or versions via SENTINEL_PACKAGE, PYTHON_VERSION, GITLEAKS_VERSION
(see runner/README.md). Prerequisite: git, plus a package
manager (Homebrew / apt / winget) so Python 3.11 can be installed if missing.
Manual install
coditation-sentinel is published on public PyPI, so this needs no credentials.
Since it's a command-line tool that wires a global git hook, install it with
pipx — it puts the sentinel command on your PATH in an
isolated environment:
brew install pipx # macOS (Linux: python3 -m pip install --user pipx)
pipx ensurepath # adds pipx's bin dir to PATH — open a new terminal after
pipx install coditation-sentinel # installs the `sentinel` command globally
sentinel install # sets global core.hooksPath + writes default policy
brew install gitleaks # required for secret scanning (macOS; see gitleaks docs for Linux/Windows)
sentinel status # verify enforcement + gitleaks
macOS / Homebrew Python users: a plain
pip install coditation-sentinelfails witherror: externally-managed-environment(PEP 668). Usepipxas above, orpip install --user coditation-sentinel. After apipx/--userinstall, open a new terminal so the updated PATH takes effect — otherwisesentinelreports "command not found".
Commands
| Command | Purpose |
|---|---|
sentinel install [--force] |
Install the global hook and default policy |
sentinel scan --staged |
Scan staged changes (this is what the hook calls) |
sentinel status |
Show enforcement status, policy source, resolved gitleaks path + whether secret scanning is active |
sentinel selftest |
Verify the hook blocks a bad commit (throwaway repo, auto-deleted) |
sentinel uninstall |
Remove the hook and revert core.hooksPath |
Configuration
Policy lives at ~/.coditation-sentinel/policy.yaml (a copy of the packaged default).
Edit it to adjust company domains, the personal-provider deny-list, and forbidden-file
patterns. gitleaks rules live alongside it in gitleaks.toml.
Policy auto-upgrades. The packaged policy carries a version:. When you upgrade
Sentinel and run sentinel install (which re-running a runner/ script does), an
older installed policy.yaml is automatically upgraded to the new version — your old
file is copied to policy.yaml.bak-<timestamp> first, so re-apply any customisations
from it. A policy already at the current version is left untouched; --force always
resets to the packaged default (also keeping a backup).
Key secret-scanning knob: secrets.require_gitleaks (default true) makes scanning
fail-closed — if gitleaks is missing or errors, the commit is blocked. Set it to
false only to knowingly accept committing without secret scanning. Sentinel finds
gitleaks on PATH and in the usual install dirs (~/.local/bin, /usr/local/bin,
/opt/homebrew/bin, %LOCALAPPDATA%\CoditationSentinel\bin), so an installed binary
still works even when the git hook runs with a reduced PATH.
A metadata-only log of non-Coditation identities used is kept at
~/.coditation-sentinel/identity-usage.log (timestamp, repo, email — never code).
Scope (Phase 1)
In: secrets, forbidden files, three-tier identity, global hook, CLI. Out (later): dependency/IaC scanning, PII detection, MDM/device enforcement, central dashboards. The local hook is the guarantee; server-side CI is intentionally not relied on.
Development
python3 -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"
pytest
Publishing to PyPI (maintainers)
Automated (recommended) — push a version tag
.github/workflows/publish.yml runs tests, builds, and publishes whenever a
v* tag is pushed (the tag must match version in pyproject.toml):
# bump version in pyproject.toml, commit, then:
git tag v0.1.1 && git push origin v0.1.1
This uses PyPI Trusted Publishing (OIDC) — no token stored in GitHub. One-time
setup on PyPI: project → Settings → Publishing → Add a trusted publisher:
owner rajeshd-coditation, repo coditation-sentinel, workflow publish.yml,
environment pypi. (Prefer a token? See the commented alternative in the workflow.)
Manual
. .venv/bin/activate && pip install build twine
# bump `version` in pyproject.toml first (PyPI rejects re-uploading an existing version)
rm -rf dist build *.egg-info && python -m build && twine check dist/*
twine upload dist/* # auth: __token__ + a PyPI API token
After it lands, pipx install coditation-sentinel and the runner/ scripts work
with no credentials. The import package is coditation_sentinel; the CLI is sentinel.
Metadata
Release files for coditation-sentinel 0.1.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| coditation_sentinel-0.1.4.tar.gz | 24.7 kB | With provenance | Details for coditation_sentinel-0.1.4.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| coditation_sentinel-0.1.4-py3-none-any.whl | Python 3 | none | any | Details for coditation_sentinel-0.1.4-py3-none-any.whl |
Total release size: 49.6 kB
Release files / coditation_sentinel-0.1.4.tar.gz
| Download URL | coditation_sentinel-0.1.4.tar.gz |
|---|---|
| Size | 24.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f4901bda67e48608ad64bdc8d002cc50f8a55cbd2bab9c77384425cbe9f2fa61
|
|
BLAKE2b-256 checksum How to use checksums |
e59ce104e12cd0fa3755e21936f97a769d8128616e06447f9dbadb557a71b091
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 2, 2026.
Transparency logRelease files / coditation_sentinel-0.1.4-py3-none-any.whl
| Download URL | coditation_sentinel-0.1.4-py3-none-any.whl |
|---|---|
| Size | 24.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7805a3ff8b25a9a1306735ed9f5e1e5f03d06f1cdae2695a3f60d6a9b84b2ee2
|
|
BLAKE2b-256 checksum How to use checksums |
8c9ba2e178a1cfa5e43a219432d3b9811874b34a37b3e60b139136f21383edda
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 2, 2026.
Transparency logSecurity for coditation-sentinel 0.1.4
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for coditation_sentinel-0.1.4.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 2, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.