depatrol
English | 日本語
Read-only control plane for dependency update bots.
depatrol watches Dependabot and Renovate across all your repositories and answers one question with evidence: is every repository actually receiving and absorbing dependency updates?
Existing tools tell you a bot is configured (OpenSSF Scorecard, Evergreen) or aggregate open alerts (GitHub Security Overview, Dependency-Track). None of them verify, bot-neutrally and continuously, that:
- every repository and manifest is covered by an update bot,
- the bot is configured according to organization policy,
- scheduled runs actually happen — Dependabot silently pauses after 90 days of untouched PRs, or after 15 failed runs,
- an update PR exists for every available fix, or the reason it cannot be created is known,
- stalled PRs are explained (CI, merge conflicts, review, rate limits, version constraints),
- merged fixes are effective on the current default branch — not reverted, not re-resolved back to a vulnerable version,
- unpatched vulnerabilities that breach a policy SLA are escalated to a known owner.
"A config file exists" and "the update machinery is healthy" are not the same thing. depatrol treats the gap between them as its product.
Status
Pre-alpha, design phase. The domain model is settled (see CONTEXT.md and docs/decisions/); the implementation language is Go (ADR 0002).
The first milestone — a feasibility-spike CLI that scans repositories with read-only GitHub credentials and reports the conditions below, every judgment carrying its evidence chain marked confirmed or inferred — is implemented; see Installation.
Installation
Every distribution channel ships from the same git tag (ADR 0006). At run time the CLI needs a read-only GitHub token in GITHUB_TOKEN (or GH_TOKEN).
npx depatrol scan --org your-org
bunx depatrol and pnpm dlx depatrol work the same way. The package resolves a platform-specific binary through optionalDependencies and has no install scripts, so npm install --ignore-scripts also works.
If npm ci fails with Cannot find module @depatrol/cli-..., the lockfile was written by an older npm that dropped other platforms' optional dependencies (npm/cli#4828). Delete package-lock.json and node_modules, then run npm install again.
go install
go install github.com/necofuryai/depatrol@latest
Binary archives
GitHub Releases carries archives for darwin (arm64 / amd64), linux (amd64 / arm64), and windows (amd64), each release with sha256 checksums.
Domain model
depatrol uses a two-layer model:
- Findings — verified observations attached to a subject (a manifest, a bot config, an exception record). Multiple findings coexist per repository; they are not exclusive states.
- ExpectedUpdate lifecycle — every update that should happen is tracked as an ExpectedUpdate (identity: repository × manifest × dependency) moving through
pending → update_open → blocked ⇄ … until it is confirmed effective on the current default branch or retired as superseded, regardless of whether a PR exists yet; a merged-but-ineffective fix stays tracked as merged_not_effective. PRs and alerts are evidence linked to the entity, not the entity itself, so tracking survives PR recreation and grouped PRs.
- Evidence — every judgment cites the observations behind it. Each observation is
confirmed (directly observed) or inferred (estimated); a judgment is only confirmed if every load-bearing observation is (weakest-link rule).
Two boundary decisions define the product:
- depatrol never resolves versions itself (ADR 0003). It verifies that your bots do what they promise — not that they promised everything possible.
- depatrol never writes anywhere (ADR 0004). Policy, owner mapping, and exceptions are declarative YAML in your own governance repository; approving an exception is a pull request merge, and the audit trail is git history.
Repository rollup vocabulary
In cross-repository views, each repository is labeled with the most severe condition present (with per-condition counts alongside). From most to least severe:
| Label |
Meaning |
sla_breached |
Past the response deadline defined by policy (derived) |
vulnerable_unpatched |
Unfixed vulnerability remains on the current default branch (derived) |
merged_not_effective |
Merged, but re-evaluation of the current default branch shows the fix is not effective |
fix_unavailable |
Alert exists but no compatible fixed version can be built |
blocked |
Update PR stopped for an explainable reason (CI, conflict, review, constraint) |
paused_or_stalled |
Bot paused, or expected runs not observed |
coverage_gap |
Manifest without bot config or security feature |
policy_drift |
Schedule, groups, or target branch deviate from org policy |
update_open |
Update PR awaiting processing |
pending |
Update known to be available but not yet effective on the default branch — before the bot creates a PR, or in the post-merge grace period until re-evaluation confirms the fix (normal within schedule/cooldown) |
healthy |
No findings, no unresolved ExpectedUpdates (derived) |
A condition covered by an approved exception is suppressed from the rollup (but stays recorded); a repository whose every condition is suppressed shows exception_active.
Background
Founded on a market and competitive study (2026-08): docs/research/2026-08-01-market-research.md (Japanese).
License
Apache-2.0. Contributions require a DCO sign-off (git commit -s).