We publish what we build, and send the fixes back.
District AI runs on open-source software, and two of the things we built along the way are open source too: a monitor for the pipelines that ship this site, and the scheduling engine behind every booking.
- trigger:websitedeploy:origins succeeded on four originsDeployed
- trigger:sentrysentry:apply failedFailed
- trigger:reporting_toolsthree jobsPassed
Scheduled pipeline, 25 minutes ago, failed on purpose after correcting drift. Not counted: this watch follows pushes.
- Docker publishimage pushed to the registryDeployed
- CItwo jobsPassed
- Auditthree jobsPassed
Three workflow runs from one push, shown as one row.
bridgewatch
A tray monitor for GitLab CI and GitHub Actions, for macOS and Linux. We wrote it because every monitor we tried read the newest pipeline on the branch, which on our project is the hourly schedule, and none could say what a push as a whole had done.
It sees the whole push
On GitLab it reads each child pipeline behind a trigger job. On GitHub, where one push starts several workflow runs that know nothing of each other, it folds them back into one row. Either way it can name the part that broke, and it notices a workflow that should have run and never started.
It knows a schedule from a push
A reconciler that fails on purpose should not turn your tray red all day. Each watch follows the sources you choose.
It answers "did it deploy?"
You name the jobs that mean shipped. The icon reports on those, and says so when something failed around them.
- Watches
- GitLab CI and GitHub Actions
- Licence
- Apache-2.0
- Built with
- Rust, Tauri 2, Svelte 5
- Ships as
- A signed macOS app, a .deb and an AppImage. The command-line tool builds from source.
Why we publish
A telephone company that asks customers to trust where their calls are handled should be easy to check. Both repositories are the ones we deploy from, with their issues, changelogs and security policies in the open.
There is a plainer reason too. A fork with private patches has to be maintained by the one company that holds them. Sending a fix back means the next upstream release already has it, for us and for everyone else.
How a fix travels
What the fork adds
District Scheduler
Our fork of Calnode, the scheduling engine behind District AI's bookings, meetings and notetaker. One Go binary that serves its own booking pages and admin console.
Fixes go upstream
A fix to Calnode goes to Calnode, rather than living on as a private patch.
The fork stays honest
Our addition sits behind one switch. With it off, you are running upstream Calnode.
- Licence
- Apache-2.0
- Built with
- Go, PostgreSQL
- Upstream
- Calnode/calnode
What District AI runs on
Ten projects that do visible work on every call or every page, each run by us under the licence shown.
| Software | What it does here | Licence |
|---|---|---|
| LiveKit | Media server, SIP bridge and the agents framework the voice attendant is built on, on our own nodes in every region | Apache-2.0 |
| PostgreSQL 17 | Every workspace's database, one instance per region | PostgreSQL Licence |
| k3s | The Kubernetes distribution each of the four origins runs on, as a single node | Apache-2.0 |
| Caddy | TLS termination and routing in front of each origin | Apache-2.0 |
| Next.js and React | This website, the customer portal and the dashboard | MIT |
| Prisma | The database layer under the portal and dashboard | Apache-2.0 |
| Tailwind CSS | The dashboard's styling | MIT |
| Grafana Alloy | Ships metrics, logs and cluster events from all four clusters to our monitoring | Apache-2.0 |
| Silero VAD | Decides when a caller has started and stopped speaking | MIT |
| Calnode | The scheduling engine District Scheduler is forked from | Apache-2.0 |
Licences as each project publishes them. Redis is absent on purpose: we use it, and its current licence is not an open-source licence.
Where to find us
Issues and pull requests are welcome on either repository. Security reports go to the address in each repository's security policy, not to a public issue.

