Ospobox¶
OSPO in a Box. Know what is happening across the open source you depend on, ship on, and answer for.
Ospobox collects activity from the forges your projects live on, scores what it finds, applies rules to the scores, and pushes the result somewhere that can act on it. That loop (collect → score → decide → act) runs today, on a schedule, with signed delivery at the far end.
Who it is for¶
Open Source Program Offices answering "what did we ship, where, and who wrote it". Engineering leaders who need the health of a dependency tree to be a number they can defend. Due-diligence and procurement teams deciding whether a project is safe to adopt. Platform and security teams who want a machine-readable signal that arrives on its own.
What you get¶
A dashboard that answers the questions you get asked¶
An overview across every organisation you watch, then a page per organisation and per repository. Two organisations sit side by side in a comparison view, which is the screen for "are we keeping up with them". Global search spans organisations and repositories, so one repository among four hundred is a search box away.
Contributors are classified internal, external or bot from your own domain list, which turns "we have 340 contributors" into a number you can put in a board deck. Dark mode and a mobile layout are there because the questions arrive at awkward times.
Health scores with the arithmetic shown¶
Every repository carries a score out of 100, built from five weighted factors: activity (30%), responsiveness (25%), community (20%), maintenance (15%), popularity (10%). Each factor states what it counted and in what units, so a score you disagree with can be argued with, factor by factor.
Six alert rules, evaluated for you¶
Inactivity, a low health score, a sharp health drop against a week-old baseline, a week-over-week activity collapse, a pull-request backlog and an issue backlog. They run after every sync and again every six hours, so a repository that has stopped syncing still trips the inactivity rule. Each finding is filed once and stays filed until somebody acknowledges it, which is what stops an alert channel becoming noise people mute.
Week-over-week trends at three levels¶
Commits, PRs opened, PRs merged, issues opened, issues closed and releases, each against the previous seven days, on the overview, the organisation page and the repository page. Rolling windows rather than calendar weeks, so Monday mornings do not read as a collapse.
Where your people actually are¶
Repositories group into projects, and each becomes a unit the portfolio reports on: how many distinct people worked on it, how many were internal, how many were coding agents, and what landed. A unit carried by one internal contributor is flagged and the person named, because that is a handover conversation waiting to happen.
Set a loaded cost per person and each project carries what it consumed. Cost is reported per project and never against a name. Ospobox counts participation and volume. It does not measure time, and every figure says which it counted.
How much of this did an agent write?¶
The share of commits crediting a coding agent, per project, read from co-authorship trailers. It is a floor rather than a total, and it says so. Agent work counts as activity in the health score and is kept out of the community factor, because an agent committing daily makes a repository active without making it a community.
Reports for the people who never log in¶
Build a report from the sections you want (activity, health, contributors, pull requests, issues, releases), export it as Markdown, HTML or PDF, and save it as a template that emails itself daily, weekly or monthly. With an LLM configured, each report opens with a generated executive summary; without one, that section simply does not appear.
A supply-chain view of what you actually ship¶
Point it at a CycloneDX SBOM and it scores your dependency exposure against advisories from OSV or AboutCode's VulnerableCode, keyed by package URL. The evidence is append-only and content-addressed, so the basis of a finding stays inspectable after the finding.
Integration that does not need polling¶
Five webhook event types (sync.completed, sync.failed, alert.created, health.changed, report.generated), signed with HMAC-SHA256, retried with backoff, and recorded in a delivery log. A REST API covers the same ground, documented at /docs and /redoc.
Operations that will not surprise you¶
Four forges on a six-hourly sync or on demand. A /health endpoint and Prometheus-compatible metrics, structured logs, optional Sentry, and a Docker deployment. JWT sessions, argon2 password hashing, CSRF on every form, per-endpoint rate limiting, login throttling, and OAuth tokens encrypted at rest.
How it works¶
Collects¶
Four forges (GitHub, GitLab, Codeberg and SourceHut) through one normalized adapter interface, on a six-hourly schedule or on demand. Commits, pull requests, issues, releases, and the metadata around them.
Beyond forges, anything a plugin can produce: a CycloneDX SBOM becomes components keyed by package URL, an advisory feed becomes advisories against those packages. Evidence is append-only and content-addressed, so collecting the same fact twice adds nothing, and a changed fact keeps its history.
Scores¶
Repositories get a health score with its reasoning attached: every component of every score carries a one-line explanation, rendered as written. Two scorers ship, a five-factor activity composite and dependency exposure over a repository's declared components.
Decides¶
Rules turn scores and activity into alerts: inactivity, low health, a sharp health drop, a week-over-week activity collapse, PR and issue backlogs. They evaluate after every sync, deduplicate against what is still open, and never file the same finding twice.
Acts¶
Alerts leave Ospobox as HMAC-signed webhooks, with retries and a delivery log, so a subscriber can hold a deployment, open a ticket, or refuse to resolve a package. Reports go out as Markdown, HTML or PDF, on a cadence, by email, and everything here is reachable over a REST API too.
What makes it unusual¶
Every judgement about the domain is a plugin. Evidence sources, scorers and alert rules are interfaces, loadable from a third-party package's entry points. The in-tree implementations load through the same registry, as worked examples with no privileges of their own. Read Extension points and check the claim.
Scores explain themselves. A number between 0 and 100 is not an answer. Every component states what it counted and in what units, so a score can be argued with, which is how one comes to be trusted.
Evidence is kept. Facts are stored with a content hash and a collection time, so the basis of a decision remains inspectable after the decision.
Reading these docs¶
Everything described in plain prose runs today. Anything not yet built is marked:
Planned
Designed and specified, awaiting implementation. The roadmap says where it sits.
Research
Part of the Software Health Control Plane proposal: funded work with partners, which this repository has not committed to. See Architecture.
Quick start¶
git clone git@git.sr.ht:~sfermigier/ospobox
cd ospobox
make install # dependencies, via uv
cp .env.example .env # then edit it
make migrate # the app does not create tables
make run # web + worker
Then open http://localhost:8000.
Development mode
With DEBUG=true you can log in as admin@admin / admin. The backdoor is disabled whenever debug is off.
To see the whole loop run end to end (collect, score, alert, signed delivery, actuation) the demo/ directory has a runbook, a receiver that verifies signatures, and a supply-chain script.
Where to go next¶
| If you want to | Read |
|---|---|
| Run it | Installation, then Configuration |
| Get a first organisation syncing | First steps |
| Do a particular job with it | Guides |
| Understand how it is built | Architecture |
| Integrate or extend it | API reference, Extension points |
| Know what is coming | Roadmap |
Stack¶
| Component | Technology |
|---|---|
| Web framework | Litestar |
| Database | PostgreSQL (prod), SQLite (dev and tests) |
| ORM | SQLAlchemy 2.x, async |
| Background jobs | SAQ |
| Plugins | Pluggy, over two surfaces: forges and chassis extensions |
| Frontend | HTMX + Alpine.js + Tailwind CSS |
| Optional | Any OpenAI-compatible API for summaries, Sentry, WeasyPrint |
Built on¶
Ospobox keys every package fact by package URL, and parses them with packageurl-python, the reference implementation. Both come from AboutCode, whose tools sit on either side of the supply-chain loop:
| Project | Where it fits | Licence |
|---|---|---|
| packageurl-python | Parsing and normalising purl subjects |
Apache-2.0 |
| VulnerableCode | An advisory evidence source beside OSV | Apache-2.0 (software), CC-BY-SA-4.0 (data) |
| ScanCode.io | Resolving a manifest into the SBOM this ingests | Apache-2.0 |
Advisory data carries its own terms: VulnerableCode's is CC-BY-SA-4.0, so anything you redistribute from it needs attribution and the same licence. Ospobox ships none of that data; queries fetch it into your own evidence store.
License¶
Open source. See the LICENSE file.