From 44b2eb2cc39d03cac84486fb852d693827145d2d Mon Sep 17 00:00:00 2001 From: Niklas Ye Date: Fri, 9 Oct 2026 14:56:13 +0200 Subject: [PATCH 1/4] Rewrite the README as highlights with screenshots; move the detail into docs/ The README was 1,240 lines of reference material and still described a SQLite quick start. It is now a short tour (highlights, screenshots of the web UI, an accurate quick start against Postgres), and each topic has its own page under docs/ with an index: deployment, configuration, Alertmanager, incidents, notifications, escalation, dead man's switches, single sign-on, web UI, API and development. SERVICE-ACCOUNTS.md is rewritten from a proposal into a reference, and TEAM-LOOKUP.md is gone with the endpoint it described. The "Upgrading to ..." sections for an unreleased product are dropped. Claude-Session: https://claude.ai/code/session_016mBLURvJoMuUEr9cB2RpUN --- CLAUDE.md | 2 +- README.md | 1407 +---------------- SERVICE-ACCOUNTS.md | 299 +--- TEAM-LOOKUP.md | 73 - docs/README.md | 21 + docs/alertmanager.md | 62 + docs/api.md | 436 +++++ docs/configuration.md | 49 + docs/dead-mans-switch.md | 81 + docs/deployment.md | 74 + docs/development.md | 93 ++ docs/escalation.md | 45 + docs/images/admin.png | Bin 0 -> 23805 bytes docs/images/alerts.png | Bin 0 -> 56163 bytes docs/images/incident-note.png | Bin 0 -> 90445 bytes docs/images/mobile-incident.png | Bin 0 -> 53667 bytes docs/images/mobile-queue.png | Bin 0 -> 54670 bytes docs/images/oncall.png | Bin 0 -> 102738 bytes docs/images/queue-dark.png | Bin 0 -> 95465 bytes docs/images/queue-light.png | Bin 0 -> 96143 bytes docs/images/stats.png | Bin 0 -> 43568 bytes docs/images/team-deadman.png | Bin 0 -> 35863 bytes docs/images/team-escalation.png | Bin 0 -> 44533 bytes docs/incidents.md | 113 ++ docs/notifications.md | 62 + docs/single-sign-on.md | 105 ++ docs/web-ui.md | 90 ++ internal/db/migrations/001_baseline.sql | 182 --- internal/db/migrations/002_admin_role.sql | 25 - internal/db/migrations/003_teams.sql | 103 -- internal/db/migrations/004_team_deadman.sql | 39 - internal/db/migrations/005_settings.sql | 35 - internal/db/migrations/006_escalation.sql | 95 -- internal/db/migrations/007_signup_invites.sql | 49 - .../db/migrations/008_incident_signature.sql | 23 - .../db/migrations/009_deadman_switches.sql | 54 - internal/db/migrations/010_alert_source.sql | 21 - internal/db/migrations/011_oidc.sql | 60 - internal/db/migrations/012_device_login.sql | 40 - .../db/migrations/013_oidc_team_groups.sql | 26 - .../db/migrations/014_service_accounts.sql | 43 - .../015_incident_service_account_actors.sql | 39 - .../db/migrations/016_rate_limit_counters.sql | 16 - internal/db/migrations/017_api_key_expiry.sql | 7 - .../migrations/018_incident_event_actor.sql | 21 - 45 files changed, 1355 insertions(+), 2535 deletions(-) delete mode 100644 TEAM-LOOKUP.md create mode 100644 docs/README.md create mode 100644 docs/alertmanager.md create mode 100644 docs/api.md create mode 100644 docs/configuration.md create mode 100644 docs/dead-mans-switch.md create mode 100644 docs/deployment.md create mode 100644 docs/development.md create mode 100644 docs/escalation.md create mode 100644 docs/images/admin.png create mode 100644 docs/images/alerts.png create mode 100644 docs/images/incident-note.png create mode 100644 docs/images/mobile-incident.png create mode 100644 docs/images/mobile-queue.png create mode 100644 docs/images/oncall.png create mode 100644 docs/images/queue-dark.png create mode 100644 docs/images/queue-light.png create mode 100644 docs/images/stats.png create mode 100644 docs/images/team-deadman.png create mode 100644 docs/images/team-escalation.png create mode 100644 docs/incidents.md create mode 100644 docs/notifications.md create mode 100644 docs/single-sign-on.md create mode 100644 docs/web-ui.md delete mode 100644 internal/db/migrations/001_baseline.sql delete mode 100644 internal/db/migrations/002_admin_role.sql delete mode 100644 internal/db/migrations/003_teams.sql delete mode 100644 internal/db/migrations/004_team_deadman.sql delete mode 100644 internal/db/migrations/005_settings.sql delete mode 100644 internal/db/migrations/006_escalation.sql delete mode 100644 internal/db/migrations/007_signup_invites.sql delete mode 100644 internal/db/migrations/008_incident_signature.sql delete mode 100644 internal/db/migrations/009_deadman_switches.sql delete mode 100644 internal/db/migrations/010_alert_source.sql delete mode 100644 internal/db/migrations/011_oidc.sql delete mode 100644 internal/db/migrations/012_device_login.sql delete mode 100644 internal/db/migrations/013_oidc_team_groups.sql delete mode 100644 internal/db/migrations/014_service_accounts.sql delete mode 100644 internal/db/migrations/015_incident_service_account_actors.sql delete mode 100644 internal/db/migrations/016_rate_limit_counters.sql delete mode 100644 internal/db/migrations/017_api_key_expiry.sql delete mode 100644 internal/db/migrations/018_incident_event_actor.sql diff --git a/CLAUDE.md b/CLAUDE.md index 278c78c..ef79927 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -12,7 +12,7 @@ Preconditions and the plan, without side effects: ``` Config is `.release.conf` here plus `make release-vars`. The process itself lives in -`~/.claude/skills/release/`; why it is shaped this way is in README.md §Releasing. +`~/.claude/skills/release/`; why it is shaped this way is in docs/development.md (Releasing). Three things about this repo specifically: diff --git a/README.md b/README.md index da37499..fc57704 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,72 @@ # Terminal Duty (terdut-server) -Incident management server for teams using Prometheus Alertmanager. +Incident management for teams that already run Prometheus Alertmanager. Point Alertmanager at it, +and alerts become incidents that get assigned to whoever is on call, paged, escalated when nobody +answers, and tracked to resolution. One binary, one Postgres. -- Receives Alertmanager webhooks directly — no adapter needed -- Turns alerts into **incidents**, correlated by Alertmanager's own `groupKey` -- Incident workflow: acknowledge, assign, snooze, note, resolve, with a full timeline -- On-call schedule management, with new incidents auto-assigned to whoever is on call -- Alert and incident statistics, including MTTA and MTTR -- Web UI for phones and desktops, served by the same binary -- REST API with per-user API key authentication -- Single binary plus a Postgres — straightforward to self-host +![The incident queue with an incident open](./docs/images/queue-light.png) ---- +## Highlights + +- **Alertmanager-native.** Receives Alertmanager webhooks directly, with no adapter, and groups + alerts into incidents by Alertmanager's own `groupKey`. An incident opens on a new occurrence, + not on every re-send. [Details](./docs/incidents.md) +- **A real incident workflow.** Acknowledge, assign, snooze, add notes, resolve and archive, with a + full timeline of who did what and when. Several clusters can feed one team without + cross-talk. [Details](./docs/incidents.md) +- **On-call rota.** Each team keeps its own rota, and new incidents go to whoever is on call. + [Web UI](./docs/web-ui.md) +- **Pages that escalate.** Push notifications through [ntfy](https://ntfy.sh), with an + Acknowledge button right in the notification, and escalation ladders that move on to the next + level when nobody answers. [Notifications](./docs/notifications.md) · + [Escalation](./docs/escalation.md) +- **Notices when the alerts stop.** Dead man's switches turn the absence of a heartbeat such as + `Watchdog` into an incident. [Details](./docs/dead-mans-switch.md) +- **Teams.** Every team owns its queue, rota, escalation, alert sources and switches; people see + only the teams they belong to. +- **Stats.** Incident counts, mean time to acknowledge and resolve, and alert frequency by name, + hour and day. [Web UI](./docs/web-ui.md) +- **Single sign-on.** OpenID Connect with group-to-team and administrator mapping, and a device + flow so a terminal client can sign in through the browser. [Details](./docs/single-sign-on.md) +- **Built for the phone first.** The web UI is served by the same binary, follows the system's + dark mode, and can be added to the home screen. +- **An API for everything.** A REST API with API keys and service accounts for automation. + [Reference](./docs/api.md) +- **Easy to run.** A scratch container image, a Helm chart, and + [terdut-operator](https://git.ryuvia.com/niklas/terdut-operator) if you want teams and + escalation as Kubernetes objects. [Deployment](./docs/deployment.md) + +## Screenshots + +| | | +|---|---| +| ![An incident with a note on its timeline](./docs/images/incident-note.png) | ![The queue in dark mode](./docs/images/queue-dark.png) | +| **Work an incident**: acknowledge, assign, snooze, note, resolve | **Dark mode**, following the system | +| ![The on-call page](./docs/images/oncall.png) | ![An escalation ladder](./docs/images/team-escalation.png) | +| **On call**: who holds the pager now, and the week ahead | **Escalation**: who is paged next, and when | +| ![Statistics](./docs/images/stats.png) | ![The alert feed](./docs/images/alerts.png) | +| **Stats**: MTTA, MTTR and what fires most | **Alerts**: the raw feed behind the incidents | + +On a phone the queue and the incident page are the same interface, with a sticky action bar: + +

+ The queue on a phone + An incident on a phone +

## Quick start -**Prerequisites:** Go 1.21+ +You need Go 1.25+ and a Postgres 14+ the server can reach. ```bash git clone https://git.ryuvia.com/niklas/terdut-server cd terdut-server +export TERDUT_DB_DSN='postgres://terdut:secret@localhost:5432/terdut?sslmode=disable' go run ./cmd/terdut ``` -The server starts on `:8080` with a `terdut.db` file in the working directory. - -### Create the first user +The server creates its schema on startup and listens on `:8080`. Create the first user, an +administrator, while no user exists yet: ```bash curl -X POST http://localhost:8080/api/bootstrap \ @@ -33,1334 +74,36 @@ curl -X POST http://localhost:8080/api/bootstrap \ -d '{"username": "admin", "email": "admin@example.com", "password": ""}' ``` -Save the `api_key.key` value from the response — it is shown **once only**. The -`password` is optional and is what signs you in to the [web UI](#web-ui). - -Use it as a bearer token for all subsequent requests: +Sign in at with that username and password. The response also carries an +API key, shown **once**, for scripts: ```bash -export KEY= curl -H "Authorization: Bearer $KEY" http://localhost:8080/api/users ``` -### Web UI +Then create a team, add an alert source to get a webhook URL, and point Alertmanager's webhook +receiver at it: see [Alertmanager configuration](./docs/alertmanager.md). -The server serves a web UI at `/`: the incident queue, each incident's alerts -and timeline with every action (acknowledge, assign, snooze, note, resolve, -archive), who is on call, the alert feed, and an *Account* tab for your own -password and the ntfy topic your pages go to. It is built for a phone first. On a phone -it navigates through a hamburger menu and has a sticky action bar, it follows the -system's dark mode, and it can be added to the home screen. From 900px wide it switches -to a sidebar with the queue and the incident side by side. The Stats page shows -incident counts, MTTA and MTTR, and alert frequency by name, hour and day over a -chosen range. +## Documentation -You sign in with a username and password. Users have no password until one is -set, and a user without one can only use API keys: +The [documentation index](./docs/README.md) lists everything. The main pages: -```bash -# an admin sets someone's first password with their API key -curl -X PUT http://localhost:8080/api/users/2/password \ - -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \ - -d '{"password": ""}' -``` - -After that, users change it themselves under *Account*. Changing your own -password requires the current one. - -How a browser stays signed in: - -- A successful login sets an `HttpOnly`, `SameSite=Lax` session cookie. It lasts - 30 days and slides forward while it is used, so an on-call phone stays signed - in. -- The cookie is marked `Secure` when `TERDUT_PUBLIC_URL` starts with `https://`, - so set it to the HTTPS address. TLS terminates at the gateway and the server - itself only ever sees plain HTTP. -- Requests authenticated by the cookie are checked for cross-origin use (Go's - `http.CrossOriginProtection`). That is the CSRF guard. Bearer-key clients are - not affected. -- Setting a password signs that user out everywhere else. -- Ten failed logins for one username within 15 minutes lock that username for - the rest of the window. - -With `TERDUT_PUBLIC_URL` set, tapping a push notification opens the incident in -the web UI (`/incidents/{id}`). - -A **Team** tab holds everything a team owns, in five sub-sections with a URL -each and a strip across the top to move between them: the on-call rota -(`/team/rota`), the membership (`/team/members`), the escalation ladder -(`/team/escalation`), the alert sources with their keys (`/team/sources`) and -the dead man's switches (`/team/deadman`). `/team` itself is an overview — who -is on call today, how many members and owners, how many ladder levels, how many -keys and how many switches — so a page fetches only what it shows. An owner -edits it; a member sees the same pages read-only, because the server refuses -their writes anyway. Somebody in more than one team picks between them above -the strip, since the choice changes the subject of all five. - -The rota is a month at a time, one coloured initial per day with a legend -underneath, and it says how many days are left uncovered — the question a rota -is read for is who holds which stretch, and a run of one colour answers it -where a list of dates does not. An owner taps a day to hand it to somebody or -empty it, and fills a whole shift from the range form folded in below. - -The **Admin** tab appears only for a system administrator, and holds what -belongs to the whole server rather than to one team. It has three sub-sections, -each with a URL of its own and a strip across the top to move between them: -every team (`/admin/teams`), every user (`/admin/users`), and the settings that -used to be environment variables (`/admin/settings`). `/admin` itself is an -overview — how many of each, and what each section is for. Adding somebody is -minting them an invite link into a team, rather than creating a bare account: -the person who accepts it picks their own password, so one never passes through -an administrator, and the link carries the team, so they land somewhere with a -queue in it. That happens on the team's own page, since an invite is a fact -about a team; the user list points there rather than asking which team beside a -form. - -A name in the team list opens **that team's page**, at `/admin/teams/{id}`: when it -was created, how many are in it and how much is open, a field to rename it, the -members with their roles, the invites into it, and deletion. The member list is the -one thing there that needed a new endpoint — `GET /api/teams/{id}/members` is -member-only and answers `404` to an administrator who is not in the team, which is -the rule and not an oversight, so the page reads `GET /api/admin/teams/{id}` instead. -An administrator still sees none of that team's incidents, alerts or rota. - -A name in the user list opens **that person's page**, at `/admin/users/{id}`: their -email and when they joined, where their notifications go, whether they are an -administrator, whether the account is disabled, the teams they are in with their -role in each, a password field for a first or forgotten one, and deletion. It is -the one place membership is edited from the person's side — the Team tab answers -"who is in this team", and answering "which teams is this person in" there means -visiting each team in turn. - -### Single sign-on (OIDC) - -terdut can sign people in through any OpenID Connect provider; the examples use -[Authentik](https://goauthentik.io/). Groups at the provider decide who may sign -in, which teams they belong to and whether they administer the install, much as -Grafana's OAuth role and org mapping does. Password login keeps working alongside -it unless you turn it off. - -**At the provider**, create an OAuth2/OpenID provider and an application for it: -a *confidential* client, redirect URI `/api/oidc/callback`, and -the `openid`, `profile` and `email` scopes. The issuer is the application's, e.g. -`https://auth.example.com/application/o/terdut/`. Then set: - -```sh -TERDUT_PUBLIC_URL=https://terdut.example.com -TERDUT_OIDC_ISSUER=https://auth.example.com/application/o/terdut/ -TERDUT_OIDC_CLIENT_ID=terdut -TERDUT_OIDC_CLIENT_SECRET=... -TERDUT_OIDC_ALLOWED_GROUPS=terdut-users,terdut-admins -TERDUT_OIDC_ADMIN_GROUP=terdut-admins -``` - -Which team a group grants is not server-wide config: each team names its own -group(s), set by that team's own owner (or an administrator) from its Members -tab, or `PUT /api/teams/{teamID}/oidc-groups {"member_group":"sre","owner_group":"sre-leads"}`. -A team must already exist before a group can grant access to it — the sync -never creates one. - -The web UI's sign-in page shows a "Sign in with " button (a plain link to -`/api/oidc/login`) above the password form, or instead of it when -`TERDUT_PASSWORD_LOGIN=false`; it asks `GET /api/auth/config` what the server offers -(`password_login`, `oidc.enabled`, `oidc.name`). A refused sign-in comes back to that -page with the reason spelled out. Access the groups grant is badged **SSO** on the -Team, Admin and per-user pages, with its edit and remove controls disabled, and the -Account page does not offer to set a password nobody could use. - -**What a sign-in does** - -1. *Who.* The provider's `(issuer, subject)` is the identity. The first time, a - user is found by email — only when the provider marks it verified, or - `TERDUT_OIDC_TRUST_EMAIL` is set — or created with no password. A username taken - by somebody else gets a numeric suffix (`alice-2`). Username and email follow the - provider at each sign-in. Authentik reports `email_verified` as false unless - configured otherwise, so linking existing users usually needs - `TERDUT_OIDC_TRUST_EMAIL=true`. -2. *Whether.* With `TERDUT_OIDC_ALLOWED_GROUPS` set, somebody in none of them is - refused and nothing is created. -3. *What.* The administrator flag follows `TERDUT_OIDC_ADMIN_GROUP`. Team roles - follow each team's own `oidc_member_group`/`oidc_owner_group`; where both of a - team's groups match, the owner group wins. - -**Managed access.** What the sync grants is marked as managed by single sign-on, -and only that is ever changed by it. It is added at sign-in, and removed at the -next sign-in after the group is gone, even if that leaves a team without an owner -(an administrator can always repair a team) — the provider is the source of truth -for what it grants, so the last-owner and last-administrator guards do not apply. -Memberships and administrators added by hand are left alone; the exception is a -hand-added member whose team's own group grants a *higher* role, who is raised and -from then on managed. Editing managed access by hand (`POST` or `DELETE` on a -team's members, revoking an SSO-granted administrator) is refused with `409`, since -the next sign-in would undo it. - -> **Upgrading past migration 013: reconfigure every team's groups.** -> `TERDUT_OIDC_GROUP_MAPPINGS` is gone, and the sync no longer creates a team by -> name. Group-to-team-role mapping is now each team's own setting — an owner sets -> it from the Members tab, or `PUT /api/teams/{teamID}/oidc-groups`. Until a team's -> owner does that, an OIDC-sourced membership in it is dropped at that user's next -> SSO sign-in, the same as any other loss of group access. Set every team's groups -> before affected users next sign in, to avoid a visible gap in access. - -**How fast changes arrive.** Groups are read only at sign-in. A session made by an -SSO sign-in has a hard ceiling (`TERDUT_OIDC_SESSION_MAX_AGE`, default 12h) that -sliding never extends, so a change at the provider reaches terdut within that time. -Password sessions are unaffected. - -> **API keys are not revoked when somebody is removed at the provider.** terdut -> holds no refresh token and never asks the provider again, so a person removed -> from every allowed group loses their sessions within `TERDUT_OIDC_SESSION_MAX_AGE` -> and cannot sign in again, but keeps any API key they made (the TUI and scripts use -> them) until an administrator disables the user in terdut. - -**Signing in from a terminal.** A client with no browser of its own, such as the -TUI over SSH, signs in with a device code, run by terdut itself so the terminal -never talks to the provider: - -1. The terminal calls `POST /api/oidc/device` and shows the person a link - (`/device?code=XXXX-XXXX`) and the code. -2. On any device the person opens the link, signs in (by the provider or by - password, whatever the login page offers), sees the code and the account, and - presses **Approve**. Only a browser session can approve; an API key cannot. -3. The terminal polls `POST /api/oidc/device/token` every 5 seconds and is given the - ordinary `terdut_session` cookie once. A person who signs in through the provider - gets the same `TERDUT_OIDC_SESSION_MAX_AGE` ceiling on the terminal's session as - on their browser's. - -A login expires after 10 minutes. `GET /api/auth/config` reports `device_login`. - -**If the provider is down**, terdut still starts (discovery is fetched on first -use) and password login is the way in. With `TERDUT_PASSWORD_LOGIN=false` that way -is closed: set it back to `true`. The first administrator comes from the bootstrap -endpoint, and stays a manual administrator that no group can revoke; on an SSO-only -install set `bootstrap.enabled: false` in the chart if you don't want that account, -or keep it and never give it a password. - -### Docker - -```bash -docker build -t terdut-server . -docker run -p 8080:8080 \ - -e TERDUT_DB_DSN='postgres://terdut:secret@host.docker.internal:5432/terdut?sslmode=disable' \ - terdut-server -``` - -The server creates its own schema on startup and needs a reachable Postgres; it stores nothing on -disk, so there is no volume to mount. - -### Kubernetes - -A Helm chart is published from this repository as an OCI artifact, versioned in lockstep -with the app — chart `x.y.z` is always app `vx.y.z`: - -```bash -helm upgrade --install terdut-server oci://git.ryuvia.com/niklas/terdut-server \ - --version 0.9.2 \ - --namespace terdut-server --create-namespace \ - --set networking.hostname=terdut.example.com -``` - -The chart expects a [Gateway API](https://gateway-api.sigs.k8s.io/) Gateway named `envoy-main` in -the `envoy-gateway-system` namespace to already exist — it renders an `HTTPRoute` against it rather -than an `Ingress`. TLS is terminated at the gateway, so the server itself never sees a certificate. - -| Value | Default | Description | -|---|---|---| -| `networking.hostname` | `terdut.example.com` | Hostname the `HTTPRoute` serves | -| `networking.listener` | `""` | Gateway listener (`sectionName`) to bind to. Empty attaches to every matching listener, **including plaintext HTTP** — set it to the HTTPS listener's name to serve TLS only | -| `networking.servicePort` | `8080` | Port the route forwards to; keep in sync with `service.port` | -| `bootstrap.enabled` | `true` | Runs a post-install hook that creates the first user and stores its API key in the `-admin-key` Secret. Already-bootstrapped servers are left alone | -| `database.dsn` | `""` | **Required.** Postgres DSN, with no password in it. The chart provisions no database | -| `database.passwordSecret.name` | `""` | Secret supplying `PGPASSWORD`. With the Zalando postgres operator, the Secret it generates for the role | -| `database.passwordSecret.key` | `password` | Key within that Secret | - -The API key travels in an `Authorization: Bearer` header, so set `networking.listener` whenever the -hostname is reachable outside a trusted network. - -#### The database - -The chart provisions no database: it takes a DSN and expects a Postgres that already exists. In this -cluster the wrapper chart declares an `acid.zalan.do/v1 postgresql` CR; anywhere else, any reachable -Postgres 14+ will do. - -The DSN carries no password. pgx falls back to libpq's environment variables for whatever the DSN -leaves out, so the password arrives as `PGPASSWORD` from a Secret and never appears in values, in -the rendered manifest or in `kubectl describe pod`. With the postgres operator that Secret is the -one it generates for the role, so a rebuild mints a new password with nothing to keep in sync — -the same wiring miniflux uses. - -The server migrates its own schema on startup, so a new database only has to exist and be writable. - -#### Backups - -Postgres is backed up where it runs, not from here. The database pod carries a -[k8up](https://k8up.io/) `k8up.io/backupcommand` annotation that streams a `pg_dump`, the same way -gitea and immich do in this cluster. - -This used to be the app's problem: the SQLite database lived on a PVC beside the server, the image -is `FROM scratch` with no interpreter to dump it, and WAL mode makes a file-level copy of the volume -non-crash-consistent — so the chart shipped an idle `python:*-alpine` sidecar purely to give k8up -somewhere to exec. The sidecar, the PVC and the `backupSidecar` values are all gone. - ---- - -## Configuration - -Two kinds of setting, split by who changes them and how often. - -**Where the server is plugged in** stays in the environment: the listen address, -the database DSN, the ntfy URL and token, the public URL. They are needed before -the database is open, and two of them are credentials. - -**How the server behaves** lives in the database and is edited by an -administrator in the web UI or through `PUT /api/admin/settings`, taking effect -on the next sweep rather than at the next restart. The variables below marked -**seed** are the value each of those starts from: written once, on first start, -and never overwritten afterwards — a redeploy cannot put a chart's default back -over an administrator's edit. - -| Variable | Default | Description | -|---|---|---| -| `TERDUT_ADDR` | `:8080` | TCP address to listen on | -| `TERDUT_DB_DSN` | — | **Required.** Postgres connection string, e.g. `postgres://terdut:secret@localhost:5432/terdut?sslmode=require` | -| `TERDUT_ARCHIVE_AFTER` | `168h` (7d) | **seed.** How long a resolved alert or incident stays in the default list before being auto-archived | -| `TERDUT_STALE_AFTER` | `6h` | **seed.** How long a firing alert may go without a refreshing webhook before it is treated as resolved — **must exceed your Alertmanager `repeat_interval`** | -| `TERDUT_DEADMAN_MATCHERS` | `alertname=Watchdog` | The **default** matchers a team starts with — switches are per team now, and this seeds teams that have no configuration of their own. `;` separates matchers, `,` the label conditions within one, `=` is exact equality. Every matcher must name an `alertname` | -| `TERDUT_DEADMAN_TIMEOUT` | `15m` | How long a heartbeat may go unheard before its switch is declared dead — **must be shorter than the `repeat_interval` of the route carrying it**. `0` disables dead man's switch handling | -| `TERDUT_DEADMAN_SEVERITY` | `critical` | Severity a dead man's switch incident opens at | -| `TERDUT_NTFY_URL` | — | ntfy server to publish push notifications to. Empty disables notifications entirely | -| `TERDUT_NTFY_TOKEN` | — | Bearer token for an access-controlled ntfy | -| `TERDUT_NTFY_FALLBACK_TOPIC` | — | Topic used when nobody is on call | -| `TERDUT_PUBLIC_URL` | — | Base URL a phone uses to reach this server: the notification's link into the web UI, its Acknowledge button, and whether the session cookie is `Secure` | -| `TERDUT_NOTIFY_REPEAT` | `15m` | **seed.** How long an incident may sit unacknowledged before it is paged again. `0` notifies once and never repeats | -| `TERDUT_PASSWORD_LOGIN` | `true` | `false` refuses password login and password sign-up (`403`), leaving single sign-on the only way in. Refused at startup unless SSO is configured | -| `TERDUT_OPERATOR_MODE` | `false` | Declares this install gitops-managed: a session's or a user's own API key's writes to teams, escalation policies, dead man's switches and integrations are refused (`403 reason:"operator_managed"`); a [service account](#service-accounts)'s are not. Team membership and the schedule stay editable regardless | -| `TERDUT_OIDC_ISSUER` | — | Turns single sign-on on. The provider's issuer URL; discovery is read from `/.well-known/openid-configuration`. See [Single sign-on](#single-sign-on-oidc) | -| `TERDUT_OIDC_CLIENT_ID` / `TERDUT_OIDC_CLIENT_SECRET` | — | **Required with an issuer.** The confidential client registered at the provider. Keep the secret in a Secret, not in values | -| `TERDUT_OIDC_NAME` | `SSO` | What the sign-in button calls the provider | -| `TERDUT_OIDC_SCOPES` | `openid profile email` | Scopes requested, comma or space separated. Authentik puts `groups` behind `profile` | -| `TERDUT_OIDC_USERNAME_CLAIM` / `_EMAIL_CLAIM` / `_GROUPS_CLAIM` | `preferred_username` / `email` / `groups` | ID token claims read for the username, email and groups | -| `TERDUT_OIDC_TRUST_EMAIL` | `false` | Link a first sign-in to an existing local user by email even if the provider does not mark the address verified | -| `TERDUT_OIDC_ALLOWED_GROUPS` | — | Comma-separated. Only people in one of these may sign in. Empty admits everybody the provider authenticates | -| `TERDUT_OIDC_ADMIN_GROUP` | — | Members are system administrators | -| `TERDUT_OIDC_SESSION_MAX_AGE` | `12h` | Hard ceiling on a session made by an SSO sign-in | - -Durations use Go syntax (`30m`, `12h`, `168h`). An unparseable value falls back to the default. - -Note that `TERDUT_STALE_AFTER` and `TERDUT_DEADMAN_TIMEOUT` point in opposite directions. Staleness -is a generous grace period around a `repeat_interval` you do not control; a dead man's switch is a -deadline you set deliberately, and the heartbeat's route is configured to beat faster than it. - -In the Helm chart the two sweeper durations are set via `sweeper.staleAfter` and `sweeper.archiveAfter`, dead man's switches via the `deadman.*` values, notifications via the `notify.*` values, single sign-on via `oidc.*` and `passwordLogin`, and operator mode via `operatorMode`. - ---- - -## Alertmanager configuration - -Alerts arrive on a team's **integration key**, which says both that the sender -may post and which team the alerts belong to. Mint one as an owner of the team: - -```bash -curl -X POST https://terdut.example.com/api/teams/1/integrations \ - -H "Authorization: Bearer $TERDUT_API_KEY" \ - -H 'Content-Type: application/json' \ - -d '{"name":"prod alertmanager"}' -``` - -The response carries the key and the full URL **once**; only a SHA-256 hash is -stored. Put it in your `alertmanager.yml`: - -```yaml -receivers: - - name: terdut - webhook_configs: - - url: http://terdut-server:8080/api/integrations//alertmanager - send_resolved: true - -route: - receiver: terdut -``` - -The whole URL is a credential, so treat it like one. Alertmanager 0.26 and -later can read it from a file with `url_file:` instead, which keeps it out of -your configuration repository: - -```yaml - - url_file: /etc/alertmanager/secrets/terdut-webhook-url/url - send_resolved: true -``` - -The webhook endpoint requires no authentication. - -If you use the [dead man's switch](#dead-mans-switch) — and the default configuration does — give -the heartbeat a route of its own, because the deadline is only as tight as the interval feeding it: - -```yaml -route: - receiver: terdut - repeat_interval: 4h - routes: - - matchers: [ 'alertname = "Watchdog"' ] - receiver: terdut - group_wait: 0s - group_interval: 1m - repeat_interval: 1m -``` - -That delivers a heartbeat every **2 minutes**, not every minute. Alertmanager only reconsiders a -group every `group_interval`, and at exactly one elapsed interval `repeat_interval` has not *quite* -passed, so the send slips to the next tick — equal values give 2×. Two minutes against the 15 minute -default is seven heartbeats per window, which is the point; use `group_interval: 30s` if you want -the numbers to mean what they say. - -kube-prometheus-stack users get the `Watchdog` alert (`expr: vector(1)`) for free; it just needs -routing to terdut rather than to `null`. - ---- - -## Alerts and incidents - -There are two objects, and the difference between them is the whole design. - -**An alert is Alertmanager's record.** It has two states, `firing` and -`resolved`, one row per fingerprint, and no human ever writes to it. The API -exposes alerts read-only. - -**An incident is the work item.** It goes `triggered → acknowledged → resolved`, -carries an assignee, a snooze, notes and a timeline, and is the only thing people -act on. Many alerts belong to one incident. - -### Correlation uses Alertmanager's `groupKey` - -Alertmanager has already grouped alerts according to the `group_by` routing tree -you configured, and it sends the resulting `groupKey` and `groupLabels` on every -webhook. Incidents adopt that answer rather than re-grouping alerts a second -time — if you want different correlation, change `group_by` in -`alertmanager.yml` and terdut follows. - -At most one incident is open per `groupKey` at a time. Alerts firing in a group -that already has an open incident join it. The incident's `severity` is a -high-water mark — the highest `severity` label any of its alerts has carried — so -an incident that hit `critical` still reads as critical after the critical alert -clears. - -### Several clusters, one team - -A team with one Alertmanager per Kubernetes cluster, each posting to its own -source, needs two settings or the clusters run together. - -1. Give every alert a `cluster` label at the source. In Prometheus that is - `externalLabels: {cluster: prod-eu}` (kube-prometheus-stack: - `prometheus.prometheusSpec.externalLabels`). -2. Add `cluster` to `group_by` in `alertmanager.yml`. - -The second one is the one that matters. Incidents are matched on the team and -Alertmanager's `groupKey`, and the `groupKey` does not include external labels: -without `cluster` in `group_by`, the same alert in two clusters has the same -key and joins one incident. With it, each cluster gets its own, `cluster` is in -the incident's `group_labels`, and the web UI shows it as a coloured chip on the -queue, the incident and the alert list, instead of leaving it in the title. -An alert that is not grouped by `cluster` still shows the chip on the alert -list, which reads the label from the alert itself. - -The queue has a cluster dropdown once there are two or more values to choose -between. It filters on the incident's `cluster` group label -(`GET /api/incidents?cluster=...`), so it only sees incidents grouped by it. - -### An incident opens only on a new occurrence - -An incident opens when an alert **transitions into firing**: a fingerprint that -was never seen, an alert with a newer `startsAt`, or a resolved alert that -started again. The unchanged firing notifications Alertmanager re-sends every -`repeat_interval` are none of those, and open nothing. - -This is what makes closing an incident by hand mean something. Without the rule, -`POST /api/incidents/{id}/resolve` would be undone by the next re-send of an -alert that never stopped firing. - -### Leaving the open state - -- **Automatically**, once every alert under the incident has stopped firing — - whether by a resolved webhook or by the sweeper's - [stale-alert expiry](#stale-alert-expiry). The incident gets - `"resolution_source": "alerts"`. -- **By hand**, via `POST /api/incidents/{id}/resolve` - (`"resolution_source": "manual"`). This is **terminal**: a later occurrence in - that group opens a *new* incident rather than reopening this one. If the alert - underneath never stops firing, the incident stays closed — that is what - resolving by hand asserts. -- **On recovery**, for a [dead man's switch](#dead-mans-switch) incident whose - heartbeat started arriving again (`"resolution_source": "recovered"`). These - incidents have no member alerts, so the automatic cascade above cannot reach - them. - -To quieten an incident you expect to come back, snooze it instead -(`POST /api/incidents/{id}/snooze`). A snooze hides the incident from the default -list without closing it, and expires by simply falling into the past. - -### On-call assignment - -A new incident is assigned to whoever holds today's schedule entry at the moment -it opens (`GET /api/schedule/current`). If nobody is scheduled it opens -unassigned. Reassign with `POST /api/incidents/{id}/assign`. - -One person holds a given day, so `POST /api/schedule` refuses a date somebody -already has: taking a shift off the person expecting to be paged for it should -not be something a plain call does by accident. Pass `"replace": true` to take -them anyway. Either way the whole request is one transaction — a week where some -days are free and some are taken moves as a unit, and a failure leaves the rota -exactly as it was rather than with a hole in it. - -### Push notifications - -With `TERDUT_NTFY_URL` set, an incident that opens is pushed to the on-call -person's phone through [ntfy](https://ntfy.sh). Everybody sets their own topic -under *Account* in the web UI, where a **Send a test push** button proves it -before an incident has to; `PUT /api/users/{id}/notify` is the same thing over -the API, and an administrator may set somebody else's. A user with no topic -falls back to `TERDUT_NTFY_FALLBACK_TOPIC`, as does an incident that opens with -nobody on call. If neither yields a topic, nothing is queued. - -The **server** is the install's one ntfy, from `TERDUT_NTFY_URL`, and is not -something a user picks. Only the topic is per-person. - -A topic is a shared secret with the ntfy server: anyone who knows it can both -read the pages and publish to it, so an unguessable one is worth the trouble. -That is also why the topic never appears in an incident's timeline, which every -API key can read. - -Three things get pushed: - -- **triggered** — an incident opened. Priority follows severity (`critical` maps - to ntfy's max priority, the one that overrides the phone's quiet settings). -- **reminder** — the incident is still `triggered` after `TERDUT_NOTIFY_REPEAT`. - Repeats until somebody acts. Acknowledging, snoozing, resolving or archiving - all stop it — snooze is the mute button. -- **resolved** — every alert under the incident stopped firing. Only sent to - whoever was paged in the first place, and only for the automatic cascade: - resolving by hand pushes nothing, since the person who did it already knows. - -Notifications carry an **Acknowledge** button that acknowledges the incident -without opening anything. It POSTs to `/api/notify/ack/{token}`, an -unauthenticated route authorised by the 256-bit token in its path — minted fresh -per notification, scoped to one incident and one action, and valid for 24 hours. -A real API key is never put in a notification, because the message is stored on -the ntfy server and cached on the device. - -The token is **not** consumed by use. Acknowledging is idempotent, so a token -stays valid for its full 24 hours and a second tap is a no-op that reports the -incident's current state rather than an error — which is what you want when a -tap is retried on a flaky mobile connection. What bounds it is scope, not a use -count: one incident, one action, one day. Expired tokens are purged by the -sweeper. - -Two consequences worth planning for: - -- `/api/notify/ack/{token}` **must stay publicly reachable**, or the button will - not work when the responder is off your network. -- Notifications sent to the fallback topic carry **no** Acknowledge button. The - topic is shared, and a button on it would let any subscriber acknowledge as - somebody else. - -Delivery is a queue, not an inline call: the webhook writes a row and a -background notifier sends it within 30 seconds, retrying with exponential -backoff up to 8 attempts. Nothing about ingestion blocks on ntfy being reachable. - -Every delivery is recorded on the incident's timeline: a `notified` event once -ntfy accepts the publish, and a `notify_failed` event when a notification -exhausts its retries. Written from the result rather than at enqueue, so the -timeline says what actually happened — and a page that never landed is visible -instead of looking the same as one that did. - -### Escalation - -Without a ladder, an unacknowledged incident re-pages the same topic every -`notify_repeat` forever. That is a louder version of the same silence: if the -person on call is asleep, out of signal, or has left, nothing else happens. - -A team can configure an ordered ladder instead. Each level has a timeout and a -set of targets, and a target is either a named person or **whoever the team's -rota says is on call today** — the target that keeps working when the rota -changes and nobody remembers to edit the policy. - -``` -level 1 5m oncall the rota gets first refusal -level 2 5m user:bob then a named second - then repeat_count more rounds - then the team's fallback topic, once -``` - -When a level's timeout passes with the incident still `triggered`, the next -level is paged. Off the end of the ladder the whole thing runs again -`repeat_count` times, and after that the team's `fallback_topic` is paged once -as the end of the line. The incident stays open throughout: running out of -people to wake is not the same as somebody answering. - -**Acknowledging or resolving stops it**, which is the point — continuing to wake -people after somebody has said "I have this" is how a tool teaches people to -mute it. **Snoozing pauses it**: a deliberate "not now" holds the ladder where -it is, and it resumes when the snooze runs out. - -Every step is on the incident's timeline with the level and the names it woke, -so somebody reading it afterwards can tell why their phone rang at 04:00. A -level whose targets are all unreachable — no ntfy topic, a disabled account, an -empty rota — is recorded as `nobody reachable` and the ladder moves on rather -than stalling on a rung that cannot ring. - -**Reminders and escalation never both run.** A team with a ladder gets -escalation; a team without keeps the reminder behaviour exactly as it was. Two -pages for one silence is the surest way to get a tool muted. - -The ladder's `fallback_topic` is per team, unlike `TERDUT_NTFY_FALLBACK_TOPIC`, -which is the install-wide topic used when an incident opens with nobody on call. -They answer different questions: one is "nobody was scheduled", the other is -"everybody scheduled has been tried". - -### Stale alert expiry - -A resolved webhook is the only signal that an alert has stopped firing, so a -notification that is dropped, silenced, or lost to a restart would otherwise pin -that alert as firing forever. A background sweeper resolves firing alerts that -Alertmanager has stopped refreshing, using either signal: - -- the `endsAt` watermark on the last notification has passed, or -- no webhook has refreshed the alert within `TERDUT_STALE_AFTER`. - -Alertmanager re-sends firing notifications every `repeat_interval`, which is what -keeps a live alert fresh — so `TERDUT_STALE_AFTER` must be comfortably larger -than your `repeat_interval` (default 4h), or live alerts will be resolved -prematurely. Alerts resolved this way are marked `"resolution_source": "expiry"` -to distinguish them from a real Alertmanager resolve (`"alertmanager"`). - -An expiry cascades: once it leaves an incident with nothing firing under it, the -incident resolves too, in the same sweep. - -### Dead man's switch - -Everything above assumes alerts arrive. If Prometheus stops evaluating, or -Alertmanager cannot reach this server, nothing arrives — and silence looks -exactly like everything being fine. A dead man's switch inverts the handling for -one designated alert so that silence is the signal: - -- **receiving** it opens no incident, and -- the **absence** of it does. - -kube-prometheus-stack already ships the alert for this. `Watchdog` is -`expr: vector(1)`, so it fires permanently and is re-sent forever; it is worth -nothing unless something downstream notices it stop. That is what -`TERDUT_DEADMAN_MATCHERS` defaults to. - -**Switches belong to a team**, which decides which of its own alerts are -heartbeats and how long a silence has to last. Each **switch** is a row of its -own — a name, one matcher, a timeout and a severity — so switches in one team -can have different deadlines. An owner adds and removes them on **Team → -Switches**, which lists each with a status (**healthy**, **dead**, or -**dormant** until its first heartbeat), when it was last heard from, and when it -last opened an incident; a matcher that several clusters satisfy is broken down -per cluster. The API is `POST`/`DELETE /api/teams/{teamID}/deadman/switches`. A -missed heartbeat opens an incident in the team whose integration received it. -Removing a switch stops the watching; an incident it already opened stays open -until somebody resolves it. - -The environment variables are the starting point, not the setting: the **first** -time the server starts, every team is given a switch per default matcher from -them, once. After that a team's switches are its own — an owner's edit or -deletion is never put back by a redeploy. A team created later starts watching -nothing until its owner says otherwise — inheriting an install-wide heartbeat -would page a new team about a source it has never heard of. - -A matcher is a set of exact label conditions, one of which must be the -`alertname`, in the format the environment variable uses (one matcher per switch; the -variable takes several, separated by `;`): - -``` -alertname=Watchdog,cluster=prod; alertname=EdgeHeartbeat -``` - -**The unit of monitoring is the fingerprint, not the alert name.** Two clusters -sending the same `Watchdog` are two independent switches, so a healthy one can -never mask a dead one. - -#### The lifecycle - -A switch is **dormant** until its first heartbeat arrives. A configured matcher -that has never been heard from opens nothing, so a fresh deploy or a restored -database does not page. It also means a matcher that never matches anything is -silently inert — check the startup log line, which lists the matchers that -survived parsing. - -Once armed, the sweeper declares it **dead** when either the heartbeat has not -been refreshed within `TERDUT_DEADMAN_TIMEOUT`, or Alertmanager explicitly -resolved it — the sender saying the heartbeat stopped needs no further waiting. -That opens an incident at `TERDUT_DEADMAN_SEVERITY`, assigned and paged like any -other, and marks the heartbeat alert `"resolution_source": "deadman"` so the -alert list stops claiming a dead switch is firing. - -It **recovers** when the heartbeat starts arriving again: the incident resolves -with `"resolution_source": "recovered"` and the all-clear goes to whoever was -paged. - -Resolving the incident by hand sticks, the same way it does for an alert-backed -one. While the switch stays silent nothing new opens — so a decommissioned -source is a one-time page rather than a nag. The switch **re-arms** on the next -heartbeat: come back and die again, and that is a new incident. - -#### Two things to know - -`TERDUT_DEADMAN_TIMEOUT` must be **shorter** than the `repeat_interval` of the -route carrying the heartbeat, which is the exact opposite of -`TERDUT_STALE_AFTER`. Inheriting a default `repeat_interval` of 4h gives you a -switch that takes four hours to notice anything, so give the heartbeat -[its own route](#alertmanager-configuration). Matched alerts are exempt from -stale-alert expiry — a heartbeat answers to its own timeout and nothing else. - -A dead man's switch incident has **no member alerts**: -`GET /api/incidents/{id}/alerts` returns an empty list. There is no alert -describing the problem, because the problem is that no alert arrived. What -happened is on the timeline instead, as a `deadman_silent` event carrying the age -of the last heartbeat, and the heartbeat's labels are on the incident's -`group_labels`. - ---- - -## API reference - -### Authentication - -All endpoints except `/api/bootstrap`, `/api/integrations/{key}/alertmanager`, -`/api/notify/ack/{token}`, `/api/login`, `/api/logout`, `/api/auth/config`, -`/api/version`, `/api/oidc/login`, `/api/oidc/callback`, `/api/oidc/device` and -`/api/oidc/device/token` require either an API key: - -``` -Authorization: Bearer -``` - -or the web UI's session cookie. A request that carries an `Authorization` header -is judged on that header alone. - -Two kinds of user exist. An **administrator** manages accounts: creating and -deleting users, setting anybody's password, minting keys for anybody, and -granting the flag itself. Everybody else works incidents — acknowledging, -assigning, snoozing, resolving, noting — and manages their own account and -nobody else's. An API key carries exactly the rights of the user it belongs to. - -A third principal, the **service account**, exists for automation (a -Kubernetes operator, most likely) that needs to manage teams, escalation -policies, dead man's switches and integrations without impersonating a human. -It is not a user — it never signs in, never appears in a team's member list, -and never holds the administrator flag — and its key is prefixed `tdsa_` so it -reads as one at a glance in a log line. See [Service accounts](#service-accounts). - -**Getting an account.** The first one comes from `/api/bootstrap`. After that -it depends on `signup_mode`, an administrator setting: - -- `invite_only` (the default) — a team owner mints a link with - `POST /api/teams/{teamID}/invites`, and the person who opens it picks a - username and password and lands in that team with the role the link carries. - Links are single-use unless told otherwise, expire after seven days, and can - be revoked before that. -- `open` — anybody who can reach the server can create an account, and must - name a team, which they then own. - -Invites are **links, not email**: this server has no SMTP, and adding it to send -one message would be a subsystem to run, secure and monitor. Send the link -however you already talk to the person. - -A domain-restricted third mode was considered and dropped: with no email there -is nothing to verify an address against, so it would only check the domain of a -string somebody typed. - -The first user, from `/api/bootstrap`, is an administrator. Users created -afterwards are not, until an administrator says so. An install always keeps at -least one: the last administrator can be neither deleted nor demoted, and -nobody can delete or demote themselves. - -Endpoints that require the flag answer `403` with -`{"error":"administrator access required"}`. - -**Teams** are the unit of tenancy, and are a separate axis from the administrator -flag. A team owns its incidents, alerts, schedule and integrations, and a user -sees exactly the teams they belong to. Within a team an **owner** configures it -(schedule, integrations, membership) and a **member** works its incidents. - -An administrator crosses that line in one direction only. They **configure any -team** without being in it — every owner-only endpoint accepts the flag, because -otherwise a team whose last owner left could never be repaired. They do **not -read any team**: the queue, the alerts and the incidents are filtered by real -membership, so an administrator sees a team's work only by joining it, which is -a membership change and shows up as one. Administration is about accounts and -the shape of a team, not about reading other people's incidents. - -Anything belonging to a team you are not in answers `404`, not `403`: whether an -incident exists is itself something only its team should learn. - -**Operator mode** (`TERDUT_OPERATOR_MODE`, see [Configuration](#configuration)) -declares this install gitops-managed. When it is on, a session or a user's own -API key gets `403 {"error": "...", "reason": "operator_managed"}` on every -write this README marks **owner**-gated under Teams below (creating, renaming -or deleting a team; its OIDC group binding; its escalation ladder; its dead -man's switches; its integrations) — a service account's writes are unaffected. -Team membership and invites are deliberately excluded: they are never -gitops-managed, in operator mode or out of it. `GET /api/auth/config` reports -`operator_mode` so a client can grey those sections out before a write is ever -attempted. - -| Method | Path | Description | -|---|---|---| -| `GET` | `/api/auth/config` | How to sign in: `{"password_login", "oidc": {"enabled","name"}, "device_login", "operator_mode"}`. No session needed | -| `GET` | `/api/version` | `{"version"}` — this build's version string. No session needed, the same as `/healthz` | -| `POST` | `/api/login` | `{"username","password"}` → sets the session cookie, returns `{user, has_password}`. `429` after too many failures; `403` when `TERDUT_PASSWORD_LOGIN=false` | -| `GET` | `/api/oidc/login` | Starts a single sign-on sign-in: redirects the browser to the provider. `?next=/path` is where to land afterwards; only a path on this server is honoured. Only exists when SSO is configured | -| `POST` | `/api/oidc/device` | Starts a device login: returns `{device_code, user_code, verification_url, interval, expires_in}`. Only exists when SSO is configured | -| `POST` | `/api/oidc/device/token` | `{"device_code"}` → `202 {"status":"pending"}`, then `200` with the session cookie once approved (once only). `410` with `{"error":"expired"}` or `{"error":"denied"}`; `429 {"error":"slow_down"}` if polled faster than `interval` | -| `POST` | `/api/oidc/device/approve` | **session** — `{"user_code"}`. Approves a pending device login as the caller. `403` for an API key; `404` for an unknown, expired or already decided code | -| `POST` | `/api/oidc/device/deny` | **session** — `{"user_code"}`. Refuses it | -| `GET` | `/api/oidc/callback` | Where the provider sends the browser back. Sets the session cookie and redirects to `/`, or to `/?sso_error=` — one of `denied`, `expired`, `failed`, `unavailable`, `not_allowed`, `no_email`, `email_conflict`, `disabled`, `not_bootstrapped` (no user exists on this install yet — sign in again once something has called `/api/bootstrap`) | -| `POST` | `/api/logout` | Ends the session and clears the cookie | -| `GET` | `/api/me` | The caller: `{user, has_password}` | - -### Users - -| Method | Path | Description | -|---|---|---| -**admin** marks an endpoint that requires the administrator flag; **self or -admin** marks one you may use on your own account and an administrator may use -on anybody's. - -| Method | Path | Who | Description | -|---|---|---|---| -| `GET` | `/api/signup` | — | Whether sign-up is open, and whether `?invite=` is usable. No session needed: the caller has no account yet | -| `POST` | `/api/signup` | — | Create an account `{"username","email","password","invite"?,"team_name"?}` and sign in. `403` without a usable invite when the mode is invite-only | -| `POST` | `/api/bootstrap` | — | Create first user + API key `{"username","email","password"?}` (only works on empty DB). The user is an administrator | -| `GET` | `/api/users` | any | List users. Open to everybody: the queue's assignment control and the schedule both have to name people | -| `GET` | `/api/users/{id}/teams` | self or admin | The teams that user is in, each with their role. `/api/teams` is always about the caller; this one answers it about somebody else, for the admin page's per-user view. `404` for a user who does not exist, so "no teams" and "no such person" are distinguishable | -| `POST` | `/api/users` | **admin** | Create user `{"username","email"}`. Not an administrator | -| `DELETE` | `/api/users/{id}` | **admin** | Delete user (cascades to keys). `409` for yourself or the last administrator | -| `PUT` | `/api/users/{id}/admin` | **admin** | Grant or revoke the administrator flag `{"is_admin"}`. `409` for yourself, the last administrator, or an administrator granted by single sign-on | -| `PUT` | `/api/users/{id}/disabled` | **admin** | Take an account out of use, or put it back `{"disabled"}`. `409` for yourself or the last administrator | -| `PUT` | `/api/users/{id}/notify` | self or admin | Set push notification target `{"ntfy_topic"}` — empty string clears it | -| `PUT` | `/api/users/{id}/password` | self or admin | Set web UI password `{"password","current_password"}`. `current_password` is required only when changing your own existing password. Ends the user's other sessions | -| `POST` | `/api/users/{id}/api-keys` | self or admin | Issue API key `{"name"}` — key shown once | -| `DELETE` | `/api/users/{id}/api-keys/{keyID}` | self or admin | Revoke API key | - -### Administration - -| Method | Path | Who | Description | -|---|---|---|---| -| `GET` | `/api/admin/teams` | **admin** | Every team on the server, with its member and open-incident counts. `/api/teams` answers "what am I in"; this answers "what is there" | -| `GET` | `/api/admin/teams/{teamID}` | **admin** | One team and who is in it: `{"team", "members"}`. `404` for a team that does not exist. `GET /api/teams/{teamID}/members` is **member**-only and still `404`s an administrator from outside the team — reading a team's shape and reading its work are different questions, so they are different endpoints | -| `GET` | `/api/admin/settings` | **admin** | The editable settings with their bounds, plus the environment-configured ones, read-only. Never credentials | -| `PUT` | `/api/admin/settings` | **admin** | Change one or more `{"key": seconds}`, or `{"signup_mode": "open"\|"invite_only"}`. `400` for an unknown key or a value outside its bounds | - -### Service accounts - -A service account is a scoped, non-human credential for automation — not a -`users` row, so it never signs in, is never a team member, and never carries -the administrator flag. Two scopes: - -- **instance** — the same reach system administration has over teams: create - one, and mint a **team**-scoped account against any of them. There is no - cap on how many instance-scoped accounts exist, but ordinarily there is one, - belonging to whatever is provisioning this install end to end. -- **team** — owner-equivalent for that one team, and nothing else: every - **owner**-gated endpoint under [Teams](#teams), membership and invites - included. Nothing narrower is enforced server-side; what actually keeps - membership out of automation's hands is that no operator built against this - scope should ever call those two endpoints — see - [operator mode](#authentication) and `SERVICE-ACCOUNTS.md`'s note on this. - -A key is shown once, at creation or rotation, and only its hash is stored — -the same handling as a user's API key. Losing it means minting a new one; -there is no way to recover a raw key from the server. - -| Method | Path | Who | Description | -|---|---|---|---| -| `GET` | `/api/service-accounts` | **admin** | Every service account. Pass `?name=` instead to look one up by its exact name — open to **any** authenticated caller (human or service account), since it returns no key material and is how an account finds its own id | -| `POST` | `/api/service-accounts` | owner\* | Create one and mint its first key `{"name","scope","team_id"?}` (`team_id` required for `scope:"team"`, absent for `scope:"instance"`). Returns `{"service_account", "key"}` — `key.key` shown once | -| `POST` | `/api/service-accounts/{id}/keys` | owner\* | Mint an additional key `{"name"}` — rotation without recreating the account. Shown once | -| `DELETE` | `/api/service-accounts/{id}/keys/{keyID}` | owner\* | Revoke one key | - -\* For an **instance**-scoped account: a system administrator only. For a -**team**-scoped account: a system administrator, that team's own human owner, -an instance-scoped service account (minting a narrower credential for a team -it just created), or — for the two key endpoints only — the account rotating -or revoking its own key, which is not a privilege escalation, the same -reasoning a user's own API keys rest on. - -### Alert ingestion - -Alerts arrive on a team's integration key. The key is both the credential and the -routing: it says that the sender may post, and which team the alerts belong to. -Create one with `POST /api/teams/{teamID}/integrations`, which returns the key -and the full URL once and stores only a SHA-256 hash. - -| Method | Path | Description | -|---|---|---| -| `POST` | `/api/integrations/{key}/alertmanager` | Alertmanager v4 webhook receiver for the key's team. `401` for an unknown key | - -This is the only way in. The pre-teams `POST /api/alertmanager/webhook` took no -credential at all — anything able to reach the port could open an incident — -and was removed in v0.13.0 once senders had moved onto keys. - -### Teams - -**owner** below means an owner of that team, a system administrator (who -passes every one of these without being a member), or that team's own -team-scoped [service account](#service-accounts) — including membership and -invites, technically, though no automation this scope was designed for -(a Kubernetes operator's CRDs, see `SERVICE-ACCOUNTS.md`) ever models team -membership or would call those two. See [Authentication](#authentication). -**member** means membership and nothing else: an administrator who is not in -the team gets the same `404` as anybody else. - -| Method | Path | Who | Description | -|---|---|---|---| -| `GET` | `/api/teams` | any | The caller's own teams, each with their role | -| `POST` | `/api/teams` | any | Create a team `{"name"}`; a human creator becomes its first owner. An instance-scoped [service account](#service-accounts) may also create one, and it gets no owner at all — expected for a team an operator is about to hand a team-scoped credential to, not an orphaned team a human made | -| `PUT` | `/api/teams/{teamID}` | **owner** | Rename it `{"name"}`. `409` if the name is taken | -| `DELETE` | `/api/teams/{teamID}` | **owner** | Delete a team and everything under it. `409` while it has open incidents | -| `GET` | `/api/teams/{teamID}/members` | member | Who is in the team, with `status` (`oncall` if the rota has them today, `unpageable` when a page to them would go nowhere — even if they are on call — else `reachable`), `on_call`, `next_shift` (first rota day after today), `pageable` and `problem` (`has no ntfy topic` / `account is disabled`; never the topic itself) and `last_active_at` (their newest session or API-key use). Every member sees the same list | -| `POST` | `/api/teams/{teamID}/members` | **owner** | Add a member, or change their role `{"user_id","role"}`. `409` when it would demote the last owner, or the membership is managed by single sign-on | -| `DELETE` | `/api/teams/{teamID}/members/{userID}` | **owner** | Remove a member. `409` for the last owner, or a membership managed by single sign-on | -| `GET` | `/api/teams/{teamID}/oidc-groups` | member | Which groups control this team's membership: `{"member_group","owner_group"}`. An empty string means no group grants that role here | -| `PUT` | `/api/teams/{teamID}/oidc-groups` | **owner** | Set them. An empty string clears a binding | -| `GET` | `/api/teams/{teamID}/integrations` | member | List integrations. Never returns keys. Each carries `status` (`active` if its key posted within 24h, `quiet` if it has but not lately, `never`), `last_used_at` (last webhook, usable or not), `last_alert_at` (when an alert last arrived on it) and `alerts_24h` (distinct alerts it refreshed in the last day). Alerts delivered before the source was recorded (migration 010) have none, so the last two fill in as Alertmanager re-sends them | -| `PATCH` | `/api/teams/{teamID}/integrations/{integrationID}` | **owner** | Rename `{"name"}`. The key does not change | -| `POST` | `/api/teams/{teamID}/integrations` | **owner** | Mint an integration `{"name","kind"}` — key and URL shown once | -| `DELETE` | `/api/teams/{teamID}/integrations/{integrationID}` | **owner** | Revoke an integration. Alerts it delivered stay, unattributed | -| `GET` | `/api/teams/{teamID}/invites` | **owner** | The team's invite links, with their uses and expiry. Never the tokens | -| `POST` | `/api/teams/{teamID}/invites` | **owner** | Mint one `{"role","max_uses"}` — the full URL is returned once | -| `DELETE` | `/api/teams/{teamID}/invites/{inviteID}` | **owner** | Revoke a link before it expires | -| `GET` | `/api/teams/{teamID}/escalation` | member | The team's [escalation ladder](#escalation) `{repeat_count, fallback_topic, levels[], last_escalated_at?, last_escalated_incident_id?}`. Empty levels means the team has none. Each level also carries `status` (`ready`, `escalating` when an unanswered incident has climbed to it, `unreachable` when nobody on it could be woken), `waiting` (ids of the open incidents on it) and, per target, `username` (who it means today — the person on call, for a rota target), `reachable` and `problem`. The extra fields are output only; `PUT` takes the plain shape | -| `PUT` | `/api/teams/{teamID}/escalation` | **owner** | Replace it wholesale. `400` for a level with no targets or no timeout — a rung that pages nobody is a silence with a number on it | -| `GET` | `/api/teams/{teamID}/deadman/switches` | member | The team's [dead man's switches](#dead-mans-switch), each `{id, name, matcher, timeout_seconds, severity, status, last_heartbeat_at, last_triggered_at, open_incident_id, sources[]}`. `status` is `healthy`, `dead` or `dormant`; `sources` has one entry per heartbeat fingerprint. Empty when the team watches nothing | -| `POST` | `/api/teams/{teamID}/deadman/switches` | **owner** | Add one: `{name?, matcher, timeout_seconds, severity?}`. `400` when the matcher names no `alertname` or holds several, or the timeout is not positive — a switch that silently watches nothing is the failure this feature exists to prevent | -| `PUT` | `/api/teams/{teamID}/deadman/switches/{switchID}` | **owner** | Replace one in place, same body and validation as create. Its id is unchanged — for an automated caller reconciling a spec change, unlike delete-and-recreate | -| `DELETE` | `/api/teams/{teamID}/deadman/switches/{switchID}` | **owner** | Stop watching. An incident it opened stays open. `404` for a switch of another team | - -### Notifications - -| Method | Path | Description | -|---|---|---| -| `POST` | `/api/notify/ack/{token}` | Acknowledge an incident from a push notification's Acknowledge button. No auth: the token in the path is the credential — one incident, one action, 24 hours, idempotent. Must stay publicly reachable | - -### Incidents - -| Method | Path | Description | -|---|---|---| -| `GET` | `/api/incidents` | List incidents. Filters: `?status=triggered\|acknowledged\|resolved`, `?severity=`, `?assigned_to=`, `?archived=true`, `?snoozed=true`, `?from=YYYY-MM-DD`, `?to=YYYY-MM-DD`, `?sort=severity`, `?cluster=`, `?limit=` (default 50, max 500) | -| `GET` | `/api/incidents/clusters` | The distinct `cluster` values on the caller's incidents from the last 90 days, sorted (`?team_id=` narrows it). An empty array when nothing carries the label | -| `GET` | `/api/incidents/{id}` | Get single incident, with its alerts inline | -| `GET` | `/api/incidents/{id}/alerts` | Alerts under this incident | -| `GET` | `/api/incidents/{id}/timeline` | Full event history, chronological | -| `POST` | `/api/incidents/{id}/acknowledge` | Acknowledge (stamps authed user + time) | -| `DELETE` | `/api/incidents/{id}/acknowledge` | Clear acknowledgement, back to `triggered` | -| `POST` | `/api/incidents/{id}/resolve` | Close by hand — **terminal**, see above | -| `POST` | `/api/incidents/{id}/assign` | Reassign `{"user_id"}` | -| `POST` | `/api/incidents/{id}/snooze` | Hide until `{"until": RFC3339}` or `{"duration": "2h"}` | -| `DELETE` | `/api/incidents/{id}/snooze` | Un-snooze | -| `POST` | `/api/incidents/{id}/archive` | Archive (hides from the default list) | -| `DELETE` | `/api/incidents/{id}/archive` | Un-archive | -| `POST` | `/api/incidents/{id}/notes` | Add a note `{"content"}` | -| `DELETE` | `/api/incidents/{id}/notes/{eventID}` | Delete own note | - -With no `?status=` filter, `GET /api/incidents` returns **open** incidents only — -the queue an on-call person wants. Currently snoozed and archived incidents are -excluded unless asked for. Actions that only make sense on an open incident -return `409` once it is resolved. - -Notes are ordinary timeline events of type `note`; only they are deletable, and -only by their author. The rest of the timeline is a record of what happened. - -#### The incident object - -| Field | Type | Notes | -|---|---|---| -| `id` | integer | Server-assigned | -| `group_key` | string | Alertmanager's `groupKey` — opaque, treat as an identifier | -| `title` | string | Rendered from `groupLabels` | -| `group_labels` | object | String→string, as sent by Alertmanager | -| `status` | string | `"triggered"`, `"acknowledged"` or `"resolved"` | -| `severity` | string | *optional* — high-water mark across the incident's alerts; never lowered | -| `triggered_at` | timestamp | When the incident opened | -| `acknowledged_by_id` / `acknowledged_by` / `acknowledged_at` | | *optional* — user id, username, time | -| `assigned_to_id` / `assigned_to` | | *optional* — user id, username | -| `snoozed_until` | timestamp | *optional* — a value in the past reads as not snoozed | -| `resolved_at` | timestamp | *optional* | -| `resolution_source` | string | *optional* — `"alerts"`, `"manual"` or `"recovered"` | -| `archived_at` | timestamp | *optional* | -| `alerts` | array | Only on `GET /api/incidents/{id}` | - -Treat `resolution_source` as an open set, as with the alert field of the same -name: degrade unknown values to "resolved, reason unknown". - -#### The timeline event object - -| Field | Type | Notes | -|---|---|---| -| `id` | integer | | -| `incident_id` | integer | | -| `type` | string | See below — treat as an open set | -| `user_id` / `username` | | *optional* — absent when the server acted rather than a person | -| `alert_id` | integer | *optional* — the alert an `alert_added` / `alert_resolved` event refers to | -| `detail` | string | *optional* — the note body, the snooze deadline, etc. | -| `created_at` | timestamp | | - -Types written today: `triggered`, `alert_added`, `alert_resolved`, -`acknowledged`, `unacknowledged`, `assigned`, `archived`, `unarchived`, `snoozed`, -`unsnoozed`, `resolved`, `note`, `notified`, `notify_failed`, `deadman_silent`. On an -`assigned` event `user_id` is the **assignee**, not the actor; the actor is in -`actor_user_id`/`actor_username` or `actor_service_account_id`/`actor_service_account_name` -(absent on assignments made before they were recorded). New types may be added; render -unknown ones generically rather than dropping them. - -On `notified` and `notify_failed`, `detail` carries the notification kind -(`triggered` | `reminder` | `resolved`), and on a failure the reason after it. -`user_id` is who was paged — absent means the page went to the shared fallback -topic and so belongs to nobody. The topic itself is never written to the -timeline: it is a shared secret with the ntfy server, and every API key can read -this. - -### Alerts - -Alerts are read-only. Everything a person does happens on the incident. - -| Method | Path | Description | -|---|---|---| -| `GET` | `/api/alerts` | List alerts. Filters: `?status=firing\|resolved`, `?name=`, `?incident_id=`, `?archived=true`, `?from=YYYY-MM-DD`, `?to=YYYY-MM-DD`, `?limit=` (default 50, max 500) | -| `GET` | `/api/alerts/{id}` | Get single alert | - -Archived alerts are hidden from `GET /api/alerts` unless `?archived=true` is -passed; alert archiving is automatic housekeeping by the sweeper, not a user -action. Resolved alerts carry `resolution_source`: `"alertmanager"` for a real -resolved webhook, `"expiry"` when the sweeper inferred it (see -[Stale alert expiry](#stale-alert-expiry)), `"deadman"` for a heartbeat declared -dead (see [Dead man's switch](#dead-mans-switch)). - -#### The alert object - -Returned by `GET /api/alerts` (as an array) and `GET /api/alerts/{id}`. -Timestamps are RFC 3339 in UTC. Fields marked *optional* are omitted entirely -when unset, so clients must treat them as nullable. - -| Field | Type | Notes | -|---|---|---| -| `id` | integer | Server-assigned; stable for the life of the row | -| `fingerprint` | string | Alertmanager's fingerprint — the upsert key | -| `name` | string | From the `alertname` label | -| `status` | string | `"firing"` or `"resolved"` | -| `labels` | object | String→string, as sent by Alertmanager | -| `annotations` | object | String→string, as sent by Alertmanager | -| `starts_at` | timestamp | When the alert instance began, **per Prometheus** | -| `ends_at` | timestamp | *optional* — absent while no end is known | -| `generator_url` | string | Link back to the originating Prometheus | -| `received_at` | timestamp | When the server last accepted a webhook for this alert — see below | -| `incident_id` | integer | *optional* — the most recent incident this alert belongs to | -| `resolution_source` | string | *optional* — `"alertmanager"`, `"expiry"` or `"deadman"` | -| `archived_at` | timestamp | *optional* — set while archived | - -##### `received_at` is a liveness heartbeat - -`starts_at` comes from Prometheus and **never changes** for the lifetime of an -alert instance. It says when the problem began, not whether it is still -happening — an alert that started twelve days ago looks identical whether -Alertmanager refreshed it a minute ago or went silent a week ago. - -`received_at` is the field that answers "is this still live". It is set to the -server's clock on **every accepted webhook** for that fingerprint, including the -unchanged firing notifications Alertmanager re-sends every `repeat_interval`. -Clients may rely on this: - -- **A firing alert whose `received_at` is advancing is still being refreshed.** - Stale-dating it against `repeat_interval` is a valid liveness check, and it is - what the built-in sweeper does (see - [Stale alert expiry](#stale-alert-expiry)). -- **`received_at` tracks accepted payloads, not delivery attempts.** A retry - that describes an older instance than the stored one is discarded, and a - discarded payload does not move `received_at`. -- **It stops advancing once the alert resolves,** because Alertmanager stops - re-sending. On an alert resolved by the sweeper - (`"resolution_source": "expiry"`) it therefore marks the last time - Alertmanager was actually heard from, which is earlier than `ends_at`. - -`GET /api/alerts` is ordered by `received_at` descending — most recently -refreshed first — and the `?from=` / `?to=` filters on both the alert and stats -endpoints select on `received_at`, not `starts_at`. - -##### `resolution_source` says how much to trust `ends_at` - -An alert can leave the firing state two ways, and `resolution_source` records -which happened. Clients may rely on this: - -- **Absent while firing.** It is set only on resolve, and a re-fire under the - same fingerprint clears it again, so its presence always agrees with - `"status": "resolved"`. -- **`"alertmanager"` — a real resolved webhook arrived.** `ends_at` is the end - time Alertmanager reported. It is an observed value and can be displayed as - fact. -- **`"expiry"` — the sweeper inferred the resolve** because Alertmanager stopped - refreshing the alert (see [Stale alert expiry](#stale-alert-expiry)). Nothing - ever reported an end, so **`ends_at` is approximate**: it is either the stale - `endsAt` watermark from the last notification, or — when that notification - carried none — the time the sweep ran, which lags the last real contact by up - to `TERDUT_STALE_AFTER` plus a sweep interval. Treat it as "no later than", - not as when the problem stopped. - - On these alerts `received_at` is the more truthful signal: it marks the last - time Alertmanager was actually heard from. Surfacing the distinction is - worthwhile, since `"expiry"` can also mean the alert is still firing and the - notification path broke. - -- **`"deadman"` — a heartbeat was declared dead** (see - [Dead man's switch](#dead-mans-switch)). Like `"expiry"`, an inference from - silence rather than an observed end, so `ends_at` is approximate — but a much - tighter one, bounded by `TERDUT_DEADMAN_TIMEOUT`. It is also the one resolution - a re-fire under the same `starts_at` can undo, since the switch coming back is - exactly the evidence that the inference was wrong. - -Treat the value as an open set and tolerate ones you do not recognise — new -sources may be added, and unknown values should degrade to "resolved, reason -unknown" rather than being rejected. - -### On-call schedule - -| Method | Path | Description | -|---|---|---| -Each team keeps its own rota, so two teams can have two different people on call -on the same day. The person taking a shift has to be in the team — paging -somebody who cannot open the incident is worse than paging nobody. - -| Method | Path | Who | Description | -|---|---|---|---| -| `POST` | `/api/teams/{teamID}/schedule` | **owner** | Assign user to dates `{"user_id", "dates":["YYYY-MM-DD",...], "replace"}` — all-or-nothing | -| `GET` | `/api/teams/{teamID}/schedule` | member | List entries. Filters: `?from=YYYY-MM-DD`, `?to=YYYY-MM-DD` | -| `DELETE` | `/api/teams/{teamID}/schedule/{id}` | **owner** | Remove schedule entry | -| `GET` | `/api/schedule/current` | any | Who is on call today (UTC) in **every** team the caller is in — one entry per team, `[]` when nobody anywhere | - -### Statistics - -Every figure counts the caller's own teams only: a report that counted other -teams' incidents would leak their volume, and their alert names through the -top-alerts list, and would not be a number about the reader's work anyway. - -All stat endpoints accept optional `?from=YYYY-MM-DD` and `?to=YYYY-MM-DD`, and exclude archived rows to match the default list views. Alert stats filter on `received_at`; incident stats filter on `triggered_at`. - -| Method | Path | Description | -|---|---|---| -| `GET` | `/api/stats/incidents` | `{total, triggered, acknowledged, resolved, mtta_seconds, mttr_seconds}` | -| `GET` | `/api/stats/alerts` | `{total, firing, resolved}` counts | -| `GET` | `/api/stats/alerts/top` | Most frequent alert names. `?limit=` (default 10, max 100) | -| `GET` | `/api/stats/alerts/by-hour` | Count per hour-of-day (UTC), all 24 slots returned | -| `GET` | `/api/stats/alerts/by-day` | Count per day-of-week, all 7 slots with names returned | - -`mtta_seconds` (time to acknowledge) and `mttr_seconds` (time to resolve) are -averages over incidents that have actually been acknowledged or resolved, and are -**null** until there are any — null means "no data", not zero. - ---- - -## Upgrading to teams - -Everything that existed before teams moves into one team called **Default**, and -every existing user becomes an owner of it. The upgrade is a no-op for the -people using it: the same queue, the same schedule, the same incidents, with a -name on them. - -What changes, and will need attention: - -- **Alert ingestion moved.** Mint a key with - `POST /api/teams/{teamID}/integrations` and point Alertmanager at the URL it - returns. In v0.12.0 the old `POST /api/alertmanager/webhook` still worked, - deprecated, routing everything to the oldest team; **v0.13.0 removes it**, so - upgrade straight from v0.11.x to v0.13.0 only after the senders are moved. -- **The schedule endpoints moved** under `/api/teams/{teamID}/schedule`, and - editing the rota is now an owner's job. `GET /api/schedule/current` stayed - where it was but now returns an **array** — one entry per team with somebody - on call — instead of a single object or a 404. This is a breaking API change - for anything that reads it, terdut-tui included. -- **Uniqueness is per team now.** Two teams can legitimately see the same alert - fingerprint, the same Alertmanager groupKey, and put somebody on call on the - same date. - -**Dead man's switches moved too.** `TERDUT_DEADMAN_MATCHERS`, `_TIMEOUT` and -`_SEVERITY` are no longer the setting; they are the default each existing team -is seeded with at startup, after which an owner manages them per team through -`/api/teams/{teamID}/deadman/switches` and a redeploy never overwrites that. - -Nothing else about an incident changes, and incidents never move between teams: -an alert belongs to whichever team's key it arrived on. - -## Upgrading to roles - -Before this release every authenticated caller could create and delete users, -set anybody's password and mint anybody's API keys. That is now the -administrator flag, and the migration **makes every existing user an -administrator** — they already held those powers, so nobody's access changes on -upgrade and demotion is a deliberate act afterwards. Promoting only the first -user would have silently stripped the rest, and could leave an install whose -only administrator is an account nobody has a password for. - -Users created after the upgrade are not administrators. Hand the flag out with: - -```bash -curl -X PUT https://terdut.example.com/api/users/7/admin \ - -H "Authorization: Bearer $TERDUT_API_KEY" \ - -H 'Content-Type: application/json' \ - -d '{"is_admin": true}' -``` - -Nothing in the API changed shape, so terdut-tui needs no new version — but a -non-administrator now gets `403` where a `200` used to come back. - -## Upgrading from SQLite - -Versions up to v0.10.2 stored everything in a SQLite file. From v0.11.1 the server needs -`TERDUT_DB_DSN` and keeps nothing on disk. - -The copy was done by `scripts/sqlite-to-postgres.go`, which **was deleted in v0.13.0** along -with the SQLite driver it was the last user of. It is still in the history — check out the -`v0.12.0` tag to get it: - -```bash -git show v0.12.0:scripts/sqlite-to-postgres.go > sqlite-to-postgres.go -``` - -The cutover is ordered, and the server must not be running while the copy happens: stop the -old version, let the new binary build the schema against an empty Postgres, run the script -with `-sqlite` and `-dsn`, then start the new version for good. On Kubernetes step three runs -as a Job with the same image against the PVC before it is removed. - -The copy preserves every id, so incidents keep their numbers and the timeline, alert -membership, outbox and ack tokens all still point where they did. It refuses a target that -already has rows, so a second run cannot double-insert. - -## Upgrading to incidents - -The incidents release moves the workflow off alerts, which is a **breaking API -change**. These endpoints are gone: - -| Removed | Replacement | +| | | |---|---| -| `POST`/`DELETE` `/api/alerts/{id}/acknowledge` | `POST`/`DELETE` `/api/incidents/{id}/acknowledge` | -| `POST`/`DELETE` `/api/alerts/{id}/archive` | `POST`/`DELETE` `/api/incidents/{id}/archive` (alert archiving is now sweeper-only) | -| `GET`/`POST` `/api/alerts/{id}/comments` | `GET /api/incidents/{id}/timeline`, `POST /api/incidents/{id}/notes` | -| `DELETE /api/alerts/{id}/comments/{commentID}` | `DELETE /api/incidents/{id}/notes/{eventID}` | +| [Deployment](./docs/deployment.md) | Docker, Helm chart, database, backups, the operator | +| [Configuration](./docs/configuration.md) | Environment variables and settings | +| [Alertmanager configuration](./docs/alertmanager.md) | Routes, keys, webhooks | +| [Alerts and incidents](./docs/incidents.md) | Correlation, lifecycle, on-call assignment | +| [Single sign-on](./docs/single-sign-on.md) | OIDC and the terminal device flow | +| [API reference](./docs/api.md) | Every endpoint | +| [Development and releasing](./docs/development.md) | Tests, CI gate, release pipeline | -The alert object also drops `acknowledged_by_id`, `acknowledged_by` and -`acknowledged_at`, and gains `incident_id`. +## Related -Migration `008_incidents.sql` runs automatically on start and preserves existing -data: every alert gets a backfilled incident carrying its acknowledgement, and -comments become timeline notes. Backfilled incidents have a `group_key` of -`backfill:` — there is no historical `groupKey` to correlate on, so -they are one-per-alert rather than grouped. +- [terdut-tui](https://git.ryuvia.com/niklas/terdut-tui): a terminal client for the same server. +- [terdut-operator](https://git.ryuvia.com/niklas/terdut-operator): a Kubernetes operator that + runs the server and manages teams, escalation, switches and alert sources as objects. -Nothing about the two documented alert contracts changes: `received_at` is still -advanced on every accepted webhook, and `resolution_source` still means what it -did. +## License -## Upgrading to dead man's switches - -Dead man's switch handling is **on by default**, watching `alertname=Watchdog` -with a 15 minute timeout. If you already route `Watchdog` to this server, the -behaviour of that alert changes on upgrade, in both directions: - -- it stops opening incidents when it arrives, and -- it starts opening one when it stops arriving. - -**Check your `repeat_interval` before upgrading.** The switch pages whenever a -heartbeat has not been refreshed within `TERDUT_DEADMAN_TIMEOUT`, so a `Watchdog` -route inheriting a 4h or 12h `repeat_interval` will page constantly against the -15 minute default. Either give the heartbeat -[its own fast route](#alertmanager-configuration) — the point of the feature — or -set `TERDUT_DEADMAN_TIMEOUT` above your current `repeat_interval` until you have. -`TERDUT_DEADMAN_TIMEOUT=0` turns the whole thing off. - -There is no migration and no schema change. An existing open incident from a -`Watchdog` that arrived under the old behaviour is unaffected; resolve it by hand. - ---- - -## Development - -```bash -make test-db # start a local Postgres for the tests (podman or docker) -make test # run all tests -go build ./... # compile all packages -go run ./cmd/terdut # run locally (needs TERDUT_DB_DSN) -``` - -The tests need a real Postgres, because the server does — there is no in-memory Postgres the -way there was an in-memory SQLite. `TERDUT_TEST_DSN` says where it is, `make test-db` starts -one on port 5433 and prints the DSN, and `make test-db-stop` removes it. Each test gets its -own schema on that server, so tests cannot see each other's rows. An unset `TERDUT_TEST_DSN` -fails the suite rather than skipping it: a run that quietly tests nothing is worse than one -that does not run. - -`make fmt lint test helm-lint` is the gate. It mirrors `.gitea/workflows/ci.yaml` step for -step, so a green run here means a green pipeline — with one deliberate exception: `make test` -adds `-race`, which CI does not. The sweeper, the notifier goroutine and the dead man's switch -sweep all run concurrently against the same database, and a race between them would surface as -a flaky incident in production rather than as a red build. - -The web UI lives in `internal/web/static/` as plain HTML, CSS and ES modules, -embedded into the binary with `go:embed`. It has no build step and no npm, so -editing a file and restarting the server is the whole loop. - -## Releasing - -``` -push or PR → ci.yaml gofmt, go vet, go test -race - govulncheck, gitleaks - helm lint + render -push tag vX.Y.Z → release.yaml the same gate, then publish: - git.ryuvia.com/niklas/terdut-server:vX.Y.Z - oci://git.ryuvia.com/niklas/terdut-server X.Y.Z - then trivy-scan the pushed image -PR to Ryuvia/charts → bump the wrapper chart to X.Y.Z; on merge - Flux reconciles and the release rolls out -``` - -Both artifacts go to the **personal** Gitea namespace rather than `ryuvia`, because Gitea -scopes package visibility to the owner with no per-package override — so `ryuvia/*` is private -because the org is. Publishing to `niklas` keeps them anonymously pullable, which is why no -pull secret is needed in the cluster. Same reasoning, and the same choice, as riksdata and -rd-web. - -Saying **"Release"** runs all three rows: the `release` skill commits, pushes, tags, waits for -the pipeline, and opens the `Ryuvia/charts` PR, stopping before the merge. See -`~/.claude/skills/release/`, or `.release.conf` here for this repo's part of it. - -The chart is published **only** from the tag, by the `chart` job. There used to be a second -publisher on every `charts/**` push to main, and the two raced for the same chart version with -different answers — chart 0.9.0 went out reading `appVersion: "latest"` that way. One -publisher, triggered by the tag (`766f439`). The cost is that a chart-only change has no -version of its own and rides the next app tag. - -Both workflows are thin drivers over the Makefile: `ci.yaml` runs `make fmt lint test` and -`make helm-lint`, `release.yaml` adds `make binaries`, `make push`, `make helm-package` and -`make helm-push`. That is deliberate — it is what makes a green local gate and a green -pipeline the same code rather than two descriptions of it, and it is how riksdata and rd-web -have always worked. - -`make push` builds and pushes in one step, unlike those two, because the image is -`linux/amd64,linux/arm64` and buildx cannot load a multi-platform result into the local image -store. `make build` stays single-platform and local-only. Both refuse `VERSION=dev`: -publishing is one command, so it is also one command to run by accident. Publishing happens -by pushing a tag. - -Two things the release process needs to know about this repo: - -- **The image scan runs after publishing**, like riksdata's and rd-web's: trivy cannot read - a locally built image on this runner, so it pulls the pushed one. A red `scan-image` means - do not bump the wrapper chart to that version — it cannot unpublish anything. The image is - `FROM scratch`, so trivy sees exactly one target, the Go binary and its module graph. -- **The wrapper chart's `values.yaml` has two `tag:` lines** — the app image and the python - backup sidecar — so `chart-bump` is given `--image` to say which one moves. The sidecar is - on its way out with SQLite: once the wrapper chart drops it and declares a `postgresql` CR - instead, there is one `tag:` line again, and `--image` becomes belt and braces. - -The wrapper chart must have **its own `version:` bumped in the same commit**. Flux reconciles -with `reconcileStrategy: ChartVersion`, so a chart whose version did not change produces no -new artifact and the change is never deployed — with no error anywhere. +See [LICENSE](./LICENSE). diff --git a/SERVICE-ACCOUNTS.md b/SERVICE-ACCOUNTS.md index 2d264c0..ff768a9 100644 --- a/SERVICE-ACCOUNTS.md +++ b/SERVICE-ACCOUNTS.md @@ -1,263 +1,60 @@ -# Service accounts: a scoped, non-human credential type +# Service accounts -This is a design note for a feature, not an implementation plan — it exists to -propose the shape before writing code. It's raised directly by `terdut-operator` -(a separate repo, no shared code — see its `DESIGN.md` §6, §9, §13), which needs -a credential for unattended, repeatable API access and currently has no good one -available. Anything automating terdut-server long-term (this operator, CI, future -integrations) hits the same gap, so this is written as a general primitive, not -operator-specific. +A non-human credential for automation (terdut-operator, CI, scripts). It is not a +`users` row: no password, no `is_admin`, no OIDC identity, so it can never be +pulled into login or group sync, and it is never mistaken for a person in an +audit trail. The bearer token has the same shape as an API key (SHA-256 hash +stored, raw value shown once), prefixed `tdsa_`. -## The problem +## Scopes -terdut-server has two credential types today, and neither fits "an unattended -process that manages teams/schedules/policies on someone's behalf": +- **instance** — acts as owner of every team's *configuration* (rename, OIDC + groups, escalation, dead man's switches, integrations, members, delete) and may + create teams. It is not a member of any team, so it reads no incidents or + queue. It is never an administrator: user management and + `/api/admin/settings` stay human-only. +- **team** — acts as owner of exactly one team, through a single synthetic + membership. It may also mint another service account for its own team. -- **User API keys** (`api_keys`, `internal/api/users.go`) are always tied to a - real `users` row and carry that user's full rights — every team they're a - member of, their admin flag if set. There's no `kind`/`service` marker - distinguishing "a human's personal automation key" from "a login session," and - no way to mint one scoped to less than the full user. -- **Integration keys** (`integrations`, `internal/api/*teams*.go`) are team-scoped, - but narrowly: they authenticate exactly one inbound Alertmanager webhook call - (`POST /api/integrations/{key}/alertmanager`) and nothing else. They're not a - general management-API credential and shouldn't become one — overloading a - narrow, one-way ingestion credential with broad read/write access would weaken - the one property that makes it safe to embed in an Alertmanager config today. +An account has many keys, so rotating is "mint a new key, revoke the old one" +without losing the account's identity or history. -The result: any automation that needs to create teams, set escalation policies, -manage dead-man switches, or rotate integration keys has to hold a real human -admin's or team owner's API key. That key is exactly as powerful as that person -logging in — full team access, and full instance access if they're an admin. -`terdut-operator`'s design ran directly into this (its DESIGN.md §6): its -described bootstrap/rotation flow assumed a repeatable, identity-scoped way to -get a credential, and `/api/bootstrap`'s actual behavior (single-shot per -install, gated on `COUNT(*) FROM users`, confirmed via `internal/api/users.go` -and `charts/terdut-server/templates/bootstrap-job.yaml`) doesn't provide one — -it mints exactly one founding admin, once, ever. +## Endpoints -## Goals +- `POST /api/service-accounts` `{name, scope, team_id}` — returns the account and + its first key. An instance-scoped account is granted by a human administrator; + a team-scoped one by an administrator, that team's owner, or an instance-scoped + account. +- `GET /api/service-accounts?name=` — look one up by name. +- `POST /api/service-accounts/{id}/keys`, `DELETE .../keys/{keyID}` — mint or + revoke a key. An instance-scoped account may manage any team-scoped account's + keys, and any account may manage its own. -- A credential type that isn't a human: doesn't touch OIDC group sync, login, - session, or the `is_admin`/account-management semantics that come with a real - `users` row. -- Two scopes matching the two shapes automation actually needs: instance-wide - (create/list teams — what a server-owning controller needs) and team-scoped - (manage one team's escalation policy, dead-man switches, integrations, - schedule, OIDC group bindings — what a per-team controller or integration - needs). -- Repeatable issuance and rotation — unlike `/api/bootstrap`, callable more than - once, by anything that already holds admin rights, without destroying and - recreating state to get a fresh credential. -- Visibly distinct from a human in every place identity shows up (audit trails, - timeline entries, UI attribution) — a service account acting on a team should - never be indistinguishable from a person. +## Seeding the operator's account -## Non-goals +`TERDUT_OPERATOR_KEY` (at least 32 characters) creates the instance-scoped account +`terdut-operator` if missing and replaces its `seed` key with this value at every +start (`internal/api/operator_key.go`). The deployer generates the key and +nothing has to call `/api/bootstrap` for it; rotating is a restart with a new +value. With `TERDUT_OPERATOR_MODE` on, configuration writes by humans are refused +and a service account of either scope passes. -- Not a general OAuth2/OIDC client-credentials flow — this is a bearer-token - primitive matching the shape `api_keys` already uses (SHA-256 hash stored, - raw key shown once at creation), not a new auth protocol. -- Not replacing integration keys — those stay as the narrow, one-way webhook - credential they are today. -- Not modeling per-endpoint or per-verb permissions within a scope — `instance` - and `team` are the only two scopes for now; finer-grained scoping is future - work if a real need shows up. +## How it is enforced -## Proposed shape +Every request resolves to one `Caller` (`internal/api/caller.go`): a human +(session or API key) or a service account. -### Schema +- `Caller.IsAdmin()` is true only for a human administrator. `AdminOnly` and + `requireSelfOrAdmin` key on it alone; do not widen them — each time a gap came up + the fix was a narrower purpose-built capability instead. +- `Caller.IsInstanceServiceAccount()` is true only for an instance-scoped account, + never for a human. `requireTeamOwner` and `callerOwnsTeam` admit it for any team. +- `Caller.Role(teamID)`/`TeamIDs()` are a human's memberships or a team-scoped + account's single owner membership; instance scope has none. +- `Caller.AsHuman()` is what a handler must call when it needs a real `user_id`; + handlers meant for people answer 403 to a service account instead of writing a + zero id. -```sql -CREATE TABLE service_accounts ( - id BIGSERIAL PRIMARY KEY, - name TEXT NOT NULL UNIQUE, -- e.g. "terdut-operator" - scope TEXT NOT NULL CHECK (scope IN ('instance', 'team')), - team_id BIGINT REFERENCES teams(id) ON DELETE CASCADE, - -- team_id required iff scope = 'team'; NULL iff scope = 'instance' - created_by BIGINT REFERENCES users(id), - created_at TIMESTAMPTZ NOT NULL DEFAULT now() -); - -CREATE TABLE service_account_keys ( - id BIGSERIAL PRIMARY KEY, - service_account_id BIGINT NOT NULL REFERENCES service_accounts(id) ON DELETE CASCADE, - key_hash TEXT NOT NULL UNIQUE, - name TEXT NOT NULL, -- e.g. "initial", "2026-Q4-rotation" - created_at TIMESTAMPTZ NOT NULL DEFAULT now(), - last_used_at TIMESTAMPTZ -); -``` - -Deliberately not a `users` row: no `password_hash`, no `is_admin`, no -`user_identities` linkage, so it's structurally impossible for a service account -to be pulled into OIDC group sync or password login. Multiple keys per account -(mirroring `api_keys`' existing one-user-many-keys shape) so rotation is "mint a -new key, revoke the old one," not "recreate the account." - -### Endpoints - -- `POST /api/service-accounts` — instance-scope/admin-only. Body: - `{"name": ..., "scope": "instance"|"team", "teamID": ... }` (teamID required - iff scope=team, and caller must be that team's owner or a system admin). - Returns the account plus its first raw key (shown once, same pattern as - `POST /api/users/{id}/api-keys`). Safe to call again with the same `name` — - see "idempotent lookup" below — unlike `/api/bootstrap`, which is inherently - one-shot by design (it's answering "does any user exist yet," a question with - no analogue once one already does). -- `POST /api/service-accounts/{id}/keys` — mint an additional key on an existing - account (self-service-equivalent: instance admin for `instance` scope, team - owner or system admin for `team` scope). Enables rotation without recreating - the account or losing its identity/audit history. -- `DELETE /api/service-accounts/{id}/keys/{keyID}` — revoke one key, mirroring - `DELETE /api/users/{id}/api-keys/{keyID}`. -- `GET /api/service-accounts?name=` — look up an existing account by name. - This is what turns "I tried to create my account and got a conflict" into a - normal flow instead of an error: a controller that expects to have already - registered itself calls this first, and only falls through to `POST` if - nothing comes back. - -### Auth middleware - -**Revised** (this section originally described an aspiration that didn't -match what shipped — `TEAM-LOOKUP.md` already caught one instance of that, -and a fuller audit found three more; this is the corrected, as-built -description, not the original proposal). - -`internal/api/middleware.go`'s dual resolution (`Authorization: Bearer` → -`apiKeyUser()`, or session cookie → `sessionUser()`) and the service-account -path (`serviceAccountFor()`) both resolve into one `Caller` type -(`internal/api/caller.go`), not two parallel, un-unified context -representations the way an earlier version of this server kept them. Every -authorization predicate reads `Caller`'s methods: - -- `Caller.IsAdmin()` — true **only** for a human system administrator, never - for a service account of either scope, under any circumstance. `AdminOnly` - and `requireSelfOrAdmin` key on this alone — user management - (`POST /api/users`, `PUT /api/users/{id}/admin`, etc.) and - `GET/PUT /api/admin/settings` stay human-only, forever. The original text - here claimed an instance-scoped service account satisfies `AdminOnly` "for - team-creation/listing purposes" — that was never true of the shipped code - (`TEAM-LOOKUP.md` caught the listing half; the creation half was always a - separate, bespoke check in `handleCreateTeam`, not `AdminOnly` itself) and - is not being made true now. Don't widen `AdminOnly`: every time this has - come up, the fix has been a narrower, purpose-built capability instead - (`?name=` lookups for teams and service accounts; now - `terdut-operator`'s own invite-minting feature for the one real gap this - boundary left — how a human ever gets a first login on a no-OIDC, - operator-managed install. See the bottom of "What this unblocks.") -- `Caller.IsInstanceServiceAccount()` — true only for an instance-scoped - service account, never for a human (including a human admin). - `handleCreateTeam` uses exactly this: a human creates a team by being a - human (and becomes its owner); an instance-scoped service account creates - one with no human owner at all. The two paths are not interchangeable, so - this predicate deliberately does not also admit a human admin. -- `Caller.Role(teamID)`/`TeamIDs()` — a human's real `team_members` rows, or - a team-scoped service account's single synthetic owner membership - (`serveAsServiceAccount`). This is what makes `requireTeamMember`/ - `requireTeamOwner` treat a team-scoped service account as owner-equivalent - for that one team, with no separate branch needed in either function. -- `Caller.ServiceAccountID()` — used by `OperatorModeBlock` ("any service - account passes") and by `callerMayManageServiceAccount`'s self-rotation - check. -- `Caller.AsHuman()` — the accessor every handler that needs a real - `user_id` to act on behalf of must call and check, instead of reading a - user off context unconditionally. Before the `Caller` type existed, four - handlers did the latter and silently misbehaved for a service-account - caller: `handleMe` and `handleTestNotification` 500'd (a zero-value user id - that matches no row), `handleDismissOnboarding` silently no-op'd (`UPDATE - ... WHERE id = 0` affects nothing, still returns 204), and - `handleCreateInvite` wrote that same zero value into `invites.created_by` - — a real foreign-key violation, not just a wrong answer, since that column - is nullable but was never passed as `nil`. All four now call `AsHuman()` - and return an explicit 403 ("this endpoint is for human accounts only") - or, for the invite case, leave `created_by` `NULL` the same way - `handleCreateServiceAccount` already did for the analogous situation. - -**Team scope is owner-equivalent for every `requireTeamOwner` endpoint, -membership and invites included — by design, not by an unclosed gap.** An -earlier version of this document flagged this as "acknowledged rather than -closed," kept in check only by the social convention that nobody *builds* -automation against those two routes. That convention is retired: -`terdut-operator`'s `TerdutTeam` controller now mints and revokes its own -team's invite link through exactly this capability (its existing -team-scoped credential, `POST`/`DELETE /api/teams/{teamID}/invites`), which -is the real fix for the human-onboarding gap below — not a narrower -carve-out of this capability. `service_accounts_test.go`'s -`TestServiceAccount_TeamScopeManagesItsOwnInvites` pins it. - -**A team-scoped account can also mint another service account scoped to its -own team** (`handleCreateServiceAccount`'s `callerOwnsTeam` branch, which a -team-scoped caller already satisfies for its own team via the synthetic -membership above). Kept, not restricted, for the same reason: a team-scoped -credential is that team's owner's reach, full stop — carving this one -capability out while leaving membership/invites alone would be an arbitrary -asymmetry. Pinned by -`TestServiceAccount_TeamScopeCanMintAnotherAccountForItsOwnTeam`. - -**`callerMayManageServiceAccount` gained the one load-bearing fix this -redesign exists for:** an instance-scoped service account may manage -(mint/revoke a key on) *any* team-scoped account, not only one admin, that -team's human owner, or the account itself. `handleCreateServiceAccount` -already let an instance-scoped caller *create* a team-scoped account for -any team; this closes the gap where adopting or rotating one it didn't just -create in the same call — exactly `terdut-operator`'s documented -adopt-on-409 crash-window recovery (its own `DESIGN.md` §5) — 403'd forever -instead of succeeding (`terdut-operator#3`). Pinned by -`TestServiceAccount_InstanceScopeAdoptsAnExistingTeamScopedAccountsKey`. - -Anywhere identity is recorded for a human (incident timeline -`acknowledged_by`/`assigned_to`, audit-relevant fields), a service-account -caller is still coerced into a bare `user_id` of `0` today — `Caller`'s new -`Identity()` accessor exists for exactly this follow-up, but wiring it in -needs a schema migration (an actor-attribution column distinct from -`user_id`) and is deliberately out of scope here. Tracked separately, not by -this document. - -## What this unblocks - -Directly resolves `terdut-operator` DESIGN.md §6's two broken assumptions: -1. **Bootstrap becomes single-purpose again.** `/api/bootstrap` mints exactly - the founding human admin, once. The operator's actual first-reconcile flow: - call `/api/bootstrap` only on a genuinely empty install; otherwise (or - immediately after, if it won the bootstrap race) call - `GET /api/service-accounts?name=terdut-operator`, and `POST` one if it - doesn't exist yet. From then on the operator never touches `/api/bootstrap` - again. -2. **Rotation becomes real.** `POST /api/service-accounts/{id}/keys` + revoke the - old one — no destructive DB-level workaround, no re-triggering a single-shot - endpoint that can't fire twice. -3. **Cross-namespace credential mirroring is no longer needed at all.** - `terdut-operator`'s current design holds every credential — instance- and - team-scoped alike — privately in the operator's own namespace, never in - the namespace of the CR each one authenticates for; reconciliation happens - entirely inside the operator's controller loop, so no CR owner ever needs - read access to a terdut-server credential regardless of same- or - cross-namespace `serverRef`. Team scoping is still what bounds the blast - radius of any individual credential: a leaked team-scoped key exposes - exactly one team's resources, never the whole server, which is what makes - holding many credentials in one place (the operator's namespace) an - acceptable trade rather than reintroducing the mirrored design's - server-admin-equivalent-everywhere problem. -4. **A human can get a first login on a no-OIDC, operator-managed install — - without ever touching `AdminOnly` or `/api/admin/settings`.** This was - filed as `terdut-server#23` ("no API path to create a human login after - bootstrap") and diagnosed, at the time, as this server needing to let a - service account through `AdminOnly`. It doesn't: the fix lives entirely - in `terdut-operator`, because a team-scoped credential was *already* - owner-equivalent for `POST /api/teams/{teamID}/invites`, and invite - redemption (`POST /api/signup` with an `invite` token) bypasses - `signup_mode` entirely — `terdut-operator` just never grew a feature to - use either fact. Its `TerdutTeam` controller now mints and surfaces one - via its own existing team-scoped credential (`spec.invite`, - `status.inviteSecretRef`, see that repo's own docs), so a human joins a - CRD-managed team by a real invite link, the same way anyone else would. - `terdut-server#23` is closed with this note once that feature ships — its - named routes stay human-only, correctly, not a gap. - -## Suggested sequencing - -Land this before `terdut-operator` implements any bootstrap/credential-handling -code — that code would otherwise be written against the current one-shot, -user-only credential model as a known-temporary workaround, which is wasted -effort on a repo that currently has zero implementation to begin with. +Where a service account acts on an incident (acknowledge, resolve), the +timeline and `acknowledged_by` record it through parallel `*_service_account_id` +columns, never as a user. diff --git a/TEAM-LOOKUP.md b/TEAM-LOOKUP.md deleted file mode 100644 index 67419cd..0000000 --- a/TEAM-LOOKUP.md +++ /dev/null @@ -1,73 +0,0 @@ -# Team lookup for service accounts: closing terdut-operator's create-path crash window - -This is a design note for a feature, not an implementation plan — same posture as -`SERVICE-ACCOUNTS.md`, and raised for the same reason: `terdut-operator`'s `TerdutTeam` -controller (ROADMAP.md Stage 2, a separate repo, no shared code) hit a gap this server has -no answer for yet. - -## The problem - -`POST /api/teams` (`handleCreateTeam`, confirmed against `internal/api/teams.go`) lets an -instance-scoped service account create a team — it has its own explicit -`isInstanceServiceAccount(...)` branch alongside the human-user path, not gated by -`AdminOnly`. If that call succeeds server-side but the caller (`TerdutTeam`'s controller) -crashes before persisting the resulting team ID locally, a retry's `POST` 409s on the name's -unique constraint (confirmed: the `isUniqueViolation` branch in the same handler). - -Recovering from that 409 means looking the team up by name, and nothing today permits that -for a service account: - -- `GET /api/teams` (`handleListTeams`) answers "what teams does the *caller* belong to", via - a `team_members` join keyed on `userFromContext`'s `caller.ID` — confirmed against source. - A service account is never a member of anything, so this always returns empty for one, - regardless of what exists. -- `GET /api/admin/teams` (`handleAdminListTeams`) is gated by `AdminOnly`, and `AdminOnly`'s - actual code (`internal/api/middleware.go`) checks only `userFromContext(...).IsAdmin` — no - branch for a service account at all, confirmed against source. This contradicts - `SERVICE-ACCOUNTS.md`'s own text, which claims "an instance-scoped [service account - satisfies] `AdminOnly` for team-creation/listing purposes" — that claim doesn't match this - endpoint's actual, shipped code. (Team *creation* is fine: `handleCreateTeam` isn't behind - `AdminOnly` at all, it has its own check. Only the listing half of that sentence is wrong.) - -This is exactly the shape of gap `SERVICE-ACCOUNTS.md`'s own `GET /api/service-accounts?name=` -closed for service accounts themselves (confirmed: that endpoint's own comment — -"the name lookup is open to any authenticated caller... what lets a service account find its -own account on the 403 that follows a second POST"). Teams never got the equivalent, because -nothing needed it until an operator started creating them unattended. - -## Goals - -- A service-account-accessible way to look up one team by exact name, mirroring - `GET /api/service-accounts?name=` as closely as possible — same shape, same reasoning, - same low sensitivity of what it discloses. -- No change to today's behavior for an empty/no-name request. - -## Proposed shape - -Extend `GET /api/teams` itself, the same way `handleListServiceAccounts` already branches on -a `?name=` query param, rather than adding a new route: - -- `name` unset (today's behavior, unchanged): the caller's own teams, via `team_members`. -- `name=` set: look up that one team by exact name — a one-or-zero-length array, not - an error on no match, mirroring `GET /api/service-accounts?name=`'s own response shape and - status codes exactly. Deliberately **not** gated by `isInstanceServiceAccount` or - `AdminOnly`: a human caller who's already a member sees this same information in their own - team list regardless, and a non-member learning only that a name is taken — not who's in - the team, not any of its data — is the same low-sensitivity disclosure - `GET /api/service-accounts?name=` already accepts for service-account names. - -## What this unblocks - -Directly resolves the crash-window gap in `terdut-operator`'s `TerdutTeam` controller: on a -409 from `POST /api/teams`, `GET /api/teams?name=` — authenticated with the -same instance-scoped credential that just got the 409 — finds the id, and the controller -proceeds as if its own create had returned it directly. The same adopt-on-409 pattern already -proven for service accounts (that repo's `DESIGN.md` §6 point 1, §5's general rule), not a -new one. - -## Suggested sequencing - -Land this before `TerdutTeam`'s create path is implemented — the same reasoning -`SERVICE-ACCOUNTS.md` gave for its own sequencing: writing that code against today's gap as a -"known-temporary workaround" is wasted effort when the fix is this small and this -well-precedented. diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..c59199e --- /dev/null +++ b/docs/README.md @@ -0,0 +1,21 @@ +# Terminal Duty documentation + +The [README](../README.md) is the short tour. These pages hold the detail. + +**Running it** +- [Deployment](./deployment.md): Docker, the Helm chart, the database, backups, and the operator. +- [Configuration](./configuration.md): environment variables and settings. +- [Single sign-on](./single-sign-on.md): OIDC, group mapping, the terminal device flow. + +**Using it** +- [The web UI](./web-ui.md): sessions, the Team and Admin tabs. +- [Alertmanager configuration](./alertmanager.md): routes, integration keys and webhooks. +- [Alerts and incidents](./incidents.md): correlation, lifecycle, on-call assignment, stale-alert expiry. +- [Push notifications](./notifications.md): ntfy pages and acknowledging from them. +- [Escalation](./escalation.md): ladders, repeats and the fallback topic. +- [Dead man's switches](./dead-mans-switch.md): noticing that alerts stopped arriving. + +**Integrating and contributing** +- [API reference](./api.md): every endpoint, authentication and error shape. +- [Service accounts](../SERVICE-ACCOUNTS.md): non-human credentials for automation. +- [Development and releasing](./development.md): tests, the CI gate, the release pipeline. diff --git a/docs/alertmanager.md b/docs/alertmanager.md new file mode 100644 index 0000000..a153e72 --- /dev/null +++ b/docs/alertmanager.md @@ -0,0 +1,62 @@ +# Alertmanager configuration + +_Pointing Alertmanager at the server._ Back to the [README](../README.md) and the [documentation index](./README.md). + +Alerts arrive on a team's **integration key**, which says both that the sender +may post and which team the alerts belong to. Mint one as an owner of the team: + +```bash +curl -X POST https://terdut.example.com/api/teams/1/integrations \ + -H "Authorization: Bearer $TERDUT_API_KEY" \ + -H 'Content-Type: application/json' \ + -d '{"name":"prod alertmanager"}' +``` + +The response carries the key and the full URL **once**; only a SHA-256 hash is +stored. Put it in your `alertmanager.yml`: + +```yaml +receivers: + - name: terdut + webhook_configs: + - url: http://terdut-server:8080/api/integrations//alertmanager + send_resolved: true + +route: + receiver: terdut +``` + +The whole URL is a credential, so treat it like one. Alertmanager 0.26 and +later can read it from a file with `url_file:` instead, which keeps it out of +your configuration repository: + +```yaml + - url_file: /etc/alertmanager/secrets/terdut-webhook-url/url + send_resolved: true +``` + +The webhook endpoint requires no authentication. + +If you use the [dead man's switch](./dead-mans-switch.md) — and the default configuration does — give +the heartbeat a route of its own, because the deadline is only as tight as the interval feeding it: + +```yaml +route: + receiver: terdut + repeat_interval: 4h + routes: + - matchers: [ 'alertname = "Watchdog"' ] + receiver: terdut + group_wait: 0s + group_interval: 1m + repeat_interval: 1m +``` + +That delivers a heartbeat every **2 minutes**, not every minute. Alertmanager only reconsiders a +group every `group_interval`, and at exactly one elapsed interval `repeat_interval` has not *quite* +passed, so the send slips to the next tick — equal values give 2×. Two minutes against the 15 minute +default is seven heartbeats per window, which is the point; use `group_interval: 30s` if you want +the numbers to mean what they say. + +kube-prometheus-stack users get the `Watchdog` alert (`expr: vector(1)`) for free; it just needs +routing to terdut rather than to `null`. diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..6af26a0 --- /dev/null +++ b/docs/api.md @@ -0,0 +1,436 @@ +# API reference + +_The REST API._ Back to the [README](../README.md) and the [documentation index](./README.md). + +## Authentication + +All endpoints except `/api/bootstrap`, `/api/integrations/{key}/alertmanager`, +`/api/notify/ack/{token}`, `/api/login`, `/api/logout`, `/api/auth/config`, +`/api/version`, `/api/oidc/login`, `/api/oidc/callback`, `/api/oidc/device` and +`/api/oidc/device/token` require either an API key: + +``` +Authorization: Bearer +``` + +or the web UI's session cookie. A request that carries an `Authorization` header +is judged on that header alone. + +Two kinds of user exist. An **administrator** manages accounts: creating and +deleting users, setting anybody's password, minting keys for anybody, and +granting the flag itself. Everybody else works incidents — acknowledging, +assigning, snoozing, resolving, noting — and manages their own account and +nobody else's. An API key carries exactly the rights of the user it belongs to. + +A third principal, the **service account**, exists for automation (a +Kubernetes operator, most likely) that needs to manage teams, escalation +policies, dead man's switches and integrations without impersonating a human. +It is not a user — it never signs in, never appears in a team's member list, +and never holds the administrator flag — and its key is prefixed `tdsa_` so it +reads as one at a glance in a log line. See [Service accounts](#service-accounts). + +**Getting an account.** The first one comes from `/api/bootstrap`. After that +it depends on `signup_mode`, an administrator setting: + +- `invite_only` (the default) — a team owner mints a link with + `POST /api/teams/{teamID}/invites`, and the person who opens it picks a + username and password and lands in that team with the role the link carries. + Links are single-use unless told otherwise, expire after seven days, and can + be revoked before that. +- `open` — anybody who can reach the server can create an account, and must + name a team, which they then own. + +Invites are **links, not email**: this server has no SMTP, and adding it to send +one message would be a subsystem to run, secure and monitor. Send the link +however you already talk to the person. + +A domain-restricted third mode was considered and dropped: with no email there +is nothing to verify an address against, so it would only check the domain of a +string somebody typed. + +The first user, from `/api/bootstrap`, is an administrator. Users created +afterwards are not, until an administrator says so. An install always keeps at +least one: the last administrator can be neither deleted nor demoted, and +nobody can delete or demote themselves. + +Endpoints that require the flag answer `403` with +`{"error":"administrator access required"}`. + +**Teams** are the unit of tenancy, and are a separate axis from the administrator +flag. A team owns its incidents, alerts, schedule and integrations, and a user +sees exactly the teams they belong to. Within a team an **owner** configures it +(schedule, integrations, membership) and a **member** works its incidents. + +An administrator crosses that line in one direction only. They **configure any +team** without being in it — every owner-only endpoint accepts the flag, because +otherwise a team whose last owner left could never be repaired. They do **not +read any team**: the queue, the alerts and the incidents are filtered by real +membership, so an administrator sees a team's work only by joining it, which is +a membership change and shows up as one. Administration is about accounts and +the shape of a team, not about reading other people's incidents. + +Anything belonging to a team you are not in answers `404`, not `403`: whether an +incident exists is itself something only its team should learn. + +**Operator mode** (`TERDUT_OPERATOR_MODE`, see [Configuration](./configuration.md#configuration)) +declares this install gitops-managed. When it is on, a session or a user's own +API key gets `403 {"error": "...", "reason": "operator_managed"}` on every +write this page marks **owner**-gated under Teams below (creating, renaming +or deleting a team; its OIDC group binding; its escalation ladder; its dead +man's switches; its integrations) — a service account's writes are unaffected. +Team membership and invites are deliberately excluded: they are never +gitops-managed, in operator mode or out of it. `GET /api/auth/config` reports +`operator_mode` so a client can grey those sections out before a write is ever +attempted. + +| Method | Path | Description | +|---|---|---| +| `GET` | `/api/auth/config` | How to sign in: `{"password_login", "oidc": {"enabled","name"}, "device_login", "operator_mode"}`. No session needed | +| `GET` | `/api/version` | `{"version"}` — this build's version string. No session needed, the same as `/healthz` | +| `POST` | `/api/login` | `{"username","password"}` → sets the session cookie, returns `{user, has_password}`. `429` after too many failures; `403` when `TERDUT_PASSWORD_LOGIN=false` | +| `GET` | `/api/oidc/login` | Starts a single sign-on sign-in: redirects the browser to the provider. `?next=/path` is where to land afterwards; only a path on this server is honoured. Only exists when SSO is configured | +| `POST` | `/api/oidc/device` | Starts a device login: returns `{device_code, user_code, verification_url, interval, expires_in}`. Only exists when SSO is configured | +| `POST` | `/api/oidc/device/token` | `{"device_code"}` → `202 {"status":"pending"}`, then `200` with the session cookie once approved (once only). `410` with `{"error":"expired"}` or `{"error":"denied"}`; `429 {"error":"slow_down"}` if polled faster than `interval` | +| `POST` | `/api/oidc/device/approve` | **session** — `{"user_code"}`. Approves a pending device login as the caller. `403` for an API key; `404` for an unknown, expired or already decided code | +| `POST` | `/api/oidc/device/deny` | **session** — `{"user_code"}`. Refuses it | +| `GET` | `/api/oidc/callback` | Where the provider sends the browser back. Sets the session cookie and redirects to `/`, or to `/?sso_error=` — one of `denied`, `expired`, `failed`, `unavailable`, `not_allowed`, `no_email`, `email_conflict`, `disabled`, `not_bootstrapped` (no user exists on this install yet — sign in again once something has called `/api/bootstrap`) | +| `POST` | `/api/logout` | Ends the session and clears the cookie | +| `GET` | `/api/me` | The caller: `{user, has_password}` | + +## Users + +| Method | Path | Description | +|---|---|---| +**admin** marks an endpoint that requires the administrator flag; **self or +admin** marks one you may use on your own account and an administrator may use +on anybody's. + +| Method | Path | Who | Description | +|---|---|---|---| +| `GET` | `/api/signup` | — | Whether sign-up is open, and whether `?invite=` is usable. No session needed: the caller has no account yet | +| `POST` | `/api/signup` | — | Create an account `{"username","email","password","invite"?,"team_name"?}` and sign in. `403` without a usable invite when the mode is invite-only | +| `POST` | `/api/bootstrap` | — | Create first user + API key `{"username","email","password"?}` (only works on empty DB). The user is an administrator | +| `GET` | `/api/users` | any | List users. Open to everybody: the queue's assignment control and the schedule both have to name people | +| `GET` | `/api/users/{id}/teams` | self or admin | The teams that user is in, each with their role. `/api/teams` is always about the caller; this one answers it about somebody else, for the admin page's per-user view. `404` for a user who does not exist, so "no teams" and "no such person" are distinguishable | +| `POST` | `/api/users` | **admin** | Create user `{"username","email"}`. Not an administrator | +| `DELETE` | `/api/users/{id}` | **admin** | Delete user (cascades to keys). `409` for yourself or the last administrator | +| `PUT` | `/api/users/{id}/admin` | **admin** | Grant or revoke the administrator flag `{"is_admin"}`. `409` for yourself, the last administrator, or an administrator granted by single sign-on | +| `PUT` | `/api/users/{id}/disabled` | **admin** | Take an account out of use, or put it back `{"disabled"}`. `409` for yourself or the last administrator | +| `PUT` | `/api/users/{id}/notify` | self or admin | Set push notification target `{"ntfy_topic"}` — empty string clears it | +| `PUT` | `/api/users/{id}/password` | self or admin | Set web UI password `{"password","current_password"}`. `current_password` is required only when changing your own existing password. Ends the user's other sessions | +| `POST` | `/api/users/{id}/api-keys` | self or admin | Issue API key `{"name"}` — key shown once | +| `DELETE` | `/api/users/{id}/api-keys/{keyID}` | self or admin | Revoke API key | + +## Administration + +| Method | Path | Who | Description | +|---|---|---|---| +| `GET` | `/api/admin/teams` | **admin** | Every team on the server, with its member and open-incident counts. `/api/teams` answers "what am I in"; this answers "what is there" | +| `GET` | `/api/admin/teams/{teamID}` | **admin** | One team and who is in it: `{"team", "members"}`. `404` for a team that does not exist. `GET /api/teams/{teamID}/members` is **member**-only and still `404`s an administrator from outside the team — reading a team's shape and reading its work are different questions, so they are different endpoints | +| `GET` | `/api/admin/settings` | **admin** | The editable settings with their bounds, plus the environment-configured ones, read-only. Never credentials | +| `PUT` | `/api/admin/settings` | **admin** | Change one or more `{"key": seconds}`, or `{"signup_mode": "open"\|"invite_only"}`. `400` for an unknown key or a value outside its bounds | + +## Service accounts + +A service account is a scoped, non-human credential for automation — not a +`users` row, so it never signs in, is never a team member, and never carries +the administrator flag. Two scopes: + +- **instance** — the same reach system administration has over teams: create + one, and mint a **team**-scoped account against any of them. There is no + cap on how many instance-scoped accounts exist, but ordinarily there is one, + belonging to whatever is provisioning this install end to end. +- **team** — owner-equivalent for that one team, and nothing else: every + **owner**-gated endpoint under [Teams](#teams), membership and invites + included. Nothing narrower is enforced server-side; what actually keeps + membership out of automation's hands is that no operator built against this + scope should ever call those two endpoints — see + [operator mode](#authentication) and [`SERVICE-ACCOUNTS.md`](../SERVICE-ACCOUNTS.md)'s note on this. + +A key is shown once, at creation or rotation, and only its hash is stored — +the same handling as a user's API key. Losing it means minting a new one; +there is no way to recover a raw key from the server. + +| Method | Path | Who | Description | +|---|---|---|---| +| `GET` | `/api/service-accounts` | **admin** | Every service account. Pass `?name=` instead to look one up by its exact name — open to **any** authenticated caller (human or service account), since it returns no key material and is how an account finds its own id | +| `POST` | `/api/service-accounts` | owner\* | Create one and mint its first key `{"name","scope","team_id"?}` (`team_id` required for `scope:"team"`, absent for `scope:"instance"`). Returns `{"service_account", "key"}` — `key.key` shown once | +| `POST` | `/api/service-accounts/{id}/keys` | owner\* | Mint an additional key `{"name"}` — rotation without recreating the account. Shown once | +| `DELETE` | `/api/service-accounts/{id}/keys/{keyID}` | owner\* | Revoke one key | + +\* For an **instance**-scoped account: a system administrator only. For a +**team**-scoped account: a system administrator, that team's own human owner, +an instance-scoped service account (minting a narrower credential for a team +it just created), or — for the two key endpoints only — the account rotating +or revoking its own key, which is not a privilege escalation, the same +reasoning a user's own API keys rest on. + +## Alert ingestion + +Alerts arrive on a team's integration key. The key is both the credential and the +routing: it says that the sender may post, and which team the alerts belong to. +Create one with `POST /api/teams/{teamID}/integrations`, which returns the key +and the full URL once and stores only a SHA-256 hash. + +| Method | Path | Description | +|---|---|---| +| `POST` | `/api/integrations/{key}/alertmanager` | Alertmanager v4 webhook receiver for the key's team. `401` for an unknown key | + +This is the only way in. The pre-teams `POST /api/alertmanager/webhook` took no +credential at all — anything able to reach the port could open an incident — +and was removed in v0.13.0 once senders had moved onto keys. + +## Teams + +**owner** below means an owner of that team, a system administrator (who +passes every one of these without being a member), or that team's own +team-scoped [service account](#service-accounts) — including membership and +invites, technically, though no automation this scope was designed for +(a Kubernetes operator's CRDs, see [`SERVICE-ACCOUNTS.md`](../SERVICE-ACCOUNTS.md)) ever models team +membership or would call those two. See [Authentication](#authentication). +**member** means membership and nothing else: an administrator who is not in +the team gets the same `404` as anybody else. + +| Method | Path | Who | Description | +|---|---|---|---| +| `GET` | `/api/teams` | any | The caller's own teams, each with their role | +| `POST` | `/api/teams` | any | Create a team `{"name"}`; a human creator becomes its first owner. An instance-scoped [service account](#service-accounts) may also create one, and it gets no owner at all — expected for a team an operator is about to hand a team-scoped credential to, not an orphaned team a human made | +| `PUT` | `/api/teams/{teamID}` | **owner** | Rename it `{"name"}`. `409` if the name is taken | +| `DELETE` | `/api/teams/{teamID}` | **owner** | Delete a team and everything under it. `409` while it has open incidents | +| `GET` | `/api/teams/{teamID}/members` | member | Who is in the team, with `status` (`oncall` if the rota has them today, `unpageable` when a page to them would go nowhere — even if they are on call — else `reachable`), `on_call`, `next_shift` (first rota day after today), `pageable` and `problem` (`has no ntfy topic` / `account is disabled`; never the topic itself) and `last_active_at` (their newest session or API-key use). Every member sees the same list | +| `POST` | `/api/teams/{teamID}/members` | **owner** | Add a member, or change their role `{"user_id","role"}`. `409` when it would demote the last owner, or the membership is managed by single sign-on | +| `DELETE` | `/api/teams/{teamID}/members/{userID}` | **owner** | Remove a member. `409` for the last owner, or a membership managed by single sign-on | +| `GET` | `/api/teams/{teamID}/oidc-groups` | member | Which groups control this team's membership: `{"member_group","owner_group"}`. An empty string means no group grants that role here | +| `PUT` | `/api/teams/{teamID}/oidc-groups` | **owner** | Set them. An empty string clears a binding | +| `GET` | `/api/teams/{teamID}/integrations` | member | List integrations. Never returns keys. Each carries `status` (`active` if its key posted within 24h, `quiet` if it has but not lately, `never`), `last_used_at` (last webhook, usable or not), `last_alert_at` (when an alert last arrived on it) and `alerts_24h` (distinct alerts it refreshed in the last day). Alerts delivered before the source was recorded (migration 010) have none, so the last two fill in as Alertmanager re-sends them | +| `PATCH` | `/api/teams/{teamID}/integrations/{integrationID}` | **owner** | Rename `{"name"}`. The key does not change | +| `POST` | `/api/teams/{teamID}/integrations` | **owner** | Mint an integration `{"name","kind"}` — key and URL shown once | +| `DELETE` | `/api/teams/{teamID}/integrations/{integrationID}` | **owner** | Revoke an integration. Alerts it delivered stay, unattributed | +| `GET` | `/api/teams/{teamID}/invites` | **owner** | The team's invite links, with their uses and expiry. Never the tokens | +| `POST` | `/api/teams/{teamID}/invites` | **owner** | Mint one `{"role","max_uses"}` — the full URL is returned once | +| `DELETE` | `/api/teams/{teamID}/invites/{inviteID}` | **owner** | Revoke a link before it expires | +| `GET` | `/api/teams/{teamID}/escalation` | member | The team's [escalation ladder](./escalation.md#escalation) `{repeat_count, fallback_topic, levels[], last_escalated_at?, last_escalated_incident_id?}`. Empty levels means the team has none. Each level also carries `status` (`ready`, `escalating` when an unanswered incident has climbed to it, `unreachable` when nobody on it could be woken), `waiting` (ids of the open incidents on it) and, per target, `username` (who it means today — the person on call, for a rota target), `reachable` and `problem`. The extra fields are output only; `PUT` takes the plain shape | +| `PUT` | `/api/teams/{teamID}/escalation` | **owner** | Replace it wholesale. `400` for a level with no targets or no timeout — a rung that pages nobody is a silence with a number on it | +| `GET` | `/api/teams/{teamID}/deadman/switches` | member | The team's [dead man's switches](./dead-mans-switch.md), each `{id, name, matcher, timeout_seconds, severity, status, last_heartbeat_at, last_triggered_at, open_incident_id, sources[]}`. `status` is `healthy`, `dead` or `dormant`; `sources` has one entry per heartbeat fingerprint. Empty when the team watches nothing | +| `POST` | `/api/teams/{teamID}/deadman/switches` | **owner** | Add one: `{name?, matcher, timeout_seconds, severity?}`. `400` when the matcher names no `alertname` or holds several, or the timeout is not positive — a switch that silently watches nothing is the failure this feature exists to prevent | +| `PUT` | `/api/teams/{teamID}/deadman/switches/{switchID}` | **owner** | Replace one in place, same body and validation as create. Its id is unchanged — for an automated caller reconciling a spec change, unlike delete-and-recreate | +| `DELETE` | `/api/teams/{teamID}/deadman/switches/{switchID}` | **owner** | Stop watching. An incident it opened stays open. `404` for a switch of another team | + +## Notifications + +| Method | Path | Description | +|---|---|---| +| `POST` | `/api/notify/ack/{token}` | Acknowledge an incident from a push notification's Acknowledge button. No auth: the token in the path is the credential — one incident, one action, 24 hours, idempotent. Must stay publicly reachable | + +## Incidents + +| Method | Path | Description | +|---|---|---| +| `GET` | `/api/incidents` | List incidents. Filters: `?status=triggered\|acknowledged\|resolved`, `?severity=`, `?assigned_to=`, `?archived=true`, `?snoozed=true`, `?from=YYYY-MM-DD`, `?to=YYYY-MM-DD`, `?sort=severity`, `?cluster=`, `?limit=` (default 50, max 500) | +| `GET` | `/api/incidents/clusters` | The distinct `cluster` values on the caller's incidents from the last 90 days, sorted (`?team_id=` narrows it). An empty array when nothing carries the label | +| `GET` | `/api/incidents/{id}` | Get single incident, with its alerts inline | +| `GET` | `/api/incidents/{id}/alerts` | Alerts under this incident | +| `GET` | `/api/incidents/{id}/timeline` | Full event history, chronological | +| `POST` | `/api/incidents/{id}/acknowledge` | Acknowledge (stamps authed user + time) | +| `DELETE` | `/api/incidents/{id}/acknowledge` | Clear acknowledgement, back to `triggered` | +| `POST` | `/api/incidents/{id}/resolve` | Close by hand — **terminal**, see above | +| `POST` | `/api/incidents/{id}/assign` | Reassign `{"user_id"}` | +| `POST` | `/api/incidents/{id}/snooze` | Hide until `{"until": RFC3339}` or `{"duration": "2h"}` | +| `DELETE` | `/api/incidents/{id}/snooze` | Un-snooze | +| `POST` | `/api/incidents/{id}/archive` | Archive (hides from the default list) | +| `DELETE` | `/api/incidents/{id}/archive` | Un-archive | +| `POST` | `/api/incidents/{id}/notes` | Add a note `{"content"}` | +| `DELETE` | `/api/incidents/{id}/notes/{eventID}` | Delete own note | + +With no `?status=` filter, `GET /api/incidents` returns **open** incidents only — +the queue an on-call person wants. Currently snoozed and archived incidents are +excluded unless asked for. Actions that only make sense on an open incident +return `409` once it is resolved. + +Notes are ordinary timeline events of type `note`; only they are deletable, and +only by their author. The rest of the timeline is a record of what happened. + +### The incident object + +| Field | Type | Notes | +|---|---|---| +| `id` | integer | Server-assigned | +| `group_key` | string | Alertmanager's `groupKey` — opaque, treat as an identifier | +| `title` | string | Rendered from `groupLabels` | +| `group_labels` | object | String→string, as sent by Alertmanager | +| `status` | string | `"triggered"`, `"acknowledged"` or `"resolved"` | +| `severity` | string | *optional* — high-water mark across the incident's alerts; never lowered | +| `triggered_at` | timestamp | When the incident opened | +| `acknowledged_by_id` / `acknowledged_by` / `acknowledged_at` | | *optional* — user id, username, time | +| `assigned_to_id` / `assigned_to` | | *optional* — user id, username | +| `snoozed_until` | timestamp | *optional* — a value in the past reads as not snoozed | +| `resolved_at` | timestamp | *optional* | +| `resolution_source` | string | *optional* — `"alerts"`, `"manual"` or `"recovered"` | +| `archived_at` | timestamp | *optional* | +| `alerts` | array | Only on `GET /api/incidents/{id}` | + +Treat `resolution_source` as an open set, as with the alert field of the same +name: degrade unknown values to "resolved, reason unknown". + +### The timeline event object + +| Field | Type | Notes | +|---|---|---| +| `id` | integer | | +| `incident_id` | integer | | +| `type` | string | See below — treat as an open set | +| `user_id` / `username` | | *optional* — absent when the server acted rather than a person | +| `alert_id` | integer | *optional* — the alert an `alert_added` / `alert_resolved` event refers to | +| `detail` | string | *optional* — the note body, the snooze deadline, etc. | +| `created_at` | timestamp | | + +Types written today: `triggered`, `alert_added`, `alert_resolved`, +`acknowledged`, `unacknowledged`, `assigned`, `archived`, `unarchived`, `snoozed`, +`unsnoozed`, `resolved`, `note`, `notified`, `notify_failed`, `deadman_silent`. On an +`assigned` event `user_id` is the **assignee**, not the actor; the actor is in +`actor_user_id`/`actor_username` or `actor_service_account_id`/`actor_service_account_name` +(absent on assignments made before they were recorded). New types may be added; render +unknown ones generically rather than dropping them. + +On `notified` and `notify_failed`, `detail` carries the notification kind +(`triggered` | `reminder` | `resolved`), and on a failure the reason after it. +`user_id` is who was paged — absent means the page went to the shared fallback +topic and so belongs to nobody. The topic itself is never written to the +timeline: it is a shared secret with the ntfy server, and every API key can read +this. + +## Alerts + +Alerts are read-only. Everything a person does happens on the incident. + +| Method | Path | Description | +|---|---|---| +| `GET` | `/api/alerts` | List alerts. Filters: `?status=firing\|resolved`, `?name=`, `?incident_id=`, `?archived=true`, `?from=YYYY-MM-DD`, `?to=YYYY-MM-DD`, `?limit=` (default 50, max 500) | +| `GET` | `/api/alerts/{id}` | Get single alert | + +Archived alerts are hidden from `GET /api/alerts` unless `?archived=true` is +passed; alert archiving is automatic housekeeping by the sweeper, not a user +action. Resolved alerts carry `resolution_source`: `"alertmanager"` for a real +resolved webhook, `"expiry"` when the sweeper inferred it (see +[Stale alert expiry](./incidents.md#stale-alert-expiry)), `"deadman"` for a heartbeat declared +dead (see [Dead man's switch](./dead-mans-switch.md)). + +### The alert object + +Returned by `GET /api/alerts` (as an array) and `GET /api/alerts/{id}`. +Timestamps are RFC 3339 in UTC. Fields marked *optional* are omitted entirely +when unset, so clients must treat them as nullable. + +| Field | Type | Notes | +|---|---|---| +| `id` | integer | Server-assigned; stable for the life of the row | +| `fingerprint` | string | Alertmanager's fingerprint — the upsert key | +| `name` | string | From the `alertname` label | +| `status` | string | `"firing"` or `"resolved"` | +| `labels` | object | String→string, as sent by Alertmanager | +| `annotations` | object | String→string, as sent by Alertmanager | +| `starts_at` | timestamp | When the alert instance began, **per Prometheus** | +| `ends_at` | timestamp | *optional* — absent while no end is known | +| `generator_url` | string | Link back to the originating Prometheus | +| `received_at` | timestamp | When the server last accepted a webhook for this alert — see below | +| `incident_id` | integer | *optional* — the most recent incident this alert belongs to | +| `resolution_source` | string | *optional* — `"alertmanager"`, `"expiry"` or `"deadman"` | +| `archived_at` | timestamp | *optional* — set while archived | + +#### `received_at` is a liveness heartbeat + +`starts_at` comes from Prometheus and **never changes** for the lifetime of an +alert instance. It says when the problem began, not whether it is still +happening — an alert that started twelve days ago looks identical whether +Alertmanager refreshed it a minute ago or went silent a week ago. + +`received_at` is the field that answers "is this still live". It is set to the +server's clock on **every accepted webhook** for that fingerprint, including the +unchanged firing notifications Alertmanager re-sends every `repeat_interval`. +Clients may rely on this: + +- **A firing alert whose `received_at` is advancing is still being refreshed.** + Stale-dating it against `repeat_interval` is a valid liveness check, and it is + what the built-in sweeper does (see + [Stale alert expiry](./incidents.md#stale-alert-expiry)). +- **`received_at` tracks accepted payloads, not delivery attempts.** A retry + that describes an older instance than the stored one is discarded, and a + discarded payload does not move `received_at`. +- **It stops advancing once the alert resolves,** because Alertmanager stops + re-sending. On an alert resolved by the sweeper + (`"resolution_source": "expiry"`) it therefore marks the last time + Alertmanager was actually heard from, which is earlier than `ends_at`. + +`GET /api/alerts` is ordered by `received_at` descending — most recently +refreshed first — and the `?from=` / `?to=` filters on both the alert and stats +endpoints select on `received_at`, not `starts_at`. + +#### `resolution_source` says how much to trust `ends_at` + +An alert can leave the firing state two ways, and `resolution_source` records +which happened. Clients may rely on this: + +- **Absent while firing.** It is set only on resolve, and a re-fire under the + same fingerprint clears it again, so its presence always agrees with + `"status": "resolved"`. +- **`"alertmanager"` — a real resolved webhook arrived.** `ends_at` is the end + time Alertmanager reported. It is an observed value and can be displayed as + fact. +- **`"expiry"` — the sweeper inferred the resolve** because Alertmanager stopped + refreshing the alert (see [Stale alert expiry](./incidents.md#stale-alert-expiry)). Nothing + ever reported an end, so **`ends_at` is approximate**: it is either the stale + `endsAt` watermark from the last notification, or — when that notification + carried none — the time the sweep ran, which lags the last real contact by up + to `TERDUT_STALE_AFTER` plus a sweep interval. Treat it as "no later than", + not as when the problem stopped. + + On these alerts `received_at` is the more truthful signal: it marks the last + time Alertmanager was actually heard from. Surfacing the distinction is + worthwhile, since `"expiry"` can also mean the alert is still firing and the + notification path broke. + +- **`"deadman"` — a heartbeat was declared dead** (see + [Dead man's switch](./dead-mans-switch.md)). Like `"expiry"`, an inference from + silence rather than an observed end, so `ends_at` is approximate — but a much + tighter one, bounded by the switch's timeout. It is also the one resolution + a re-fire under the same `starts_at` can undo, since the switch coming back is + exactly the evidence that the inference was wrong. + +Treat the value as an open set and tolerate ones you do not recognise — new +sources may be added, and unknown values should degrade to "resolved, reason +unknown" rather than being rejected. + +## On-call schedule + +| Method | Path | Description | +|---|---|---| +Each team keeps its own rota, so two teams can have two different people on call +on the same day. The person taking a shift has to be in the team — paging +somebody who cannot open the incident is worse than paging nobody. + +| Method | Path | Who | Description | +|---|---|---|---| +| `POST` | `/api/teams/{teamID}/schedule` | **owner** | Assign user to dates `{"user_id", "dates":["YYYY-MM-DD",...], "replace"}` — all-or-nothing | +| `GET` | `/api/teams/{teamID}/schedule` | member | List entries. Filters: `?from=YYYY-MM-DD`, `?to=YYYY-MM-DD` | +| `DELETE` | `/api/teams/{teamID}/schedule/{id}` | **owner** | Remove schedule entry | +| `GET` | `/api/schedule/current` | any | Who is on call today (UTC) in **every** team the caller is in — one entry per team, `[]` when nobody anywhere | + +## Statistics + +Every figure counts the caller's own teams only: a report that counted other +teams' incidents would leak their volume, and their alert names through the +top-alerts list, and would not be a number about the reader's work anyway. + +All stat endpoints accept optional `?from=YYYY-MM-DD` and `?to=YYYY-MM-DD`, and exclude archived rows to match the default list views. Alert stats filter on `received_at`; incident stats filter on `triggered_at`. + +| Method | Path | Description | +|---|---|---| +| `GET` | `/api/stats/incidents` | `{total, triggered, acknowledged, resolved, mtta_seconds, mttr_seconds}` | +| `GET` | `/api/stats/alerts` | `{total, firing, resolved}` counts | +| `GET` | `/api/stats/alerts/top` | Most frequent alert names. `?limit=` (default 10, max 100) | +| `GET` | `/api/stats/alerts/by-hour` | Count per hour-of-day (UTC), all 24 slots returned | +| `GET` | `/api/stats/alerts/by-day` | Count per day-of-week, all 7 slots with names returned | + +`mtta_seconds` (time to acknowledge) and `mttr_seconds` (time to resolve) are +averages over incidents that have actually been acknowledged or resolved, and are +**null** until there are any — null means "no data", not zero. diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 0000000..b89a49a --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,49 @@ +# Configuration + +_Environment variables and settings._ Back to the [README](../README.md) and the [documentation index](./README.md). + +Two kinds of setting, split by who changes them and how often. + +**Where the server is plugged in** stays in the environment: the listen address, +the database DSN, the ntfy URL and token, the public URL. They are needed before +the database is open, and two of them are credentials. + +**How the server behaves** lives in the database and is edited by an +administrator in the web UI or through `PUT /api/admin/settings`, taking effect +on the next sweep rather than at the next restart. The variables below marked +**seed** are the value each of those starts from: written once, on first start, +and never overwritten afterwards — a redeploy cannot put a chart's default back +over an administrator's edit. + +| Variable | Default | Description | +|---|---|---| +| `TERDUT_ADDR` | `:8080` | TCP address to listen on | +| `TERDUT_DB_DSN` | — | **Required.** Postgres connection string, e.g. `postgres://terdut:secret@localhost:5432/terdut?sslmode=require` | +| `TERDUT_ARCHIVE_AFTER` | `168h` (7d) | **seed.** How long a resolved alert or incident stays in the default list before being auto-archived | +| `TERDUT_STALE_AFTER` | `6h` | **seed.** How long a firing alert may go without a refreshing webhook before it is treated as resolved — **must exceed your Alertmanager `repeat_interval`** | +| `TERDUT_NTFY_URL` | — | ntfy server to publish push notifications to. Empty disables notifications entirely | +| `TERDUT_NTFY_TOKEN` | — | Bearer token for an access-controlled ntfy | +| `TERDUT_NTFY_FALLBACK_TOPIC` | — | Topic used when nobody is on call | +| `TERDUT_PUBLIC_URL` | — | Base URL a phone uses to reach this server: the notification's link into the web UI, its Acknowledge button, and whether the session cookie is `Secure` | +| `TERDUT_NOTIFY_REPEAT` | `15m` | **seed.** How long an incident may sit unacknowledged before it is paged again. `0` notifies once and never repeats | +| `TERDUT_PASSWORD_LOGIN` | `true` | `false` refuses password login and password sign-up (`403`), leaving single sign-on the only way in. Refused at startup unless SSO is configured | +| `TERDUT_TRUSTED_PROXIES` | `1` | How many reverse proxies in front of the server append to `X-Forwarded-For`; the per-address rate limits use the entry that many hops from the right. `0` ignores the header | +| `TERDUT_OPERATOR_KEY` | — | At least 32 characters. When set, the instance-scoped service account `terdut-operator` is created if missing and its `seed` key replaced with this value at every start — how terdut-operator authenticates without a bootstrap handshake. An instance-scoped account acts as owner of every team (team configuration) but is not a member of any, so it reads no incidents | +| `TERDUT_OPERATOR_MODE` | `false` | Declares this install gitops-managed: a session's or a user's own API key's writes to teams, escalation policies, dead man's switches and integrations are refused (`403 reason:"operator_managed"`); a [service account](./api.md#service-accounts)'s are not. Team membership and the schedule stay editable regardless | +| `TERDUT_OIDC_ISSUER` | — | Turns single sign-on on. The provider's issuer URL; discovery is read from `/.well-known/openid-configuration`. See [Single sign-on](./single-sign-on.md#single-sign-on-oidc) | +| `TERDUT_OIDC_CLIENT_ID` / `TERDUT_OIDC_CLIENT_SECRET` | — | **Required with an issuer.** The confidential client registered at the provider. Keep the secret in a Secret, not in values | +| `TERDUT_OIDC_NAME` | `SSO` | What the sign-in button calls the provider | +| `TERDUT_OIDC_SCOPES` | `openid profile email` | Scopes requested, comma or space separated. Authentik puts `groups` behind `profile` | +| `TERDUT_OIDC_USERNAME_CLAIM` / `_EMAIL_CLAIM` / `_GROUPS_CLAIM` | `preferred_username` / `email` / `groups` | ID token claims read for the username, email and groups | +| `TERDUT_OIDC_TRUST_EMAIL` | `false` | Link a first sign-in to an existing local user by email even if the provider does not mark the address verified | +| `TERDUT_OIDC_ALLOWED_GROUPS` | — | Comma-separated. Only people in one of these may sign in. Empty admits everybody the provider authenticates | +| `TERDUT_OIDC_ADMIN_GROUP` | — | Members are system administrators | +| `TERDUT_OIDC_SESSION_MAX_AGE` | `12h` | Hard ceiling on a session made by an SSO sign-in | + +Durations use Go syntax (`30m`, `12h`, `168h`). An unparseable value falls back to the default. + +Note that `TERDUT_STALE_AFTER` and a dead man's switch timeout point in opposite directions. Staleness +is a generous grace period around a `repeat_interval` you do not control; a dead man's switch is a +deadline you set deliberately, and the heartbeat's route is configured to beat faster than it. + +In the Helm chart the two sweeper durations are set via `sweeper.staleAfter` and `sweeper.archiveAfter`, notifications via the `notify.*` values, single sign-on via `oidc.*` and `passwordLogin`, and operator mode via `operatorMode`. diff --git a/docs/dead-mans-switch.md b/docs/dead-mans-switch.md new file mode 100644 index 0000000..bd2a43b --- /dev/null +++ b/docs/dead-mans-switch.md @@ -0,0 +1,81 @@ +# Dead man's switches + +_Detecting that alerts have stopped arriving._ Back to the [README](../README.md) and the [documentation index](./README.md). + +Everything above assumes alerts arrive. If Prometheus stops evaluating, or +Alertmanager cannot reach this server, nothing arrives — and silence looks +exactly like everything being fine. A dead man's switch inverts the handling for +one designated alert so that silence is the signal: + +- **receiving** it opens no incident, and +- the **absence** of it does. + +kube-prometheus-stack already ships the alert for this. `Watchdog` is +`expr: vector(1)`, so it fires permanently and is re-sent forever; it is worth +nothing unless something downstream notices it stop. It is the usual first switch. + +**Switches belong to a team**, which decides which of its own alerts are +heartbeats and how long a silence has to last. Each **switch** is a row of its +own — a name, one matcher, a timeout and a severity — so switches in one team +can have different deadlines. An owner adds and removes them on **Team → +Switches**, which lists each with a status (**healthy**, **dead**, or +**dormant** until its first heartbeat), when it was last heard from, and when it +last opened an incident; a matcher that several clusters satisfy is broken down +per cluster. The API is `POST`/`DELETE /api/teams/{teamID}/deadman/switches`. A +missed heartbeat opens an incident in the team whose integration received it. +Removing a switch stops the watching; an incident it already opened stays open +until somebody resolves it. + +A new team watches nothing until its owner (or terdut-operator, from a +`TerdutTeam`) adds a switch: inheriting an install-wide heartbeat would page a +new team about a source it has never heard of. + +A matcher is a set of exact label conditions, one of which must be the +`alertname`, , one matcher per switch, `,` between the label conditions: + +``` +alertname=Watchdog,cluster=prod +``` + +**The unit of monitoring is the fingerprint, not the alert name.** Two clusters +sending the same `Watchdog` are two independent switches, so a healthy one can +never mask a dead one. + +## The lifecycle + +A switch is **dormant** until its first heartbeat arrives. A configured matcher +that has never been heard from opens nothing, so a fresh deploy or a restored +database does not page. It also means a matcher that never matches anything is +silently inert. + +Once armed, the sweeper declares it **dead** when either the heartbeat has not +been refreshed within the switch's `timeout_seconds`, or Alertmanager explicitly +resolved it — the sender saying the heartbeat stopped needs no further waiting. +That opens an incident at the switch's `severity`, assigned and paged like any +other, and marks the heartbeat alert `"resolution_source": "deadman"` so the +alert list stops claiming a dead switch is firing. + +It **recovers** when the heartbeat starts arriving again: the incident resolves +with `"resolution_source": "recovered"` and the all-clear goes to whoever was +paged. + +Resolving the incident by hand sticks, the same way it does for an alert-backed +one. While the switch stays silent nothing new opens — so a decommissioned +source is a one-time page rather than a nag. The switch **re-arms** on the next +heartbeat: come back and die again, and that is a new incident. + +## Two things to know + +A switch's timeout must be **shorter** than the `repeat_interval` of the +route carrying the heartbeat, which is the exact opposite of +`TERDUT_STALE_AFTER`. Inheriting a default `repeat_interval` of 4h gives you a +switch that takes four hours to notice anything, so give the heartbeat +[its own route](./alertmanager.md#alertmanager-configuration). Matched alerts are exempt from +stale-alert expiry — a heartbeat answers to its own timeout and nothing else. + +A dead man's switch incident has **no member alerts**: +`GET /api/incidents/{id}/alerts` returns an empty list. There is no alert +describing the problem, because the problem is that no alert arrived. What +happened is on the timeline instead, as a `deadman_silent` event carrying the age +of the last heartbeat, and the heartbeat's labels are on the incident's +`group_labels`. diff --git a/docs/deployment.md b/docs/deployment.md new file mode 100644 index 0000000..20e1ae9 --- /dev/null +++ b/docs/deployment.md @@ -0,0 +1,74 @@ +# Deployment + +_Running the server in a container and on Kubernetes with the Helm chart._ Back to the [README](../README.md) and the [documentation index](./README.md). + +## Docker + +```bash +docker build -t terdut-server . +docker run -p 8080:8080 \ + -e TERDUT_DB_DSN='postgres://terdut:secret@host.docker.internal:5432/terdut?sslmode=disable' \ + terdut-server +``` + +The server creates its own schema on startup and needs a reachable Postgres; it stores nothing on +disk, so there is no volume to mount. + +## Kubernetes + +A Helm chart is published from this repository as an OCI artifact, versioned in lockstep +with the app — chart `x.y.z` is always app `vx.y.z`: + +```bash +helm upgrade --install terdut-server oci://git.ryuvia.com/niklas/terdut-server \ + --version 0.9.2 \ + --namespace terdut-server --create-namespace \ + --set networking.hostname=terdut.example.com +``` + +The chart expects a [Gateway API](https://gateway-api.sigs.k8s.io/) Gateway named `envoy-main` in +the `envoy-gateway-system` namespace to already exist — it renders an `HTTPRoute` against it rather +than an `Ingress`. TLS is terminated at the gateway, so the server itself never sees a certificate. + +| Value | Default | Description | +|---|---|---| +| `networking.hostname` | `terdut.example.com` | Hostname the `HTTPRoute` serves | +| `networking.listener` | `""` | Gateway listener (`sectionName`) to bind to. Empty attaches to every matching listener, **including plaintext HTTP** — set it to the HTTPS listener's name to serve TLS only | +| `networking.servicePort` | `8080` | Port the route forwards to; keep in sync with `service.port` | +| `bootstrap.enabled` | `true` | Runs a post-install hook that creates the first user and stores its API key in the `-admin-key` Secret. Already-bootstrapped servers are left alone | +| `database.dsn` | `""` | **Required.** Postgres DSN, with no password in it. The chart provisions no database | +| `database.passwordSecret.name` | `""` | Secret supplying `PGPASSWORD`. With the Zalando postgres operator, the Secret it generates for the role | +| `database.passwordSecret.key` | `password` | Key within that Secret | + +The API key travels in an `Authorization: Bearer` header, so set `networking.listener` whenever the +hostname is reachable outside a trusted network. + +### The database + +The chart provisions no database: it takes a DSN and expects a Postgres that already exists. In this +cluster the wrapper chart declares an `acid.zalan.do/v1 postgresql` CR; anywhere else, any reachable +Postgres 14+ will do. + +The DSN carries no password. pgx falls back to libpq's environment variables for whatever the DSN +leaves out, so the password arrives as `PGPASSWORD` from a Secret and never appears in values, in +the rendered manifest or in `kubectl describe pod`. With the postgres operator that Secret is the +one it generates for the role, so a rebuild mints a new password with nothing to keep in sync — +the same wiring miniflux uses. + +The server migrates its own schema on startup, so a new database only has to exist and be writable. + +### Backups + +Postgres is backed up where it runs, not from here. The database pod carries a +[k8up](https://k8up.io/) `k8up.io/backupcommand` annotation that streams a `pg_dump`, the same way +gitea and immich do in this cluster. + +## On Kubernetes with the operator + +[terdut-operator](https://git.ryuvia.com/niklas/terdut-operator) runs a server for you from a +`TerdutServer` object and manages its teams, escalation ladders, dead man's switches and alert +sources as Kubernetes objects. It hands the server a generated key through `TERDUT_OPERATOR_KEY` +(see [Configuration](./configuration.md) and [`SERVICE-ACCOUNTS.md`](../SERVICE-ACCOUNTS.md)), and +the server then treats configuration as operator-managed (`TERDUT_OPERATOR_MODE`), refusing edits +made by hand in the web UI. Use the Helm chart above for a plain install, the operator when you +want that configuration in gitops. diff --git a/docs/development.md b/docs/development.md new file mode 100644 index 0000000..ae4b154 --- /dev/null +++ b/docs/development.md @@ -0,0 +1,93 @@ +# Development and releasing + +_Building, testing and releasing the server._ Back to the [README](../README.md) and the [documentation index](./README.md). + +## Upgrading + +The schema is a single baseline (`internal/db/migrations/001_schema.sql`) and no +release has shipped yet, so there is no upgrade path from earlier development +databases: start from an empty one. Changes after the first release arrive as +new numbered migrations. + +## Development + +```bash +make test-db # start a local Postgres for the tests (podman or docker) +make test # run all tests +go build ./... # compile all packages +go run ./cmd/terdut # run locally (needs TERDUT_DB_DSN) +``` + +The tests need a real Postgres, because the server does — there is no in-memory Postgres. +`TERDUT_TEST_DSN` says where it is, `make test-db` starts +one on port 5433 and prints the DSN, and `make test-db-stop` removes it. Each test gets its +own schema on that server, so tests cannot see each other's rows. An unset `TERDUT_TEST_DSN` +fails the suite rather than skipping it: a run that quietly tests nothing is worse than one +that does not run. + +`make fmt lint test helm-lint` is the gate. It mirrors `.gitea/workflows/ci.yaml` step for +step, so a green run here means a green pipeline — with one deliberate exception: `make test` +adds `-race`, which CI does not. The sweeper, the notifier goroutine and the dead man's switch +sweep all run concurrently against the same database, and a race between them would surface as +a flaky incident in production rather than as a red build. + +The web UI lives in `internal/web/static/` as plain HTML, CSS and ES modules, +embedded into the binary with `go:embed`. It has no build step and no npm, so +editing a file and restarting the server is the whole loop. + +## Releasing + +``` +push or PR → ci.yaml gofmt, go vet, go test -race + govulncheck, gitleaks + helm lint + render +push tag vX.Y.Z → release.yaml the same gate, then publish: + git.ryuvia.com/niklas/terdut-server:vX.Y.Z + oci://git.ryuvia.com/niklas/terdut-server X.Y.Z + then trivy-scan the pushed image +PR to Ryuvia/charts → bump the wrapper chart to X.Y.Z; on merge + Flux reconciles and the release rolls out +``` + +Both artifacts go to the **personal** Gitea namespace rather than `ryuvia`, because Gitea +scopes package visibility to the owner with no per-package override — so `ryuvia/*` is private +because the org is. Publishing to `niklas` keeps them anonymously pullable, which is why no +pull secret is needed in the cluster. Same reasoning, and the same choice, as riksdata and +rd-web. + +Saying **"Release"** runs all three rows: the `release` skill commits, pushes, tags, waits for +the pipeline, and opens the `Ryuvia/charts` PR, stopping before the merge. See +`~/.claude/skills/release/`, or `.release.conf` here for this repo's part of it. + +The chart is published **only** from the tag, by the `chart` job. There used to be a second +publisher on every `charts/**` push to main, and the two raced for the same chart version with +different answers — chart 0.9.0 went out reading `appVersion: "latest"` that way. One +publisher, triggered by the tag (`766f439`). The cost is that a chart-only change has no +version of its own and rides the next app tag. + +Both workflows are thin drivers over the Makefile: `ci.yaml` runs `make fmt lint test` and +`make helm-lint`, `release.yaml` adds `make binaries`, `make push`, `make helm-package` and +`make helm-push`. That is deliberate — it is what makes a green local gate and a green +pipeline the same code rather than two descriptions of it, and it is how riksdata and rd-web +have always worked. + +`make push` builds and pushes in one step, unlike those two, because the image is +`linux/amd64,linux/arm64` and buildx cannot load a multi-platform result into the local image +store. `make build` stays single-platform and local-only. Both refuse `VERSION=dev`: +publishing is one command, so it is also one command to run by accident. Publishing happens +by pushing a tag. + +Two things the release process needs to know about this repo: + +- **The image scan runs after publishing**, like riksdata's and rd-web's: trivy cannot read + a locally built image on this runner, so it pulls the pushed one. A red `scan-image` means + do not bump the wrapper chart to that version — it cannot unpublish anything. The image is + `FROM scratch`, so trivy sees exactly one target, the Go binary and its module graph. +- **The wrapper chart's `values.yaml` has two `tag:` lines** — the app image and the python + backup sidecar — so `chart-bump` is given `--image` to say which one moves. Once the wrapper + chart drops the sidecar and declares a `postgresql` CR instead, there is one `tag:` line + again, and `--image` becomes belt and braces. + +The wrapper chart must have **its own `version:` bumped in the same commit**. Flux reconciles +with `reconcileStrategy: ChartVersion`, so a chart whose version did not change produces no +new artifact and the change is never deployed — with no error anywhere. diff --git a/docs/escalation.md b/docs/escalation.md new file mode 100644 index 0000000..583aa2b --- /dev/null +++ b/docs/escalation.md @@ -0,0 +1,45 @@ +# Escalation + +_Escalation ladders: who is paged next when nobody acknowledges._ Back to the [README](../README.md) and the [documentation index](./README.md). + +Without a ladder, an unacknowledged incident re-pages the same topic every +`notify_repeat` forever. That is a louder version of the same silence: if the +person on call is asleep, out of signal, or has left, nothing else happens. + +A team can configure an ordered ladder instead. Each level has a timeout and a +set of targets, and a target is either a named person or **whoever the team's +rota says is on call today** — the target that keeps working when the rota +changes and nobody remembers to edit the policy. + +``` +level 1 5m oncall the rota gets first refusal +level 2 5m user:bob then a named second + then repeat_count more rounds + then the team's fallback topic, once +``` + +When a level's timeout passes with the incident still `triggered`, the next +level is paged. Off the end of the ladder the whole thing runs again +`repeat_count` times, and after that the team's `fallback_topic` is paged once +as the end of the line. The incident stays open throughout: running out of +people to wake is not the same as somebody answering. + +**Acknowledging or resolving stops it**, which is the point — continuing to wake +people after somebody has said "I have this" is how a tool teaches people to +mute it. **Snoozing pauses it**: a deliberate "not now" holds the ladder where +it is, and it resumes when the snooze runs out. + +Every step is on the incident's timeline with the level and the names it woke, +so somebody reading it afterwards can tell why their phone rang at 04:00. A +level whose targets are all unreachable — no ntfy topic, a disabled account, an +empty rota — is recorded as `nobody reachable` and the ladder moves on rather +than stalling on a rung that cannot ring. + +**Reminders and escalation never both run.** A team with a ladder gets +escalation; a team without keeps the reminder behaviour exactly as it was. Two +pages for one silence is the surest way to get a tool muted. + +The ladder's `fallback_topic` is per team, unlike `TERDUT_NTFY_FALLBACK_TOPIC`, +which is the install-wide topic used when an incident opens with nobody on call. +They answer different questions: one is "nobody was scheduled", the other is +"everybody scheduled has been tried". diff --git a/docs/images/admin.png b/docs/images/admin.png new file mode 100644 index 0000000000000000000000000000000000000000..ea088af186ba299625767376cd092d862a55184c GIT binary patch literal 23805 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 O{)`Tr9LmtQzxscpAm`iw literal 0 HcmV?d00001 diff --git a/docs/images/alerts.png b/docs/images/alerts.png new file mode 100644 index 0000000000000000000000000000000000000000..f556dcdaa67f9ab6f66d93d0d7ee0b681cb2d49f GIT binary patch literal 56163 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 literal 0 HcmV?d00001 diff --git a/docs/images/incident-note.png b/docs/images/incident-note.png new file mode 100644 index 0000000000000000000000000000000000000000..0b4cb167815e887dbfc4b951b26ec7fbb04325c2 GIT binary patch literal 90445 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

H+a%bNXoeUpS1eNQJ&NTZx4{&*W=h<~{G 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 literal 0 HcmV?d00001 diff --git a/docs/images/mobile-incident.png b/docs/images/mobile-incident.png new file mode 100644 index 0000000000000000000000000000000000000000..4762343242d0b1069654ac030712424dc4f4d104 GIT binary patch literal 53667 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

+eQ95o85xfOKg)D|Z;SkT)EKN(pE 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 DP$z+8g^nWCj2Vd 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 bP0N1(uzkN=e(MmE00000NkvXXu0mjf6Z2Tj literal 0 HcmV?d00001 diff --git a/docs/images/oncall.png b/docs/images/oncall.png new file mode 100644 index 0000000000000000000000000000000000000000..0a2a6677191969a3968bb0b256ec1063908e3210 GIT binary patch literal 102738 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 literal 0 HcmV?d00001 diff --git a/docs/images/queue-dark.png b/docs/images/queue-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..75d231b3515b27f00f7553bd5265bffa0656fb54 GIT binary patch literal 95465 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 literal 0 HcmV?d00001 diff --git a/docs/images/queue-light.png b/docs/images/queue-light.png new file mode 100644 index 0000000000000000000000000000000000000000..8c05295be67a3dbe98e9762a1f869e36af8a6814 GIT binary patch literal 96143 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

v<=jlRP`BQP}>(hFH* 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

qV4WnKlLb5 zCLxeG|Mw$yc_}_HcjwES8T$=<5JJR~$8+X93zJw`r6$+V#hbX^d~zw0EE}wpyz!3|T=FdTQA3$;G@D_i9xHhxrfpce*C!&`eSotSi z`Ety7Y=FbFq=urn(?{(SlK8N3c&nJqqc{m)-7u+owI4^yAo*3GTJqd`fkQG`ndm)8 z?nQo~*V6=eUl`nzOTA!q90KQ*jQ_W>7i+BSIB8~H1@fq@NRXpH@*nMk9A(!;Q03-? z3VW->L5%wkO!6awosG!#o6JAzUtJU4>=|4Q$TPgM|TMFQWYg-?mtN)LXFjh%ifqyhaHLob*$OviV9n=v1|MN`K!`OY}1 z1V|9U5lg9%9k5qswk|n*!)-)~5vCy|7Fmih=7Hm?EvK-KB$lilwK|}46rfj5tx%Be zQe^B^cT}HOTF#w8pGDal?D~DI)g(ZWdL?-I!Xy==lt9g4qf3mwwaNnmtFZMbQUC@> zknClD!XBzFvm!%w6{Y1U`})lxPwtmN&MA)`?QhXGoh@H#uY*pgd_apH`eC} z5&{aXf0Kque90pteQIklr_M~T{@d&CI~Z5*vtrmgs{9){5;l2>tcGJf9_G8YQqqKiKbr5?g`*7^5mBAhIf$rrk@}a?G+6=ZvHib zV5B;2hnL7#iX{`04eIl{AM(=Hz7Ms3u9n4rOuT=sbTajIW1PSI zW^OsA4ihwZoD(cVGvZWkZ15h@G7wr#m#ETpl$&g(6YIgQZ(u?`|g?W&qa60iW0 z-52lpAZBdFsT|<{N zzszfESs^SySxVzM)ow9ql|LJFG0I*Ht>$_!_ZA() zZK&{aJ5;JZmPx8F4g#evl+7&wo?Ke;Cq+sQnx4qI$CFj z?ZGV_^@c2pT``0m3}1+dW4JjM?zoihIFA{cS#Uu?AakjsTP!An6gl9delX7U7M@N! zqtr+sKJ3w%dHd+Kjqw{!d;Featl{~;Zb{g`u9N3JwzD2WY#Ny1FmrWkt0 ze60qoL$03+40<@lu+fSH9!=ra=vLv)7XZm8U6bH1p*t&aQMvP>zhH$)%W2g|BsZ;#P|q7ZR4 z?`of~6CGX8?T}ALxLoDtwFo*?kJ}TLA!Ujngt&j{xBKjo3IE)FsE*I-)v7DvyqVsc zV1?!|JLHG^#3{ zDl)jPA6!4*6avzbwiiEF^{>QNQiNvq>Q_pulT4p>f{|?iEQ2F*pOh?7rrl2qDmo0l0ti43`sLbhqbTW~yo98&jneObH>Uj%@jM+)KPQ zQpqeZqxLLjl>2JLdg~H|dW8YsNEb~|ykQa`7KENg;2DTgI~h6Q@D`MpRYL?)RITW6 z%vQ01H5`=47pBu_Ma7WlSk|HUte>-4qASFsM`uZ5ZKZvZ_f|&F#YdNTkKC=)1Ac}t zbd21ZHr#S9wAP-Hq;~%pX?$ID)3JZMbavUif0p{e=pKH3ff8j;`kmO{NgJ<96qM9C z|Eg!_tvsk?;Wl;qzPECIZr;7HGaF-Se5e3VQNqCbcVyBwadvQUWdNoA?)-A#*2MFU z*Yqyo{NU4#zQgC!^Sk*ypP{X-e+!Lw*!M&OUVgOC>YH|l#=kCscSm?P`G5b}){kb_ zf1qrFNANB$+`9a_K6~T*TeEcM%2#DBF$bR^7~1Nv4>&_XWPcXjJo3j3nwIR5A5%Gqvv|XvR?jfOQ6) z%sg}B68Uj_G!zzhxkj50oAq}GeSFLoiLCx%n4f>?4=#S1?#A7za1T{?0cr42heY5J zIYE7N$e>Ay()Hg>JqF`9&7&_KslsI5ZRtI@Fq|+1-(yN~K8A>kk@b?*zKK63IXqh$ z$HE~Dst;4rHR6w%2?MK&Cj0Qx2+^?F4+UBAyFM{@&oy9*fFDt9JUX8_s<82sEDcP2|PX}62CM;>}=C6%crjk8jyIdWxp*L*XBo7lr+J`Y2V@v-Q1?2O)a*vTq zRSrGm<+70e=jaPq(}0Mt=hjOOF5NlIJwC9j$-;dFW>f;0fEu%qH*BDMdl$(vGF;4$ zIyg?ks|UKeHNJv+0CFD+SDfg8-5c=Ic+53?unh4*IS}0J?Hfd~a+n9FxVs*C&bPgT z!JAFbr93++|3`p2o9riX;Ky%rk4w;KzaI-Eho%AI7QhicJaN}w)xu5#+2fVMnEd#Y z%H>RF9JiZ0;U&WQj$`(*zy!lROR!KirTbdj>3#=bdguT<+ti7k1XQ@6>(lK|mMW9X zWVK{xavvM>ZONwC(xd4LYaI~3iW(;RB{Y!!__rY9X^!XP-o&ScLfM?f&3swNh7+sX zA2U4RJy(~q)0GWu2T_rQbA;Gw6M22H5HvAC^Sdhp7wx*Zz}?s=^a)Z*IOE4$hiWiI z_{8xW4xW}~ja{4kN18_MmQ&nLxlf5363A}kgc0)za|e22_f!YE5eV4^ii^+yoeX{@ z3Yv-u@50Pe@#v0{2_bXzQzWJdb(fH%%VJMZOAiF!OrDUSJ2&?n^)(z5wHSgo)GBlG zhW;1m#M6ikkHR27!6T=z|10};N`G~HA&#C>rIvEm`!l`QZ}9JxeSr2!0JNscRRD{h zCzVp^wIiLU8|dPA}enM2sr|yq50Es~RYbU(A|S zSt8Bsd3Yx!JlvXdjuBPreWurHSsI1)znl%wT>%`n0&)V`5sI&#{PzuwWu(ihgA7AfglI;zP~ zAMAszyoDSKkj`f;0YOPaI;CWU@}+IQ>dK^8!3$UAdF z)BwLTygm`&z}Lvv`HkSx0<5uti4j{DkFlT~?G`y+$9lQOo@YIrXOLr#s z6#z81B`FI&Vbj^^WC3uJ`85hsCerJ$P`lQm=j@+1KmBPj9nYpu00T7`z&QST+>nT~ z%|yCE|FfmR;>SyIGlkE(0?@Q_vSG;#hp|>YEQ)Don;+HBvyj4LY8!07sV21ajupSf zXMi4z#$^eO;$#R-<`#1@}irSav){`xjD*q6>75h*2eLnUbb$(>5X)J8-i)0 z5CvysTK0$nP7_0tKGLP=LOW2GA$Nvz_b;fn^IVMM820Z(TRqu$-9FbDe{1ZF=|8|B zstp>qTKYAxa-)fw*z3W8avfY2>A)BvRpD2xJC)WSl3?99|5K)TIKPMZ9AHgf+-UDm zlf**3*ulQSZtlJ%MV=8F%SJb9l?lGaE{{B;##!@Br_aRhj*nQX?16@7UnHujV%+na z)=zj~EtleaJM$kWTr3l<2^uhR%+GncqUS537=@C2z0?W@IA!LI@>D z=+XOMCH08UvX-~fHRU7+gmGyT`ZCxko3JOLqfP9JZD~ ze_f}AjcSi(?0#PDoVFu4uBA6AEBnoSs!>G3T#Y(lUFnM=C1FziD>Sh+n`FplwbJtr zkbUy5zGbOWFa4#;vz5ww7gtLjvB+W^*0dFsQ2mNKn>aQqDW%Bo6`~~?Q`Sgcp1KB! zVZ**BAOKe4=zXFzHEF};PZu4cBnnvLAhSH9Gn-E_14*M;#9uCglp+)5ic-9p-0MFQ z4s@ao+AcSeDUr($3vNVKq-G0}HGO`_XT161qc||I8ySli=M$K)l$0)cFNz&An9csL zKeu}RNfS&|A9i;RIyDQtS7GMlaYK~!y0j*tBBw-6Q z@OAR6WBo^m)1aB2KYzmle8F+QMJjW~SGzK5kxl7D*2F#|Z)s5iia<35Un|eKCf*Po zykY4PI3j2!(s*>=j;o+1nik#*g%>3RP+*`98(KSKc=N9H*z=eEd%eBPU!Mn89mhY| z!B`ls@_djF^iz{7z2GNa`VJEcfM`zqB4B-<{mfEe9@9$HPy{4Mz*bu$IE6}Og zgOAF3kwj`2^3Hq@TdKl}cq?IAU7xz1!H>D=Fp#`l#Uc!H=9a+`5=~yO2!3Z{LML8< z;+8O=4BRH#C61O_(@@5)w=e2Jaa55uDnk7ZmfSu$=!vY158ot!1ylUxeycD+`QNZD zV8E78PszaW+w@r+#<;8eXgV$5_M4fJh zFCX|_#W@s4cjEF|8#4X%UH` zF!n)+-3KcGdiEI6dA@rf9{fCb(UgPaf08hUa2ODx&3Ye?fZ#7I{_6ocGC@z|eWQD? zZ7gVZA3FRulK}KS-Ax&JA0+&rqW`V=-%HK^R6~c|e}griJk(*FWFVnWUyHN`J&KEgM3g`43qd&AeyVm(w*F{$^w@k{ zy|KU^&3-+=P->r4E~W6&A7JspV=KqDLrmota2OR-s2Nu%d>+T4P90sD7uq5}A<5Lm zQ{53Mi5N55)IAh*9e$hht_wUThhlFj5(zA~{`AE;InXK>ebPXbz~P#D*h$T`LN3=j zXY@s7xa>$$AJG2=1EHsS_Q3OUyp*?@`lA&g7!hAF|2}4xx0xj25_3YswCYVt$19AP z%?Mm7PrTs~*5<0ID2r!hc_w#jAC(w0;x#MGo(r=(Wjjyv0X30;1HLY6%!uo^n;gM- zys~7z@0vTnM%tojX!|f?Xn594HT)#!(;sT5v6Uzg${7p!%D|qrgqWdlJRKIN(CAsv zqfE!joTMW(Pa*^C| zU9Vj3E*=LT{ySrEhr}KJ%vZ#Q2MXPpoZ^N8=GFejoc>`Fxna?q=9F+mKuj%n@&XP zsd^u&SRu)wLxkl~JA&K&vGEWr*bJ!A4uN&3{^Ziz(4JKh`oa84ic%GN6R&7;-?22rc zHvkE;V#{82Z;Kmf=n4<~M2xYP7c@Oz6sVLk3eo;n#VwzE$`bO9TEj3U03c?2Q&wZ8 zQ^*zn>a(Frrg@y!H>HV^iYrNj}@!h5_s8 zdO_R%tF9+0`7lo#a{4exz1?5(#B>GFtpBL1MzzWoYqU0Am>=`)jP^W{U>x^3%@je@ zaQ242ZfqvULb$wYWGzk#H61f#To{1Y_v(r)2||gBYbBSd3Kf7yrzDdCFHJ4jyiDVH z<{AnPEbH^x^Z@I}z(iHT07=W$q~G;9@O)D2SuYB+ZF*X;rmFu7d=(qeHeg&7V+TrSS$uWwatS>Ll!jTBkE z$vP{-+{!yR!+9C{n>~X5=V8iv#&Cyx!tVQVrhg#{1=MS+Y$#|-Kx1*gP?J63_66S+ zG#(RCojCFZELZMrPe|s79r+Aelgx0Z(qc;0`gCAw^(sr)x>wo0F-qM`${py6d6@aMyeF0p?K!x!+r0+qpD}TrTpyi00waZ>a13D-^o?tD>>nunMwg$= zp`Ayb@$ut)JH0M*?$m}-e zbWYuZ%*kebm6-C3QuT|lb1P~$f=~@-9tTz)56Haa9Xk={pcPyQS&Bz^)_=HGOB!in za)MK$vsI||F?U_A?(^peBSE#_puK$!DN#n;F-eN0dL0T%&3>kM5q_v1TeU`1U+#AD zXpK*P?if#NcgMR$c^Oucvk9^g zIK&+h&VECGt@S~-NSUb1w^4;2*Y{zfSPgQG)z^KqyE-YvI4%tlUZfFXVE3H)m-jo& z1yBln9#-&kdjP%xAdIM%id0BYVQkDQj_7ZIIe58U&l_W!^4S+N^93B~6dHfXu+9jG z<3)?9wSNR-l@iXi{T3Sp<2#xLghDqI;5HYtI&i0XzC|m`#a30@?8cOX(tF z8MZ$QCgL{d?95|5kG%|30sTvsUF&vDT_r_^L<2h|VFQFB*h+R_*sbV?0LZS6&|ol8 zoqA1sz@W;Bv)4NWU|j$Zn}FjKdfJ;E2@?pA^JF?WSeqh=!x<0a)>RUYSo|ewXQ$TD zU<5#PnbKo=lw_@x#4{i)TFJKeW7(!DhGC~x8S9Id*S2W`^e-*6>}C!Yek3bGH2zupU>>DBih1+JB$;d{pZD){*b{up>TPIYMmz zK43}IT@Uut$@@^~@>auHx+8|+c2oPIj2e^FX4&VMlQ~lY1p4!qe(C@nTe^8NHW!x@ zuBW@+@rG7|;DJ$$u+M_z*b&x^iE|=o(-eJjK^=%*c4GW~CX9=k$Lu_SIogb#1>J z7+@$FkdPj_Q&B=-=oU$7q!f@Ak!C022)1 zXoq_lnDTaN@cChBS`psySD*3$=*ExxG!gpNttO+de0k64j~|%`mi1pc+_~%-Gr1z22^H zoInz*Wt0jAS1K`(0d;{$6;&y>Y_WKvq-r~aUBTeXN`(q|cBY?ihC{Q~5|ScDtkdkl zj&2lvP7VVNFa|}29{8uiGKi{Ei#cLHWuw zRU{Li63+MJjcZGITHj%HhkwRtBcVO++s@^_lSs*;`dW%dOMOIVr|LslE%q;njQKAc z3wAqU<`hQ?uNw~nNB!?vZkp{s4Ba%Cml0HzIy|^D{_D%77{2KMo!eYtjlFlC{_y6x z>hjiARDAVD8(zOmS00DV^0&GmDbHI*QB|JUecTgiDHW>62@DLZz``_EeAkMB3ty4J z%GHF2%EF2oT-A{}>pUO4EJ4Lt7{yJgV;U2&Etp7%1)m55{S!n0*)#u4D+BEq>Ku*h z?$RjhFx&|dOjy-Rd~5h?!MAQ!hWa#U+k*_QmeaCT2gAWwV)9y6iXDESJ$MgWVRenn z`m(YsMzwAg%Af!$#sv7-3(^;8fQm$b3{h54H9vJawju z1E>6W5pSA~cQ&&8Im#z*nhoj6VZdsJFaH_}wj+&_JFEfBol~!_E1? z7PouUVF)Fv2(B&)MZq_!-xQfq+Z}V4WMp0~Y?)vXPV>tPzw)%wTf-l<==W_DfMM@` zhA(K~5Y%AuBM8&i96XF!B92&K?fw`{(3+%-=qq!dg>pa}*sw+Hi{l7_rETi$>0Ug( z8BL8JIErO8qkn$1IdmSw+H@kYX;-MF7Xg>P)*}+|89Vd_RVKXWfNaJe2LfzjBc2g9 zd!Jl^7|q2;YFR8c>hgUMtlTl)?7czd+Mtoyk8=VbJQ?BFW#`V<0#Eg1S-#G-#7>;N zT)*s{XE;Fdl*9Cz3`K)_ic4{0?i)IzFNVsXkyJqhiL-5&&d9LWetwXUEHHS9WWp(| zX%*`GHCq@81`kHJ@i{*Kr1s3~5#%FJlfH1*-f(BKZ^w{Ia!(-31jK1C|e zbf$HHV7<7J0JZt(Qg8Hr#P*#!xEK{()qtTgQ4D+L+a%E>&VyMz)Q67@Ni)xZ*-`N+ zL;3Bw1H*USii4KWDmiQ10mBE^l0d&#;JbN3A2N8BIoYch5go=^Z`*Pna}LOvcw;d| z17qF+H~p41k>93Ru5n(YqFpPc1G5RXerJqA=NOQDbq7*sXOv=3cOToG#z;2T(82=% zNH82)Pl#yz5L<_kxG2g}oDck0b(Si9!27%wfZoD^2EXA27It=UFpnBD!9P}3-oQe8 zvFx0XDI{7lHnJDL(7~BbF98HzSqZA&8@JkqhqeiVP1AhmPu&h9+dK7Z-kuz8{hI!~ zhr_aW?sFVSxAY=UEjfim1`p9FOPT-;ebc}rxsqrV#f!DjO1Kg9L4J@F>FC3t*pkLU z68y%5I-PTj4r0_BwmYHR(=e~xe0*AYKfRFv>A2?sCrlkyekU6GMsk2`s@U5`u7DC? z3Gg`@)1g}!tc>kXOZVTA{XYA;Upm!nZM$Cq)GU9Jj!{z!`3gg(k`LIIuvl#b6=V+O)BuL?%?;w`~B(72Ml#h<|$Hvn{&M%!Ue8SxL=RXg}qWfh6cfyCL)BVm)LIA)$aFg^K6U>7&iZ>WQegnwbwPcP4L`PS*W3`%( z63TXe?&$jB4r)yoYhi<0@`s4?=dsd6M`Sp4GMfkDVAy!QFD_TSfDb(!3m;C}E(k_` z&u*Ce`5pOI+)7J5YpJ<9ee&_eM&OAzf^8{Dg{pgHY$+WZzHf)5ZwbPc-JfrZ+NdXR z=SFbd6fh@7eaIqBf8H*P-9?&~s?E3HL5vC~m0^2-)Auq^*9ldD-4TIIg|wyKkQJa) zQ7O<13a=r006sgr+B5W`23PKb*B)66!QpRKY-nA%BYNB|0(OXjIvG+b7BE>*kWh!B zZ3rMEfX{^ihb`1W0M35?2X$M1k+yIBj!xYEUW2C#1(jZycfXlVUF!JvN3C0y zL6g>(sN}$}YRRI^`ajn5;k7E`NH=ofZ8glUtgJ+n9u^ArO9yQJChgbKvN)SPT&h|> zzMq%p5}@Le{{DmlXo16^auidqsi2BiliCrCr{9MJl|qPTPO#XmrH&F>*JFPQvsw&D zo}Au@192P#n3gAugq%QNGFtPy$LGHX!)5n%jFu?N6h=p}$k3n>m=SmdA$@SN?+3yG z$Neik{W3GTnGI-!M-~J%uoeb;DrdKsKF%KWkNqA37d80ODi*}EM#rF=M^*;0LafZ- zoddK~5fKDALOJ~CRS#4^QA2|Lfr6O3A=F=^fDEIXpsxU3j|rMtMuHleO~ArNdf~!b z?z;Ybw-f!vE`uUPuz?GjwV(Yd^V3!P3ipBONxK5Bj0q&X3|Qz_>ZViD&8x#(%@@W^) zG_}A#8+r|7_3q-4QE3=>WbGScGvGr&s0@tzRxn6dc*D%Atnqdyo8>{SGxVu_QyLGa zhrdqKoguAwoCy|t($8dwr?L^!0^|t1TtA8tUlFHUD*EviELU^B>f*8szL`g&9rt5n zS5zEe)%?*xPL_5xni(U-Vwd^-=h{{mGJlzN;?$7U;(gmA+o%fF@U3gl8I@sQKFvkg+VD%%~Hh zERk}ht8UAuj4b9lpOhtz0<8(0r?QjK9eMk6mM{q{2hkG81=6KCE|e*`@#6th1Zcxk zVV7{%UAecaz{GYShBEHIQLWYnIxKng2{TEH1Dai^ykMto0j*dp!uq4zH`yORPe*I+>nr*uZBcBqL>@mg{K|XotW>VndM<2ZGZ}aSL0$?4qKOR`995-5nLa%60&jVG% zU^HQ&q1Zp?U~~vNvi{G)7Qj*X#vX}Yk6=v{EVkw7jc0y@n6-;dO@&6_Asv1fF4`a8PFe zU;XF(U?VW!^8(hm;A}^DflSJKf95`Ez~oagt??v6%#fNUXw=FN`aHIjETKC6l*l5?Phl={ zzubU0rZ;i!nK3-jZ;N8<8Dl?;&Bjo*fm)TO8a+n<+!2kWx(_wYIBG0u&o#3+Dr7v_e)@r(Ut&F8=5nx`+9lnQr^y{NN#|(1{ zZ^ufg_aoRBIZlVxcHNT#l`Hi&t~aRq9@G8&5R5e^465WS(;=dcNR@zlEnwJ!5X!Xx zm%RIlVZzzi^>7`QS5=jo92Lf%K8>ayZ zs^RuQ1`d@?v@_pAc(4=}*I-x05PPq7G*1w$vyh+UpJAtiE&_9kL@HsqG z{B-eFxx&X#7o)CNx{jb!KK zhCL&-iQj)3wtD(Cl8O=^9=;>T&;66~Okr8+`pL;5jTM{`r%MZrIRPUWM#I|mYu^nb zJR^*fUe5Hj7D@`E-jKi|AAQl*RC5!g)Gcv*bO|mS34HnSMDY_I)W6~uz-*D|bqV$m z0`uu~!Lg})?h_bwC8Bo6nI65gQIGgg>s-(LyHw}$(wcSWR&;IC!X62Ax4HvX_xBj3 zVI9d0x_}$kLg3vmGZ0*fSAKURH0sP8YCg*U@O7ku_lh(F>a!&H&|@0t9J^GqD8c}f zZxqqVkD7zR)!r7^m*7*JFMqW*jt^e8iM1&#q>2&|@5OR|SH?YPWrSiWq?#zY4U>v$C#IH$^!{G zKREa_pC`k(va&F?QRPm#e(s#)uq$^5U1Wgh#aaItG#W+_V*p z-0@ufFBE&GN*T@~MjEC#oHTyrny-wL#ZjHwZ#J4$7yZ^sSR2{OZ76?f*1bTzA zA3&Qfb1*o(965%EFlA#1zf1@OA0j$>MH$@%($guscL+qx1?<#2T{H|{C^AOh*%$rs z(8MS^-NWihhp+14%b{?< z#srJSWKy)mK+oxJs1{z~np&>8tAW4){qZdw!tSouvN`YVlW+e9$-0Z&-v16$fsC7- zp8gJ6FKY)>2YW3o2b^ys^lFaOf%v7g7FW$tl4tRDTBExZP7)&z=<1z2F7HUNpjQRR z`_0`glc}Z{uJagYFWvtvBnYTn8+8eP6zx;wTF4;6n?RXLJ6y={@UGFUlFJ)x@R^2@ z2zH1Q9C4FD;SPS&s;WS{Tw;0I)nz_h=<^47%p4L|+Es_?M}(sExY{*~RyrYxYWN^A z!$HZeN9&T|@{%F#m&^dZzMD8gZ_4f(?J2#j^(TkCIC_|*&LpumA7M)+ED-0<6PFO# za_?R_Y{T`!%r?u+gGY4mM>CXg`uF2?7< zzDkMG;BMOkk_&0sb`^*;pdU?a>y0qiOk^A7^674ga?sI#9`PX|+m=0%4U5%*EHL3c z_vR;Na*U*n2=c;%-*fu1uYlKdvgrR-=#Fb_MgjpSE6Wj$P}rCRlh~DRcA7#kBN1Kq zlotzRsE;MNIla*zOyYuigEEyP0ZhbWUGcM4vl+W7%uv6%9O~)-J`W0$wrzl*S|yyP zKR4f#bF;+olj`7ejWf?%l7goCd69!_63-ilG*6D3Wz7dBl!+ee#c0RmdWpnh1ou0x zWK|B*HJXsT@f;3yYsHa!p@yZ(g`ZXv#J{j0t6rrQgdP+Ho_?C=L{abTa0XJ`d)CxH z{A(rIXo5EMk04Wdajt2@9ou?qfohvaQ!81}ok-z%w)>-NM8utud|JR9S<~sxrfwIn z&(`$LBHKQ>2Kky4G%6hf!U0w`PHZC;u_0i1k|k+7l=bh(jf zov;$MJqHLXYSS8{ok!GtOkaxQ(9Rp}C1FD_%xG3NRwDvOfk$FHVJUjt@ghg z0wdPIAq@u6GvbX97~^g{t{{Qs>h-L^dS0xSNZ1<3ge*Hqbet3$h2vuXx`qg-<3PZ0 zz!<{y){3&Qs&;zhZ;dIDo;+)vanLDo*^I3M;icJIKWb{|A|;z1bp?ta;Y+)LPMG(a z3fn~_RV!>#CXWfj60dwI1pPa=Yvkt6g1Lg5(}9+lE)?US zLUalYr73>KEyo|cdAXLPPo=I)>yr5SS?LO~M66BJB2~EZv-9oGVyITFG=MoxSSGEJ zwY(Y=%`x`~+4U-yyYCUJ?vAPUWnmFHwiw^aYhm{Df&=6fdUt+idmX3WaYUt`9&zK@ z`^w22?wV{XpWFHE@q)Dx!1X(D6i?_PZ+<()5`%LF!6PieLQ`n{_M6gY{8pvs!Ntd7 zuWVb3`pYJrZ|uJNDh);fp-tEeloZWgE~{bW{2%QSt#1A~hgtpKw_>R3ua5d}jrt2E$|NP1ZE z9wm0$@S3g+n8hs|toA8ld2!AeSO5dR_bxA#d|w5`UrC*jT!NM4xha=0W5Fv^i$sMa zy17(rRzn)sj8jcZg%>G2up++Qu))Y(>LOOb9G!*Enk)APagOg5eVg@E$~7SoB%=zAQeui4Ub&XLs|sn#)kNT&4iT zz0`@40JygwgY0M*3SSL)8u+v27SMM7z@vGhY(Ie)PqssVugA?Y5}MhM#U^T7%+P?t zmZDo7lo~aVziiM;ADV18%r`~59G9kFgxXiD;UUz;SL)9U1H)+bL1xU6Gp|NIr5f5X zxTA9C3Rc^OjpgB?zmmW{vREtfrrsnr0Y8okGeah&gsY{j$wn(J)isc!XGEm&Vhk1M_n;1h5=gRwU0%Y;4qJI}llXwfyCD-l*>AGhtG zk0+i2EL7fptO<;%Ol{G4kDU^G{D`4a^TMdrG!mH4i0T9&&em!;IaA#X5;mQ9BN*cw z_}pNrGv#%mr3Ja_Di@9c1(1Avc(n8F%41|cjza^NR=EM)9ld z1|wa1%0`BYmr$4bTP0wrPX)F@MYB3Www{6MWw@7ZCZ3lE)O3iUvg(AK+pbIcHR*K< zfq`drxN`o1eI)P#+2$eDRhuqF-bwapPax9`xsyYHumR;J4mS>9bF7wZ7hYm;wZ(dx zJyr%<0}j`%?V@*gmL3q}ko_1!>g7emQmJ}Eo+_k2x6uR(C{w=p9cDGM(}E})xkd*+ zqe1E|VYLFNRKeV?kY!#j9g4>gxJJNn>;}T5F#WUwMqF$x#tR42`HXQ0j)x-cxoZcJ z8EX1NRbElw2TOl9^gfY9PyjZsu~=fRmMd%J3bIA=iWP)WR#ldBs7|zes&p&i%k6+@ zYu=!N2EVfcToHX!ra%{1 zg|x+LH-1*SK&RH^%j3fCMt@s~vhmuX7Y=pt!^6EKnbP+$i~WM*XOH&J>yID*n!!g- zav&0>y&WF5@jodg@u_$ot%yZleTT-7fHp}WZ9xoSezkx#vXP25XYK;_6^o4I@m|M?lEp{Mj zwIsd6=P9q9))k-MM?!@R^qmcgmF5%o|r7uf+ zCgbYzul+RX0Bols#^&Rmkvs(%@_WCCN6LQ=-OMgJv(vmNa6v`UJDxLOH6}#VaiA-^ z*bzac`CD^BT_KTrLNAjb>>le=szaiQZrHG0*ZT*TKR3+LTL|G5F zW%3NonfPFzZg6U4lze@ju3mI`!R{42Do5#fk3l>9>?PVLz(P>zl?nNFZ&Qttn1!U} z<3nP)0_qH(3fFXIzu^e4T;HIqf&_coY+UFda9NakKP#G;&eo2t1(}KaTu*M zS&1vXE=uZFESjF_D?ct9z;bDxHV=Uh*?tNke6aH?*@Wn%V+8{VqQYK!4PNqA=hIIZ z;|-^Wv&WpV)AMFcFMREi9)qzH`d%>$QXGo2YvU=J6asnrs!+y6{7XJpq=H)2BpkV8 z&#DuBou(V+afDA+lgKVP6O2`{>vK~1ftI7|r@aG?LZzR_9tSZN29QgB-k9$3G^Fc& z>s|+7|CRe(fgjXXDZcO&NxxyIO=cPVV&3%HUVMf(inNeVTj!@{72hKn1v)rVMe%uB zS2EWOIl~hx2VO84X|!`0S!>=LHwq2Wc>F3J2Nm3IR_n9|r9#7#pO@~Yn!v4*Heim@ z(rVqEs8w;qs~poNbIy<1vTKoQMSMbUUp>$l(Lc(zammo1?stoaA>LWa_1Eja$BK+x zTs6Q}IKZu+`8BFVvFRXPOhd$GLx53z`PvZ1mk_TOyj}s>I7P-jA*E6_dsAdhJsvg%RjfSpmLS$zD1a>sz-29nHm59FV^%~KL^>Y$v#V_F|{ zLMRwW!KUN+rfd;n5jJs zcdarJR3@f%$kFF&ztLvw=Px34X>DPC)uVy*m55YiLU$RxvpsR>QG|s|5cPxCo0|(w z!ROs4cP;NXI)1AlresAIp0QEAF~%L^@Z1hU+FZ%U5u2ov6@^fHO4^aA5V>Ge@Edne zw+?}DOCqd#vfVOR`l-r5yt?E*YNzLMz}7)0s}x7c-pS^2a^*>V?Ea=-@$uwFQDDIE znO5Lw=Rx<0Yr!T}LPvG^Z4I=mOdukZUeDz%tr=I5^QJ1>IS*s(`RbjMvaIT~*mTp~ zO^F%*-lfs$^ELndveHw@0LuNDd$V@nbjZT|HBhRyjMs>koZ93VTPlp1-uPeHotKAJ)F#xwSL0>j2 z7;z9Kx4t7dYQCuBxl0_?ygfa{Inc4ZIW*JAfQofiY^`9_jm(uJ2Wu69K@a&hH6uLt zOGTJ6I%L=$H}o15<@{PE(DS0!&2$;Rwj^_w&#o>N z&peVF-)tMuNHOPoYm-{*dPAi4$j;fr?Op+wQ{M3^_4iJ^Rj2b*@-~&h^ye3u8PS0E zhvPk~MAaCd7mT4k3At{GtJ-yx4wO9vo`wR9Ta@y??IN1|`PIV)wO(9ry8_;t-)Y0= zzArhFU?9NbplhGRqH(>xovNq2gh+kg%%shl!!@)o#$O@KKBZX@o>QNpRAFNqs-|CUK`0y} z_zcyr{vdIrhRq{VoP~x)>8-hD`R%vUPkD5_1u42IMRODOjmh-6ZpcSEI1=@zKfa4} z%$$ynuEj+mB@t}7dlVR}(*_H!s2Eutl~t6b_(LwT{^(vRxBYV}kGk~25gW(Y*UVLh zyqg2cSCzZIyL?(abw89;Zp)nI-oAHSy&WqHj+gL^g3A=})>m_tGR z(wgk8%aK-aO;HLR_InB5zghLZ92`AjWEG#Zb{B4yhxh7OOm%PLQ*|k=Qg41>Fou7= zZ+IHejRIFJ1W3M9cx8xUedA6K|5Z5yoamc(BmLX)phWB1uAyMT&>zG-nXZ{h+T!%9 z@iCFx@cL@y2{?6<(ngK3r(X8w1$>hCdaJ|gB~G7r{MQJ4)<~WPovg*VngDK^dt%*1 zR?BP=7Yz2ErCTEZdU0l{g+QSKF+SXp7-lIW(QTiC2dzcKCs--INEOC~RVckYeSZRP zO<5DD349l}q;)dIl+`?a6M1sXu(avEOLtL<3bdOZdkiIVXt@**SFPOU@ZW~r zi^mo@LglbP3-UQ&<&nn^i;BLL?v0*W^i?WPQciL!G%0=@!J(E#Fc||9ky9eiqNq^2Ti6qJOdf z`dCP>q416(mm?*Uv`^Et*m&`Q3PZ2JV=G3b8qebT-+NjaF@w!ueDb!jp_*9A?b~2M zPb`GNb7P+G!$I&T1UVqjSRhwj!YTXpBFdmNwVAoM_(}>NL7G-l%f>WS4M(q&sTG)9 zJ>GPP;Yn0opY;dTY9T4&7aqW_qZeUMw(Y%Tqybx?~VkVCM~qPO|1eX=r{eP~TH&HDI-%Q@#p)3*9pAlqaVcFz*q zFa)FHnNo~Z7Q_`s^S#plS&;q{*D5aeDpRkpEk#5270uV?0@Nl|I@ylRgIwy80obZC zz9$QvS{c2A^PJ5BkY~=S>t?wLA{wk%nDv?&uSkbIQrZ@}l8k6`wmGRvjkh`sr6iibN419X#gF~>j{oM&`p{wNb3WM%Xb_aCo zKL7_=_c&>RKwY`WLaIZqNm*4r$Mc>#_o6f>p|3o#d7`6hJDldLULDwnti&iyNLSgS z$yHg?TXs2j?qVg?+F%CeN1_^2eBo|ImxLl1)xXdgMX&I3fM56f0E<_`>&r-2qHJTG zMr_!*?{div?Txclfh;&yw8?i%vkSR}1!p%KHR;_-!+}|aDq!ufU5?UMQc^Xxvb82g z{dhl8{37$F>l_L41TS?L%)x9J67rFYWxPR*_9B4TuRyWQD3(f->YLvi`pLhM73EMk zOVQe8Fbwu%e(Oyf*t_!Uy3KX-Ts{pJB-JEX7;DCeI8!}^WF(HLXk^a2aq%G%`m>x@ zc&XXIb|*tgqKkFo)7GQ8Sif9y~Cryv2UmE%`8mCU-;@6LMgr8r9b2FKR-~_3l6ldsR$s8s!yg z1@4Xpv>KF@eCz6PT}Qyso(Z7K_)E8MNs|s!-X#b|t*OWzRuPTwOvaIYd7BWNj6bmp z3(f#}n>~&!W{v(;ctCrV4i9xvM(}@$akzkJK`Zoc2m;8B&_*fd6h(psRmzT~!yX4A z1hnSy0Xqn;H;)czHN)=ONpNg=_GCM}_G8)EFMhDUJ+YJP+OB#$dWTaQkB~HqsTT)OGd99=*%T6`L{zQjLhyzt7}Yl@5X$&_tq!&Y*iJbII^<73@LvJ6YXH0-^;5vGVKM%@H%NF8AaN zCHV53O09Ea=;1SO{EBXw@taJX_P;6p?tz%@q>EyrpI|y z(C59c;)v-)E`}HI{yu3N1L!PKp!U3oZ5ZJ(bC%ciYB~V!y!cOg3bT6=ZB{hc5wi>X z@lNjVYU!5xO|%9~e5LW^_7$R9$vMDWTM)Uxg=g{c;lq0++Ml&sxesE;McpI~1LlFY z!q`+}Yvk?UACnC9dg7+?Ls^>luV{Oe`IghChGG;fH?4Uv%7dInEgj^eN>nQME$H($ z)mC_{Q*ojKhfO?(LpmZ=gwLVyh1RHhD_MlLyEUt3w#v8OSTyZJ%!^4XWzx>{>K_KE zSgI?5Wm`bKK?%Cgo>o4-H0UmERi5lrZERM7*wdZF{xmQbvU3(t&{t^RH0>CN8{ai- zf*qaRuxq7mWxKwkLwb$F=y-RF(J9ma?yt`@Z09EyGyYpIdk!V@IA1iH@5OPxa3P#{ zY;v~K^q8>r8leL0WPJ&FkAq)c9>ZGP>IhR@Yvc0*d2T4l#XT#3!8RXkLPlsS)XlT< z(qM>|LG=f9Jgw^QeeyV%zkiS*nO>ZQ{a}6veo%s3g9mv#5on~`@#s)}Y`S#EE_@ik zloRbLyv@yCYCC-MTZS%F{}(eF9{ZW?j0LB)HCAk}-HbZDk8+HIl3btE#(jI%R2u8P z4ia9)AQ1O@(S595iP&`FwVq`t9Q_;sXT*lORIT}&Cb&*t@GCDe`0qpc3k?MJ|A?Z( z5XoQFBseJa?>+yU_5uWBT&;gtVOOq-ocQAl{#J&qaOEljCTOVIm|wb4dRxKZjVQY> zb|cv0Id5d!PXYqbnCh zCF+;qer8Skea$oDjf=G$vaZdGWQ2!?d=>)=7Z%8^aI>=;cl5e`d3>WhOl56;x@DiJ zy0@D!ubZY$^q%`zHTh$hL3C30VpHj9Ysa%B0%86lk!l+k#c}hEq?0l&#t{6qwaxi- zBIOCrJJI9!(^67iDrsJb@V*u%p2374?=z*sotnf~r`f4^3$1yx>Q3e%uw$ITOb)In zA$fwB?{81vq5}P~ub66T1#o|wP=<|4>%t&L4k;HU5U2!#ul35%6|D6R>MoYs!gQeU zID_YD26hATGt??*$ap0R$^tk-Z9WGtubak zs~LAxTqtZ*+}u7tT`+s|J<8{XfO7^(1)m42u~QqyD3-PHEdOem&lNA6DO6%u_BEO| zS}K2SL@lnBw#0c#jIa7#?Su2*<%W5J8cDD2)fIoEig>52o~hV*G+^8ta2V8@fa7jy z+ZC2b5=U1wU0BnVr#Rt~Tz7PKJxuWodOk9;t7}h$HFtmAD2zZIy>BQ0Co1$zK7lh+ z$bbIE>YKGF#GWMl?wCjU{LAosxCkK;8Ocl2o7u~F={t=Y50W$u%D{M=+Zy_mo!0tK zMRFE^P{~#+qxU&JF<*c53Hd%Wd3e-_Pi!hhytVzNkyRVU5|Q{p1s!E$l<-O$w6NB~ zC(~|6o%(U*%G?!pM-V{p!WNA+s!p}T%_7qnl8mz1zC2ekwplFHU#h)7s8OIN@!fE6 z*iLv6$i9XRm5TbDKNJj;T5)`i%W`_u3A7|)Z5g=U35Gwd_C=>gfRzOoXehJvGZ9;q zB`@Km26eYsh-@qtJtf5}fAaA;-?~;;(xRj2T=^Rb6>nTsT%TY;Qs^rV+2nq;u>YzS zM}y42nI27MH|+5=Ei}qxu~m-vbk)a~&dgB#i}X`G%u0`V&C}}>uMut)U+)=qq7}@g zLzUztpzz7`CD6vD%N3VwM#Zi6xu4cP=+{W~P6i3g_eSU(vsvKca2-*!Q1&?2D?|7M zE(%-7)fQ)Abc>2(i%|Wuhgk~(?Rs`2BF$wSK*@0E*Ym4M7S^V;8$XF%wfi+@-v~kJ zJe>opZ|?^wZanhR3;8;^CK(sUh1=)7?($^G#TMM@@T?y%VtBCy_3?{A4F3tc28wrU zeya5n4g8c%30=V=qR0y0cKY}=KKGHjxNe-vRXI=jv8ZcTDa4D{=;8Pf(yW(JU%j{V zMa^Prx*FQ;TaS{jC@MPgKuL`=^mxr4Rg^EYI^=4eiy>a^FvNs>yuB;y)_|9HzQd`- zBop*?c)k;~DQX0jGg)!o3s}eiN+? zoLDQXI>(R|SdPgkCx5}JpmetQFQWFf%A-nw^T|Wf=_`(&B&ioSkQ;l1g{&*GSQ%i zt>TmengZ^)IC>JX@g5z%4}j@VZ1ncfdU;$wMzEk>#Wpa@0VQkW#9@Yc+}YwyVZtOq z(Lo}&w`qdkG{9zA*Kq?tnF&D27E}zxx5YIuS(!zvvwcJW;GR1beZk2J}dJ%rvZ1nNO z^mV86id~mu|ElxSY8lQ5bZLwR8(*kMZbI-IN$r&WCjw~es80hwb3oNUlxG6wfj;z+7Z0=){id^%Vm;2fT#mRKX!HP>Qq`3IB!RtCYlaH&8AuVpx-pJcKA35j6#%ukTO5T0drqqO6cD50uW{x zw4M{KmIuqiVGuLXD0Dymo7(>ZGPR)f7AzExb{70QEd75_v#bX+*qH*euqr~p)T3&3 zzN0B=X53D#BtJF6;seDmi!(8Wpu+*ZIQGG^!Io^l*2Si^o;lct9er}Bn0ZUR`#c7v zk|)DIr*>o{6n9ftcXfH*xO%)yDf8N3#1B7d%O}b%?4MySBQ`T>VQfsoF#+$mezs%ff9@kPNT9O>TzM?pM^9L_S5#f-=_-mVr^tnm9ywA^VxISe15AOzlZv~el z$`?bf^Vecr>MT+}D8)2K+YOnGK?hw~g5r(C7aCH0;9dvwj)A`o?%b zbFcTaTElFEtj$A&JnoJoZ z?{!4+E9ouD7%aKdx&l&(C8~(RM|@LHo|ffli6`lVWEU1PPhhKxQ$^V5nA-GV5Bf?q zUElO&cPF@mgna9Q)2?NQ-{gZDp#dK7?W(IsZ$!#jFRNR@DQHK30Ik{O0W6w;oQc!I z(XBG+mr=0_j@B%9I}s8o+T=7h{cshTY%Oz?z>P^eM=;}-yhT*mh@BrtKohabh#ei;G)7n!Ppte!0)JRv#J!@Vrq2#Km@ zj;ScWX2$tSh2&Tg64H#)3|1JxgBl6UPtNRpxJ3|s>DKat%o_V^SkR(Nx44d2Hq)6~ z!*DOYm<|w#-+qIiJk(lj(0iSU)=K}_FCqQcRUN*G)N6Pues|e)4cKo+1`XtCOksVX zNBm5rM-E(nbXC;TpB=9{p!>?V>kxeCW-F>wNo$6A;)BZW16HlED{y0{yX>s@zL@v7 z(GXpHDG(@dpNVUmo4lbnaENR&9i}nKpTHrg!)=xDdwJK@Drn~s?TsrWDfolj?&gm= zu==psL`h(@FG?@Vr_{2m^=48FU&o7Z6^RgI+M;{Lpdhb~7h>*_^1$&>d4AfyppWFm zZT6_ER2Q*<>!k1sJ_#AKTxghMG*!gj++!E>xty z*xSD~q`w>-8>35szd$iy7kI?@=KrnTV3zW~FMtsz=xhJch%gg^R?#pl9#mld$wc}u zK=4l{k~=G*-{GgFjli?RrH$tPbN8n6!(%4t$-VU5<;NS_Omipjv!Ue~P76G@)7A@L z=R)qz@3Df{X@PI2WY&6@oSRqY%TC@QG586%)0GO7-!+fH?V%Z$-7>JK?4wg7CjSVc zD;FcNaF4>z`})oKxzn{V!=0VOET=Ogi*L;iC$Bl0oxF}H1@2yq2a2v?v0fxsb&;6BuloNQt1*GQJmW)&2NPeUih%MFH35m3npy`C zKi;Bu8$(M>VBtC-l2R#K!vJ?Sg7sL45%V!TeQA2B-U<+yA!a#~+XMMb97@dI9NIgDgh_{!h)ZKR0(> zqSkFgw8nrteqq9igWceC_$X!vOXffQNd*>&5=4Ujv_gpdVrv>qlTaN*m{wq#bn!m) zb}#UM8jAQsk>~?8)t{FCJyaaZ?o=``{J)Eyxhn$~2snDW8i1~c07ULjEw)C3KB)*D z4iz-Cj2;?Ue!f2glprDtrt$srp})y*4H8UU7kUwRA6O9WKW+Xyj9`;4nyNu$-`GH> zpv-;wpFW@m`=ZHRX4nuMg4w@QVnhd*AO3qHD>_|-_dmAl`DfC>QNk=cFvkVd%+S^Z zF`EL6p`GFn3;8>}VB_kFbU6CKSg=16_n*V}*7}Z=WiH!4CFQ^#`^RWw1^Za zoez76c@*_}BrjdYWMD(a7m9RzK)dmJLy&Rce){K{O_z<;Hx||}WV|r@7j-?sS$Le6 zcOOjQJ}Em@30yvpwYUjE)Le!KioK>+Um^(f_mS{>=#bjq(Rq0CZb*Wuxsfy2&%6Ge z%+AIkHD*#BuOS$vYgylK`ve?G+E_Z>7jD0w*KbC;eEfoOXLcogzp_X0MM_Be#qy^k zLFF)>lmVy`2sAuoZM`vN%Q&r$Dbl`cGJ}zy`?hP3HXDW#ON*GE9#aE0H-IfWJov|L zPQhSZpsupvNuseUHzN4r)9AW=KRFP6HCS+q$#mS{KS`(1Oc!y)lYc4(I&vZU1hAmE zC4aalNbw7DNCS7q7#fJ!2SgwjOQ}v8vEGpIY3x=XzDOwU1uzQ0yIRK!(IJYMzTFLS6h*ANsF`5S z0GJ@wf;iy5!8#~K2y4T<1&83q+m~~>;Pr~~KO6Od_9Fx?_~#9``xySN!Y(HOe0py8 zPv0BJ6_ok;p8jbu0DFoqYy8jh0Q(h;fs4_to`$Hnn(q^#)IHG&PMDjaq?GHr8VPqiq%xgSUxZtfRkG=3?ES2v$YwIZi7)k<7tZUN`KnYOa zOnNJw)XZZ~#7j_ihg2)Pv|;;%8RIiR4_hf7YWCM~E1|R`!>yXYGtDZT*sl!u?ySP7 zvRmOp$5+SlDw*zr8$qD&1sCk9AH4R<=^+C$W!`%0B-)oI@+|RV<>pz+#z@{jf}s>l zD!c=TPnaRW8jct?qcY!QgiPW0d9zLlpFb6!SVlqJLf{#Ie;EWL>Q>Fw# z3jD*}9B~m(UgLq@SoBD42Ym>uKFrZ5B?HI*Z68KBeCdnPg^ws5_Ja{5)7<3QK(lv|2L??y7(yHop%>Q(q z%hvsT9?|D)Emy!kkErRu77xaFb%id0c_1|APHacNuxyIV&{{YsfVKFG*?~iB90C`a zh_jPYE4cjM9`m92vASsfbQU~Jnp1tl<-P?Gm5Et6}KNJ4drwg*<@o4Z2b;-A!z<=*J@{H>_v+Spz^!t{t2&n<4Zs0 zz^#^#z1Usj`~8i$oy{xlJ)4!Jr?nzEzZQYbb7v1O3k|8p6SMDWYRLn#ftywt{`W|a zKK9@1lUdrRBn`oEh^~7$3$s13X4fAc4dT}VC{k(niN#n8>B%cd;gjD^EX5Kd9NN-KDi(3%p9}7)$l}X%Ea62Xr&2Qh_-FmUL@o{;J^$v$RPJ$ z5UZuFx;PWU(*=$TwZIZK>88`cmk>`z!3B$pgp6$@{p#CTzXaE64i zU;i15ZHTO8n@J*N35hIYL?y(x6eC+o%94GH!H_ITO(}k|MWO5w8td0S-!MapWD8Sd z-?A_7Ju~&bzxR5t_va7SrJ1>V=6TM2&gY!-xj!ecQ|9W{-@&yl`$=?51ft37GjYt+ ziniLx?E;fAAin$T+4I?*Le;Dpz)HV6UD|!<^5i(AEH-qGcf0L7o3{F3xSJ+7Eu@q7 zFjLpLEm2kMgpoKHwK))4AIt@2Ylp`vGZRY7pm2KQykvh_u{kp-?y2{%7J@n*361WQ z)>g+IAL{q9=XO89T5=yT6)waj$&h_kryHP~AS%ZQWOy`dnP$O6T6lxEO0r&)p@P}h z79RGgciNf2U_P+#%LP!n;GP2MsN$o{jKgewTzFiFID#7Mdv_xCF*OKInwK_AdhZ{q zqPzU91LhDA1nnO(b_{uzbnm+jejo*|T+NA@4$BZ_Aw2HmpnX@c zsm(=-tj5dFLBvzC@u%@}56Wsa@y9F>4grsZq7h=QX*D{Ue}XZ!WFN_+u{CT!786-< z0pZeZjcxl@EJ8oz2DD``40f9$25SB^&n72j$>xv1X?&sV4~hHD<;o+h>`lX zFG8>^v)F9vo9G_y778pg3SOdip3X?~m1w}V$4?W%G&6LOUB|Vlm z#MSUzQ5CF&SxeBR+F#KJN8kcEeF7Dq>YgYul&e3KrB8%V@rxD*Zh`D>D8c ze9E|r2Nn)8qi@H=ZX}qb9IqR6#^YAHI-L@dRt`M+s+XwXwc+2bxVtT#wUBn(OLgc% zio=dpO3Re$-HB2fE~KsIIEthsvWVNFtq~|A#UTn=v0dKBUOu^Nb9n$0wD!?=GIu}8 zwN;%^8YIFt>aRUfDj#t7H}V)jVG^XM)?9@3D_EogF+gW$+7TR(V5XkQez)yxd7@VU zV=Gsc8XADiG7ewWB6yVT=Wr_X#z!kAOp`DDXu8jDXd@H-kgl=pbzO)Q`%8|%ld4&j zfxv{X!g(un=PY2+ZU0*7fRlnB>H8OfcmrHLeOH6Bn%fj^xvx?Q%uFCXljBX~mt2tTVurtVLtl<(Qfdbs-Qm4ke6(HseJlhhSeuQOHi|YNEKHc!YfXP z?gJp?t37F{x&wI<)9W(irUbPIhG5?jBgO2Hl{K7r+E7n-boIJt>hSCE{|2EjX4mJj?q^8}SXtatA3y_Ih z&4!e%f#;C67_0e(+7QF^$c;awryT=6O3f-j<_k9Z8}jw-#p7`9S;pYGB&YB=1eo$0 z!fl5t5mOp}E>95x88&DkZk`*f@dj)o`d#$44-RQ<7Kln_A(U>)-zc$P3geo4_pecz z-se2O-El-%MEdX&4t4XUzxp1kEljz3FP_WY9SsO{V2}p`N)o(gfvnjw8S?U50zgOw zNxBUjHRAU<*Ai`TT}*_L`5u6@`SAn3^7)%g?AK^+*-J)=Fw*j=p|bw*#7#tFXVLM4 zBl96fN!B28y1ox~s&2d-K0z<7knVFv!#qvut$=OqiIr8@I;>R8gb})iT6v>VCB6&1 z@d%g#-T`Z>o6nQjm@5|Q0Wzgl%!I_F3_l7v1lO#uFO4jXU@0>>6uS^&7c++iL_(%% zBX=dn)w&+xc0MP&c6iP5=-g4-*?Q$0si?#6UMVtn->Eu`Vv9~6;t#~3aSQ)6{u*Z{ zdMP!J_dW_6a915Nl6lJL<(1@0XzTb^WuiAcs%)@!l{>lJrE0y*(Yt+T3k#NLV8VNK z@Xn9A7*CXc!o9L2$iA00*au7);v`%MRZ-H7Jc!)6)a&;d*vkDefB|?iH(Lq&*<#P? z%q}neV&&Tz85{3T*O`kOuI9#DUol?jC`}sNw_7{%6FKW*vTP-05TL2TH)JBB2)1MN zSy;)mqtDupnyiIA!lh0UwBfqF%9;L6`a@eo=~+p zJ^29xmmm`Ns|B=mk7ym&02c;bjl|>LQS;F6^T4%ZKT!R$-`NzTFp#Ykj4)F000gVT zV|yGL>5mnJeRfRYaU^Nb(LS{RK`=G7$qv&HwS|KbBMTlKo~U|3fFO&&2NNhUAyZk# zL+Kq2S4#gSNp~Y&Y>?#*G17Tsr=ZgScZ*`autL;AYpmWX*uTsKQ-;l50kPX(h}1V9 z30_HjD-67B6(7dYFv(gFwTdOD7FZ+NeiaXcpvu-&q=IBb#Qxcaz}gTlY9yrWQ`I(f z1mHd_h-%r+_S_UOO^l0fv7`=AlM2SWUQ%k#a;mmq&*X8JkFIr;jsLcIeCSvBM7^l& z4X+$a?C4By1LMhi89~Iia`^`!uU%*%hzq6Io5oKs`~XRK(!9wJ{kn7b0UMFIL%=ty zY3!k%$z2#a1Ol~(p%sI=lgv&i1-|u?-QumIz;VVwcis*vFzPhr2cyx|btk)u9K)=y zi;-@3#DoML?3z=I^FP=chVue}nV#^FenBPnS;k~@Q8wkenB)%)l}6ypu@W|q-tc-k zhM_B-0bl3}Vcd?z`Nu<}pvp7leo$LDOIvKgvP`aEb<~znj#q z6m?#;A`%xyq5uSH&djP$%6(n?NPXoNV>Y)>$udYe{PMiQ!ZTk*! z*gA*dG%Rl(LO8rpYYZjA7ytRbN_==zuDda*UVcMSMQUACL+<6E`23 z&s!CaH*CyL>M2pkAs*yvLEf!faQv42z2ieiS-NQ1qXe9Eb6jF;hJ_7g}0e@Kdxy(RwI->C%_xS?RVM^W;exX&Y+$4ta%tI%(4{d*tfe;;qo^&_N%a zg}dEvR-C(S`e#Yoho|K=Xy@s-5T&zBI3S}%XD%Ji9a%ijv^#%*$+w53#$y5HPR zDN?*z{geRv!)@E0Z2RIUMe`sWKQ&hBlLKtA`Gyq#kzM*k0J^W(#(BPTnpY z`8k(U@Ut{&Slc%AD_Ydsa|f5!GL@5~S25H64h3%U^l{9q&r}{X&U4bw$ZzAuv13}4`ZaPI6~8!$PqJ96Esc(R@(*5o+pmEP6->#OjH&YsXHa7gl+17^gVDC<2L6{JAOX&TzA;rR*TYNBNa?4LbnqzBwc&mVf&s!InmJ zi<)dU_DhmAx-ws3RyF2kn}XiGHrce+Sp&C|IPYi4SvyzTHfJin{4#O2O3Sx1CN;`La$9KS z8zH&;nl{Cv@-|A((D&*og`!X4DpPV!^}C1Lr^#)3Gi1*3Z};V~@2ADYko3vgen=Gh zwjny*eKuy>+S_&=x6&O0Fyj=ZMy=xEk7QShT3u>iQJiA6&Xt>vb<*jnwtc?-(o+v> zT_#u8tt(zSdCw^CYP(If*O=a~a=SSjC2w`w+pak)m|}I)Yirc4KSmMvtbDC1yWe!l zrdH=G=jK>#>e}?&{i<>boclFVf+KM?F~8KK`rXn>vSy-9?FZYl-u>hWu`|G-gZv`= zg(%~Q)&FIE+=l%wTKtEjT40jyf25a?w3+lDn#Uh-VpAN_|KK|PN%5nINg4X&pG)Y=FL_tA6{kJj|XJ{u}by7Y;7q(&C+!)1Rq#JnFCojd;1>$nJG;0VAJ;e|7u+tcfD z1>X@_7gGm6V9c`Rc)OyDQ)6b-$88%8UT?qRqF+c4BxTo~tvG6Pfn+Gn9}^!xIQbCt zSm$TOiWi77zkCOOpI9kpLn*PLGQ^n;GJD>-_r26~4wLdbY~{qlOLTX39zKj>B+IO* zE0o%6{E^kyg`(TTbrUA%q%nMD*UMd?m@m4iPY*THLEUXwv}?q4UhhCb&xNKLvPYweVQKbF0!n#rF<0CH1lcU$UOUizuWK#BVe7lJoZfW{6PJ|JnE9B zc{KLo^qADqhY{lImYIBF>CtdFUkgsAT27% zegN!v%_o`DI7l2?V8y8Gx<&x1(%C2eIy+z}DGN$#Ps3gyl`4L2o<#=;dP7YoXauOL zCJF`u57UqRz`?FJGg|B~*+#Zfo5vGtbartIzXFHV>UM7Q*X__Igch#edAGZ#yl!G| zAdPuU5-@N?+6*PzhV*SNwF&oFt#1D4sq@+F9oU_k9WK)W#H9Ka9-2{+MI^f)8EM|X zJY4tcuI1{cP>)^N-Re>Ln%kS5JDOj1VBn60p&0%M=sANc`hWgl0%`UCnm78lwz-NY z5*zTjcU;tVY`rA(-+T7i?r>1v(SLdYB;Hrr$tH!GFZIu>#9=&DKg&cww4t)GH;R%>QcK0O% znxrkok>%kKDZzwIvUOd|iI-)t_SPAz(?T`qj7#$)nOnd*OjtA595@yf*eegN3nD8{ zRdey~>Z!qjVU0yi$1($X;|g)30cIAJhhtj$u4-Y4uj%iJcU zvPGks#@;_aFj08uv9Qtn5sZX_1uxWhgjs*3J`_k5cU6$8+`@}5FBO^lT$6onK!syY ze1IN%%F@iV?+(AiZML36Z?OO9ra74-p)eSe?lE1zK^Dt@Ada=|yyvJBm_Yi#OB&7U zOYmu3Ee?XEEpDy;rd|F%_y}b01wnl&0{Q9}X*?}~VP9m=5s7>?Q=rFu%)?$XLGiKS ziFbQ3Pd%bUm1fQ;f6SIyHz>IPhHxrI2?K7{HTLiUag5`wk=^O#=Dt!yF!p1N+dgI^ zPw3)n?C}S$uI$I2T)c6Jb>kn51t?@80Neu7#86BSA8M3K9!NFMHuoh9v+AxHl$}wi z5BKBJSBnu9G>ccgXPZLG?^MyJn+$D2Z<41)aNr5t^5?VZ>xvIEV^3xBNx-{)@waT; zy&iNYhfhd=nA=Ko`{C8#3=f5wTKWjh6SCG-8Y{&;9grn#t%} zU;4^eR2mbhF%cQMGT%MY$D;rl9O>0r@jcQFDRH21Te{af|LSjTZKa*Nzz|j;$v};0 ziM5%&zNK+WR1T6Qfl0sIS=rzGJS^fe+kw`5&s>htI;Oy}0girp${r3B#neur0^^{^ zBimXQgUCChyS(!EEteSxlWt>)42b!zZ$N9A9zn?{hPKF*v<92pykXSUIb~?MP zoT_Qet+{m&tsSOtVfQjl5 zrc-C>y|f+3u56eFL7NKA zJGcK5^<9ZeLGPnJd2kJT+#@HG|LQw2c*U~rX<@8E&ds7jtqMly@*L%3H$ME`<{Kbk z>&8Xc!62z#+T&RcT&!AKSwESNIGTO=HbTF4F^s}}rADSmq`avqr>}n}|+uwR=9dxoG;mUpDyf zsat%?TxP3pQN!w{U9m5W!a#S=*hzFg8a8?!FTfh?+sX5_yq*O`ys%pMQ#*_!!3;7J z#fot+{$s4&UhURp-T_lGP(B)i_uX-OVs`ShKJOR!945cLQkpRB zVCTT-$Dh8T3}Ie=K&fa<9Xl*A7PM zI4~g@rOCtVFB+i)d>1TpQlR11m+bndaAozM`l5bZug<<*Vo!##3%0*&X)2Z{m>fPA z#vAlZ1bIpWK{!>Ay>RN*W%*&5_=u;SsV@*!NNSJ*5yT;b`>v5;*VVp292!c5 zPg1Oz_k8ry;OsVB=g?hkm$;;!l$Mr+%iKMY>}d~|%{58S;ZrN;nr*xosLCzQ8L=B%ydrM<%VukQP|ITCnoh}AMw0d@VGSV?eM#=jN QAncjo{z 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

6tP9#r%UEKv}zQI+ac;9^p;lX;0AeWF99c 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 X`x}|nX5@feczBAkYBD7cAHV!Rd~#cO literal 0 HcmV?d00001 diff --git a/docs/images/team-escalation.png b/docs/images/team-escalation.png new file mode 100644 index 0000000000000000000000000000000000000000..45d88ca1f1d9010d2d50880a808713433b892e2c GIT binary patch literal 44533 zcmZsCby!qi)b2Qf5`ut)0^-m;2!b>W-Q6`vcQ{CwqjYzNbb~ZQDjfpS($d|Xa|eI- z`{TRM{pURAoM)f4_u6}%wcquwwS$!vrEsuFu>b%7j*PUpDgf{V0suTd#dwT*(^Uyj z0RSEiDa)%%Ad$%9)AO16)r-rk^NXwNo7<+A_Vld6_{5a_g5v(cQ2{{_vez`Y_{7*a z1Qe8XG76ft^@z2NZCp|+8aie|Vlw}L5Pc)t^2$19Rt`;l^W^kw2}#-0^GiFJ=grN{ zV{}XnOVnGZwba-93F~ z=GMh!RYRkH=2p(e=FhhFuTCtWQ4(SjEN|J~a<#Vicl|!dt>3BZ+G`m&G7ne)DgFK! zxx{BW;r%5mF&Xgql#(G4KQYv zjj=8J-TKN&+^aG^wxzIsvg>PI>I+9cFb)YSW^-Dn^Y!Igo%?z&)BM0b{MT5VY0x{Rn8AMv70O6l2G2nY|=_5bH;t_tG8MzsOLQ6~65R}maE004xC zfw}_FfbjqK`UR?udIg7oP}l!jf$+v5sE7Y0CGsNY}(UdrG^-`k6B3Gb=6{(N3r@bRn%)+j?~Q?MPguia^yUi9RZAt6 ze*Jzy85MgHD9=*dV>`X#bX4Fho76QoAt{us(plcP68?G;dYp6|HdEq9eyNbYZ|G6f zc2m|+zFj`zSlDM^uEY3 zBBGNJG-yq&s$IP82{c(`|_qok3Yis?TE7lUtnTGn_wa0{Pn;aC{!Gyl-W<(k? zTc@v-9NrHFvX(Q&W`53o;_`S9j(*e1qSY35^YJE>O@s@psk)cZ=!L{~FXEeWa!m%D2=-z(n= zebxHKR<{J07+wAPYN&qGy|skBT5H{PznO=)_ulmm(bbpPr)tU9F}}*T_;Fimy*O)? zkr7>&hmHK9-91*ftsPpz#wXn4+BV{37g}bwB(0uW!A`z*8tI`r-rTyfnGSC`Ho9;2 z6__DcBfHS1+l3y?7y(&>;+g+rm06l-w$ z$Ll?-ZM)l8Z%7}Bg3jY)VrlABRul5xzO{-Zt}3~os-tx;Y$N&{E>7deoh1@^k6uHG z=8IRh dW_+#Fqo&YSc7mw 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 b_(LUIU};yUviA{a6-)/api/oidc/callback`, and +the `openid`, `profile` and `email` scopes. The issuer is the application's, e.g. +`https://auth.example.com/application/o/terdut/`. Then set: + +```sh +TERDUT_PUBLIC_URL=https://terdut.example.com +TERDUT_OIDC_ISSUER=https://auth.example.com/application/o/terdut/ +TERDUT_OIDC_CLIENT_ID=terdut +TERDUT_OIDC_CLIENT_SECRET=... +TERDUT_OIDC_ALLOWED_GROUPS=terdut-users,terdut-admins +TERDUT_OIDC_ADMIN_GROUP=terdut-admins +``` + +Which team a group grants is not server-wide config: each team names its own +group(s), set by that team's own owner (or an administrator) from its Members +tab, or `PUT /api/teams/{teamID}/oidc-groups {"member_group":"sre","owner_group":"sre-leads"}`. +A team must already exist before a group can grant access to it — the sync +never creates one. + +The web UI's sign-in page shows a "Sign in with " button (a plain link to +`/api/oidc/login`) above the password form, or instead of it when +`TERDUT_PASSWORD_LOGIN=false`; it asks `GET /api/auth/config` what the server offers +(`password_login`, `oidc.enabled`, `oidc.name`). A refused sign-in comes back to that +page with the reason spelled out. Access the groups grant is badged **SSO** on the +Team, Admin and per-user pages, with its edit and remove controls disabled, and the +Account page does not offer to set a password nobody could use. + +**What a sign-in does** + +1. *Who.* The provider's `(issuer, subject)` is the identity. The first time, a + user is found by email — only when the provider marks it verified, or + `TERDUT_OIDC_TRUST_EMAIL` is set — or created with no password. A username taken + by somebody else gets a numeric suffix (`alice-2`). Username and email follow the + provider at each sign-in. Authentik reports `email_verified` as false unless + configured otherwise, so linking existing users usually needs + `TERDUT_OIDC_TRUST_EMAIL=true`. +2. *Whether.* With `TERDUT_OIDC_ALLOWED_GROUPS` set, somebody in none of them is + refused and nothing is created. +3. *What.* The administrator flag follows `TERDUT_OIDC_ADMIN_GROUP`. Team roles + follow each team's own `oidc_member_group`/`oidc_owner_group`; where both of a + team's groups match, the owner group wins. + +**Managed access.** What the sync grants is marked as managed by single sign-on, +and only that is ever changed by it. It is added at sign-in, and removed at the +next sign-in after the group is gone, even if that leaves a team without an owner +(an administrator can always repair a team) — the provider is the source of truth +for what it grants, so the last-owner and last-administrator guards do not apply. +Memberships and administrators added by hand are left alone; the exception is a +hand-added member whose team's own group grants a *higher* role, who is raised and +from then on managed. Editing managed access by hand (`POST` or `DELETE` on a +team's members, revoking an SSO-granted administrator) is refused with `409`, since +the next sign-in would undo it. + +> **Upgrading past migration 013: reconfigure every team's groups.** +> `TERDUT_OIDC_GROUP_MAPPINGS` is gone, and the sync no longer creates a team by +> name. Group-to-team-role mapping is now each team's own setting — an owner sets +> it from the Members tab, or `PUT /api/teams/{teamID}/oidc-groups`. Until a team's +> owner does that, an OIDC-sourced membership in it is dropped at that user's next +> SSO sign-in, the same as any other loss of group access. Set every team's groups +> before affected users next sign in, to avoid a visible gap in access. + +**How fast changes arrive.** Groups are read only at sign-in. A session made by an +SSO sign-in has a hard ceiling (`TERDUT_OIDC_SESSION_MAX_AGE`, default 12h) that +sliding never extends, so a change at the provider reaches terdut within that time. +Password sessions are unaffected. + +> **API keys are not revoked when somebody is removed at the provider.** terdut +> holds no refresh token and never asks the provider again, so a person removed +> from every allowed group loses their sessions within `TERDUT_OIDC_SESSION_MAX_AGE` +> and cannot sign in again, but keeps any API key they made (the TUI and scripts use +> them) until an administrator disables the user in terdut. + +**Signing in from a terminal.** A client with no browser of its own, such as the +TUI over SSH, signs in with a device code, run by terdut itself so the terminal +never talks to the provider: + +1. The terminal calls `POST /api/oidc/device` and shows the person a link + (`/device?code=XXXX-XXXX`) and the code. +2. On any device the person opens the link, signs in (by the provider or by + password, whatever the login page offers), sees the code and the account, and + presses **Approve**. Only a browser session can approve; an API key cannot. +3. The terminal polls `POST /api/oidc/device/token` every 5 seconds and is given the + ordinary `terdut_session` cookie once. A person who signs in through the provider + gets the same `TERDUT_OIDC_SESSION_MAX_AGE` ceiling on the terminal's session as + on their browser's. + +A login expires after 10 minutes. `GET /api/auth/config` reports `device_login`. + +**If the provider is down**, terdut still starts (discovery is fetched on first +use) and password login is the way in. With `TERDUT_PASSWORD_LOGIN=false` that way +is closed: set it back to `true`. The first administrator comes from the bootstrap +endpoint, and stays a manual administrator that no group can revoke; on an SSO-only +install set `bootstrap.enabled: false` in the chart if you don't want that account, +or keep it and never give it a password. diff --git a/docs/web-ui.md b/docs/web-ui.md new file mode 100644 index 0000000..5c20c3f --- /dev/null +++ b/docs/web-ui.md @@ -0,0 +1,90 @@ +# The web UI + +_What the web UI offers, how sign-in and sessions work, and the Team and Admin tabs._ Back to the [README](../README.md) and the [documentation index](./README.md). + +The server serves a web UI at `/`: the incident queue, each incident's alerts +and timeline with every action (acknowledge, assign, snooze, note, resolve, +archive), who is on call, the alert feed, and an *Account* tab for your own +password and the ntfy topic your pages go to. It is built for a phone first. On a phone +it navigates through a hamburger menu and has a sticky action bar, it follows the +system's dark mode, and it can be added to the home screen. From 900px wide it switches +to a sidebar with the queue and the incident side by side. The Stats page shows +incident counts, MTTA and MTTR, and alert frequency by name, hour and day over a +chosen range. + +You sign in with a username and password. Users have no password until one is +set, and a user without one can only use API keys: + +```bash +# an admin sets someone's first password with their API key +curl -X PUT http://localhost:8080/api/users/2/password \ + -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \ + -d '{"password": ""}' +``` + +After that, users change it themselves under *Account*. Changing your own +password requires the current one. + +How a browser stays signed in: + +- A successful login sets an `HttpOnly`, `SameSite=Lax` session cookie. It lasts + 30 days and slides forward while it is used, so an on-call phone stays signed + in. +- The cookie is marked `Secure` when `TERDUT_PUBLIC_URL` starts with `https://`, + so set it to the HTTPS address. TLS terminates at the gateway and the server + itself only ever sees plain HTTP. +- Requests authenticated by the cookie are checked for cross-origin use (Go's + `http.CrossOriginProtection`). That is the CSRF guard. Bearer-key clients are + not affected. +- Setting a password signs that user out everywhere else. +- Ten failed logins for one username within 15 minutes lock that username for + the rest of the window. + +With `TERDUT_PUBLIC_URL` set, tapping a push notification opens the incident in +the web UI (`/incidents/{id}`). + +A **Team** tab holds everything a team owns, in five sub-sections with a URL +each and a strip across the top to move between them: the on-call rota +(`/team/rota`), the membership (`/team/members`), the escalation ladder +(`/team/escalation`), the alert sources with their keys (`/team/sources`) and +the dead man's switches (`/team/deadman`). `/team` itself is an overview — who +is on call today, how many members and owners, how many ladder levels, how many +keys and how many switches — so a page fetches only what it shows. An owner +edits it; a member sees the same pages read-only, because the server refuses +their writes anyway. Somebody in more than one team picks between them above +the strip, since the choice changes the subject of all five. + +The rota is a month at a time, one coloured initial per day with a legend +underneath, and it says how many days are left uncovered — the question a rota +is read for is who holds which stretch, and a run of one colour answers it +where a list of dates does not. An owner taps a day to hand it to somebody or +empty it, and fills a whole shift from the range form folded in below. + +The **Admin** tab appears only for a system administrator, and holds what +belongs to the whole server rather than to one team. It has three sub-sections, +each with a URL of its own and a strip across the top to move between them: +every team (`/admin/teams`), every user (`/admin/users`), and the settings that +used to be environment variables (`/admin/settings`). `/admin` itself is an +overview — how many of each, and what each section is for. Adding somebody is +minting them an invite link into a team, rather than creating a bare account: +the person who accepts it picks their own password, so one never passes through +an administrator, and the link carries the team, so they land somewhere with a +queue in it. That happens on the team's own page, since an invite is a fact +about a team; the user list points there rather than asking which team beside a +form. + +A name in the team list opens **that team's page**, at `/admin/teams/{id}`: when it +was created, how many are in it and how much is open, a field to rename it, the +members with their roles, the invites into it, and deletion. The member list is the +one thing there that needed a new endpoint — `GET /api/teams/{id}/members` is +member-only and answers `404` to an administrator who is not in the team, which is +the rule and not an oversight, so the page reads `GET /api/admin/teams/{id}` instead. +An administrator still sees none of that team's incidents, alerts or rota. + +A name in the user list opens **that person's page**, at `/admin/users/{id}`: their +email and when they joined, where their notifications go, whether they are an +administrator, whether the account is disabled, the teams they are in with their +role in each, a password field for a first or forgotten one, and deletion. It is +the one place membership is edited from the person's side — the Team tab answers +"who is in this team", and answering "which teams is this person in" there means +visiting each team in turn. diff --git a/internal/db/migrations/001_baseline.sql b/internal/db/migrations/001_baseline.sql deleted file mode 100644 index 2cfb54e..0000000 --- a/internal/db/migrations/001_baseline.sql +++ /dev/null @@ -1,182 +0,0 @@ --- The Postgres baseline: the schema as it stood at the end of the SQLite line, --- in one file rather than ten. --- --- The ten SQLite migrations are in git history up to the commit that introduced --- this one, and they replay against nothing here: their shape was incremental --- (columns added, then dropped again in 008) and 008's backfill rewrote data --- that a Postgres install never had. An existing SQLite database is carried over --- by scripts/sqlite-to-postgres.go, which copies rows into this schema. --- --- Two conventions inherited deliberately: --- --- * Timestamps are BIGINT unix seconds, not timestamptz. Everything in Go --- already speaks epochs, and converting was a second change riding along --- with the port. Worth revisiting on its own. --- --- * Ids are GENERATED BY DEFAULT, not ALWAYS, so the migration script can --- insert rows with their original ids and keep every foreign key intact. --- setval at the end of the copy puts the sequences past them. - -CREATE TABLE users ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - username TEXT NOT NULL UNIQUE, - email TEXT NOT NULL UNIQUE, - created_at BIGINT NOT NULL DEFAULT FLOOR(EXTRACT(EPOCH FROM now()))::bigint, - -- Where this user's notifications go. NULL means they get none; incidents - -- assigned to them fall back to the configured fallback topic. - ntfy_topic TEXT, - -- NULL means the user has no password and can only use API keys. - password_hash TEXT -); - -CREATE TABLE api_keys ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE, - key_hash TEXT NOT NULL UNIQUE, - name TEXT NOT NULL, - created_at BIGINT NOT NULL DEFAULT FLOOR(EXTRACT(EPOCH FROM now()))::bigint, - last_used_at BIGINT -); - --- A session is a browser's credential, the cookie counterpart of an API key: --- only the hash of the token is stored. expires_at slides forward while the --- session is in use, so an on-call phone stays signed in. -CREATE TABLE sessions ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - token_hash TEXT NOT NULL UNIQUE, - user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE, - created_at BIGINT NOT NULL, - last_seen_at BIGINT NOT NULL, - expires_at BIGINT NOT NULL, - user_agent TEXT -); - -CREATE INDEX idx_sessions_user ON sessions(user_id); - --- The machine-owned signal record: what Alertmanager says is true right now. --- Workflow state lives on incidents, never here, because the webhook upsert owns --- these rows and would overwrite it. -CREATE TABLE alerts ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - fingerprint TEXT NOT NULL UNIQUE, - name TEXT NOT NULL, - status TEXT NOT NULL CHECK (status IN ('firing', 'resolved')), - labels JSONB NOT NULL DEFAULT '{}'::jsonb, - annotations JSONB NOT NULL DEFAULT '{}'::jsonb, - starts_at BIGINT NOT NULL, - ends_at BIGINT, - generator_url TEXT NOT NULL DEFAULT '', - received_at BIGINT NOT NULL DEFAULT FLOOR(EXTRACT(EPOCH FROM now()))::bigint, - archived_at BIGINT, - -- Why the alert left the firing state: 'alertmanager' when a resolved - -- webhook set it, 'expiry' when the sweeper inferred it from staleness. - resolution_source TEXT -); - -CREATE INDEX alerts_status_idx ON alerts(status); -CREATE INDEX alerts_name_idx ON alerts(name); -CREATE INDEX alerts_received_at_idx ON alerts(received_at DESC); -CREATE INDEX alerts_archived_at_idx ON alerts(archived_at); - -CREATE TABLE schedule_entries ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE, - date TEXT NOT NULL UNIQUE, -- YYYY-MM-DD; one person per day - created_at BIGINT NOT NULL DEFAULT FLOOR(EXTRACT(EPOCH FROM now()))::bigint -); - -CREATE INDEX schedule_entries_date_idx ON schedule_entries(date); - --- The human work item: what people acknowledge, assign, snooze, discuss and --- resolve. Correlation uses Alertmanager's own groupKey, so incidents follow the --- group_by routing tree the operator already tuned. -CREATE TABLE incidents ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - group_key TEXT NOT NULL, -- Alertmanager groupKey, opaque - title TEXT NOT NULL, -- rendered from group_labels - group_labels JSONB NOT NULL DEFAULT '{}'::jsonb, - status TEXT NOT NULL CHECK (status IN ('triggered', 'acknowledged', 'resolved')), - severity TEXT, -- highest `severity` label across firing members - triggered_at BIGINT NOT NULL, - acknowledged_by BIGINT REFERENCES users(id) ON DELETE SET NULL, - acknowledged_at BIGINT, - assigned_to BIGINT REFERENCES users(id) ON DELETE SET NULL, - snoozed_until BIGINT, - resolved_at BIGINT, - resolution_source TEXT, -- 'alerts' | 'manual' - archived_at BIGINT -); - --- Load-bearing: at most one OPEN incident per group_key. This is what makes --- "resolved incident + a new alert occurrence = a new incident" work, and it is --- the constraint the webhook's find-or-open lookup relies on. -CREATE UNIQUE INDEX incidents_open_group_key_idx ON incidents(group_key) WHERE resolved_at IS NULL; -CREATE INDEX incidents_status_idx ON incidents(status); -CREATE INDEX incidents_triggered_at_idx ON incidents(triggered_at DESC); -CREATE INDEX incidents_archived_at_idx ON incidents(archived_at); - --- Membership is historical, not a pointer on alerts: one alert row (one --- fingerprint) resolves and re-fires over time and belongs to a different --- incident each occurrence. -CREATE TABLE incident_alerts ( - incident_id BIGINT NOT NULL REFERENCES incidents(id) ON DELETE CASCADE, - alert_id BIGINT NOT NULL REFERENCES alerts(id) ON DELETE CASCADE, - added_at BIGINT NOT NULL DEFAULT FLOOR(EXTRACT(EPOCH FROM now()))::bigint, - PRIMARY KEY (incident_id, alert_id) -); - -CREATE INDEX incident_alerts_alert_id_idx ON incident_alerts(alert_id); - --- The timeline. Append-only, and the only history this server keeps: alert rows --- are mutated in place, so without this there is no record that anything --- happened. Notes are events too, so one query renders the whole story. -CREATE TABLE incident_events ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - incident_id BIGINT NOT NULL REFERENCES incidents(id) ON DELETE CASCADE, - -- triggered | alert_added | alert_resolved | acknowledged | unacknowledged - -- | assigned | snoozed | unsnoozed | resolved | note | notified | notify_failed - type TEXT NOT NULL, - user_id BIGINT REFERENCES users(id) ON DELETE SET NULL, -- NULL = the server acted - alert_id BIGINT REFERENCES alerts(id) ON DELETE SET NULL, - detail TEXT, - created_at BIGINT NOT NULL DEFAULT FLOOR(EXTRACT(EPOCH FROM now()))::bigint -); - -CREATE INDEX incident_events_incident_idx ON incident_events(incident_id, created_at); - --- Delivery is an outbox rather than an inline HTTP call: a POST made while --- holding the webhook's transaction would hold a connection open across a --- network round trip. The webhook inserts a row; the notifier goroutine --- delivers it. -CREATE TABLE notifications ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - incident_id BIGINT NOT NULL REFERENCES incidents(id) ON DELETE CASCADE, - -- Nullable: a notification sent to the fallback topic belongs to nobody, - -- because nobody was on call when the incident opened. - user_id BIGINT REFERENCES users(id) ON DELETE SET NULL, - topic TEXT NOT NULL, -- resolved at enqueue: who was on call then - kind TEXT NOT NULL CHECK (kind IN ('triggered', 'reminder', 'resolved')), - created_at BIGINT NOT NULL, - send_after BIGINT NOT NULL, -- retry backoff watermark - attempts BIGINT NOT NULL DEFAULT 0, - sent_at BIGINT, - last_error TEXT -- kept after the last attempt, for debugging -); - --- The delivery loop's only query: what is due and still unsent. -CREATE INDEX notifications_pending_idx ON notifications(send_after) WHERE sent_at IS NULL; --- Reminders and resolved notices both look up an incident's newest row. -CREATE INDEX notifications_incident_idx ON notifications(incident_id, id DESC); - --- A notification body is stored on the ntfy server and cached on the device, so --- a real API key must never appear in one. Each delivery mints its own token --- instead: one incident, one action, one day. -CREATE TABLE incident_ack_tokens ( - token_hash TEXT PRIMARY KEY, -- SHA-256 of the raw token, as with api_keys - incident_id BIGINT NOT NULL REFERENCES incidents(id) ON DELETE CASCADE, - user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE, - created_at BIGINT NOT NULL, - expires_at BIGINT NOT NULL -); - -CREATE INDEX incident_ack_tokens_expires_idx ON incident_ack_tokens(expires_at); diff --git a/internal/db/migrations/002_admin_role.sql b/internal/db/migrations/002_admin_role.sql deleted file mode 100644 index 99cc095..0000000 --- a/internal/db/migrations/002_admin_role.sql +++ /dev/null @@ -1,25 +0,0 @@ --- A system administrator role, and the first thing in this server that one user --- can do and another cannot. --- --- Until now every authenticated caller could create and delete users, set --- anybody's password and mint API keys for anybody — auth.go said so in a --- comment. That was defensible with one operator and a hand-made account; it is --- not once people sign themselves up (see #7). --- --- EVERY EXISTING USER BECOMES AN ADMIN. They already hold these powers, so --- this migration changes nobody's access: it names what is already true, and --- leaves demotion as a deliberate act somebody performs afterwards. The --- alternative — promoting only user 1 — would silently strip the others, and --- could leave an install whose only admin is an account nobody has a password --- for. --- --- New users are not admins: the column defaults to false, and the only ways to --- become one are this backfill, the bootstrap endpoint, or an existing admin --- granting it. -ALTER TABLE users ADD COLUMN is_admin BOOLEAN NOT NULL DEFAULT false; - -UPDATE users SET is_admin = true; - --- The queue's assignment dropdown and the on-call schedule read every user, and --- the admin screens in #5 will filter on this. -CREATE INDEX users_is_admin_idx ON users(is_admin) WHERE is_admin; diff --git a/internal/db/migrations/003_teams.sql b/internal/db/migrations/003_teams.sql deleted file mode 100644 index ea1358d..0000000 --- a/internal/db/migrations/003_teams.sql +++ /dev/null @@ -1,103 +0,0 @@ --- Teams: the unit of tenancy. Everything a person works on now belongs to one. --- --- Until this migration the install was one shared space — every user saw every --- alert and every incident, and the Alertmanager webhook was unauthenticated, so --- anything that could reach the port could open an incident for everybody. --- --- The shape, in one paragraph: a team owns its incidents, alerts, schedule and --- integrations. A user belongs to as many teams as they like, with a role in --- each: an `owner` configures the team, a `member` works its incidents. An --- integration key is what an alert arrives on, and the key is what says which --- team the alert belongs to. --- --- EVERYTHING EXISTING MOVES INTO ONE DEFAULT TEAM, and every existing user --- becomes an owner of it. That keeps an upgrade a no-op for the people using it: --- the same queue, the same schedule, the same incidents, with a name on them. - -CREATE TABLE teams ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - created_at BIGINT NOT NULL DEFAULT FLOOR(EXTRACT(EPOCH FROM now()))::bigint -); - --- role is free text with a CHECK rather than an enum, so adding a third role --- later is a migration and not a type rewrite. -CREATE TABLE team_members ( - team_id BIGINT NOT NULL REFERENCES teams(id) ON DELETE CASCADE, - user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE, - role TEXT NOT NULL CHECK (role IN ('owner', 'member')), - joined_at BIGINT NOT NULL DEFAULT FLOOR(EXTRACT(EPOCH FROM now()))::bigint, - PRIMARY KEY (team_id, user_id) -); - -CREATE INDEX team_members_user_idx ON team_members(user_id); - --- How alerts get in, and the only thing that says which team they belong to. --- The key is stored as a SHA-256 hash, like api_keys and the ack tokens: a --- leaked database gives nobody the ability to post alerts. -CREATE TABLE integrations ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - team_id BIGINT NOT NULL REFERENCES teams(id) ON DELETE CASCADE, - kind TEXT NOT NULL CHECK (kind IN ('alertmanager')), - name TEXT NOT NULL, - key_hash TEXT NOT NULL UNIQUE, - created_at BIGINT NOT NULL DEFAULT FLOOR(EXTRACT(EPOCH FROM now()))::bigint, - last_used_at BIGINT -); - -CREATE INDEX integrations_team_idx ON integrations(team_id); - --- --------------------------------------------------------------------------- --- The default team, and everything that already exists moving into it. --- --- Created unconditionally, even on an empty install, so there is always a team --- for the bootstrap user to land in and for the first integration to hang off. --- --------------------------------------------------------------------------- - -INSERT INTO teams (name) VALUES ('Default'); - -INSERT INTO team_members (team_id, user_id, role) -SELECT (SELECT id FROM teams WHERE name = 'Default'), id, 'owner' FROM users; - --- --------------------------------------------------------------------------- --- team_id on everything a team owns. --- --- Added nullable, backfilled, then made NOT NULL: adding a NOT NULL column with --- no default to a table with rows is rejected, and a DEFAULT pointing at the --- default team would quietly keep working after the default team is gone. --- --------------------------------------------------------------------------- - -ALTER TABLE alerts ADD COLUMN team_id BIGINT REFERENCES teams(id) ON DELETE CASCADE; -ALTER TABLE incidents ADD COLUMN team_id BIGINT REFERENCES teams(id) ON DELETE CASCADE; -ALTER TABLE schedule_entries ADD COLUMN team_id BIGINT REFERENCES teams(id) ON DELETE CASCADE; - -UPDATE alerts SET team_id = (SELECT id FROM teams WHERE name = 'Default'); -UPDATE incidents SET team_id = (SELECT id FROM teams WHERE name = 'Default'); -UPDATE schedule_entries SET team_id = (SELECT id FROM teams WHERE name = 'Default'); - -ALTER TABLE alerts ALTER COLUMN team_id SET NOT NULL; -ALTER TABLE incidents ALTER COLUMN team_id SET NOT NULL; -ALTER TABLE schedule_entries ALTER COLUMN team_id SET NOT NULL; - --- --------------------------------------------------------------------------- --- The uniqueness rules were all written for one tenant, and every one of them --- is wrong now: two teams monitoring two clusters legitimately see the same --- fingerprint, the same groupKey, and want somebody on call on the same day. --- --------------------------------------------------------------------------- - -ALTER TABLE alerts DROP CONSTRAINT alerts_fingerprint_key; -CREATE UNIQUE INDEX alerts_team_fingerprint_idx ON alerts(team_id, fingerprint); - -DROP INDEX incidents_open_group_key_idx; --- Still load-bearing, now per team: at most one OPEN incident per group_key --- within a team. This is what makes "resolved incident + a new alert occurrence --- = a new incident" work, and what the webhook's find-or-open lookup relies on. -CREATE UNIQUE INDEX incidents_open_group_key_idx - ON incidents(team_id, group_key) WHERE resolved_at IS NULL; - -ALTER TABLE schedule_entries DROP CONSTRAINT schedule_entries_date_key; -CREATE UNIQUE INDEX schedule_entries_team_date_idx ON schedule_entries(team_id, date); - --- The list views all filter by team first. -CREATE INDEX alerts_team_received_idx ON alerts(team_id, received_at DESC); -CREATE INDEX incidents_team_triggered_idx ON incidents(team_id, triggered_at DESC); diff --git a/internal/db/migrations/004_team_deadman.sql b/internal/db/migrations/004_team_deadman.sql deleted file mode 100644 index 3a066fd..0000000 --- a/internal/db/migrations/004_team_deadman.sql +++ /dev/null @@ -1,39 +0,0 @@ --- Dead man's switches become a team's own configuration. --- --- They were three environment variables — TERDUT_DEADMAN_MATCHERS, _TIMEOUT and --- _SEVERITY — which made them one setting for the whole install. That was the --- last piece of the alerting path a team could not control: a team could take --- its own alerts on its own key and still not say which of them were --- heartbeats, or how long a silence had to last before somebody was paged. --- --- One row per team rather than one row per switch. The unit of monitoring is --- still the fingerprint, as it always was — two clusters sending the same --- heartbeat alertname are two independent switches — and the matcher string --- keeps the format the environment variable used, so a value can be moved from --- one to the other unchanged. --- --- No rows are seeded here: a migration cannot read the environment. The server --- inserts a row per team at startup from its own configuration, and the same --- values therefore carry forward into the first team's row without anybody --- retyping them. See seedDeadmanConfigs. -CREATE TABLE deadman_configs ( - team_id BIGINT PRIMARY KEY REFERENCES teams(id) ON DELETE CASCADE, - - -- ";" separates matchers, "," the label conditions within one, "=" is exact - -- equality: `alertname=Watchdog,cluster=prod; alertname=EdgeHeartbeat`. - -- Every matcher must name an alertname. Empty watches nothing. - matchers TEXT NOT NULL DEFAULT '', - - -- Seconds rather than a Go duration string: the column is compared and - -- arithmetic is done on it, and a value that has to be parsed before it can - -- be believed is a value that can be stored unparseable. Zero disables the - -- team's switches entirely. - timeout_seconds BIGINT NOT NULL DEFAULT 0, - - -- The severity these incidents open at. They have no member alerts to - -- derive one from, and a heartbeat's own severity label is meaningless — - -- Watchdog ships as "none". - severity TEXT NOT NULL DEFAULT 'critical', - - updated_at BIGINT NOT NULL DEFAULT FLOOR(EXTRACT(EPOCH FROM now()))::bigint -); diff --git a/internal/db/migrations/005_settings.sql b/internal/db/migrations/005_settings.sql deleted file mode 100644 index c9e060c..0000000 --- a/internal/db/migrations/005_settings.sql +++ /dev/null @@ -1,35 +0,0 @@ --- Settings that an administrator can change without a redeploy, and the flag --- that takes an account out of use without deleting it. --- --- Three of the server's tunables were environment variables, which meant --- changing how long an incident waits before it is paged again required editing --- a chart, merging it, and waiting for a reconcile. They are behaviour, not --- infrastructure, and the difference is who needs to change them and how often. --- --- What stays in the environment: the ntfy URL and token, the database DSN, the --- listen address and the public URL. Those are where the server is plugged in --- rather than how it behaves, they are needed before the database is open, and --- two of them are credentials. --- --- Key/value rather than a column per setting. A settings table with one row and --- a column per knob needs a migration for every new knob, and #6 and #7 will --- both add some. The cost is that values are text and the accessor has to say --- what type it wanted; settings.go does that in one place. --- --- No rows are seeded here: a migration cannot read the environment. The server --- inserts each key from its own configuration at startup, once, so an install --- that upgrades keeps exactly the behaviour it had. See SeedSettings. -CREATE TABLE settings ( - key TEXT PRIMARY KEY, - value TEXT NOT NULL, - updated_at BIGINT NOT NULL DEFAULT FLOOR(EXTRACT(EPOCH FROM now()))::bigint -); - --- Disabling an account rather than deleting it: the person has left, or the --- credential is suspect, and their incidents, acknowledgements and timeline --- entries must stay exactly where they are. Deleting a user nulls their --- acknowledged_by and assigned_to, which quietly rewrites history. --- --- A disabled user cannot sign in and their API keys stop working, but they are --- still a name the timeline can show and still a member of their teams. -ALTER TABLE users ADD COLUMN disabled_at BIGINT; diff --git a/internal/db/migrations/006_escalation.sql b/internal/db/migrations/006_escalation.sql deleted file mode 100644 index 245567d..0000000 --- a/internal/db/migrations/006_escalation.sql +++ /dev/null @@ -1,95 +0,0 @@ --- Escalation: page somebody else when the first person does not answer. --- --- This is the gap the whole multi-tenancy line of work was opened to close. --- Until now an unacknowledged incident re-paged the same topic every --- notify_repeat forever, which is a louder version of the same silence: if the --- person on call is asleep, has no signal, or has left, nothing else happens. --- --- Shape: one policy per team, an ordered list of levels, each level with a --- timeout and a set of targets. When a level's timeout passes and the incident --- is still triggered, the next level is paged. When the last level passes, the --- chain repeats repeat_count times, and then the team's fallback topic is paged --- once as the end of the line. --- --- A team WITHOUT a policy keeps exactly today's behaviour: page the assignee, --- then remind on the same topic. Escalation is opt-in per team, and the two --- never both run for one incident -- see enqueueReminders. -CREATE TABLE escalation_policies ( - -- One per team for now, hence the team as the key rather than an id with a - -- unique index: routing different alerts to different chains needs the - -- alert to carry something to route ON, which is a separate question. - team_id BIGINT PRIMARY KEY REFERENCES teams(id) ON DELETE CASCADE, - - -- How many extra times to run the whole chain after it has been walked - -- once. 0 means walk it once and stop at the fallback. - repeat_count BIGINT NOT NULL DEFAULT 0 CHECK (repeat_count >= 0 AND repeat_count <= 10), - - -- Where the last page goes when every level has been tried. Per team now: - -- TERDUT_NTFY_FALLBACK_TOPIC was one topic for the whole install, which in - -- a multi-team server pages the wrong people. Empty means the chain simply - -- ends. - fallback_topic TEXT NOT NULL DEFAULT '', - - updated_at BIGINT NOT NULL DEFAULT FLOOR(EXTRACT(EPOCH FROM now()))::bigint -); - -CREATE TABLE escalation_levels ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - team_id BIGINT NOT NULL REFERENCES escalation_policies(team_id) ON DELETE CASCADE, - -- 1-based, dense. The API rewrites the whole ladder on every edit rather - -- than patching one rung, so there is no way to leave a gap. - position BIGINT NOT NULL, - -- How long this level has to produce an acknowledgement before the next one - -- is paged. Seconds, like every other duration in this schema. - timeout_seconds BIGINT NOT NULL CHECK (timeout_seconds > 0), - - UNIQUE (team_id, position) -); - --- Who a level pages. Either a named person, or whoever the team's rota says is --- on call today -- which is the target that keeps working when the rota --- changes and nobody remembers to edit the policy. -CREATE TABLE escalation_targets ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - level_id BIGINT NOT NULL REFERENCES escalation_levels(id) ON DELETE CASCADE, - kind TEXT NOT NULL CHECK (kind IN ('user', 'oncall')), - -- Set for kind='user', NULL for kind='oncall'. - user_id BIGINT REFERENCES users(id) ON DELETE CASCADE, - - CHECK ((kind = 'user' AND user_id IS NOT NULL) OR (kind = 'oncall' AND user_id IS NULL)) -); - -CREATE INDEX escalation_targets_level_idx ON escalation_targets(level_id); - --- --------------------------------------------------------------------------- --- Where an incident is in its chain. --- --- On the incident rather than in a side table: it is read on every notifier --- tick alongside the incident's status, and one row per incident is exactly --- what the state is. --- --------------------------------------------------------------------------- - --- 0 means no level has been paged yet, which is the state of every incident --- that existed before escalation and of every incident in a team with no --- policy. 1 is the first level. -ALTER TABLE incidents ADD COLUMN escalation_level BIGINT NOT NULL DEFAULT 0; - --- When the current level was entered, and therefore what its timeout is --- measured from. NULL while escalation_level is 0. -ALTER TABLE incidents ADD COLUMN escalation_level_at BIGINT; - --- How many times the chain has been walked in full. Compared against the --- policy's repeat_count. -ALTER TABLE incidents ADD COLUMN escalation_round BIGINT NOT NULL DEFAULT 0; - --- The notifier's escalation query: incidents still waiting, oldest level first. -CREATE INDEX incidents_escalation_idx - ON incidents(escalation_level_at) - WHERE resolved_at IS NULL AND status = 'triggered'; - --- 'escalated' joins the outbox kinds: a page that went out because nobody --- answered the last one, which is worth telling apart from the first page and --- from a reminder when reading the timeline or debugging a delivery. -ALTER TABLE notifications DROP CONSTRAINT notifications_kind_check; -ALTER TABLE notifications ADD CONSTRAINT notifications_kind_check - CHECK (kind IN ('triggered', 'reminder', 'resolved', 'escalated')); diff --git a/internal/db/migrations/007_signup_invites.sql b/internal/db/migrations/007_signup_invites.sql deleted file mode 100644 index c615353..0000000 --- a/internal/db/migrations/007_signup_invites.sql +++ /dev/null @@ -1,49 +0,0 @@ --- Self-service sign-up, and the invite links that make it useful. --- --- Until now the only way to get an account was for somebody who already had one --- to create it, and the login page told people to "ask an admin". That is a --- workable arrangement for one operator and an impossible one for a team. --- --- An invite is a link, not an email: this server has no SMTP and adding it to --- send one message would be a new subsystem to run, secure and monitor. The --- person inviting sends the link however they already talk to the person they --- are inviting. -CREATE TABLE invites ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - - -- SHA-256 of the raw token, like api_keys, the integration keys and the - -- acknowledgement tokens. A leaked database hands nobody an account. - token_hash TEXT NOT NULL UNIQUE, - - -- Which team the invitee lands in, and as what. An invite always names a - -- team: an account in no team sees an empty queue and can be paged by - -- nobody, which is not a state to invite somebody into. - team_id BIGINT NOT NULL REFERENCES teams(id) ON DELETE CASCADE, - role TEXT NOT NULL CHECK (role IN ('owner', 'member')), - - created_by BIGINT REFERENCES users(id) ON DELETE SET NULL, - created_at BIGINT NOT NULL DEFAULT FLOOR(EXTRACT(EPOCH FROM now()))::bigint, - - -- Invites expire. A link that works forever is a credential nobody - -- remembers issuing, sitting in a chat log. - expires_at BIGINT NOT NULL, - - -- Single-use by default: max_uses 1. A team onboarding six people at once - -- can raise it rather than minting six links. - max_uses BIGINT NOT NULL DEFAULT 1 CHECK (max_uses > 0 AND max_uses <= 100), - uses BIGINT NOT NULL DEFAULT 0, - - -- Revoked by hand, separately from expiry, so "this link is no longer - -- wanted" and "this link timed out" stay distinguishable in the listing. - revoked_at BIGINT -); - -CREATE INDEX invites_team_idx ON invites(team_id); - --- Who redeemed which invite. Kept after the invite is gone — the answer to "how --- did this account get here" should outlive the link that made it. -ALTER TABLE users ADD COLUMN invited_via BIGINT REFERENCES invites(id) ON DELETE SET NULL; - --- Where a person is in the first-run checklist, so it can be resumed and --- dismissed rather than nagging forever. One row per user, created on demand. -ALTER TABLE users ADD COLUMN onboarding_dismissed_at BIGINT; diff --git a/internal/db/migrations/008_incident_signature.sql b/internal/db/migrations/008_incident_signature.sql deleted file mode 100644 index 3e63b31..0000000 --- a/internal/db/migrations/008_incident_signature.sql +++ /dev/null @@ -1,23 +0,0 @@ --- Similar incidents: a signature per incident, so "has this happened before" --- is an indexed equality instead of a search. --- --- The signature is the alert name plus the group labels that identify WHAT is --- broken, minus the ones that only say WHERE it happened to run this time --- (instance, pod, ...). Two incidents with the same signature in the same team --- are the same problem for a responder's purposes. --- --- Computed in Go for new incidents (incidentSignature in incident_store.go). --- The backfill below MUST produce the same string; keep the volatile list in --- both places in step. -ALTER TABLE incidents ADD COLUMN signature TEXT NOT NULL DEFAULT ''; - -UPDATE incidents SET signature = - COALESCE(NULLIF(group_labels->>'alertname', ''), title) || '|' || - COALESCE(( - SELECT string_agg(e.k || '=' || e.v, ',' ORDER BY e.k) - FROM jsonb_each_text(incidents.group_labels) AS e(k, v) - WHERE e.k <> 'alertname' - AND e.k NOT IN ('instance', 'pod', 'pod_name', 'pod_ip', 'container', 'container_name', 'endpoint') - ), ''); - -CREATE INDEX incidents_signature_idx ON incidents(team_id, signature, triggered_at DESC); diff --git a/internal/db/migrations/009_deadman_switches.sql b/internal/db/migrations/009_deadman_switches.sql deleted file mode 100644 index e693d46..0000000 --- a/internal/db/migrations/009_deadman_switches.sql +++ /dev/null @@ -1,54 +0,0 @@ --- Dead man's switches become rows of their own. --- --- 004 kept a team's switches in one string with one timeout and one severity, --- which was enough to configure them and not enough to show them: there was no --- thing to list, nothing to hang a status on, and every switch in a team had to --- share a deadline. A row per switch gives each its own name, matcher, timeout --- and severity, and gives the Team → Switches page something to be a list of. --- --- The matcher keeps the syntax the string used, one matcher per row: --- `alertname=Watchdog,cluster=prod`. The unit of monitoring is still the --- fingerprint, so a matcher that many clusters satisfy is still one switch row --- watching several independent heartbeats. -CREATE TABLE deadman_switches ( - id BIGSERIAL PRIMARY KEY, - team_id BIGINT NOT NULL REFERENCES teams(id) ON DELETE CASCADE, - - -- What the owner calls it. Defaults to the matcher when they do not say. - name TEXT NOT NULL, - - -- "," separates the label conditions, "=" is exact equality, and alertname is - -- mandatory: it is what keeps the sweeper's candidate query on an index. - matcher TEXT NOT NULL, - - -- Seconds of silence before the switch is declared dead. Never zero: a switch - -- that cannot fire is deleted, not disabled. - timeout_seconds BIGINT NOT NULL CHECK (timeout_seconds > 0), - - -- The severity its incidents open at. See 004 for why they carry their own. - severity TEXT NOT NULL DEFAULT 'critical', - - created_at BIGINT NOT NULL DEFAULT FLOOR(EXTRACT(EPOCH FROM now()))::bigint -); - -CREATE INDEX deadman_switches_team_idx ON deadman_switches (team_id); - --- Carry every team's configuration over, one row per matcher. A team whose --- timeout was zero had switches turned off, which is now "no rows". -INSERT INTO deadman_switches (team_id, name, matcher, timeout_seconds, severity) -SELECT c.team_id, btrim(m), btrim(m), c.timeout_seconds, c.severity -FROM deadman_configs c, - LATERAL regexp_split_to_table(c.matchers, ';') AS m -WHERE c.timeout_seconds > 0 - AND btrim(m) <> '' -ORDER BY c.team_id; - --- The server seeds environment defaults into teams once, and remembers that it --- did. An install that had a row per team was already seeded; without this --- marker the first start after upgrading would seed teams that had switched --- theirs off. -INSERT INTO settings (key, value) -SELECT 'deadman_seeded', '1' -WHERE EXISTS (SELECT 1 FROM deadman_configs); - -DROP TABLE deadman_configs; diff --git a/internal/db/migrations/010_alert_source.sql b/internal/db/migrations/010_alert_source.sql deleted file mode 100644 index f397fad..0000000 --- a/internal/db/migrations/010_alert_source.sql +++ /dev/null @@ -1,21 +0,0 @@ --- Which alert source an alert last arrived on. --- --- Team -> Sources shows when each source last posted, which integrations --- already knew (last_used_at, stamped on every webhook). What it could not say --- was what a source delivered: an alert never recorded the key it came in on, so --- "prod alertmanager" and "staging alertmanager" were indistinguishable once --- inside. This column is that link, and lets the page show each source's last --- alert and how many alerts it has kept fresh over the past day. --- --- Last sender wins: every accepted payload restamps it, the way it advances --- received_at. Two sources posting the same fingerprint into one team is --- already one alert, and it is attributed to whichever spoke last. --- --- Nullable, and not backfilled. Alerts that arrived before this migration have --- no source, and NULL says so honestly rather than guessing. It heals by itself: --- Alertmanager re-sends every alert each repeat_interval, and each re-send is an --- accepted payload. Deleting a source keeps its alerts, unattributed. -ALTER TABLE alerts ADD COLUMN integration_id BIGINT REFERENCES integrations(id) ON DELETE SET NULL; - -CREATE INDEX alerts_integration_idx ON alerts (integration_id, received_at) - WHERE integration_id IS NOT NULL; diff --git a/internal/db/migrations/011_oidc.sql b/internal/db/migrations/011_oidc.sql deleted file mode 100644 index 557d72c..0000000 --- a/internal/db/migrations/011_oidc.sql +++ /dev/null @@ -1,60 +0,0 @@ --- Single sign-on through an OpenID Connect provider (Authentik, and anything --- else that speaks OIDC). --- --- Four things change, and none of them touches a password user: every new column --- has a default that says "this is how it has always worked". --- --- 1. user_identities says which provider account a user is. It is keyed on --- (issuer, subject), never on email or username: those are mutable at the --- provider, and a recycled address must not inherit somebody's account. A --- user can have several identities (a second provider later), and none at all --- (a local, password-only user), which is why this is a table and not two --- columns on users. --- --- 2. team_members.source and users.admin_source record who granted a role. 'oidc' --- rows are owned by the group sync: it adds them when a group grants access --- and removes them when it stops, and nothing else may edit them. 'manual' rows --- are everything that existed before this migration, and are never touched by --- the sync. Without the marker the sync could not tell a membership it created --- from one an owner added by hand, and would have to either leave stale access --- behind or delete people it had no business deleting. --- --- 3. sessions.max_expires_at is a hard ceiling on a session's life. Ordinary --- sessions slide for as long as they are used; a session made by an SSO login --- must not, because the login is the only moment the groups are re-read. --- Capping the session is what makes "removed from the group in the provider" --- take effect within a bounded time. NULL means no ceiling. --- --- 4. oidc_logins holds a login that has been started and not yet finished: the --- state, nonce and PKCE verifier the callback must see again. A row rather --- than a signed cookie, so it survives a restart and needs no signing key. --- Only the hash of the state is stored, like every other token here; the --- nonce and verifier are useless without the state that names the row. -CREATE TABLE user_identities ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE, - issuer TEXT NOT NULL, - subject TEXT NOT NULL, - created_at BIGINT NOT NULL DEFAULT FLOOR(EXTRACT(EPOCH FROM now()))::bigint, - last_login_at BIGINT NOT NULL DEFAULT FLOOR(EXTRACT(EPOCH FROM now()))::bigint, - UNIQUE (issuer, subject) -); - -CREATE INDEX user_identities_user_idx ON user_identities (user_id); - -ALTER TABLE team_members - ADD COLUMN source TEXT NOT NULL DEFAULT 'manual' CHECK (source IN ('manual', 'oidc')); - -ALTER TABLE users - ADD COLUMN admin_source TEXT NOT NULL DEFAULT 'manual' CHECK (admin_source IN ('manual', 'oidc')); - -ALTER TABLE sessions ADD COLUMN max_expires_at BIGINT; - -CREATE TABLE oidc_logins ( - state_hash TEXT PRIMARY KEY, - nonce TEXT NOT NULL, - pkce_verifier TEXT NOT NULL, - expires_at BIGINT NOT NULL -); - -CREATE INDEX oidc_logins_expires_idx ON oidc_logins (expires_at); diff --git a/internal/db/migrations/012_device_login.sql b/internal/db/migrations/012_device_login.sql deleted file mode 100644 index 1764e62..0000000 --- a/internal/db/migrations/012_device_login.sql +++ /dev/null @@ -1,40 +0,0 @@ --- Signing in from a terminal, for clients that cannot open a browser on the --- machine they run on (the TUI over SSH is the reason). --- --- The flow is the OAuth device authorization grant, run by terdut itself rather --- than the identity provider, so the terminal never talks to the provider and --- the server issues its ordinary session at the end: --- --- 1. The terminal asks for a login and gets two secrets: a device code it --- keeps and polls with, and a short user code it shows the person. --- 2. The person opens the verification URL on any device, signs in by whatever --- means the server offers, sees the user code, and approves it. --- 3. The terminal's next poll finds the row approved and is given a session. --- --- Only the hash of the device code is stored, like every other token here: the --- device code is what earns a session, so a database read must not yield one. --- The user code is shown on screens and typed by people, so it is stored as is; --- on its own it can only be approved, never redeemed. --- --- user_id is the person who approved. It is empty until then, and the session --- is minted at redemption, not at approval: an approval nobody collects must not --- leave a live session lying about. --- --- last_polled_at lets the server refuse a client that polls faster than the --- interval it was told. -CREATE TABLE device_logins ( - device_hash TEXT PRIMARY KEY, - user_code TEXT NOT NULL UNIQUE, - status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'approved', 'denied')), - user_id BIGINT REFERENCES users(id) ON DELETE CASCADE, - expires_at BIGINT NOT NULL, - last_polled_at BIGINT NOT NULL DEFAULT 0 -); - -CREATE INDEX device_logins_expires_idx ON device_logins (expires_at); - --- Where to send the browser once a single sign-on login completes. A person who --- opens /device?code=... without a session has to sign in first and then come --- back to it, and the same is true of any other deep link. Validated when it is --- stored: only a path on this server is ever kept. -ALTER TABLE oidc_logins ADD COLUMN next TEXT NOT NULL DEFAULT '/'; diff --git a/internal/db/migrations/013_oidc_team_groups.sql b/internal/db/migrations/013_oidc_team_groups.sql deleted file mode 100644 index d269402..0000000 --- a/internal/db/migrations/013_oidc_team_groups.sql +++ /dev/null @@ -1,26 +0,0 @@ --- Per-team OIDC group configuration, replacing the global --- TERDUT_OIDC_GROUP_MAPPINGS env var. --- --- Group -> team -> role used to be one global list an operator set for the --- whole install, matched against a team by name, and the sync would create --- the team if no team by that name existed yet. That put the decision of --- which group controls a team in the server's environment rather than the --- team's own hands, meant changing it needed an env var edit and a restart, --- and let a typo in a team name silently create a stray team. --- --- Each team now names, itself, which group grants membership and which --- grants ownership. Nullable: most teams need neither. No uniqueness --- constraint on either column — two teams may legitimately watch the same --- provider group (a broad team and a narrower one both keyed off overlapping --- groups is a choice for their owners to make, not one the schema should --- refuse). --- --- BREAKING CHANGE, deliberately not auto-migrated: TERDUT_OIDC_GROUP_MAPPINGS --- stops being read as of this version, and the sync no longer creates a team --- by name. Every team's group binding must be set again through --- PUT /api/teams/{teamID}/oidc-groups. Until an owner does that, an --- OIDC-sourced membership in that team is dropped at that user's next SSO --- sign-in, the same way any other loss of group access is handled. See the --- README's OIDC section. -ALTER TABLE teams ADD COLUMN oidc_member_group TEXT; -ALTER TABLE teams ADD COLUMN oidc_owner_group TEXT; diff --git a/internal/db/migrations/014_service_accounts.sql b/internal/db/migrations/014_service_accounts.sql deleted file mode 100644 index bd93644..0000000 --- a/internal/db/migrations/014_service_accounts.sql +++ /dev/null @@ -1,43 +0,0 @@ --- Service accounts: a scoped, non-human credential for automation (e.g. --- terdut-operator) that needs to manage teams, escalation policies, dead --- man's switches, integrations and OIDC group bindings without impersonating --- a human user. See SERVICE-ACCOUNTS.md for the design this implements. --- --- Deliberately not a users row: no password_hash, no is_admin, no --- user_identities linkage, so a service account can never be pulled into --- OIDC group sync or password login, and is never mistaken for a human in an --- audit trail. --- --- scope is 'instance' (acts with the same reach system administration has --- over teams: create one, list them, mint a 'team'-scoped account against --- any of them) or 'team' (acts as that one team's owner, and nothing else). --- The CHECK ties team_id's presence to scope directly, rather than leaving it --- to application code to keep the two consistent. -CREATE TABLE service_accounts ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - scope TEXT NOT NULL CHECK (scope IN ('instance', 'team')), - team_id BIGINT REFERENCES teams(id) ON DELETE CASCADE, - created_by BIGINT REFERENCES users(id) ON DELETE SET NULL, - created_at BIGINT NOT NULL DEFAULT FLOOR(EXTRACT(EPOCH FROM now()))::bigint, - CONSTRAINT service_accounts_scope_team_id_chk CHECK ( - (scope = 'team' AND team_id IS NOT NULL) OR - (scope = 'instance' AND team_id IS NULL) - ) -); - -CREATE INDEX service_accounts_team_id_idx ON service_accounts(team_id); - --- One account, many keys: rotation is minting a new one and revoking the --- old, the same shape api_keys already has, so an account's identity and --- audit history survive a rotation instead of being recreated by it. -CREATE TABLE service_account_keys ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - service_account_id BIGINT NOT NULL REFERENCES service_accounts(id) ON DELETE CASCADE, - key_hash TEXT NOT NULL UNIQUE, - name TEXT NOT NULL, - created_at BIGINT NOT NULL DEFAULT FLOOR(EXTRACT(EPOCH FROM now()))::bigint, - last_used_at BIGINT -); - -CREATE INDEX service_account_keys_service_account_id_idx ON service_account_keys(service_account_id); diff --git a/internal/db/migrations/015_incident_service_account_actors.sql b/internal/db/migrations/015_incident_service_account_actors.sql deleted file mode 100644 index b225f34..0000000 --- a/internal/db/migrations/015_incident_service_account_actors.sql +++ /dev/null @@ -1,39 +0,0 @@ --- Service-account actors on incident mutations (terdut-server#25). A --- team-scoped service account acknowledging/resolving/snoozing/noting an --- incident is not a users row, so it cannot be written into --- acknowledged_by/incident_events.user_id — doing so either violates the --- users(id) FK (new rows) or, for incident_events.user_id, silently matches --- zero rows on delete. These columns are the service-account-shaped parallel --- to the existing human ones: nullable, mutually exclusive with their human --- counterpart, ON DELETE SET NULL so a deleted service account doesn't take --- the incident history with it. -ALTER TABLE incidents - ADD COLUMN acknowledged_by_service_account_id BIGINT - REFERENCES service_accounts(id) ON DELETE SET NULL; - -ALTER TABLE incident_events - ADD COLUMN service_account_id BIGINT - REFERENCES service_accounts(id) ON DELETE SET NULL; - --- At most one actor kind per row: both NULL ("the server acted") is valid, --- exactly one set is valid, both set is a bug this constraint refuses to --- store rather than silently accepting. -ALTER TABLE incidents - ADD CONSTRAINT incidents_ack_actor_xor_chk CHECK ( - acknowledged_by IS NULL OR acknowledged_by_service_account_id IS NULL - ); - -ALTER TABLE incident_events - ADD CONSTRAINT incident_events_actor_xor_chk CHECK ( - user_id IS NULL OR service_account_id IS NULL - ); - -CREATE INDEX incidents_acknowledged_by_service_account_id_idx - ON incidents(acknowledged_by_service_account_id); -CREATE INDEX incident_events_service_account_id_idx - ON incident_events(service_account_id); - --- assigned_to_service_account_id is deliberately not added here: it would sit --- unpopulated until handleIncidentAssign itself tracks an actor, which is a --- separate, pre-existing gap (it records the assignee today, never the --- actor, for humans either) tracked in its own follow-up issue. diff --git a/internal/db/migrations/016_rate_limit_counters.sql b/internal/db/migrations/016_rate_limit_counters.sql deleted file mode 100644 index 5553401..0000000 --- a/internal/db/migrations/016_rate_limit_counters.sql +++ /dev/null @@ -1,16 +0,0 @@ --- Backs the rate limiters (failed logins, sign-ups, OIDC/device start) with --- Postgres instead of an in-memory map, now that the server runs more than --- one replica in production (v0.37.0): a counter that only ever sees its own --- pod's traffic quietly let every one of these limits through multiplied by --- the replica count. --- --- window_start is the start of the current fixed window for key, in the same --- "unix seconds" shape every other timestamp in this schema uses. The window --- resets rather than slides, matching the in-memory limiter it replaces: --- once a key's window is older than the limiter's window length, the next --- failure starts a fresh one instead of extending the stale one. -CREATE TABLE rate_limit_counters ( - key TEXT PRIMARY KEY, - window_start BIGINT NOT NULL, - count INT NOT NULL -); diff --git a/internal/db/migrations/017_api_key_expiry.sql b/internal/db/migrations/017_api_key_expiry.sql deleted file mode 100644 index 17f8ab5..0000000 --- a/internal/db/migrations/017_api_key_expiry.sql +++ /dev/null @@ -1,7 +0,0 @@ --- Optional expiry on a user's own API keys. NULL (the existing default for --- every row already in this table) means "never expires" -- the same --- behavior these keys have always had, so no existing integration breaks. --- Service account keys are deliberately NOT touched: they are a different --- table, managed by automation, and already distinguished by their own --- "tdsa_" prefix. -ALTER TABLE api_keys ADD COLUMN expires_at BIGINT; diff --git a/internal/db/migrations/018_incident_event_actor.sql b/internal/db/migrations/018_incident_event_actor.sql deleted file mode 100644 index cfee52f..0000000 --- a/internal/db/migrations/018_incident_event_actor.sql +++ /dev/null @@ -1,21 +0,0 @@ --- Who performed an assignment (terdut-server#35). On an 'assigned' event --- incident_events.user_id is the assignee, so the actor needs columns of its --- own. Only populated for 'assigned' events; every other event type keeps --- using user_id/service_account_id for the actor. Older 'assigned' rows stay --- NULL (the actor was never recorded). Same shape as migration 015: nullable, --- mutually exclusive, ON DELETE SET NULL. --- --- assigned_to_service_account_id is still deliberately not added: making --- service accounts assignable is a separate change (request body, assignee --- picker, notifier, filters). -ALTER TABLE incident_events - ADD COLUMN actor_user_id BIGINT REFERENCES users(id) ON DELETE SET NULL, - ADD COLUMN actor_service_account_id BIGINT REFERENCES service_accounts(id) ON DELETE SET NULL; - -ALTER TABLE incident_events - ADD CONSTRAINT incident_events_assign_actor_xor_chk CHECK ( - actor_user_id IS NULL OR actor_service_account_id IS NULL - ); - -CREATE INDEX incident_events_actor_user_id_idx ON incident_events(actor_user_id); -CREATE INDEX incident_events_actor_service_account_id_idx ON incident_events(actor_service_account_id); -- 2.52.0 From 9029d48584fc86b0c0fbc1e897616ddc6baacde4 Mon Sep 17 00:00:00 2001 From: Niklas Ye Date: Fri, 9 Oct 2026 14:56:13 +0200 Subject: [PATCH 2/4] Let an operator authenticate with a seeded key, and reset the schema - TERDUT_OPERATOR_KEY creates or re-keys the instance-scoped service account "terdut-operator" at every start, so terdut-operator needs no bootstrap handshake. An instance-scoped account now acts as owner of every team's configuration, but is not a member of any team. - POST /api/teams takes an external_id (instance service accounts only) and is idempotent on it, so automation finds its own team again after a crash instead of adopting by display name. GET /api/teams?name= is removed. - Integration and dead man's switch names are unique per team (409). The escalation PUT accepts usernames and resolves them itself. - The 18 migrations are squashed into 001_schema.sql, with no Default team. TERDUT_DEADMAN_* and the env seeding of switches are removed: teams carry their own. Existing development databases must be recreated. Security and robustness: - GET /api/users no longer returns other people's email or ntfy topic to non-admins. - The access log records the route pattern, so integration keys and ack tokens in the path are not written to the log. Server errors are logged. - Rate limits take the client address TERDUT_TRUSTED_PROXIES hops from the right of X-Forwarded-For instead of trusting the first, forgeable entry. - /api/bootstrap runs in a transaction under an advisory lock, so two concurrent calls cannot both create an administrator. - API key last_used_at is written at most every five minutes. Cleanup: remove GET /api/incidents/{id}/alerts, unused exports, SQLite remnants in comments and config. Claude-Session: https://claude.ai/code/session_016mBLURvJoMuUEr9cB2RpUN --- .gitea/workflows/ci.yaml | 4 +- .gitignore | 2 - Makefile | 2 +- .../terdut-server/templates/deployment.yaml | 8 +- charts/terdut-server/values.yaml | 47 +- cmd/terdut/main.go | 13 +- internal/api/alertmanager.go | 2 +- internal/api/alerts.go | 6 +- internal/api/api_test.go | 43 +- internal/api/archiver.go | 4 +- internal/api/auth.go | 56 +- internal/api/caller.go | 21 +- internal/api/deadman.go | 112 ---- internal/api/deadman_test.go | 31 +- internal/api/device.go | 22 +- internal/api/escalation.go | 42 +- internal/api/escalation_test.go | 42 ++ internal/api/export_test.go | 31 + internal/api/helpers.go | 29 +- internal/api/incidents.go | 74 +-- internal/api/incidents_test.go | 3 +- internal/api/middleware.go | 80 ++- internal/api/notifier.go | 2 +- internal/api/notify_ack.go | 4 +- internal/api/oidc.go | 6 +- internal/api/oidc_teams.go | 4 +- internal/api/operator_key.go | 72 +++ internal/api/operator_key_test.go | 134 ++++ internal/api/router.go | 14 +- internal/api/schedule.go | 20 +- internal/api/service_accounts.go | 19 +- internal/api/settings.go | 28 +- internal/api/signup.go | 32 +- internal/api/similar.go | 2 +- internal/api/stats.go | 25 +- internal/api/teams.go | 172 ++--- internal/api/teams_test.go | 115 ++-- internal/api/testdb_test.go | 5 +- internal/api/users.go | 93 ++- internal/config/config.go | 71 ++- internal/db/db.go | 8 +- internal/db/migrations/001_schema.sql | 587 ++++++++++++++++++ internal/models/alert.go | 4 +- internal/models/team.go | 4 + internal/oidc/grants.go | 3 - internal/web/static/js/format.js | 2 +- 46 files changed, 1445 insertions(+), 655 deletions(-) create mode 100644 internal/api/export_test.go create mode 100644 internal/api/operator_key.go create mode 100644 internal/api/operator_key_test.go create mode 100644 internal/db/migrations/001_schema.sql diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml index 693ad74..3111081 100644 --- a/.gitea/workflows/ci.yaml +++ b/.gitea/workflows/ci.yaml @@ -46,8 +46,8 @@ jobs: - go-build-cache:/root/.cache/go-build - gobin-cache:/go/bin - # The suite needs a real Postgres -- there is no in-memory Postgres the way there was - # an in-memory SQLite, so each test gets its own schema on a shared server instead. + # The suite needs a real Postgres -- there is no in-memory Postgres, + # so each test gets its own schema on a shared server instead. # The job and the service share the dind bridge, so the service is reachable by its # name rather than on localhost. services: diff --git a/.gitignore b/.gitignore index aa08c62..31709d7 100644 --- a/.gitignore +++ b/.gitignore @@ -7,8 +7,6 @@ # one (which has an unreachable entry) cannot abort a release /.helm-repos.yaml -# SQLite database files -*.db *.db-shm *.db-wal diff --git a/Makefile b/Makefile index 3f9b660..d284c30 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ help: ## Show this help # -race below. Both need a Postgres to test against; see test-db. # The suite needs a Postgres, because the server does: there is no in-memory -# Postgres the way there was an in-memory SQLite. TERDUT_TEST_DSN says where, and +# Postgres. TERDUT_TEST_DSN says where, and # the tests fail rather than skip without it — a suite that quietly tests nothing # is worse than one that does not run. `make test-db` starts a local one; # ci.yaml runs the same thing as a service container. diff --git a/charts/terdut-server/templates/deployment.yaml b/charts/terdut-server/templates/deployment.yaml index 15557d6..49acee1 100644 --- a/charts/terdut-server/templates/deployment.yaml +++ b/charts/terdut-server/templates/deployment.yaml @@ -95,12 +95,6 @@ spec: value: "{{ .Values.sweeper.staleAfter }}" - name: TERDUT_ARCHIVE_AFTER value: "{{ .Values.sweeper.archiveAfter }}" - - name: TERDUT_DEADMAN_MATCHERS - value: "{{ .Values.deadman.matchers }}" - - name: TERDUT_DEADMAN_TIMEOUT - value: "{{ .Values.deadman.timeout }}" - - name: TERDUT_DEADMAN_SEVERITY - value: "{{ .Values.deadman.severity }}" {{- if .Values.notify.ntfyUrl }} - name: TERDUT_NTFY_URL value: "{{ .Values.notify.ntfyUrl }}" @@ -122,6 +116,8 @@ spec: value: "{{ .Values.notify.publicUrl | default (printf "https://%s" .Values.networking.hostname) }}" - name: TERDUT_PASSWORD_LOGIN value: {{ .Values.passwordLogin | quote }} + - name: TERDUT_TRUSTED_PROXIES + value: {{ .Values.trustedProxies | quote }} - name: TERDUT_OPERATOR_MODE value: {{ .Values.operatorMode | quote }} {{- if .Values.oidc.enabled }} diff --git a/charts/terdut-server/values.yaml b/charts/terdut-server/values.yaml index 64d3de4..e084c23 100644 --- a/charts/terdut-server/values.yaml +++ b/charts/terdut-server/values.yaml @@ -72,43 +72,10 @@ sweeper: # How long a resolved alert stays in the default list before auto-archiving. archiveAfter: 168h -# Alerts treated as dead man's switches: receiving one opens no incident, and -# the absence of one does. The Watchdog alert kube-prometheus-stack ships is -# exactly this — an always-firing alert whose only value is something noticing -# when it stops. -deadman: - # Which alerts to treat as heartbeats. ";" separates matchers, "," separates - # the label conditions within one, "=" is exact equality. Every matcher must - # name an alertname: - # alertname=Watchdog,cluster=prod; alertname=EdgeHeartbeat - # Each distinct label set is watched independently, so two clusters sending - # the same alertname are two switches and a live one cannot mask a dead one. - matchers: "alertname=Watchdog" - # How long a heartbeat may go unheard before its switch is declared dead. - # - # This must be SHORTER than the Alertmanager repeat_interval of the route - # carrying the heartbeat — the opposite of sweeper.staleAfter. The default - # repeat_interval of 4h (12h in many setups) makes for a useless dead man's - # switch, so give the heartbeat a route of its own: - # - # - matchers: [ 'alertname = "Watchdog"' ] - # receiver: terdut - # group_wait: 0s - # group_interval: 1m - # repeat_interval: 1m - # - # That delivers every 2m rather than every 1m: a group is only reconsidered - # each group_interval, and at exactly one elapsed interval repeat_interval has - # not quite passed, so equal values give 2x. Fine against 15m; use - # group_interval: 30s if you want a true 1m. - # - # Set to 0 to disable dead man's switch handling entirely. - timeout: 15m - # Severity a dead man's switch incident opens at. These incidents have no - # member alerts to derive one from, and the heartbeat's own severity label is - # meaningless — Watchdog ships as "none". Only "critical" maps to the ntfy - # priority that overrides a phone's quiet hours. - severity: critical +# How many reverse proxies in front of the server append to X-Forwarded-For. +# The per-address login/sign-up rate limits take the client address that many +# entries from the right. 0 ignores the header. +trustedProxies: 1 notify: # ntfy server that push notifications are published to, e.g. @@ -190,10 +157,8 @@ oidc: # Hard ceiling on a session made by a single sign-on login. sessionMaxAge: 12h -# Backups are no longer this chart's business. The SQLite database lived on a PVC -# beside the app, so it needed a sidecar with a sqlite3 module for k8up to exec a -# dump in; Postgres is backed up where it runs, through a k8up.io/backupcommand -# pg_dump annotation on the database pod itself. +# Backups are not this chart's business: Postgres is backed up where it runs, +# through a k8up.io/backupcommand pg_dump annotation on the database pod itself. bootstrap: enabled: true diff --git a/cmd/terdut/main.go b/cmd/terdut/main.go index 2997f5c..08d8661 100644 --- a/cmd/terdut/main.go +++ b/cmd/terdut/main.go @@ -39,21 +39,16 @@ func main() { RepeatEvery: cfg.NotifyRepeat, } - // Dead man's switches live per team now. The environment variables are the - // defaults a team starts from: every team without a configuration of its - // own gets one from them here, and an owner's later edit is never - // overwritten by a redeploy. - deadman := api.ParseDeadmanConfig(cfg.DeadmanMatchers, cfg.DeadmanTimeout, cfg.DeadmanSeverity) - if err := api.SeedDeadmanConfigs(context.Background(), database, deadman); err != nil { - log.Fatalf("seed dead man's switch defaults: %v", err) - } - // The behaviour knobs move into the database on first start, after which an // administrator owns them and a redeploy leaves them alone. if err := api.SeedSettings(context.Background(), database, cfg); err != nil { log.Fatalf("seed settings: %v", err) } + if err := api.SeedOperatorKey(context.Background(), database, cfg.OperatorKey); err != nil { + log.Fatalf("%v", err) + } + router := api.NewRouter(database, notify, cfg, version) srv := &http.Server{ diff --git a/internal/api/alertmanager.go b/internal/api/alertmanager.go index 071684b..7e3cc39 100644 --- a/internal/api/alertmanager.go +++ b/internal/api/alertmanager.go @@ -87,7 +87,7 @@ func handleIntegrationWebhook(db *sql.DB, notify NotifyConfig) http.HandlerFunc respond(w, http.StatusUnauthorized, errResp("unknown integration key")) return } - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } receiveWebhook(w, r, db, notify, src) diff --git a/internal/api/alerts.go b/internal/api/alerts.go index a2b0b2b..5bdecf1 100644 --- a/internal/api/alerts.go +++ b/internal/api/alerts.go @@ -90,7 +90,7 @@ func handleListAlerts(db *sql.DB) http.HandlerFunc { fmt.Sprintf("%s WHERE %s ORDER BY a.received_at DESC LIMIT %s", alertSelectFrom, clause, args.add(limit)), args.all()...) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } defer rows.Close() @@ -99,7 +99,7 @@ func handleListAlerts(db *sql.DB) http.HandlerFunc { for rows.Next() { a, err := scanAlert(rows) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } alerts = append(alerts, a) @@ -121,7 +121,7 @@ func handleGetAlert(db *sql.DB) http.HandlerFunc { return } if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, a) diff --git a/internal/api/api_test.go b/internal/api/api_test.go index ec26d42..bae9c57 100644 --- a/internal/api/api_test.go +++ b/internal/api/api_test.go @@ -78,6 +78,10 @@ func newTSWith(t *testing.T, deadman api.DeadmanConfig, cfg api.NotifyConfig, co s := &ts{Server: srv, key: key, db: database, notify: cfg, deadman: deadman} + // A fresh install has no team, so the tests that want "the" team make it + // here: it is id 1, owned by the admin, which is what defaultTeam names. + decode(t, s.req(t, http.MethodPost, "/api/teams", map[string]string{"name": "Default"}), &struct{}{}) + var integration struct { Key string `json:"key"` } @@ -768,7 +772,7 @@ func TestWebhook_IgnoresOutOfOrderRetry(t *testing.T) { // An expiry resolve writes ends_at as an upper bound, not an observed end: an // Alertmanager watermark already on the row is preserved, and a row that never // carried one is stamped at sweep time. Clients are told to read it that way — -// see "resolution_source says how much to trust ends_at" in the README. +// see "resolution_source says how much to trust ends_at" in docs/api.md. func TestExpiry_EndsAtIsUpperBound(t *testing.T) { s := newTS(t) @@ -813,7 +817,7 @@ func TestExpiry_EndsAtIsUpperBound(t *testing.T) { // // received_at is documented as a public liveness signal, so these lock the // behaviour clients are told they may rely on. See "received_at is a liveness -// heartbeat" in the README and the comment on models.Alert.ReceivedAt. +// heartbeat" in docs/api.md and the comment on models.Alert.ReceivedAt. // --------------------------------------------------------------------------- // The heartbeat itself: an unchanged firing notification — what Alertmanager @@ -875,3 +879,38 @@ func TestStats_ByDayReturnsSevenSlots(t *testing.T) { t.Errorf("expected 7 day slots, got %d", len(slots)) } } + +// Two simultaneous bootstraps on an empty install must not both win. +func TestBootstrap_ConcurrentCallsCreateOneAdmin(t *testing.T) { + database := newTestDB(t) + srv := httptest.NewServer(api.NewRouter(database, api.NotifyConfig{}, testConfig(), "test")) + t.Cleanup(srv.Close) + + const n = 8 + codes := make(chan int, n) + for i := 0; i < n; i++ { + go func(i int) { + body, _ := json.Marshal(map[string]string{"username": fmt.Sprintf("u%d", i), "email": fmt.Sprintf("u%d@x.com", i)}) + resp, err := http.Post(srv.URL+"/api/bootstrap", "application/json", bytes.NewReader(body)) + if err != nil { + codes <- 0 + return + } + resp.Body.Close() + codes <- resp.StatusCode + }(i) + } + created := 0 + for i := 0; i < n; i++ { + if <-codes == http.StatusCreated { + created++ + } + } + var users int + if err := database.QueryRow("SELECT COUNT(*) FROM users").Scan(&users); err != nil { + t.Fatal(err) + } + if created != 1 || users != 1 { + t.Errorf("expected exactly one bootstrap to win, got %d created and %d users", created, users) + } +} diff --git a/internal/api/archiver.go b/internal/api/archiver.go index 6759596..b99df7c 100644 --- a/internal/api/archiver.go +++ b/internal/api/archiver.go @@ -154,9 +154,7 @@ func expireStale(ctx context.Context, db *sql.DB, staleAfter time.Duration, skip } // staleAlertIDs reads the ids in one go and closes the cursor before the caller -// writes. Under SQLite's single connection an open read would have blocked the -// update outright; with a pool it is no longer a deadlock, but reading the set -// first still keeps the write off a cursor the same transaction is walking. +// writes, which keeps the write off a cursor the same transaction is walking. func staleAlertIDs(ctx context.Context, db *sql.DB, now time.Time, staleAfter time.Duration) ([]int64, error) { rows, err := db.QueryContext(ctx, ` SELECT id FROM alerts diff --git a/internal/api/auth.go b/internal/api/auth.go index 804f4d5..100acfb 100644 --- a/internal/api/auth.go +++ b/internal/api/auth.go @@ -10,6 +10,7 @@ import ( "strconv" "strings" "sync" + "sync/atomic" "time" "github.com/go-chi/chi/v5" @@ -28,6 +29,9 @@ const ( // sessionTouchEvery bounds how often a request may slide the expiry. sessionTouchEvery = time.Hour + // keyTouchEvery is the same bound for an API key's last_used_at. + keyTouchEvery = 5 * time.Minute + minPasswordLen = 10 // maxPasswordLen is bcrypt's limit; it rejects longer input outright. maxPasswordLen = 72 @@ -126,14 +130,32 @@ func purgeRateLimits(ctx context.Context, db *sql.DB) { } } +// trustedProxies is how many X-Forwarded-For hops clientAddr trusts. Set once +// by NewRouter from config. +var trustedProxies atomic.Int32 + // clientAddr is the address a login is counted against. Behind the gateway -// RemoteAddr is the gateway itself, so the first X-Forwarded-For hop is used -// when present. It can be forged, but only to dodge the address limit; the -// per-username limit does not depend on it. +// RemoteAddr is the gateway itself, so the client address is read from +// X-Forwarded-For, counting trustedProxies entries from the right: each trusted +// proxy appends the address it saw, so the entries to the left of those are +// client-supplied and could be forged to dodge the limit. func clientAddr(r *http.Request) string { - if xff := r.Header.Get("X-Forwarded-For"); xff != "" { - first, _, _ := strings.Cut(xff, ",") - return strings.TrimSpace(first) + if n := int(trustedProxies.Load()); n > 0 { + var hops []string + for _, v := range r.Header.Values("X-Forwarded-For") { + for _, h := range strings.Split(v, ",") { + if h = strings.TrimSpace(h); h != "" { + hops = append(hops, h) + } + } + } + if len(hops) > 0 { + i := len(hops) - n + if i < 0 { + i = 0 + } + return hops[i] + } } host, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { @@ -241,7 +263,7 @@ func handleLogin(db *sql.DB, limiter *loginLimiter, publicURL string) http.Handl "SELECT id, password_hash FROM users WHERE username = $1", username, ).Scan(&userID, &hash) if err != nil && !errors.Is(err, sql.ErrNoRows) { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } @@ -258,13 +280,13 @@ func handleLogin(db *sql.DB, limiter *loginLimiter, publicURL string) http.Handl limiter.clear(r.Context(), userKey) if err := startSession(w, r, db, userID, publicURL); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } user, err := fetchUser(r.Context(), db, userID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, meResponse{User: user, HasPassword: true}) @@ -320,7 +342,7 @@ func handleMe(db *sql.DB) http.HandlerFunc { } user, err := fetchUser(r.Context(), db, caller.ID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } var hash sql.NullString @@ -332,7 +354,7 @@ func handleMe(db *sql.DB) http.HandlerFunc { // transient database problem, not a missing user — worth a 500 // rather than silently answering "no password, not dismissed", // which a client would otherwise take at face value. - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, meResponse{ @@ -384,7 +406,7 @@ func handleSetPassword(db *sql.DB) http.HandlerFunc { return } if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } @@ -397,30 +419,30 @@ func handleSetPassword(db *sql.DB) http.HandlerFunc { hash, err := hashPassword(req.Password) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } tx, err := db.BeginTx(r.Context(), nil) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } defer tx.Rollback() if _, err := tx.ExecContext(r.Context(), "UPDATE users SET password_hash = $1 WHERE id = $2", hash, id); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } keep, _ := sessionFromContext(r.Context()) // zero when changed with an API key if _, err := tx.ExecContext(r.Context(), "DELETE FROM sessions WHERE user_id = $1 AND id != $2", id, keep); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if err := tx.Commit(); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } w.WriteHeader(http.StatusNoContent) diff --git a/internal/api/caller.go b/internal/api/caller.go index 95501de..a656445 100644 --- a/internal/api/caller.go +++ b/internal/api/caller.go @@ -2,7 +2,6 @@ package api import ( "context" - "fmt" "git.ryuvia.com/niklas/terdut-server/internal/models" ) @@ -61,7 +60,7 @@ func (c Caller) IsAdmin() bool { // by being a human (and becomes its owner as a side effect), an // instance-scoped service account creates one with no human owner at all; // the two paths are not interchangeable, so this predicate must not also -// admit a human admin the way MayActAsInstanceAdmin deliberately does. +// admit a human admin the way an administrator check would. func (c Caller) IsInstanceServiceAccount() bool { return c.sa != nil && c.sa.scope == models.ServiceAccountScopeInstance } @@ -110,24 +109,6 @@ func (c Caller) ServiceAccountName() (string, bool) { return c.sa.name, true } -// Identity is a stable, log/audit-facing string distinguishing a human -// caller from a service account — "user:42" or "service-account:7". Not -// wired into any database column — incidents.go's acknowledged_by/ -// incident_events.user_id use AsHuman()/ServiceAccountID() directly against -// the parallel *_service_account_id columns (migration 015) instead, since a -// column needs the id, not this rendered string. assigned_to stays -// human-only and out of scope (terdut-server#25's follow-up). -func (c Caller) Identity() string { - switch { - case c.user != nil: - return fmt.Sprintf("user:%d", c.user.ID) - case c.sa != nil: - return fmt.Sprintf("service-account:%d", c.sa.id) - default: - return "unknown" - } -} - func callerFromContext(ctx context.Context) (Caller, bool) { c, ok := ctx.Value(ctxCaller).(Caller) return c, ok diff --git a/internal/api/deadman.go b/internal/api/deadman.go index 70bbd01..6b813f0 100644 --- a/internal/api/deadman.go +++ b/internal/api/deadman.go @@ -65,28 +65,6 @@ func (m DeadmanMatcher) matches(labels map[string]string) bool { return true } -// DeadmanConfig is the server-wide default a team's switches are seeded from: -// the environment's matchers, timeout and severity. Switches themselves are rows -// of a team's own — see DeadmanSwitch — and this is only how a fresh install -// starts out. -type DeadmanConfig struct { - Matchers []DeadmanMatcher - - // Timeout is how long a matched alert may go without a refreshing webhook - // before it is declared dead. It must be shorter than Alertmanager's - // repeat_interval for the heartbeat's route, which is what refreshes it. - // Zero disables dead man's switch handling entirely. - Timeout time.Duration - - // Severity is the severity every dead man's switch incident opens at. These - // incidents have no member alerts to derive one from, and the heartbeat's - // own severity label is meaningless — Watchdog ships as "none". - Severity string -} - -// enabled reports whether there is anything to watch. -func (c DeadmanConfig) enabled() bool { return c.Timeout > 0 && len(c.Matchers) > 0 } - // DeadmanSwitch inverts the handling of the alerts it matches: receiving one // opens nothing, and the absence of one opens an incident. // @@ -160,46 +138,6 @@ func parseDeadmanMatcher(entry string) (DeadmanMatcher, error) { return m, nil } -// ParseDeadmanConfig reads the matcher list from its configured form: -// ";" separates matchers, and each is parsed as parseDeadmanMatcher does. -// -// A malformed or alertname-less entry is dropped rather than fatal, following -// config.duration's rule that one bad tuning knob should not take the server -// down. Silence would be worse here than elsewhere, though — a typo that -// disarms the switch is exactly the failure this feature exists to catch — so -// the matchers that survived are logged. -func ParseDeadmanConfig(matchers string, timeout time.Duration, severity string) DeadmanConfig { - cfg := DeadmanConfig{Timeout: timeout, Severity: severity} - - for _, entry := range strings.Split(matchers, ";") { - entry = strings.TrimSpace(entry) - if entry == "" { - continue - } - m, err := parseDeadmanMatcher(entry) - if err != nil { - log.Printf("deadman: ignoring matcher %q: %v", entry, err) - continue - } - cfg.Matchers = append(cfg.Matchers, m) - } - - switch { - case timeout <= 0: - log.Print("deadman: disabled (timeout is zero)") - case len(cfg.Matchers) == 0: - log.Print("deadman: disabled (no usable matchers)") - default: - rendered := make([]string, 0, len(cfg.Matchers)) - for _, m := range cfg.Matchers { - rendered = append(rendered, m.String()) - } - log.Printf("deadman: default for new teams: %s, timeout %s, severity %s", - strings.Join(rendered, "; "), timeout, severity) - } - return cfg -} - // deadmanAlert is one heartbeat: the alert row carrying its last sighting, and // the switch that claimed it. type deadmanAlert struct { @@ -490,56 +428,6 @@ func deadmanSets(ctx context.Context, db *sql.DB) (map[int64]deadmanSet, error) return scanDeadmanSwitches(rows) } -// deadmanSeededKey is the settings row that records the environment defaults -// were handed out. Without it, a team that deleted its last switch would get -// the default back on the next restart. -const deadmanSeededKey = "deadman_seeded" - -// SeedDeadmanConfigs gives every team the server's environment defaults as -// switches, exactly once per install, so a fresh install watches Watchdog -// without anybody setting it up. -// -// Once seeded it never runs again: a team's switches are its own, and a redeploy -// must not quietly put the environment's value back over an owner's edit or -// deletion. Installs that upgraded from per-team configuration were already -// seeded, which migration 009 records. -// -// A team created after that gets none and watches nothing until its owner says -// otherwise. That is deliberate: inheriting an install-wide heartbeat would page -// a new team about a source it has never heard of, and a switch nobody chose is -// the kind that gets muted rather than fixed. -func SeedDeadmanConfigs(ctx context.Context, db *sql.DB, cfg DeadmanConfig) error { - if !cfg.enabled() { - return nil - } - - tx, err := db.BeginTx(ctx, nil) - if err != nil { - return err - } - defer tx.Rollback() //nolint:errcheck - - res, err := tx.ExecContext(ctx, - "INSERT INTO settings (key, value) VALUES ($1, '1') ON CONFLICT (key) DO NOTHING", - deadmanSeededKey) - if err != nil { - return err - } - if n, _ := res.RowsAffected(); n == 0 { - return nil - } - - for _, m := range cfg.Matchers { - if _, err := tx.ExecContext(ctx, ` - INSERT INTO deadman_switches (team_id, name, matcher, timeout_seconds, severity) - SELECT id, $1, $1, $2, $3 FROM teams`, - m.config(), int64(cfg.Timeout.Seconds()), cfg.Severity); err != nil { - return err - } - } - return tx.Commit() -} - // --------------------------------------------------------------------------- // Status // --------------------------------------------------------------------------- diff --git a/internal/api/deadman_test.go b/internal/api/deadman_test.go index 4d6d172..485be77 100644 --- a/internal/api/deadman_test.go +++ b/internal/api/deadman_test.go @@ -1,7 +1,6 @@ package api_test import ( - "context" "net/http" "strings" "testing" @@ -122,8 +121,11 @@ func TestDeadman_MixedGroupExcludesHeartbeat(t *testing.T) { t.Fatalf("expected 1 incident for the real alert, got %d", got) } - var alerts []map[string]any - decode(t, s.req(t, http.MethodGet, "/api/incidents/1/alerts", nil), &alerts) + var incident struct { + Alerts []map[string]any `json:"alerts"` + } + decode(t, s.req(t, http.MethodGet, "/api/incidents/1", nil), &incident) + alerts := incident.Alerts if len(alerts) != 1 { t.Fatalf("expected 1 member alert, got %d", len(alerts)) } @@ -717,26 +719,3 @@ func TestDeadman_DeleteIsScopedToTheTeam(t *testing.T) { t.Errorf("expected no switches, got %d", got) } } - -// The environment's defaults are handed out once and then belong to the teams. -func TestDeadman_SeedRunsOnce(t *testing.T) { - s := newTS(t) - cfg := api.ParseDeadmanConfig("alertname=Watchdog", time.Hour, "critical") - - if err := api.SeedDeadmanConfigs(context.Background(), s.db, cfg); err != nil { - t.Fatalf("seed: %v", err) - } - if got := len(listSwitches(t, s)); got != 1 { - t.Fatalf("the first seed should add the default, got %d switches", got) - } - - // The owner deletes it; a restart must not put it back. - id := int64(listSwitches(t, s)[0]["id"].(float64)) - s.req(t, http.MethodDelete, "/api/teams/"+defaultTeam+"/deadman/switches/"+id64(id), nil).Body.Close() - if err := api.SeedDeadmanConfigs(context.Background(), s.db, cfg); err != nil { - t.Fatalf("seed again: %v", err) - } - if got := len(listSwitches(t, s)); got != 0 { - t.Errorf("a second seed resurrected %d switch(es)", got) - } -} diff --git a/internal/api/device.go b/internal/api/device.go index d694b50..120dad9 100644 --- a/internal/api/device.go +++ b/internal/api/device.go @@ -81,7 +81,7 @@ func handleDeviceStart(db *sql.DB, limiter *loginLimiter, publicURL string) http deviceCode, deviceHash, err := randomToken() if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } @@ -105,7 +105,7 @@ func handleDeviceStart(db *sql.DB, limiter *loginLimiter, publicURL string) http } if err != nil { log.Printf("device login: start: %v", err) - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } @@ -160,7 +160,7 @@ func handleDeviceDecision(db *sql.DB, approve bool) http.HandlerFunc { WHERE user_code = $3 AND status = 'pending' AND expires_at > $4`, status, caller.ID, code, time.Now().Unix()) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if n, _ := res.RowsAffected(); n == 0 { @@ -190,7 +190,7 @@ func handleDeviceToken(db *sql.DB, ssoMaxAge time.Duration, publicURL string) ht tx, err := db.BeginTx(r.Context(), nil) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } defer tx.Rollback() //nolint:errcheck @@ -206,7 +206,7 @@ func handleDeviceToken(db *sql.DB, ssoMaxAge time.Duration, publicURL string) ht return } if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } @@ -226,11 +226,11 @@ func handleDeviceToken(db *sql.DB, ssoMaxAge time.Duration, publicURL string) ht } if _, err := tx.ExecContext(r.Context(), "UPDATE device_logins SET last_polled_at = $1 WHERE device_hash = $2", now.Unix(), hash); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if err := tx.Commit(); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusAccepted, map[string]string{"status": "pending"}) @@ -240,7 +240,7 @@ func handleDeviceToken(db *sql.DB, ssoMaxAge time.Duration, publicURL string) ht // Approved. Single use: the row goes before the session is made, so two // racing polls cannot both be given one. if _, err := tx.ExecContext(r.Context(), "DELETE FROM device_logins WHERE device_hash = $1", hash); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } var disabled, sso bool @@ -252,7 +252,7 @@ func handleDeviceToken(db *sql.DB, ssoMaxAge time.Duration, publicURL string) ht return } if err := tx.Commit(); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if disabled { @@ -269,12 +269,12 @@ func handleDeviceToken(db *sql.DB, ssoMaxAge time.Duration, publicURL string) ht } if err := startSessionCapped(w, r, db, userID.Int64, publicURL, maxAge); err != nil { log.Printf("device login: start session: %v", err) - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } user, err := fetchUser(r.Context(), db, userID.Int64) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, meResponse{User: user, HasPassword: false}) diff --git a/internal/api/escalation.go b/internal/api/escalation.go index 59c3a84..ed3275c 100644 --- a/internal/api/escalation.go +++ b/internal/api/escalation.go @@ -3,6 +3,7 @@ package api import ( "context" "database/sql" + "errors" "log" "net/http" "strconv" @@ -343,12 +344,12 @@ func handleGetEscalation(db *sql.DB) http.HandlerFunc { policy, err := loadEscalationPolicy(r.Context(), db, teamID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } view, err := escalationStatus(r.Context(), db, teamID, policy) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, view) @@ -543,6 +544,10 @@ type escalationLevelJSON struct { type escalationTargetJSON struct { Kind string `json:"kind"` UserID *int64 `json:"user_id,omitempty"` + // Username is accepted in place of user_id on a PUT, and resolved to the + // id before anything is stored. It is never returned: the stored form is + // the id, which survives a rename. + Username string `json:"username,omitempty"` } type escalationJSON struct { @@ -600,6 +605,27 @@ func handleSetEscalation(db *sql.DB) http.HandlerFunc { return } for i, l := range req.Levels { + for j, t := range l.Targets { + if t.Username == "" { + continue + } + if t.Kind != "user" || t.UserID != nil { + respond(w, http.StatusBadRequest, errResp("username belongs on a user target, instead of user_id")) + return + } + var id int64 + err := db.QueryRowContext(r.Context(), "SELECT id FROM users WHERE username = $1", t.Username).Scan(&id) + if errors.Is(err, sql.ErrNoRows) { + respond(w, http.StatusBadRequest, errResp("unknown user "+strconv.Quote(t.Username))) + return + } + if err != nil { + serverError(w, r, err) + return + } + req.Levels[i].Targets[j].UserID = &id + req.Levels[i].Targets[j].Username = "" + } if l.TimeoutSeconds <= 0 { respond(w, http.StatusBadRequest, errResp("every level needs a timeout")) return @@ -632,7 +658,7 @@ func handleSetEscalation(db *sql.DB) http.HandlerFunc { tx, err := db.BeginTx(r.Context(), nil) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } defer tx.Rollback() //nolint:errcheck @@ -645,13 +671,13 @@ func handleSetEscalation(db *sql.DB) http.HandlerFunc { fallback_topic = excluded.fallback_topic, updated_at = excluded.updated_at`, teamID, req.RepeatCount, req.FallbackTopic); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } // The levels are replaced, not merged; the cascade takes the targets. if _, err := tx.ExecContext(r.Context(), "DELETE FROM escalation_levels WHERE team_id = $1", teamID); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } @@ -661,7 +687,7 @@ func handleSetEscalation(db *sql.DB) http.HandlerFunc { INSERT INTO escalation_levels (team_id, position, timeout_seconds) VALUES ($1, $2, $3) RETURNING id`, teamID, int64(i+1), l.TimeoutSeconds).Scan(&levelID); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } for _, t := range l.Targets { @@ -676,13 +702,13 @@ func handleSetEscalation(db *sql.DB) http.HandlerFunc { } if err := tx.Commit(); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } policy, err := loadEscalationPolicy(r.Context(), db, teamID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, escalationResponse(policy, teamID)) diff --git a/internal/api/escalation_test.go b/internal/api/escalation_test.go index 39a428a..e36f96f 100644 --- a/internal/api/escalation_test.go +++ b/internal/api/escalation_test.go @@ -502,3 +502,45 @@ func TestEscalation_StatusWithoutALadder(t *testing.T) { t.Errorf("a team with no ladder should read as empty, got %+v", v) } } + +// A user target may name the person instead of carrying an id; the server +// resolves it and stores the id. +func TestEscalation_UserTargetByUsername(t *testing.T) { + s := newTS(t) + id := teamUser(t, s, "alice", "") + + put := func(username string) *http.Response { + return s.req(t, http.MethodPut, "/api/teams/"+defaultTeam+"/escalation", map[string]any{ + "repeat_count": 0, + "levels": []map[string]any{{ + "timeout_seconds": 300, + "targets": []map[string]any{{"kind": "user", "username": username}}, + }}, + }) + } + + resp := put("alice") + resp.Body.Close() + if resp.StatusCode >= 300 { + t.Fatalf("PUT by username: %d", resp.StatusCode) + } + var got struct { + Levels []struct { + Targets []struct { + UserID *int64 `json:"user_id"` + Username string `json:"username"` + } `json:"targets"` + } `json:"levels"` + } + decode(t, s.req(t, http.MethodGet, "/api/teams/"+defaultTeam+"/escalation", nil), &got) + if len(got.Levels) != 1 || len(got.Levels[0].Targets) != 1 || + got.Levels[0].Targets[0].UserID == nil || *got.Levels[0].Targets[0].UserID != id { + t.Errorf("expected the target stored as user %d, got %+v", id, got) + } + + bad := put("nobody") + bad.Body.Close() + if bad.StatusCode != http.StatusBadRequest { + t.Errorf("unknown username should be a 400, got %d", bad.StatusCode) + } +} diff --git a/internal/api/export_test.go b/internal/api/export_test.go new file mode 100644 index 0000000..9928297 --- /dev/null +++ b/internal/api/export_test.go @@ -0,0 +1,31 @@ +package api + +import ( + "strings" + "time" +) + +// DeadmanConfig is a test fixture only: a set of matchers with one timeout and +// severity, turned into switches over the API by the test helpers. Production +// has no server-wide default any more -- switches belong to teams. +type DeadmanConfig struct { + Matchers []DeadmanMatcher + Timeout time.Duration + Severity string +} + +// ParseDeadmanConfig reads a ";"-separated matcher list the way the removed +// environment variable did, dropping malformed entries. +func ParseDeadmanConfig(matchers string, timeout time.Duration, severity string) DeadmanConfig { + cfg := DeadmanConfig{Timeout: timeout, Severity: severity} + for _, entry := range strings.Split(matchers, ";") { + entry = strings.TrimSpace(entry) + if entry == "" { + continue + } + if m, err := parseDeadmanMatcher(entry); err == nil { + cfg.Matchers = append(cfg.Matchers, m) + } + } + return cfg +} diff --git a/internal/api/helpers.go b/internal/api/helpers.go index 4ea7dcd..1b73b51 100644 --- a/internal/api/helpers.go +++ b/internal/api/helpers.go @@ -5,6 +5,7 @@ import ( "database/sql" "encoding/json" "errors" + "github.com/go-chi/chi/v5" "log" "net/http" "strconv" @@ -17,8 +18,7 @@ import ( // sqlArgs accumulates query arguments and hands back the placeholder for each. // // Postgres numbers its placeholders, so a dynamically assembled WHERE clause has -// to keep its $1, $2, … in step with the order of the values — which SQLite's -// positional `?` did for free. Handing out the placeholder and storing the value +// to keep its $1, $2, … in step with the order of the values. Handing out the placeholder and storing the value // in one call is what keeps them in step: a filter can be added, removed or // reordered without renumbering anything by hand. type sqlArgs struct{ vals []any } @@ -31,8 +31,7 @@ func (a *sqlArgs) add(v any) string { // addList stores every value and returns their placeholders as "$1, $2, …", // ready to drop into an IN (…) clause. Returns an empty string for no values, -// which no caller should reach: `IN ()` is a syntax error in Postgres as it was -// in SQLite, so callers check for an empty set before building the query. +// which no caller should reach: `IN ()` is a syntax error in Postgres, so callers check for an empty set before building the query. func (a *sqlArgs) addList(vs []any) string { parts := make([]string, len(vs)) for i, v := range vs { @@ -45,7 +44,7 @@ func (a *sqlArgs) addList(vs []any) string { func (a *sqlArgs) all() []any { return a.vals } // nowEpoch is the SQL expression for "now, as unix seconds", matching how every -// timestamp in this schema is stored. SQLite spelled it unixepoch(). +// timestamp in this schema is stored. // // FLOOR, not a bare cast: EXTRACT returns fractional seconds and casting to // bigint rounds half up, so a row written at .6 of a second would claim a @@ -56,11 +55,9 @@ const nowEpoch = "FLOOR(EXTRACT(EPOCH FROM now()))::bigint" // isUniqueViolation reports whether err is a broken unique constraint, which // callers turn into 409 Conflict rather than 500. // -// Postgres reports it as SQLSTATE 23505 on a typed error; the SQLite driver this -// replaced only put "UNIQUE constraint failed" in the message, which is why the -// check used to be a substring match. Matching the code means a renamed -// constraint or a translated message cannot quietly turn a conflict back into a -// 500. +// Postgres reports it as SQLSTATE 23505 on a typed error. Matching the code +// means a renamed constraint or a translated message cannot quietly turn a +// conflict back into a 500. func isUniqueViolation(err error) bool { var pgErr *pgconn.PgError return errors.As(err, &pgErr) && pgErr.Code == pgerrcode.UniqueViolation @@ -72,6 +69,18 @@ func respond(w http.ResponseWriter, status int, v any) { json.NewEncoder(w).Encode(v) } +// serverError answers 500 and logs why. The response stays opaque, so the log +// line is the only record of what failed. +func serverError(w http.ResponseWriter, r *http.Request, err error) { + // The route pattern, not the path: two routes carry a credential in it. + route := r.URL.Path + if rc := chi.RouteContext(r.Context()); rc != nil && rc.RoutePattern() != "" { + route = rc.RoutePattern() + } + log.Printf("%s %s: %v", r.Method, route, err) + respond(w, http.StatusInternalServerError, errResp("internal error")) +} + // maxBodyBytes caps an ordinary JSON request body. 1 MiB is far more than any // endpoint below needs — it exists so an unauthenticated caller (signup, // login, bootstrap) can't make the server buffer an arbitrarily large body diff --git a/internal/api/incidents.go b/internal/api/incidents.go index 19c12a1..50cc9ac 100644 --- a/internal/api/incidents.go +++ b/internal/api/incidents.go @@ -37,7 +37,7 @@ func handleListClusters(db *sql.DB) http.HandlerFunc { label, strings.Join(where, " AND ")), args.all()...) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } defer rows.Close() @@ -46,13 +46,13 @@ func handleListClusters(db *sql.DB) http.HandlerFunc { for rows.Next() { var v string if err := rows.Scan(&v); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } clusters = append(clusters, v) } if err := rows.Err(); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, clusters) @@ -138,7 +138,7 @@ func handleListIncidents(db *sql.DB) http.HandlerFunc { incidentSelectFrom, strings.Join(where, " AND "), order, args.add(limit)), args.all()...) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } defer rows.Close() @@ -147,13 +147,13 @@ func handleListIncidents(db *sql.DB) http.HandlerFunc { for rows.Next() { i, err := scanIncident(rows) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } incidents = append(incidents, i) } if err := rows.Err(); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, incidents) @@ -172,35 +172,17 @@ func handleGetIncident(db *sql.DB) http.HandlerFunc { return } if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if inc.Alerts, err = incidentAlerts(r, db, id); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, inc) } } -func handleIncidentAlerts(db *sql.DB) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - id, ok := incidentIDParam(w, r, db) - if !ok { - return - } - if !incidentExists(w, r, db, id) { - return - } - alerts, err := incidentAlerts(r, db, id) - if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) - return - } - respond(w, http.StatusOK, alerts) - } -} - func handleIncidentTimeline(db *sql.DB) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { id, ok := incidentIDParam(w, r, db) @@ -225,7 +207,7 @@ func handleIncidentTimeline(db *sql.DB) http.HandlerFunc { WHERE e.incident_id = $1 ORDER BY e.created_at ASC, e.id ASC`, id) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } defer rows.Close() @@ -239,14 +221,14 @@ func handleIncidentTimeline(db *sql.DB) http.HandlerFunc { &e.ActorUserID, &e.ActorUsername, &e.ActorServiceAccountID, &e.ActorServiceAccountName, &e.AlertID, &e.Detail, &ts); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } e.CreatedAt = time.Unix(ts, 0).UTC() events = append(events, e) } if err := rows.Err(); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, events) @@ -262,7 +244,7 @@ func handleIncidentAcknowledge(db *sql.DB) http.HandlerFunc { userID, saID := callerActorIDs(r.Context()) acked, err := acknowledgeIncidentAs(r.Context(), db, id, userID, saID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if !acked { @@ -272,7 +254,7 @@ func handleIncidentAcknowledge(db *sql.DB) http.HandlerFunc { // (acknowledged) already holds. inc, err := fetchIncident(r.Context(), db, id) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if inc.Status == "resolved" { @@ -300,7 +282,7 @@ func handleIncidentUnacknowledge(db *sql.DB) http.HandlerFunc { return } if err := logEvent(r.Context(), db, id, evUnacknowledged, userID, saID, nil, nil); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } w.WriteHeader(http.StatusNoContent) @@ -335,16 +317,16 @@ func handleIncidentResolve(db *sql.DB) http.HandlerFunc { } // A person closing an incident is the clearest possible "I have this". if err := stopEscalation(r.Context(), db, id); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if err := logEvent(r.Context(), db, id, evResolved, userID, saID, nil, nil); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if req.Resolution != "" { if err := logEvent(r.Context(), db, id, evResolutionNote, userID, saID, nil, &req.Resolution); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } } @@ -385,7 +367,7 @@ func handleIncidentAssign(db *sql.DB) http.HandlerFunc { // the actor_* columns. actorUserID, actorSAID := callerActorIDs(r.Context()) if err := logAssignedEvent(r.Context(), db, id, req.UserID, actorUserID, actorSAID); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respondIncident(w, r, db, id) @@ -443,7 +425,7 @@ func handleIncidentSnooze(db *sql.DB) http.HandlerFunc { } detail := until.UTC().Format(time.RFC3339) if err := logEvent(r.Context(), db, id, evSnoozed, userID, saID, nil, &detail); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respondIncident(w, r, db, id) @@ -462,7 +444,7 @@ func handleIncidentUnsnooze(db *sql.DB) http.HandlerFunc { return } if err := logEvent(r.Context(), db, id, evUnsnoozed, userID, saID, nil, nil); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } w.WriteHeader(http.StatusNoContent) @@ -478,7 +460,7 @@ func handleIncidentArchive(db *sql.DB) http.HandlerFunc { res, err := db.ExecContext(r.Context(), "UPDATE incidents SET archived_at = "+nowEpoch+" WHERE id = $1", id) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if n, _ := res.RowsAffected(); n == 0 { @@ -487,7 +469,7 @@ func handleIncidentArchive(db *sql.DB) http.HandlerFunc { } userID, saID := callerActorIDs(r.Context()) if err := logEvent(r.Context(), db, id, evArchived, userID, saID, nil, nil); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respondIncident(w, r, db, id) @@ -503,7 +485,7 @@ func handleIncidentUnarchive(db *sql.DB) http.HandlerFunc { res, err := db.ExecContext(r.Context(), "UPDATE incidents SET archived_at = NULL WHERE id = $1", id) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if n, _ := res.RowsAffected(); n == 0 { @@ -512,7 +494,7 @@ func handleIncidentUnarchive(db *sql.DB) http.HandlerFunc { } userID, saID := callerActorIDs(r.Context()) if err := logEvent(r.Context(), db, id, evUnarchived, userID, saID, nil, nil); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } w.WriteHeader(http.StatusNoContent) @@ -557,7 +539,7 @@ func handleCreateNote(db *sql.DB) http.HandlerFunc { VALUES ($1, $2, $3, $4, $5, $6) RETURNING id`, id, noteType, userID, saID, req.Content, now.Unix()).Scan(&eventID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } @@ -598,7 +580,7 @@ func handleDeleteNote(db *sql.DB) http.HandlerFunc { AND (user_id = $5 OR service_account_id = $6)`, eventID, id, evNote, evResolutionNote, userID, saID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if n, _ := res.RowsAffected(); n == 0 { @@ -652,7 +634,7 @@ func incidentExists(w http.ResponseWriter, r *http.Request, db *sql.DB, id int64 func updateOpenIncident(w http.ResponseWriter, r *http.Request, db *sql.DB, id int64, query string, args ...any) bool { res, err := db.ExecContext(r.Context(), query, args...) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return false } if n, _ := res.RowsAffected(); n > 0 { @@ -668,7 +650,7 @@ func updateOpenIncident(w http.ResponseWriter, r *http.Request, db *sql.DB, id i func respondIncident(w http.ResponseWriter, r *http.Request, db *sql.DB, id int64) { inc, err := fetchIncident(r.Context(), db, id) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, inc) diff --git a/internal/api/incidents_test.go b/internal/api/incidents_test.go index 6fbd466..4dc23d7 100644 --- a/internal/api/incidents_test.go +++ b/internal/api/incidents_test.go @@ -794,8 +794,7 @@ func TestStats_Incidents(t *testing.T) { } // An empty window is a report of zero, not a failure. SUM over no rows is NULL -// in Postgres as it was in SQLite, and that used to come back as a 500 the -// moment every incident was archived — the state a quiet installation settles +// in Postgres, and that used to come back as a 500 the moment every incident was archived — the state a quiet installation settles // into. func TestStats_IncidentsEmptyWindowIsZeroNotAnError(t *testing.T) { s := newTS(t) diff --git a/internal/api/middleware.go b/internal/api/middleware.go index ae0aee7..a9e0fc6 100644 --- a/internal/api/middleware.go +++ b/internal/api/middleware.go @@ -5,10 +5,14 @@ import ( "crypto/sha256" "database/sql" "encoding/hex" + "log" "net/http" "strings" "time" + "github.com/go-chi/chi/v5" + "github.com/go-chi/chi/v5/middleware" + "git.ryuvia.com/niklas/terdut-server/internal/config" "git.ryuvia.com/niklas/terdut-server/internal/models" ) @@ -106,7 +110,7 @@ func securityHeaders(publicURL string) func(http.Handler) http.Handler { // // 403 and not 404: the route exists and the caller is authenticated, they are // simply not allowed. Hiding the endpoint would buy nothing — every one of them -// is in the README. +// is in docs/api.md. func AdminOnly(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { caller, ok := userFromContext(r.Context()) @@ -141,19 +145,23 @@ func requireSelfOrAdmin(w http.ResponseWriter, r *http.Request, targetID int64) // resolve and has to be caught afterwards. func apiKeyUser(ctx context.Context, db *sql.DB, token string) (int64, bool) { var keyID, userID int64 + var lastUsed sql.NullInt64 err := db.QueryRowContext(ctx, - `SELECT id, user_id FROM api_keys + `SELECT id, user_id, last_used_at FROM api_keys WHERE key_hash = $1 AND (expires_at IS NULL OR expires_at > $2)`, hashToken(token), time.Now().Unix(), - ).Scan(&keyID, &userID) + ).Scan(&keyID, &userID, &lastUsed) if err != nil { return 0, false } - // best-effort; don't fail the request if this update fails - db.ExecContext(ctx, - "UPDATE api_keys SET last_used_at = $1 WHERE id = $2", - time.Now().Unix(), keyID) + // best-effort; don't fail the request if this update fails. Throttled like + // the session expiry, so a polling client does not write a row per request. + if now := time.Now(); !lastUsed.Valid || now.Sub(time.Unix(lastUsed.Int64, 0)) > keyTouchEvery { + db.ExecContext(ctx, + "UPDATE api_keys SET last_used_at = $1 WHERE id = $2", + now.Unix(), keyID) + } return userID, true } @@ -206,7 +214,7 @@ func serveAs(w http.ResponseWriter, r *http.Request, next http.Handler, db *sql. // table with one row per membership. teams, err := callerMemberships(r.Context(), db, userID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } @@ -222,10 +230,8 @@ func hashToken(token string) string { return hex.EncodeToString(h[:]) } -// userFromContext is a thin compatibility wrapper over Caller.AsHuman(), so -// every call site written before the Caller abstraction (alerts.go, -// incidents.go, schedule.go, stats.go, and more) needs no change and keeps -// its exact existing behavior. +// userFromContext returns the human behind the request, or false for a service +// account: Caller.AsHuman() on the request's Caller. func userFromContext(ctx context.Context) (models.User, bool) { c, _ := callerFromContext(ctx) return c.AsHuman() @@ -245,13 +251,13 @@ type serviceAccountPrincipal struct { func serviceAccountFor(ctx context.Context, db *sql.DB, token string) (serviceAccountPrincipal, bool) { var sa serviceAccountPrincipal var keyID int64 - var teamID sql.NullInt64 + var teamID, lastUsed sql.NullInt64 err := db.QueryRowContext(ctx, ` - SELECT k.id, a.id, a.name, a.scope, a.team_id + SELECT k.id, a.id, a.name, a.scope, a.team_id, k.last_used_at FROM service_account_keys k JOIN service_accounts a ON a.id = k.service_account_id WHERE k.key_hash = $1`, hashToken(token), - ).Scan(&keyID, &sa.id, &sa.name, &sa.scope, &teamID) + ).Scan(&keyID, &sa.id, &sa.name, &sa.scope, &teamID, &lastUsed) if err != nil { return serviceAccountPrincipal{}, false } @@ -260,9 +266,11 @@ func serviceAccountFor(ctx context.Context, db *sql.DB, token string) (serviceAc } // best-effort; don't fail the request if this update fails - db.ExecContext(ctx, - "UPDATE service_account_keys SET last_used_at = $1 WHERE id = $2", - time.Now().Unix(), keyID) + if now := time.Now(); !lastUsed.Valid || now.Sub(time.Unix(lastUsed.Int64, 0)) > keyTouchEvery { + db.ExecContext(ctx, + "UPDATE service_account_keys SET last_used_at = $1 WHERE id = $2", + now.Unix(), keyID) + } return sa, true } @@ -286,10 +294,8 @@ func serveAsServiceAccount(w http.ResponseWriter, r *http.Request, next http.Han next.ServeHTTP(w, r.WithContext(ctx)) } -// isInstanceServiceAccount is a thin compatibility wrapper over -// Caller.IsInstanceServiceAccount(), for call sites outside this package's -// core predicates (handleCreateTeam, handleCreateServiceAccount) that -// needed this exact, narrow check before the Caller abstraction existed. +// isInstanceServiceAccount is Caller.IsInstanceServiceAccount() on the +// request's Caller. func isInstanceServiceAccount(ctx context.Context) bool { c, _ := callerFromContext(ctx) return c.IsInstanceServiceAccount() @@ -397,6 +403,13 @@ func requireTeamOwner(w http.ResponseWriter, r *http.Request, teamID int64) bool if ok && role == models.RoleOwner { return true } + // The operator's instance-scoped account manages every team's + // configuration, which is what lets it use one credential instead of + // minting one per team. This is owner reach only: it does not make the + // account a member, so it still reads no team's incidents. + if c, _ := callerFromContext(r.Context()); c.IsInstanceServiceAccount() { + return true + } if caller, _ := userFromContext(r.Context()); caller.IsAdmin { return true } @@ -414,3 +427,26 @@ func sessionFromContext(ctx context.Context) (int64, bool) { id, ok := ctx.Value(ctxSession).(int64) return id, ok } + +// requestLogger logs one line per request with the matched route pattern in +// place of the URL path. Two routes carry a credential in the path (the +// integration key and the ack token), and chi's stock logger would write it to +// the log verbatim. +func requestLogger(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + start := time.Now() + ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor) + next.ServeHTTP(ww, r) + route := "unmatched" + if rc := chi.RouteContext(r.Context()); rc != nil { + if p := rc.RoutePattern(); p != "" { + route = p + } + } + status := ww.Status() + if status == 0 { + status = http.StatusOK + } + log.Printf("%s %s %d %dB %s", r.Method, route, status, ww.BytesWritten(), time.Since(start).Round(time.Millisecond)) + }) +} diff --git a/internal/api/notifier.go b/internal/api/notifier.go index 8f5b621..610e79b 100644 --- a/internal/api/notifier.go +++ b/internal/api/notifier.go @@ -449,7 +449,7 @@ func renderNotification(inc models.Incident, n outboxRow, firing int, cfg Notify // originLabel is the label that says where an alert came from, for a team with // several Kubernetes clusters behind it. It comes from Prometheus's // externalLabels and reaches an incident through Alertmanager's group_by; the -// web UI reads the same label, and the README ("Several clusters, one team") +// web UI reads the same label, and docs/incidents.md ("Several clusters, one team") // explains how to set it up. const originLabel = "cluster" diff --git a/internal/api/notify_ack.go b/internal/api/notify_ack.go index 43c4507..86e9e63 100644 --- a/internal/api/notify_ack.go +++ b/internal/api/notify_ack.go @@ -62,7 +62,7 @@ func handleNotifyAck(db *sql.DB) http.HandlerFunc { acked, err := acknowledgeIncident(r.Context(), db, incidentID, userID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if !acked { @@ -73,7 +73,7 @@ func handleNotifyAck(db *sql.DB) http.HandlerFunc { // ntfy show a success toast rather than a failure. inc, err := fetchIncident(r.Context(), db, incidentID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, map[string]any{ diff --git a/internal/api/oidc.go b/internal/api/oidc.go index fe4baa7..5221cd7 100644 --- a/internal/api/oidc.go +++ b/internal/api/oidc.go @@ -130,12 +130,12 @@ func handleOIDCLogin(db *sql.DB, prov *oidc.Provider, limiter *loginLimiter, pub state, stateHash, err := randomToken() if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } nonce, _, err := randomToken() if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } verifier := oidc.NewVerifier() @@ -149,7 +149,7 @@ func handleOIDCLogin(db *sql.DB, prov *oidc.Provider, limiter *loginLimiter, pub INSERT INTO oidc_logins (state_hash, nonce, pkce_verifier, next, expires_at) VALUES ($1, $2, $3, $4, $5)`, stateHash, nonce, verifier, next, now.Add(oidcLoginTTL).Unix()); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } diff --git a/internal/api/oidc_teams.go b/internal/api/oidc_teams.go index 7c8fb18..0bdc8ef 100644 --- a/internal/api/oidc_teams.go +++ b/internal/api/oidc_teams.go @@ -31,7 +31,7 @@ func handleGetTeamOIDCGroups(db *sql.DB) http.HandlerFunc { "SELECT COALESCE(oidc_member_group, ''), COALESCE(oidc_owner_group, '') FROM teams WHERE id = $1", teamID).Scan(&g.MemberGroup, &g.OwnerGroup) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, g) @@ -66,7 +66,7 @@ func handleSetTeamOIDCGroups(db *sql.DB) http.HandlerFunc { oidc_owner_group = NULLIF($2, '') WHERE id = $3`, req.MemberGroup, req.OwnerGroup, teamID); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } w.WriteHeader(http.StatusNoContent) diff --git a/internal/api/operator_key.go b/internal/api/operator_key.go new file mode 100644 index 0000000..952a0ec --- /dev/null +++ b/internal/api/operator_key.go @@ -0,0 +1,72 @@ +package api + +import ( + "context" + "database/sql" + "fmt" + + "git.ryuvia.com/niklas/terdut-server/internal/models" +) + +const ( + // operatorAccountName is the instance-scoped service account the operator + // key belongs to. + operatorAccountName = "terdut-operator" + + // operatorKeyName names the one key SeedOperatorKey manages on it, so a + // rotation replaces that key and leaves any others alone. + operatorKeyName = "seed" +) + +// SeedOperatorKey makes key the operator account's credential: it creates the +// instance-scoped service account if needed and replaces its "seed" key with +// this one. Idempotent, so every replica can run it at every start, and a +// rotated key simply wins on the next restart. +// +// The key is hashed like any other, so only the caller that generated it ever +// holds the raw value. An empty key does nothing. +func SeedOperatorKey(ctx context.Context, db *sql.DB, key string) error { + if key == "" { + return nil + } + tx, err := db.BeginTx(ctx, nil) + if err != nil { + return fmt.Errorf("seed operator key: %w", err) + } + defer tx.Rollback() //nolint:errcheck + + // Serialise replicas starting together; transaction-scoped, so it needs no + // explicit release. + if _, err := tx.ExecContext(ctx, "SELECT pg_advisory_xact_lock($1)", operatorKeyLockKey); err != nil { + return fmt.Errorf("seed operator key: lock: %w", err) + } + + var accountID int64 + err = tx.QueryRowContext(ctx, + "SELECT id FROM service_accounts WHERE name = $1 AND scope = $2", + operatorAccountName, models.ServiceAccountScopeInstance).Scan(&accountID) + if err == sql.ErrNoRows { + err = tx.QueryRowContext(ctx, + "INSERT INTO service_accounts (name, scope) VALUES ($1, $2) RETURNING id", + operatorAccountName, models.ServiceAccountScopeInstance).Scan(&accountID) + } + if err != nil { + return fmt.Errorf("seed operator key: account: %w", err) + } + + if _, err := tx.ExecContext(ctx, + "DELETE FROM service_account_keys WHERE service_account_id = $1 AND name = $2", + accountID, operatorKeyName); err != nil { + return fmt.Errorf("seed operator key: drop old key: %w", err) + } + if _, err := tx.ExecContext(ctx, + "INSERT INTO service_account_keys (service_account_id, key_hash, name) VALUES ($1, $2, $3)", + accountID, hashToken(key), operatorKeyName); err != nil { + return fmt.Errorf("seed operator key: store key: %w", err) + } + return tx.Commit() +} + +// operatorKeyLockKey is the transaction-scoped advisory lock SeedOperatorKey +// holds; distinct from the other lock keys in this package. +const operatorKeyLockKey int64 = 7265_0010 diff --git a/internal/api/operator_key_test.go b/internal/api/operator_key_test.go new file mode 100644 index 0000000..2481842 --- /dev/null +++ b/internal/api/operator_key_test.go @@ -0,0 +1,134 @@ +package api_test + +import ( + "context" + "encoding/json" + "net/http" + "testing" + + "git.ryuvia.com/niklas/terdut-server/internal/api" +) + +const ( + operatorKeyOne = "tdsa_operator-key-number-one-0123456789" + operatorKeyTwo = "tdsa_operator-key-number-two-0123456789" +) + +func TestSeedOperatorKey_AuthenticatesAsInstanceAccount(t *testing.T) { + s := newTS(t) + if err := api.SeedOperatorKey(context.Background(), s.db, operatorKeyOne); err != nil { + t.Fatal(err) + } + + resp := s.reqAs(t, operatorKeyOne, http.MethodPost, "/api/teams", map[string]string{"name": "seeded"}) + resp.Body.Close() + if resp.StatusCode != http.StatusCreated { + t.Fatalf("seeded key should create a team, got %d", resp.StatusCode) + } +} + +func TestSeedOperatorKey_RotationReplacesAndIsIdempotent(t *testing.T) { + s := newTS(t) + ctx := context.Background() + for _, key := range []string{operatorKeyOne, operatorKeyOne, operatorKeyTwo} { + if err := api.SeedOperatorKey(ctx, s.db, key); err != nil { + t.Fatal(err) + } + } + + old := s.reqAs(t, operatorKeyOne, http.MethodGet, "/api/teams", nil) + old.Body.Close() + if old.StatusCode != http.StatusUnauthorized { + t.Errorf("rotated-out key should be refused, got %d", old.StatusCode) + } + cur := s.reqAs(t, operatorKeyTwo, http.MethodGet, "/api/teams", nil) + cur.Body.Close() + if cur.StatusCode != http.StatusOK { + t.Errorf("current key should work, got %d", cur.StatusCode) + } + + var accounts, keys int + s.db.QueryRow("SELECT COUNT(*) FROM service_accounts WHERE name = 'terdut-operator'").Scan(&accounts) + s.db.QueryRow("SELECT COUNT(*) FROM service_account_keys").Scan(&keys) + if accounts != 1 || keys != 1 { + t.Errorf("expected one account and one key, got %d and %d", accounts, keys) + } +} + +func TestSeedOperatorKey_EmptyKeyDoesNothing(t *testing.T) { + s := newTS(t) + if err := api.SeedOperatorKey(context.Background(), s.db, ""); err != nil { + t.Fatal(err) + } + var n int + s.db.QueryRow("SELECT COUNT(*) FROM service_accounts").Scan(&n) + if n != 0 { + t.Errorf("expected no service account, got %d", n) + } +} + +// The instance account configures a team it did not create, which is what lets +// the operator hold one credential instead of one per team, yet it is not a +// member and so reads none of the team's incidents. +func TestInstanceAccount_ActsAsOwnerOfAnyTeamButIsNoMember(t *testing.T) { + s := newTS(t) + other := newTeam(t, s, "other") + if err := api.SeedOperatorKey(context.Background(), s.db, operatorKeyOne); err != nil { + t.Fatal(err) + } + + rename := s.reqAs(t, operatorKeyOne, http.MethodPut, "/api/teams/"+id64(other.id), map[string]string{"name": "renamed"}) + rename.Body.Close() + if rename.StatusCode >= 300 { + t.Errorf("instance account should rename any team, got %d", rename.StatusCode) + } + + // Not a member: the team's queue is not visible to it. + var queue []map[string]any + decode(t, s.reqAs(t, operatorKeyOne, http.MethodGet, "/api/incidents", nil), &queue) + if len(queue) != 0 { + t.Errorf("instance account should see no incidents, got %v", queue) + } +} + +// external_id lets automation find its own team again after a crash, without +// trusting a display name. +func TestCreateTeam_ExternalIDIsIdempotentAndInstanceOnly(t *testing.T) { + s := newTS(t) + if err := api.SeedOperatorKey(context.Background(), s.db, operatorKeyOne); err != nil { + t.Fatal(err) + } + create := func(name string) (int, map[string]any) { + resp := s.reqAs(t, operatorKeyOne, http.MethodPost, "/api/teams", + map[string]string{"name": name, "external_id": "ns/platform"}) + var out map[string]any + _ = json.NewDecoder(resp.Body).Decode(&out) + resp.Body.Close() + return resp.StatusCode, out + } + + code, first := create("Platform") + if code != http.StatusCreated { + t.Fatalf("first create: %d", code) + } + // Same identity, even under a new display name: the same team comes back. + code, again := create("Platform renamed") + if code != http.StatusOK || again["id"] != first["id"] { + t.Errorf("repeat with the same external_id: want 200 and team %v, got %d %v", first["id"], code, again) + } + + // A different identity cannot take the name. + resp := s.reqAs(t, operatorKeyOne, http.MethodPost, "/api/teams", + map[string]string{"name": "Platform", "external_id": "other/platform"}) + resp.Body.Close() + if resp.StatusCode != http.StatusConflict { + t.Errorf("taken name under another external_id: want 409, got %d", resp.StatusCode) + } + + // A person cannot set one. + resp = s.req(t, http.MethodPost, "/api/teams", map[string]string{"name": "Mine", "external_id": "x/y"}) + resp.Body.Close() + if resp.StatusCode != http.StatusForbidden { + t.Errorf("a user setting external_id: want 403, got %d", resp.StatusCode) + } +} diff --git a/internal/api/router.go b/internal/api/router.go index 1b24f08..14ff537 100644 --- a/internal/api/router.go +++ b/internal/api/router.go @@ -23,12 +23,13 @@ func NewRouter(db *sql.DB, notify NotifyConfig, cfg config.Config, version strin // One limiter each, both process-wide for the life of the router: login // counts failed passwords, sign-up counts account creation, and mixing the // two would let a burst of sign-ups lock somebody out of logging in. + trustedProxies.Store(int32(cfg.TrustedProxies)) loginLimit := newLoginLimiter(db) signupLimiter := newLoginLimiter(db) oidcLimit := newLoginLimiter(db) r := chi.NewRouter() - r.Use(middleware.Logger) + r.Use(requestLogger) r.Use(middleware.Recoverer) r.Use(securityHeaders(notify.PublicURL)) @@ -48,11 +49,7 @@ func NewRouter(db *sql.DB, notify NotifyConfig, cfg config.Config, version strin // Alert ingestion. The key in the path says both that the sender may post // and which team the alerts belong to, which is why it needs no session. - // - // This is the only way in. The pre-teams /api/alertmanager/webhook, which - // took no credential at all, was removed in v0.13.0 once the cluster's - // Alertmanager had moved onto a key; a sender still posting there gets the - // JSON 404 every unknown /api path gets. + // This is the only way in. r.Post("/api/integrations/{key}/alertmanager", handleIntegrationWebhook(db, notify)) // Signing up. Both are unauthenticated by necessity: the caller has no @@ -116,9 +113,7 @@ func NewRouter(db *sql.DB, notify NotifyConfig, cfg config.Config, version strin r.Post("/api/users/{id}/api-keys", handleCreateAPIKey(db)) r.Delete("/api/users/{id}/api-keys/{keyID}", handleDeleteAPIKey(db)) - // Administration: who exists, and who is an administrator. Until #3 - // these were open to any authenticated caller, which meant every user - // could delete every other one. + // Administration: who exists, and who is an administrator. r.Group(func(r chi.Router) { r.Use(AdminOnly) @@ -147,7 +142,6 @@ func NewRouter(db *sql.DB, notify NotifyConfig, cfg config.Config, version strin r.Get("/api/incidents", handleListIncidents(db)) r.Get("/api/incidents/clusters", handleListClusters(db)) r.Get("/api/incidents/{id}", handleGetIncident(db)) - r.Get("/api/incidents/{id}/alerts", handleIncidentAlerts(db)) r.Get("/api/incidents/{id}/timeline", handleIncidentTimeline(db)) r.Get("/api/incidents/{id}/similar", handleIncidentSimilar(db)) r.Post("/api/incidents/{id}/acknowledge", handleIncidentAcknowledge(db)) diff --git a/internal/api/schedule.go b/internal/api/schedule.go index 089800c..7535218 100644 --- a/internal/api/schedule.go +++ b/internal/api/schedule.go @@ -69,7 +69,7 @@ func handleCreateSchedule(db *sql.DB) http.HandlerFunc { // be, so the delete and the insert share one transaction. tx, err := db.BeginTx(r.Context(), nil) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } defer tx.Rollback() @@ -79,7 +79,7 @@ func handleCreateSchedule(db *sql.DB) http.HandlerFunc { if _, err := tx.ExecContext(r.Context(), "DELETE FROM schedule_entries WHERE team_id = $1 AND date = $2", teamID, d); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } } @@ -91,12 +91,12 @@ func handleCreateSchedule(db *sql.DB) http.HandlerFunc { errResp("date already assigned: "+d+" (pass replace to take it)")) return } - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } } if err := tx.Commit(); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } @@ -107,7 +107,7 @@ func handleCreateSchedule(db *sql.DB) http.HandlerFunc { } all, err := scheduleRange(r.Context(), db, teamID, req.Dates[0], req.Dates[len(req.Dates)-1]) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } created := []models.ScheduleEntry{} @@ -147,7 +147,7 @@ func handleListSchedule(db *sql.DB) http.HandlerFunc { entries, err := scheduleRange(r.Context(), db, teamID, from, to) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, entries) @@ -171,7 +171,7 @@ func handleDeleteSchedule(db *sql.DB) http.HandlerFunc { res, err := db.ExecContext(r.Context(), "DELETE FROM schedule_entries WHERE id = $1 AND team_id = $2", id, teamID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if n, _ := res.RowsAffected(); n == 0 { @@ -197,7 +197,7 @@ func handleCurrentSchedule(db *sql.DB) http.HandlerFunc { WHERE s.date = $1 AND s.team_id = ANY($2) ORDER BY t.name`, today, callerTeamIDs(r.Context())) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } defer rows.Close() @@ -207,14 +207,14 @@ func handleCurrentSchedule(db *sql.DB) http.HandlerFunc { var e models.ScheduleEntry var ts int64 if err := rows.Scan(&e.ID, &e.TeamID, &e.TeamName, &e.UserID, &e.Username, &e.Date, &ts); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } e.CreatedAt = time.Unix(ts, 0).UTC() entries = append(entries, e) } if err := rows.Err(); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, entries) diff --git a/internal/api/service_accounts.go b/internal/api/service_accounts.go index c03bfcd..b95cb3e 100644 --- a/internal/api/service_accounts.go +++ b/internal/api/service_accounts.go @@ -50,6 +50,9 @@ func callerIsAdmin(ctx context.Context) bool { // writing a response: callers here need to combine it with other ways of // being allowed, not stop at the first no. func callerOwnsTeam(ctx context.Context, teamID int64) bool { + if c, _ := callerFromContext(ctx); c.IsInstanceServiceAccount() { + return true + } role, ok := callerRole(ctx, teamID) return ok && role == models.RoleOwner } @@ -132,7 +135,7 @@ func handleCreateServiceAccount(db *sql.DB) http.HandlerFunc { key, err := mintServiceAccountKey(r.Context(), db, sa.ID, "initial") if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusCreated, map[string]any{"service_account": sa, "key": key}) @@ -233,7 +236,7 @@ func handleCreateServiceAccountKey(db *sql.DB) http.HandlerFunc { return } if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if !callerMayManageServiceAccount(r.Context(), sa) { @@ -255,7 +258,7 @@ func handleCreateServiceAccountKey(db *sql.DB) http.HandlerFunc { key, err := mintServiceAccountKey(r.Context(), db, sa.ID, req.Name) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusCreated, key) @@ -274,7 +277,7 @@ func handleDeleteServiceAccountKey(db *sql.DB) http.HandlerFunc { return } if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if !callerMayManageServiceAccount(r.Context(), sa) { @@ -290,7 +293,7 @@ func handleDeleteServiceAccountKey(db *sql.DB) http.HandlerFunc { res, err := db.ExecContext(r.Context(), "DELETE FROM service_account_keys WHERE id = $1 AND service_account_id = $2", keyID, sa.ID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if n, _ := res.RowsAffected(); n == 0 { @@ -325,7 +328,7 @@ func handleListServiceAccounts(db *sql.DB) http.HandlerFunc { rows, err := db.QueryContext(r.Context(), query, args...) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } defer rows.Close() @@ -335,14 +338,14 @@ func handleListServiceAccounts(db *sql.DB) http.HandlerFunc { var sa models.ServiceAccount var created int64 if err := rows.Scan(&sa.ID, &sa.Name, &sa.Scope, &sa.TeamID, &sa.CreatedBy, &created); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } sa.CreatedAt = time.Unix(created, 0).UTC() accounts = append(accounts, sa) } if err := rows.Err(); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, accounts) diff --git a/internal/api/settings.go b/internal/api/settings.go index f736c5f..fb22c44 100644 --- a/internal/api/settings.go +++ b/internal/api/settings.go @@ -203,7 +203,7 @@ func handleSetSettings(db *sql.DB) http.HandlerFunc { tx, err := db.BeginTx(r.Context(), nil) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } defer tx.Rollback() //nolint:errcheck @@ -215,12 +215,12 @@ func handleSetSettings(db *sql.DB) http.HandlerFunc { ON CONFLICT (key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at`, key, value); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } } if err := tx.Commit(); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } @@ -261,7 +261,7 @@ func handleAdminListTeams(db *sql.DB) http.HandlerFunc { FROM teams t ORDER BY t.name`) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } defer rows.Close() @@ -272,14 +272,14 @@ func handleAdminListTeams(db *sql.DB) http.HandlerFunc { var created int64 if err := rows.Scan(&t.ID, &t.Name, &created, &t.Members, &t.OpenIncidents, &t.OIDCMemberGroup, &t.OIDCOwnerGroup); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } t.CreatedAt = time.Unix(created, 0).UTC() teams = append(teams, t) } if err := rows.Err(); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, teams) @@ -319,7 +319,7 @@ func handleAdminGetTeam(db *sql.DB) http.HandlerFunc { return } if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } t.CreatedAt = time.Unix(created, 0).UTC() @@ -333,7 +333,7 @@ func handleAdminGetTeam(db *sql.DB) http.HandlerFunc { WHERE m.team_id = $1 ORDER BY u.username`, teamID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } defer rows.Close() @@ -343,14 +343,14 @@ func handleAdminGetTeam(db *sql.DB) http.HandlerFunc { var m models.TeamMember var joined int64 if err := rows.Scan(&m.TeamID, &m.UserID, &m.Username, &m.Role, &joined, &m.Source); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } m.JoinedAt = time.Unix(joined, 0).UTC() members = append(members, m) } if err := rows.Err(); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } @@ -396,7 +396,7 @@ func handleRenameTeam(db *sql.DB) http.HandlerFunc { respond(w, http.StatusConflict, errResp("a team with that name already exists")) return } - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if n, _ := res.RowsAffected(); n == 0 { @@ -435,7 +435,7 @@ func handleSetUserDisabled(db *sql.DB) http.HandlerFunc { } last, err := isLastAdmin(r.Context(), db, id) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if last { @@ -453,7 +453,7 @@ func handleSetUserDisabled(db *sql.DB) http.HandlerFunc { "UPDATE users SET disabled_at = NULL WHERE id = $1", id) } if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if n, _ := res.RowsAffected(); n == 0 { @@ -475,7 +475,7 @@ func handleSetUserDisabled(db *sql.DB) http.HandlerFunc { user, err := fetchUser(r.Context(), db, id) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, user) diff --git a/internal/api/signup.go b/internal/api/signup.go index 9b32e83..0d2a3f8 100644 --- a/internal/api/signup.go +++ b/internal/api/signup.go @@ -170,13 +170,13 @@ func handleSignup(db *sql.DB, limiter *loginLimiter, publicURL string) http.Hand hash, err := hashPassword(req.Password) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } tx, err := db.BeginTx(r.Context(), nil) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } defer tx.Rollback() //nolint:errcheck @@ -194,7 +194,7 @@ func handleSignup(db *sql.DB, limiter *loginLimiter, publicURL string) http.Hand respond(w, http.StatusConflict, errResp("username or email already exists")) return } - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } @@ -207,7 +207,7 @@ func handleSignup(db *sql.DB, limiter *loginLimiter, publicURL string) http.Hand respond(w, http.StatusConflict, errResp("a team with that name already exists")) return } - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } role = models.RoleOwner @@ -216,7 +216,7 @@ func handleSignup(db *sql.DB, limiter *loginLimiter, publicURL string) http.Hand if _, err := tx.ExecContext(r.Context(), "INSERT INTO team_members (team_id, user_id, role) VALUES ($1, $2, $3)", teamID, userID, role); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } @@ -226,7 +226,7 @@ func handleSignup(db *sql.DB, limiter *loginLimiter, publicURL string) http.Hand res, err := tx.ExecContext(r.Context(), "UPDATE invites SET uses = uses + 1 WHERE id = $1 AND uses < max_uses", inv.id) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if n, _ := res.RowsAffected(); n == 0 { @@ -236,14 +236,14 @@ func handleSignup(db *sql.DB, limiter *loginLimiter, publicURL string) http.Hand } if err := tx.Commit(); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } // Signed in immediately: the alternative is a form that says "now go // and log in", which is the same credential typed twice. if err := startSession(w, r, db, userID, publicURL); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } user, _ := fetchUser(r.Context(), db, userID) @@ -291,7 +291,7 @@ func handleListInvites(db *sql.DB) http.HandlerFunc { WHERE team_id = $1 ORDER BY id DESC`, teamID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } defer rows.Close() @@ -303,7 +303,7 @@ func handleListInvites(db *sql.DB) http.HandlerFunc { var revoked *int64 if err := rows.Scan(&i.ID, &i.TeamID, &i.Role, &created, &expires, &i.MaxUses, &i.Uses, &revoked); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } i.CreatedAt = time.Unix(created, 0).UTC() @@ -312,7 +312,7 @@ func handleListInvites(db *sql.DB) http.HandlerFunc { out = append(out, i) } if err := rows.Err(); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, out) @@ -356,7 +356,7 @@ func handleCreateInvite(db *sql.DB, publicURL string) http.HandlerFunc { raw, hash, err := randomToken() if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } // created_by is nullable (ON DELETE SET NULL) for exactly this @@ -382,7 +382,7 @@ func handleCreateInvite(db *sql.DB, publicURL string) http.HandlerFunc { RETURNING id, team_id, role, created_at, expires_at, max_uses, uses`, hash, teamID, req.Role, createdBy, expires.Unix(), req.MaxUses). Scan(&out.ID, &out.TeamID, &out.Role, &created, &expiresAt, &out.MaxUses, &out.Uses); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } out.CreatedAt = time.Unix(created, 0).UTC() @@ -412,7 +412,7 @@ func handleRevokeInvite(db *sql.DB) http.HandlerFunc { "UPDATE invites SET revoked_at = "+nowEpoch+ " WHERE id = $1 AND team_id = $2 AND revoked_at IS NULL", id, teamID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if n, _ := res.RowsAffected(); n == 0 { @@ -450,7 +450,7 @@ func handleTestNotification(cfg NotifyConfig, db *sql.DB) http.HandlerFunc { var topic *string if err := db.QueryRowContext(r.Context(), "SELECT ntfy_topic FROM users WHERE id = $1", caller.ID).Scan(&topic); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if topic == nil || *topic == "" { @@ -501,7 +501,7 @@ func handleDismissOnboarding(db *sql.DB) http.HandlerFunc { "UPDATE users SET onboarding_dismissed_at = NULL WHERE id = $1", caller.ID) } if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } w.WriteHeader(http.StatusNoContent) diff --git a/internal/api/similar.go b/internal/api/similar.go index b316289..c13f400 100644 --- a/internal/api/similar.go +++ b/internal/api/similar.go @@ -37,7 +37,7 @@ func handleIncidentSimilar(db *sql.DB) http.HandlerFunc { out, err := similarIncidents(r.Context(), db, id, limit) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, out) diff --git a/internal/api/stats.go b/internal/api/stats.go index ee30af9..a9ab4da 100644 --- a/internal/api/stats.go +++ b/internal/api/stats.go @@ -24,7 +24,7 @@ func handleStatsAlerts(db *sql.DB) http.HandlerFunc { FROM alerts WHERE %s`, where), args.all()..., ).Scan(&total, &firing, &resolved) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, map[string]int64{ @@ -55,7 +55,7 @@ func handleStatsTop(db *sql.DB) http.HandlerFunc { ORDER BY cnt DESC LIMIT %s`, where, args.add(limit)), args.all()...) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } defer rows.Close() @@ -68,13 +68,13 @@ func handleStatsTop(db *sql.DB) http.HandlerFunc { for rows.Next() { var e entry if err := rows.Scan(&e.Name, &e.Count); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } result = append(result, e) } if err := rows.Err(); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, result) @@ -93,7 +93,7 @@ func handleStatsByHour(db *sql.DB) http.HandlerFunc { GROUP BY hr ORDER BY hr ASC`, where), args.all()...) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } defer rows.Close() @@ -103,13 +103,13 @@ func handleStatsByHour(db *sql.DB) http.HandlerFunc { var hr int var cnt int64 if err := rows.Scan(&hr, &cnt); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } counts[hr] = cnt } if err := rows.Err(); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } @@ -129,8 +129,7 @@ func handleStatsByDay(db *sql.DB) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { where, args := statsFilter(r.URL.Query(), "received_at", callerTeamIDs(r.Context())) - // Postgres EXTRACT(DOW …) → 0=Sunday … 6=Saturday, the same numbering - // SQLite's strftime('%w') returned, so the frontend needs no change. + // Postgres EXTRACT(DOW …) → 0=Sunday … 6=Saturday. rows, err := db.QueryContext(r.Context(), fmt.Sprintf(` SELECT EXTRACT(DOW FROM to_timestamp(received_at) AT TIME ZONE 'UTC')::int AS dow, COUNT(*) AS cnt @@ -139,7 +138,7 @@ func handleStatsByDay(db *sql.DB) http.HandlerFunc { GROUP BY dow ORDER BY dow ASC`, where), args.all()...) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } defer rows.Close() @@ -149,13 +148,13 @@ func handleStatsByDay(db *sql.DB) http.HandlerFunc { var dow int var cnt int64 if err := rows.Scan(&dow, &cnt); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } counts[dow] = cnt } if err := rows.Err(); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } @@ -198,7 +197,7 @@ func handleStatsIncidents(db *sql.DB) http.HandlerFunc { FROM incidents WHERE %s`, where), args.all()..., ).Scan(&total, &triggered, &acknowledged, &resolved, &mtta, &mttr) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } diff --git a/internal/api/teams.go b/internal/api/teams.go index e2b17c7..e92d7d9 100644 --- a/internal/api/teams.go +++ b/internal/api/teams.go @@ -13,19 +13,12 @@ import ( "github.com/go-chi/chi/v5" ) -// handleListTeams lists the caller's own teams, each with their role in it, -// or — with ?name= — looks up one team by exact name regardless of caller -// identity (TEAM-LOOKUP.md). An administrator listing every team goes -// through the admin endpoint instead: the no-name case here answers "what am -// I part of", which is what the UI's team filter and the combined queue are -// built from. +// handleListTeams lists the caller's own teams, each with their role in it. +// An administrator listing every team goes through the admin endpoint instead: +// this answers "what am I part of", which is what the UI's team filter and the +// combined queue are built from. func handleListTeams(db *sql.DB) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - if name := strings.TrimSpace(r.URL.Query().Get("name")); name != "" { - handleListTeamsByName(db, w, r, name) - return - } - caller, _ := userFromContext(r.Context()) rows, err := db.QueryContext(r.Context(), ` SELECT t.id, t.name, t.created_at, m.role, m.source @@ -34,7 +27,7 @@ func handleListTeams(db *sql.DB) http.HandlerFunc { WHERE m.user_id = $1 ORDER BY t.name`, caller.ID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } defer rows.Close() @@ -44,45 +37,20 @@ func handleListTeams(db *sql.DB) http.HandlerFunc { var t models.Team var created int64 if err := rows.Scan(&t.ID, &t.Name, &created, &t.Role, &t.Source); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } t.CreatedAt = time.Unix(created, 0).UTC() teams = append(teams, t) } if err := rows.Err(); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, teams) } } -// handleListTeamsByName answers "is there a team named exactly this", open to -// any authenticated caller including a service account (TEAM-LOOKUP.md) — -// mirrors handleListServiceAccounts' own ?name= lookup: a one-or-zero-length -// array, never an error on no match, and no caller-identity filtering at -// all, since what it discloses (a name is taken, nothing about who's in it -// or any of its data) is the same low sensitivity that lookup already -// accepts for service-account names. -func handleListTeamsByName(db *sql.DB, w http.ResponseWriter, r *http.Request, name string) { - var t models.Team - var created int64 - err := db.QueryRowContext(r.Context(), - "SELECT id, name, created_at FROM teams WHERE name = $1", name, - ).Scan(&t.ID, &t.Name, &created) - if errors.Is(err, sql.ErrNoRows) { - respond(w, http.StatusOK, []models.Team{}) - return - } - if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) - return - } - t.CreatedAt = time.Unix(created, 0).UTC() - respond(w, http.StatusOK, []models.Team{t}) -} - // handleUserTeams lists one user's teams, for the admin page's per-user view: // "what is this person in", which /api/teams cannot answer because it is always // about the caller. @@ -106,7 +74,7 @@ func handleUserTeams(db *sql.DB) http.HandlerFunc { var exists bool if err := db.QueryRowContext(r.Context(), "SELECT EXISTS (SELECT 1 FROM users WHERE id = $1)", id).Scan(&exists); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if !exists { @@ -121,7 +89,7 @@ func handleUserTeams(db *sql.DB) http.HandlerFunc { WHERE m.user_id = $1 ORDER BY t.name`, id) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } defer rows.Close() @@ -131,14 +99,14 @@ func handleUserTeams(db *sql.DB) http.HandlerFunc { var t models.Team var created int64 if err := rows.Scan(&t.ID, &t.Name, &created, &t.Role, &t.Source); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } t.CreatedAt = time.Unix(created, 0).UTC() teams = append(teams, t) } if err := rows.Err(); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, teams) @@ -161,6 +129,12 @@ func handleCreateTeam(db *sql.DB) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var req struct { Name string `json:"name"` + // ExternalID makes the call idempotent for automation: a team + // already carrying it is returned as-is (200) instead of created, so + // a client that crashed between the POST and recording the id finds + // its own team again. Instance-scoped service accounts only; a name + // that belongs to a different team is still a 409. + ExternalID string `json:"external_id"` } if err := decodeJSON(r, &req); err != nil { respond(w, http.StatusBadRequest, errResp("invalid request body")) @@ -173,6 +147,10 @@ func handleCreateTeam(db *sql.DB) http.HandlerFunc { } caller, isUser := userFromContext(r.Context()) + if req.ExternalID != "" && !isInstanceServiceAccount(r.Context()) { + respond(w, http.StatusForbidden, errResp("external_id is for instance-scoped service accounts")) + return + } if !isUser && !isInstanceServiceAccount(r.Context()) { // A team-scoped service account authenticates as owner of exactly // one team already (see serveAsServiceAccount); letting it create @@ -183,37 +161,57 @@ func handleCreateTeam(db *sql.DB) http.HandlerFunc { tx, err := db.BeginTx(r.Context(), nil) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } defer tx.Rollback() //nolint:errcheck var team models.Team var created int64 + if req.ExternalID != "" { + err := tx.QueryRowContext(r.Context(), + "SELECT id, name, created_at FROM teams WHERE external_id = $1", req.ExternalID). + Scan(&team.ID, &team.Name, &created) + if err == nil { + team.ExternalID = &req.ExternalID + team.CreatedAt = time.Unix(created, 0).UTC() + respond(w, http.StatusOK, team) + return + } + if !errors.Is(err, sql.ErrNoRows) { + serverError(w, r, err) + return + } + } + var externalID *string + if req.ExternalID != "" { + externalID = &req.ExternalID + } if err := tx.QueryRowContext(r.Context(), - "INSERT INTO teams (name) VALUES ($1) RETURNING id, name, created_at", - req.Name).Scan(&team.ID, &team.Name, &created); err != nil { + "INSERT INTO teams (name, external_id) VALUES ($1, $2) RETURNING id, name, created_at", + req.Name, externalID).Scan(&team.ID, &team.Name, &created); err != nil { if isUniqueViolation(err) { respond(w, http.StatusConflict, errResp("a team with that name already exists")) return } - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if isUser { if _, err := tx.ExecContext(r.Context(), "INSERT INTO team_members (team_id, user_id, role) VALUES ($1, $2, $3)", team.ID, caller.ID, models.RoleOwner); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } } if err := tx.Commit(); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } team.CreatedAt = time.Unix(created, 0).UTC() + team.ExternalID = externalID if isUser { team.Role = models.RoleOwner } @@ -241,7 +239,7 @@ func handleDeleteTeam(db *sql.DB) http.HandlerFunc { if err := db.QueryRowContext(r.Context(), "SELECT COUNT(*) FROM incidents WHERE team_id = $1 AND resolved_at IS NULL", teamID). Scan(&open); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if open > 0 { @@ -251,7 +249,7 @@ func handleDeleteTeam(db *sql.DB) http.HandlerFunc { res, err := db.ExecContext(r.Context(), "DELETE FROM teams WHERE id = $1", teamID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if n, _ := res.RowsAffected(); n == 0 { @@ -322,7 +320,7 @@ func handleListTeamMembers(db *sql.DB) http.HandlerFunc { WHERE m.team_id = $1 ORDER BY u.username`, teamID, todayUTC()) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } defer rows.Close() @@ -334,7 +332,7 @@ func handleListTeamMembers(db *sql.DB) http.HandlerFunc { var hasTopic, disabled bool if err := rows.Scan(&m.TeamID, &m.UserID, &m.Username, &m.Role, &joined, &m.Source, &hasTopic, &disabled, &lastActive, &m.OnCall, &m.NextShift); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } m.JoinedAt = time.Unix(joined, 0).UTC() @@ -360,7 +358,7 @@ func handleListTeamMembers(db *sql.DB) http.HandlerFunc { members = append(members, m) } if err := rows.Err(); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, members) @@ -396,7 +394,7 @@ func handleAddTeamMember(db *sql.DB) http.HandlerFunc { } if managed, err := isSSOManagedMember(r.Context(), db, teamID, req.UserID); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } else if managed { respond(w, http.StatusConflict, errResp(ssoManagedMsg)) @@ -408,7 +406,7 @@ func handleAddTeamMember(db *sql.DB) http.HandlerFunc { if req.Role == models.RoleMember { last, err := isLastTeamOwner(r.Context(), db, teamID, req.UserID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if last { @@ -453,7 +451,7 @@ func handleRemoveTeamMember(db *sql.DB) http.HandlerFunc { } if managed, err := isSSOManagedMember(r.Context(), db, teamID, userID); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } else if managed { respond(w, http.StatusConflict, errResp(ssoManagedMsg)) @@ -462,7 +460,7 @@ func handleRemoveTeamMember(db *sql.DB) http.HandlerFunc { last, err := isLastTeamOwner(r.Context(), db, teamID, userID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if last { @@ -473,7 +471,7 @@ func handleRemoveTeamMember(db *sql.DB) http.HandlerFunc { res, err := db.ExecContext(r.Context(), "DELETE FROM team_members WHERE team_id = $1 AND user_id = $2", teamID, userID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if n, _ := res.RowsAffected(); n == 0 { @@ -572,7 +570,7 @@ func handleListIntegrations(db *sql.DB) http.HandlerFunc { WHERE i.team_id = $1 ORDER BY i.id`, teamID, now.Add(-sourceQuietAfter).Unix()) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } defer rows.Close() @@ -584,7 +582,7 @@ func handleListIntegrations(db *sql.DB) http.HandlerFunc { var lastUsed, lastAlert *int64 if err := rows.Scan(&i.ID, &i.TeamID, &i.Kind, &i.Name, &created, &lastUsed, &lastAlert, &i.Alerts24h); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } i.CreatedAt = time.Unix(created, 0).UTC() @@ -601,7 +599,7 @@ func handleListIntegrations(db *sql.DB) http.HandlerFunc { integrations = append(integrations, i) } if err := rows.Err(); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, integrations) @@ -644,7 +642,7 @@ func handleCreateIntegration(db *sql.DB, publicURL string) http.HandlerFunc { raw, hash, err := randomToken() if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } @@ -656,7 +654,11 @@ func handleCreateIntegration(db *sql.DB, publicURL string) http.HandlerFunc { RETURNING id, team_id, kind, name, created_at`, teamID, req.Kind, req.Name, hash). Scan(&i.ID, &i.TeamID, &i.Kind, &i.Name, &created); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + if isUniqueViolation(err) { + respond(w, http.StatusConflict, errResp("an integration with that name already exists in this team")) + return + } + serverError(w, r, err) return } i.CreatedAt = time.Unix(created, 0).UTC() @@ -703,7 +705,11 @@ func handleRenameIntegration(db *sql.DB) http.HandlerFunc { res, err := db.ExecContext(r.Context(), "UPDATE integrations SET name = $1 WHERE id = $2 AND team_id = $3", req.Name, id, teamID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + if isUniqueViolation(err) { + respond(w, http.StatusConflict, errResp("an integration with that name already exists in this team")) + return + } + serverError(w, r, err) return } if n, _ := res.RowsAffected(); n == 0 { @@ -732,7 +738,7 @@ func handleDeleteIntegration(db *sql.DB) http.HandlerFunc { res, err := db.ExecContext(r.Context(), "DELETE FROM integrations WHERE id = $1 AND team_id = $2", id, teamID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if n, _ := res.RowsAffected(); n == 0 { @@ -790,16 +796,6 @@ func teamParam(w http.ResponseWriter, r *http.Request) (int64, bool) { return id, true } -// defaultTeamID is the oldest team, which on an upgraded install is the -// "Default" team every pre-teams row was moved into and on a fresh one is the -// team migration 003 creates. Bootstrap puts the first user in it, so somebody -// signing in to a new server lands somewhere rather than in no team at all. -func defaultTeamID(ctx context.Context, db *sql.DB) (int64, error) { - var id int64 - err := db.QueryRowContext(ctx, "SELECT id FROM teams ORDER BY id LIMIT 1").Scan(&id) - return id, err -} - // --------------------------------------------------------------------------- // A team's dead man's switches // --------------------------------------------------------------------------- @@ -833,12 +829,12 @@ func handleListTeamDeadman(db *sql.DB) http.HandlerFunc { set, err := deadmanSetForTeam(r.Context(), db, teamID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } out, err := deadmanStatuses(r.Context(), db, teamID, set, time.Now()) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, out) @@ -901,7 +897,11 @@ func handleCreateTeamDeadman(db *sql.DB) http.HandlerFunc { INSERT INTO deadman_switches (team_id, name, matcher, timeout_seconds, severity) VALUES ($1, $2, $3, $4, $5) RETURNING id`, teamID, req.Name, m.config(), req.TimeoutSeconds, req.Severity).Scan(&id); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + if isUniqueViolation(err) { + respond(w, http.StatusConflict, errResp("a switch with that name already exists in this team")) + return + } + serverError(w, r, err) return } @@ -975,7 +975,11 @@ func handleUpdateTeamDeadman(db *sql.DB) http.HandlerFunc { WHERE id = $5 AND team_id = $6`, req.Name, m.config(), req.TimeoutSeconds, req.Severity, switchID, teamID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + if isUniqueViolation(err) { + respond(w, http.StatusConflict, errResp("a switch with that name already exists in this team")) + return + } + serverError(w, r, err) return } if n, _ := res.RowsAffected(); n == 0 { @@ -990,12 +994,12 @@ func handleUpdateTeamDeadman(db *sql.DB) http.HandlerFunc { // handleListTeamDeadman would give it. set, err := deadmanSetForTeam(r.Context(), db, teamID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } statuses, err := deadmanStatuses(r.Context(), db, teamID, set, time.Now()) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } for _, s := range statuses { @@ -1004,7 +1008,7 @@ func handleUpdateTeamDeadman(db *sql.DB) http.HandlerFunc { return } } - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) } } @@ -1029,7 +1033,7 @@ func handleDeleteTeamDeadman(db *sql.DB) http.HandlerFunc { res, err := db.ExecContext(r.Context(), "DELETE FROM deadman_switches WHERE id = $1 AND team_id = $2", switchID, teamID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if n, _ := res.RowsAffected(); n == 0 { diff --git a/internal/api/teams_test.go b/internal/api/teams_test.go index 8cebe1a..85879f9 100644 --- a/internal/api/teams_test.go +++ b/internal/api/teams_test.go @@ -6,8 +6,6 @@ import ( "io" "net/http" "testing" - - "git.ryuvia.com/niklas/terdut-server/internal/models" ) // The whole point of #4: two teams sharing one server must not see each other's @@ -146,7 +144,6 @@ func TestTeams_IncidentsAreScopedToTheReceivingTeam(t *testing.T) { otherID := int64(blueIncidents[0]["id"].(float64)) for _, path := range []string{ "/api/incidents/" + id64(otherID), - "/api/incidents/" + id64(otherID) + "/alerts", "/api/incidents/" + id64(otherID) + "/timeline", } { resp := red.call(http.MethodGet, path, nil) @@ -461,70 +458,58 @@ func TestTeams_OutsiderSeesNothing(t *testing.T) { // GET /api/teams?name= (TEAM-LOOKUP.md) // --------------------------------------------------------------------------- -func TestListTeamsByName_FindsExactMatch(t *testing.T) { - s := newTS(t) - instanceKey := createServiceAccount(t, s, s.key, "terdut-operator", models.ServiceAccountScopeInstance, 0) - teamID := createTeamAs(t, s, instanceKey, "platform") - - teams := list(t, s.reqAs(t, instanceKey, http.MethodGet, "/api/teams?name=platform", nil)) - if len(teams) != 1 { - t.Fatalf("expected exactly one match for ?name=platform, got %d: %v", len(teams), teams) - } - if int64(teams[0]["id"].(float64)) != teamID { - t.Errorf("id = %v, want %d", teams[0]["id"], teamID) - } - // No membership, so no role to report (models.Team's own doc comment: - // "empty when nobody in particular is asking"). - if _, has := teams[0]["role"]; has { - t.Errorf("expected no role on a name-lookup match, got %v", teams[0]["role"]) - } -} - -func TestListTeamsByName_NoMatchIsAnEmptyArrayNotAnError(t *testing.T) { - s := newTS(t) - instanceKey := createServiceAccount(t, s, s.key, "terdut-operator", models.ServiceAccountScopeInstance, 0) - - resp := s.reqAs(t, instanceKey, http.MethodGet, "/api/teams?name=does-not-exist", nil) - if resp.StatusCode != http.StatusOK { - t.Fatalf("expected 200 on no match, got %d", resp.StatusCode) - } - teams := list(t, resp) - if len(teams) != 0 { - t.Errorf("expected an empty array, got %v", teams) - } -} - -// The actual motivating scenario (TEAM-LOOKUP.md): a service account that -// already created a team, interrupted before it could remember the id, -// recovers it via ?name= on the same name its own POST 409s on. -func TestListTeamsByName_RecoversAfterCreateConflict(t *testing.T) { - s := newTS(t) - instanceKey := createServiceAccount(t, s, s.key, "terdut-operator", models.ServiceAccountScopeInstance, 0) - original := createTeamAs(t, s, instanceKey, "recovered") - - conflict := s.reqAs(t, instanceKey, http.MethodPost, "/api/teams", map[string]string{"name": "recovered"}) - if conflict.StatusCode != http.StatusConflict { - t.Fatalf("expected 409 recreating the same name, got %d", conflict.StatusCode) - } - conflict.Body.Close() - - teams := list(t, s.reqAs(t, instanceKey, http.MethodGet, "/api/teams?name=recovered", nil)) - if len(teams) != 1 || int64(teams[0]["id"].(float64)) != original { - t.Fatalf("expected to recover the original team %d via ?name=, got %v", original, teams) - } -} - -// Not gated by isInstanceServiceAccount or AdminOnly (TEAM-LOOKUP.md): any -// authenticated caller may ask whether a name is taken, the same low -// sensitivity GET /api/service-accounts?name= already accepts. -func TestListTeamsByName_OpenToAnyAuthenticatedCaller(t *testing.T) { +// Everybody signed in can list users to name them, but only an admin (or the +// row's owner) sees an email or an ntfy topic, which is a publish secret. +func TestListUsers_RedactsEmailAndTopicForOthers(t *testing.T) { s := newTS(t) red := newTeam(t, s, "red") - _ = createTeamAs(t, s, s.key, "blue-target") + _ = newTeam(t, s, "blue") + s.exec(t, "UPDATE users SET ntfy_topic = 'secret-topic'") - // red's own member, not a member of "blue-target", still gets a match. - teams := list(t, red.call(http.MethodGet, "/api/teams?name=blue-target", nil)) - if len(teams) != 1 || teams[0]["name"] != "blue-target" { - t.Errorf("expected a non-member caller to still find the team by name, got %v", teams) + var asAdmin []map[string]any + decode(t, s.req(t, http.MethodGet, "/api/users", nil), &asAdmin) + for _, u := range asAdmin { + if u["email"] == "" || u["ntfy_topic"] != "secret-topic" { + t.Errorf("admin should see everything, got %v", u) + } + } + + asMember := list(t, red.call(http.MethodGet, "/api/users", nil)) + if len(asMember) < 3 { + t.Fatalf("expected the whole user list, got %v", asMember) + } + for _, u := range asMember { + own := u["username"] == "red-user" + if own != (u["email"] != "") || own != (u["ntfy_topic"] != nil) { + t.Errorf("only red-user's own row should keep email and topic, got %v", u) + } + } +} + +// Names identify integrations and switches within a team. +func TestTeamNames_AreUniquePerTeam(t *testing.T) { + s := newTS(t) // creates one integration named "test" in the default team + + dup := s.req(t, http.MethodPost, "/api/teams/"+defaultTeam+"/integrations", map[string]string{"name": "test"}) + dup.Body.Close() + if dup.StatusCode != http.StatusConflict { + t.Errorf("duplicate integration name: expected 409, got %d", dup.StatusCode) + } + + body := map[string]any{"matcher": "alertname=Watchdog", "timeout_seconds": 60, "severity": "critical"} + first := s.req(t, http.MethodPost, "/api/teams/"+defaultTeam+"/deadman/switches", body) + first.Body.Close() + second := s.req(t, http.MethodPost, "/api/teams/"+defaultTeam+"/deadman/switches", body) + second.Body.Close() + if first.StatusCode != http.StatusCreated || second.StatusCode != http.StatusConflict { + t.Errorf("duplicate switch name: expected 201 then 409, got %d then %d", first.StatusCode, second.StatusCode) + } + + // The same name in another team is fine. + other := newTeam(t, s, "elsewhere") + ok := s.req(t, http.MethodPost, "/api/teams/"+id64(other.id)+"/integrations", map[string]string{"name": "test"}) + ok.Body.Close() + if ok.StatusCode != http.StatusCreated { + t.Errorf("same name in another team: expected 201, got %d", ok.StatusCode) } } diff --git a/internal/api/testdb_test.go b/internal/api/testdb_test.go index 33d6294..25852e3 100644 --- a/internal/api/testdb_test.go +++ b/internal/api/testdb_test.go @@ -13,9 +13,8 @@ import ( "git.ryuvia.com/niklas/terdut-server/internal/db" ) -// Tests run against a real Postgres, because the server does. SQLite's -// ":memory:" gave every test a private database for free; Postgres has no -// equivalent, so isolation is bought with a schema per test. +// Tests run against a real Postgres, because the server does. Isolation is +// bought with a schema per test. // // A schema rather than a database: CREATE DATABASE copies a template on disk and // costs a hundred milliseconds or so each time, while CREATE SCHEMA plus the one diff --git a/internal/api/users.go b/internal/api/users.go index aa457a2..ba3f7f7 100644 --- a/internal/api/users.go +++ b/internal/api/users.go @@ -15,6 +15,10 @@ import ( "github.com/go-chi/chi/v5" ) +// bootstrapLockKey is the transaction-scoped advisory lock handleBootstrap +// holds; distinct from the migration and notifier keys. +const bootstrapLockKey = 0x7465726475744254 + func handleBootstrap(db *sql.DB) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var req struct { @@ -40,15 +44,30 @@ func handleBootstrap(db *sql.DB) http.HandlerFunc { } h, err := hashPassword(req.Password) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } passwordHash = &h } + // Check-then-insert has to be one atomic step: two concurrent calls on + // an empty install would otherwise both see zero users and both create + // an admin. The transaction-scoped lock serialises them, and the loser + // sees the winner's row. + tx, err := db.BeginTx(r.Context(), nil) + if err != nil { + serverError(w, r, err) + return + } + defer tx.Rollback() //nolint:errcheck + if _, err := tx.ExecContext(r.Context(), "SELECT pg_advisory_xact_lock($1)", bootstrapLockKey); err != nil { + serverError(w, r, err) + return + } + var count int - if err := db.QueryRowContext(r.Context(), "SELECT COUNT(*) FROM users").Scan(&count); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + if err := tx.QueryRowContext(r.Context(), "SELECT COUNT(*) FROM users").Scan(&count); err != nil { + serverError(w, r, err) return } if count > 0 { @@ -57,34 +76,29 @@ func handleBootstrap(db *sql.DB) http.HandlerFunc { } var userID int64 - if err := db.QueryRowContext(r.Context(), + if err := tx.QueryRowContext(r.Context(), "INSERT INTO users (username, email, password_hash, is_admin) VALUES ($1, $2, $3, true) RETURNING id", req.Username, req.Email, passwordHash).Scan(&userID); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } raw, hash, err := randomToken() if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } var keyID int64 - if err := db.QueryRowContext(r.Context(), + if err := tx.QueryRowContext(r.Context(), "INSERT INTO api_keys (user_id, key_hash, name) VALUES ($1, $2, $3) RETURNING id", userID, hash, "bootstrap").Scan(&keyID); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } - // The default team exists from migration 003, on a fresh install too. - // Without a membership the first user signs in to a working server with - // no queue, no schedule and nowhere for an integration to hang off. - if teamID, err := defaultTeamID(r.Context(), db); err == nil { - db.ExecContext(r.Context(), //nolint:errcheck - "INSERT INTO team_members (team_id, user_id, role) VALUES ($1, $2, $3) "+ - "ON CONFLICT (team_id, user_id) DO NOTHING", - teamID, userID, models.RoleOwner) + if err := tx.Commit(); err != nil { + serverError(w, r, err) + return } user, _ := fetchUser(r.Context(), db, userID) @@ -93,12 +107,19 @@ func handleBootstrap(db *sql.DB) http.HandlerFunc { } } +// handleListUsers is readable by anyone signed in, because the assignment +// control and the schedule need to name people. What it returns about other +// people is therefore only what naming them takes: email and ntfy_topic are +// blanked unless the caller is an admin or the row is their own. The topic in +// particular is a publish secret. func handleListUsers(db *sql.DB) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { + caller, _ := userFromContext(r.Context()) + seeAll := caller.IsAdmin rows, err := db.QueryContext(r.Context(), "SELECT id, username, email, created_at, ntfy_topic, is_admin, admin_source, disabled_at FROM users ORDER BY id") if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } defer rows.Close() @@ -109,15 +130,19 @@ func handleListUsers(db *sql.DB) http.HandlerFunc { var ts int64 var disabled *int64 if err := rows.Scan(&u.ID, &u.Username, &u.Email, &ts, &u.NtfyTopic, &u.IsAdmin, &u.AdminSource, &disabled); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } u.CreatedAt = time.Unix(ts, 0).UTC() u.DisabledAt = unixPtr(disabled) + if !seeAll && u.ID != caller.ID { + u.Email = "" + u.NtfyTopic = nil + } users = append(users, u) } if err := rows.Err(); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, users) @@ -147,7 +172,7 @@ func handleCreateUser(db *sql.DB) http.HandlerFunc { respond(w, http.StatusConflict, errResp("username or email already exists")) return } - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } user, _ := fetchUser(r.Context(), db, id) @@ -185,7 +210,7 @@ func handleSetNotifyTarget(db *sql.DB) http.HandlerFunc { res, err := db.ExecContext(r.Context(), "UPDATE users SET ntfy_topic = $1 WHERE id = $2", topic, id) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if n, _ := res.RowsAffected(); n == 0 { @@ -195,7 +220,7 @@ func handleSetNotifyTarget(db *sql.DB) http.HandlerFunc { user, err := fetchUser(r.Context(), db, id) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, user) @@ -217,7 +242,7 @@ func handleDeleteUser(db *sql.DB) http.HandlerFunc { return } if last, err := isLastAdmin(r.Context(), db, id); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } else if last { respond(w, http.StatusConflict, errResp("cannot delete the last administrator")) @@ -226,7 +251,7 @@ func handleDeleteUser(db *sql.DB) http.HandlerFunc { res, err := db.ExecContext(r.Context(), "DELETE FROM users WHERE id = $1", id) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } n, _ := res.RowsAffected() @@ -283,7 +308,7 @@ func handleCreateAPIKey(db *sql.DB) http.HandlerFunc { raw, hash, err := randomToken() if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } var expiresAt *int64 @@ -298,7 +323,7 @@ func handleCreateAPIKey(db *sql.DB) http.HandlerFunc { if err := db.QueryRowContext(r.Context(), "INSERT INTO api_keys (user_id, key_hash, name, expires_at) VALUES ($1, $2, $3, $4) RETURNING id", userID, hash, req.Name, expiresAt).Scan(&keyID); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } key := models.APIKey{ @@ -329,7 +354,7 @@ func handleListAPIKeys(db *sql.DB) http.HandlerFunc { `SELECT id, name, created_at, last_used_at, expires_at FROM api_keys WHERE user_id = $1 ORDER BY created_at DESC`, userID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } defer rows.Close() @@ -340,7 +365,7 @@ func handleListAPIKeys(db *sql.DB) http.HandlerFunc { var created int64 var lastUsed, expires *int64 if err := rows.Scan(&k.ID, &k.Name, &created, &lastUsed, &expires); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } k.UserID = userID @@ -350,7 +375,7 @@ func handleListAPIKeys(db *sql.DB) http.HandlerFunc { keys = append(keys, k) } if err := rows.Err(); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, keys) @@ -376,7 +401,7 @@ func handleDeleteAPIKey(db *sql.DB) http.HandlerFunc { res, err := db.ExecContext(r.Context(), "DELETE FROM api_keys WHERE id = $1 AND user_id = $2", keyID, userID) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } n, _ := res.RowsAffected() @@ -442,7 +467,7 @@ func handleSetAdmin(db *sql.DB) http.HandlerFunc { if err := db.QueryRowContext(r.Context(), "SELECT EXISTS (SELECT 1 FROM users WHERE id = $1 AND is_admin AND admin_source = 'oidc')", id).Scan(&managed); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if managed { @@ -456,7 +481,7 @@ func handleSetAdmin(db *sql.DB) http.HandlerFunc { return } if last, err := isLastAdmin(r.Context(), db, id); err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } else if last { respond(w, http.StatusConflict, errResp("cannot revoke the last administrator")) @@ -467,7 +492,7 @@ func handleSetAdmin(db *sql.DB) http.HandlerFunc { res, err := db.ExecContext(r.Context(), "UPDATE users SET is_admin = $1 WHERE id = $2", *req.IsAdmin, id) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } if n, _ := res.RowsAffected(); n == 0 { @@ -477,7 +502,7 @@ func handleSetAdmin(db *sql.DB) http.HandlerFunc { user, err := fetchUser(r.Context(), db, id) if err != nil { - respond(w, http.StatusInternalServerError, errResp("internal error")) + serverError(w, r, err) return } respond(w, http.StatusOK, user) diff --git a/internal/config/config.go b/internal/config/config.go index 565638c..581bbd4 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -5,17 +5,21 @@ import ( "fmt" "net/url" "os" + "strconv" "strings" "time" ) +// MinOperatorKeyLength is the shortest TERDUT_OPERATOR_KEY accepted: it is a +// bearer credential with instance reach, so a short one is refused outright. +const MinOperatorKeyLength = 32 + type Config struct { Addr string // DSN is the Postgres connection string, e.g. // postgres://terdut:secret@host:5432/terdut?sslmode=require. Required: - // unlike the SQLite path it replaced there is no sensible default, and a - // server that silently came up against the wrong database would be worse + // there is no sensible default, and a server that silently came up against the wrong database would be worse // than one that refuses to start. DSN string @@ -26,25 +30,6 @@ type Config struct { // repeat_interval (default 4h), which is what refreshes the alert. StaleAfter time.Duration - // DeadmanMatchers selects the alerts that are heartbeats rather than - // problems: receiving one opens no incident, and the absence of one does. - // - // ";" separates matchers, "," the label conditions within one, "=" is exact - // equality — `alertname=Watchdog,cluster=prod; alertname=Heartbeat`. Every - // matcher must name an alertname. See api.ParseDeadmanConfig. - DeadmanMatchers string - - // DeadmanTimeout is how long a heartbeat may go unheard before its switch is - // declared dead. It must be *shorter* than the Alertmanager repeat_interval - // of the route carrying the heartbeat — the opposite of StaleAfter, and the - // reason a dead man's switch usually wants a route of its own. Zero disables - // dead man's switch handling entirely. - DeadmanTimeout time.Duration - - // DeadmanSeverity is the severity a dead man's switch incident opens at. - // These incidents have no member alerts to derive one from. - DeadmanSeverity string - // NtfyURL is the ntfy server push notifications are published to. Empty // disables notifications entirely. NtfyURL string @@ -70,6 +55,20 @@ type Config struct { // Config, which is what a test or a new caller builds, keeps passwords working. DisablePasswordLogin bool + // OperatorKey, when set, is the credential of the instance-scoped service + // account "terdut-operator", created or re-keyed at every start. It is how + // terdut-operator gets in without a bootstrap handshake: the operator + // generates the key, hands it to the server here, and uses it as its bearer + // token. Empty means no such account is managed. + OperatorKey string + + // TrustedProxies is how many reverse proxies sit in front of the server and + // append to X-Forwarded-For. The per-address rate limits take the client + // address that many entries from the right, because everything further left + // is whatever the client chose to send. 0 ignores the header and uses the + // connection's own address. + TrustedProxies int + // OIDC configures single sign-on. The zero value, with no Issuer, is off. OIDC OIDC @@ -133,24 +132,12 @@ func Load() Config { if addr == "" { addr = ":8080" } - deadmanMatchers := os.Getenv("TERDUT_DEADMAN_MATCHERS") - if deadmanMatchers == "" { - deadmanMatchers = "alertname=Watchdog" - } - deadmanSeverity := os.Getenv("TERDUT_DEADMAN_SEVERITY") - if deadmanSeverity == "" { - deadmanSeverity = "critical" - } return Config{ Addr: addr, DSN: os.Getenv("TERDUT_DB_DSN"), ArchiveAfter: duration("TERDUT_ARCHIVE_AFTER", 7*24*time.Hour), StaleAfter: duration("TERDUT_STALE_AFTER", 6*time.Hour), - DeadmanMatchers: deadmanMatchers, - DeadmanTimeout: duration("TERDUT_DEADMAN_TIMEOUT", 15*time.Minute), - DeadmanSeverity: deadmanSeverity, - NtfyURL: os.Getenv("TERDUT_NTFY_URL"), NtfyToken: os.Getenv("TERDUT_NTFY_TOKEN"), NtfyFallbackTopic: os.Getenv("TERDUT_NTFY_FALLBACK_TOPIC"), @@ -158,7 +145,10 @@ func Load() Config { NotifyRepeat: duration("TERDUT_NOTIFY_REPEAT", 15*time.Minute), DisablePasswordLogin: !boolean("TERDUT_PASSWORD_LOGIN", true), - OIDC: loadOIDC(), + + OperatorKey: strings.TrimSpace(os.Getenv("TERDUT_OPERATOR_KEY")), + TrustedProxies: integer("TERDUT_TRUSTED_PROXIES", 1), + OIDC: loadOIDC(), OperatorMode: boolean("TERDUT_OPERATOR_MODE", false), } @@ -187,6 +177,9 @@ func loadOIDC() OIDC { // provider would come up and then fail every login, which is harder to notice // than not starting. func (c Config) Validate() error { + if c.OperatorKey != "" && len(c.OperatorKey) < MinOperatorKeyLength { + return fmt.Errorf("TERDUT_OPERATOR_KEY must be at least %d characters", MinOperatorKeyLength) + } o := c.OIDC if !o.Enabled() { if c.DisablePasswordLogin { @@ -226,6 +219,16 @@ func str(env, def string) string { return def } +// integer reads a non-negative int env var; anything else takes the default. +func integer(env string, def int) int { + if s := os.Getenv(env); s != "" { + if n, err := strconv.Atoi(strings.TrimSpace(s)); err == nil && n >= 0 { + return n + } + } + return def +} + // list reads a comma- or space-separated env var. func list(env, def string) []string { s := os.Getenv(env) diff --git a/internal/db/db.go b/internal/db/db.go index c43bce8..5b14708 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -35,8 +35,7 @@ const ( // // The pool is modest on purpose: this server's concurrency comes from a handful // of HTTP handlers plus two background loops, and a cloud-native-pg instance -// sized for it has a low max_connections. It is still a pool, unlike the single -// connection SQLite forced, so the notifier no longer blocks a webhook. +// sized for it has a low max_connections. func Open(dsn string) (*sql.DB, error) { if dsn == "" { return nil, fmt.Errorf("empty DSN: set TERDUT_DB_DSN") @@ -76,9 +75,8 @@ const migrationLockKey int64 = 7265_0003 // Migrate applies every embedded migration that has not been applied yet, in // filename order, recording each in schema_migrations. // -// Each file runs inside a transaction, which SQLite's version did not do: a -// migration that failed half way used to leave the schema in whatever state it -// had reached. Postgres has transactional DDL, so the rollback is real. +// Each file runs inside a transaction, so a migration that fails half way +// leaves the schema as it was: Postgres has transactional DDL. func Migrate(db *sql.DB) error { ctx := context.Background() conn, err := db.Conn(ctx) diff --git a/internal/db/migrations/001_schema.sql b/internal/db/migrations/001_schema.sql new file mode 100644 index 0000000..a7cb016 --- /dev/null +++ b/internal/db/migrations/001_schema.sql @@ -0,0 +1,587 @@ +-- Terdut Server schema. One baseline: the project has not shipped, so the +-- migration history that led here (SQLite import, a Default team, per-team +-- deadman configs later replaced by switches) is not carried. Later changes are +-- new numbered files after this one. +-- +-- Timestamps are Unix epoch seconds in BIGINT columns throughout. + +CREATE TABLE alerts ( + id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, + fingerprint text NOT NULL, + name text NOT NULL, + status text NOT NULL, + labels jsonb DEFAULT '{}'::jsonb NOT NULL, + annotations jsonb DEFAULT '{}'::jsonb NOT NULL, + starts_at bigint NOT NULL, + ends_at bigint, + generator_url text DEFAULT ''::text NOT NULL, + received_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, + archived_at bigint, + resolution_source text, + team_id bigint NOT NULL, + integration_id bigint, + CONSTRAINT alerts_status_check CHECK ((status = ANY (ARRAY['firing'::text, 'resolved'::text]))) +); + +CREATE TABLE api_keys ( + id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, + user_id bigint NOT NULL, + key_hash text NOT NULL, + name text NOT NULL, + created_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, + last_used_at bigint, + expires_at bigint +); + +CREATE TABLE deadman_switches ( + id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, + team_id bigint NOT NULL, + name text NOT NULL, + matcher text NOT NULL, + timeout_seconds bigint NOT NULL, + severity text DEFAULT 'critical'::text NOT NULL, + created_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, + CONSTRAINT deadman_switches_timeout_seconds_check CHECK ((timeout_seconds > 0)) +); + +CREATE TABLE device_logins ( + device_hash text NOT NULL, + user_code text NOT NULL, + status text DEFAULT 'pending'::text NOT NULL, + user_id bigint, + expires_at bigint NOT NULL, + last_polled_at bigint DEFAULT 0 NOT NULL, + CONSTRAINT device_logins_status_check CHECK ((status = ANY (ARRAY['pending'::text, 'approved'::text, 'denied'::text]))) +); + +CREATE TABLE escalation_levels ( + id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, + team_id bigint NOT NULL, + "position" bigint NOT NULL, + timeout_seconds bigint NOT NULL, + CONSTRAINT escalation_levels_timeout_seconds_check CHECK ((timeout_seconds > 0)) +); + +CREATE TABLE escalation_policies ( + team_id bigint NOT NULL, + repeat_count bigint DEFAULT 0 NOT NULL, + fallback_topic text DEFAULT ''::text NOT NULL, + updated_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, + CONSTRAINT escalation_policies_repeat_count_check CHECK (((repeat_count >= 0) AND (repeat_count <= 10))) +); + +CREATE TABLE escalation_targets ( + id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, + level_id bigint NOT NULL, + kind text NOT NULL, + user_id bigint, + CONSTRAINT escalation_targets_check CHECK ((((kind = 'user'::text) AND (user_id IS NOT NULL)) OR ((kind = 'oncall'::text) AND (user_id IS NULL)))), + CONSTRAINT escalation_targets_kind_check CHECK ((kind = ANY (ARRAY['user'::text, 'oncall'::text]))) +); + +CREATE TABLE incident_ack_tokens ( + token_hash text NOT NULL, + incident_id bigint NOT NULL, + user_id bigint NOT NULL, + created_at bigint NOT NULL, + expires_at bigint NOT NULL +); + +CREATE TABLE incident_alerts ( + incident_id bigint NOT NULL, + alert_id bigint NOT NULL, + added_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL +); + +CREATE TABLE incident_events ( + id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, + incident_id bigint NOT NULL, + type text NOT NULL, + user_id bigint, + alert_id bigint, + detail text, + created_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, + service_account_id bigint, + actor_user_id bigint, + actor_service_account_id bigint, + CONSTRAINT incident_events_actor_xor_chk CHECK (((user_id IS NULL) OR (service_account_id IS NULL))), + CONSTRAINT incident_events_assign_actor_xor_chk CHECK (((actor_user_id IS NULL) OR (actor_service_account_id IS NULL))) +); + +CREATE TABLE incidents ( + id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, + group_key text NOT NULL, + title text NOT NULL, + group_labels jsonb DEFAULT '{}'::jsonb NOT NULL, + status text NOT NULL, + severity text, + triggered_at bigint NOT NULL, + acknowledged_by bigint, + acknowledged_at bigint, + assigned_to bigint, + snoozed_until bigint, + resolved_at bigint, + resolution_source text, + archived_at bigint, + team_id bigint NOT NULL, + escalation_level bigint DEFAULT 0 NOT NULL, + escalation_level_at bigint, + escalation_round bigint DEFAULT 0 NOT NULL, + signature text DEFAULT ''::text NOT NULL, + acknowledged_by_service_account_id bigint, + CONSTRAINT incidents_ack_actor_xor_chk CHECK (((acknowledged_by IS NULL) OR (acknowledged_by_service_account_id IS NULL))), + CONSTRAINT incidents_status_check CHECK ((status = ANY (ARRAY['triggered'::text, 'acknowledged'::text, 'resolved'::text]))) +); + +CREATE TABLE integrations ( + id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, + team_id bigint NOT NULL, + kind text NOT NULL, + name text NOT NULL, + key_hash text NOT NULL, + created_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, + last_used_at bigint, + CONSTRAINT integrations_kind_check CHECK ((kind = 'alertmanager'::text)) +); + +CREATE TABLE invites ( + id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, + token_hash text NOT NULL, + team_id bigint NOT NULL, + role text NOT NULL, + created_by bigint, + created_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, + expires_at bigint NOT NULL, + max_uses bigint DEFAULT 1 NOT NULL, + uses bigint DEFAULT 0 NOT NULL, + revoked_at bigint, + CONSTRAINT invites_max_uses_check CHECK (((max_uses > 0) AND (max_uses <= 100))), + CONSTRAINT invites_role_check CHECK ((role = ANY (ARRAY['owner'::text, 'member'::text]))) +); + +CREATE TABLE notifications ( + id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, + incident_id bigint NOT NULL, + user_id bigint, + topic text NOT NULL, + kind text NOT NULL, + created_at bigint NOT NULL, + send_after bigint NOT NULL, + attempts bigint DEFAULT 0 NOT NULL, + sent_at bigint, + last_error text, + CONSTRAINT notifications_kind_check CHECK ((kind = ANY (ARRAY['triggered'::text, 'reminder'::text, 'resolved'::text, 'escalated'::text]))) +); + +CREATE TABLE oidc_logins ( + state_hash text NOT NULL, + nonce text NOT NULL, + pkce_verifier text NOT NULL, + expires_at bigint NOT NULL, + next text DEFAULT '/'::text NOT NULL +); + +CREATE TABLE rate_limit_counters ( + key text NOT NULL, + window_start bigint NOT NULL, + count integer NOT NULL +); + +CREATE TABLE schedule_entries ( + id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, + user_id bigint NOT NULL, + date text NOT NULL, + created_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, + team_id bigint NOT NULL +); + +CREATE TABLE service_account_keys ( + id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, + service_account_id bigint NOT NULL, + key_hash text NOT NULL, + name text NOT NULL, + created_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, + last_used_at bigint +); + +CREATE TABLE service_accounts ( + id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, + name text NOT NULL, + scope text NOT NULL, + team_id bigint, + created_by bigint, + created_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, + CONSTRAINT service_accounts_scope_check CHECK ((scope = ANY (ARRAY['instance'::text, 'team'::text]))), + CONSTRAINT service_accounts_scope_team_id_chk CHECK ((((scope = 'team'::text) AND (team_id IS NOT NULL)) OR ((scope = 'instance'::text) AND (team_id IS NULL)))) +); + +CREATE TABLE sessions ( + id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, + token_hash text NOT NULL, + user_id bigint NOT NULL, + created_at bigint NOT NULL, + last_seen_at bigint NOT NULL, + expires_at bigint NOT NULL, + user_agent text, + max_expires_at bigint +); + +CREATE TABLE settings ( + key text NOT NULL, + value text NOT NULL, + updated_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL +); + +CREATE TABLE team_members ( + team_id bigint NOT NULL, + user_id bigint NOT NULL, + role text NOT NULL, + joined_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, + source text DEFAULT 'manual'::text NOT NULL, + CONSTRAINT team_members_role_check CHECK ((role = ANY (ARRAY['owner'::text, 'member'::text]))), + CONSTRAINT team_members_source_check CHECK ((source = ANY (ARRAY['manual'::text, 'oidc'::text]))) +); + +CREATE TABLE teams ( + id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, + name text NOT NULL, + created_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, + oidc_member_group text, + oidc_owner_group text, + -- A stable identity for a team managed by automation (terdut-operator: + -- "/" of its TerdutTeam), so it can find or recreate its own + -- team without trusting a display name. NULL for a team a person made. + external_id text +); + +CREATE TABLE user_identities ( + id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, + user_id bigint NOT NULL, + issuer text NOT NULL, + subject text NOT NULL, + created_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, + last_login_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL +); + +CREATE TABLE users ( + id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, + username text NOT NULL, + email text NOT NULL, + created_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, + ntfy_topic text, + password_hash text, + is_admin boolean DEFAULT false NOT NULL, + disabled_at bigint, + invited_via bigint, + onboarding_dismissed_at bigint, + admin_source text DEFAULT 'manual'::text NOT NULL, + CONSTRAINT users_admin_source_check CHECK ((admin_source = ANY (ARRAY['manual'::text, 'oidc'::text]))) +); + +ALTER TABLE alerts + ADD CONSTRAINT alerts_pkey PRIMARY KEY (id); + +ALTER TABLE api_keys + ADD CONSTRAINT api_keys_key_hash_key UNIQUE (key_hash); + +ALTER TABLE api_keys + ADD CONSTRAINT api_keys_pkey PRIMARY KEY (id); + +ALTER TABLE deadman_switches + ADD CONSTRAINT deadman_switches_pkey PRIMARY KEY (id); + +ALTER TABLE device_logins + ADD CONSTRAINT device_logins_pkey PRIMARY KEY (device_hash); + +ALTER TABLE device_logins + ADD CONSTRAINT device_logins_user_code_key UNIQUE (user_code); + +ALTER TABLE escalation_levels + ADD CONSTRAINT escalation_levels_pkey PRIMARY KEY (id); + +ALTER TABLE escalation_levels + ADD CONSTRAINT escalation_levels_team_id_position_key UNIQUE (team_id, "position"); + +ALTER TABLE escalation_policies + ADD CONSTRAINT escalation_policies_pkey PRIMARY KEY (team_id); + +ALTER TABLE escalation_targets + ADD CONSTRAINT escalation_targets_pkey PRIMARY KEY (id); + +ALTER TABLE incident_ack_tokens + ADD CONSTRAINT incident_ack_tokens_pkey PRIMARY KEY (token_hash); + +ALTER TABLE incident_alerts + ADD CONSTRAINT incident_alerts_pkey PRIMARY KEY (incident_id, alert_id); + +ALTER TABLE incident_events + ADD CONSTRAINT incident_events_pkey PRIMARY KEY (id); + +ALTER TABLE incidents + ADD CONSTRAINT incidents_pkey PRIMARY KEY (id); + +ALTER TABLE integrations + ADD CONSTRAINT integrations_key_hash_key UNIQUE (key_hash); + +ALTER TABLE integrations + ADD CONSTRAINT integrations_pkey PRIMARY KEY (id); + +ALTER TABLE invites + ADD CONSTRAINT invites_pkey PRIMARY KEY (id); + +ALTER TABLE invites + ADD CONSTRAINT invites_token_hash_key UNIQUE (token_hash); + +ALTER TABLE notifications + ADD CONSTRAINT notifications_pkey PRIMARY KEY (id); + +ALTER TABLE oidc_logins + ADD CONSTRAINT oidc_logins_pkey PRIMARY KEY (state_hash); + +ALTER TABLE rate_limit_counters + ADD CONSTRAINT rate_limit_counters_pkey PRIMARY KEY (key); + +ALTER TABLE schedule_entries + ADD CONSTRAINT schedule_entries_pkey PRIMARY KEY (id); + +ALTER TABLE service_account_keys + ADD CONSTRAINT service_account_keys_key_hash_key UNIQUE (key_hash); + +ALTER TABLE service_account_keys + ADD CONSTRAINT service_account_keys_pkey PRIMARY KEY (id); + +ALTER TABLE service_accounts + ADD CONSTRAINT service_accounts_name_key UNIQUE (name); + +ALTER TABLE service_accounts + ADD CONSTRAINT service_accounts_pkey PRIMARY KEY (id); + +ALTER TABLE sessions + ADD CONSTRAINT sessions_pkey PRIMARY KEY (id); + +ALTER TABLE sessions + ADD CONSTRAINT sessions_token_hash_key UNIQUE (token_hash); + +ALTER TABLE settings + ADD CONSTRAINT settings_pkey PRIMARY KEY (key); + +ALTER TABLE team_members + ADD CONSTRAINT team_members_pkey PRIMARY KEY (team_id, user_id); + +ALTER TABLE teams + ADD CONSTRAINT teams_name_key UNIQUE (name); + +ALTER TABLE teams + ADD CONSTRAINT teams_external_id_key UNIQUE (external_id); + +ALTER TABLE teams + ADD CONSTRAINT teams_pkey PRIMARY KEY (id); + +ALTER TABLE user_identities + ADD CONSTRAINT user_identities_issuer_subject_key UNIQUE (issuer, subject); + +ALTER TABLE user_identities + ADD CONSTRAINT user_identities_pkey PRIMARY KEY (id); + +ALTER TABLE users + ADD CONSTRAINT users_email_key UNIQUE (email); + +ALTER TABLE users + ADD CONSTRAINT users_pkey PRIMARY KEY (id); + +ALTER TABLE users + ADD CONSTRAINT users_username_key UNIQUE (username); + +CREATE INDEX alerts_archived_at_idx ON alerts USING btree (archived_at); + +CREATE INDEX alerts_integration_idx ON alerts USING btree (integration_id, received_at) WHERE (integration_id IS NOT NULL); + +CREATE INDEX alerts_name_idx ON alerts USING btree (name); + +CREATE INDEX alerts_received_at_idx ON alerts USING btree (received_at DESC); + +CREATE INDEX alerts_status_idx ON alerts USING btree (status); + +CREATE UNIQUE INDEX alerts_team_fingerprint_idx ON alerts USING btree (team_id, fingerprint); + +CREATE INDEX alerts_team_received_idx ON alerts USING btree (team_id, received_at DESC); + +CREATE INDEX deadman_switches_team_idx ON deadman_switches USING btree (team_id); + +CREATE INDEX device_logins_expires_idx ON device_logins USING btree (expires_at); + +CREATE INDEX escalation_targets_level_idx ON escalation_targets USING btree (level_id); + +CREATE INDEX idx_sessions_user ON sessions USING btree (user_id); + +CREATE INDEX incident_ack_tokens_expires_idx ON incident_ack_tokens USING btree (expires_at); + +CREATE INDEX incident_alerts_alert_id_idx ON incident_alerts USING btree (alert_id); + +CREATE INDEX incident_events_actor_service_account_id_idx ON incident_events USING btree (actor_service_account_id); + +CREATE INDEX incident_events_actor_user_id_idx ON incident_events USING btree (actor_user_id); + +CREATE INDEX incident_events_incident_idx ON incident_events USING btree (incident_id, created_at); + +CREATE INDEX incident_events_service_account_id_idx ON incident_events USING btree (service_account_id); + +CREATE INDEX incidents_acknowledged_by_service_account_id_idx ON incidents USING btree (acknowledged_by_service_account_id); + +CREATE INDEX incidents_archived_at_idx ON incidents USING btree (archived_at); + +CREATE INDEX incidents_escalation_idx ON incidents USING btree (escalation_level_at) WHERE ((resolved_at IS NULL) AND (status = 'triggered'::text)); + +CREATE UNIQUE INDEX incidents_open_group_key_idx ON incidents USING btree (team_id, group_key) WHERE (resolved_at IS NULL); + +CREATE INDEX incidents_signature_idx ON incidents USING btree (team_id, signature, triggered_at DESC); + +CREATE INDEX incidents_status_idx ON incidents USING btree (status); + +CREATE INDEX incidents_team_triggered_idx ON incidents USING btree (team_id, triggered_at DESC); + +CREATE INDEX incidents_triggered_at_idx ON incidents USING btree (triggered_at DESC); + +CREATE INDEX integrations_team_idx ON integrations USING btree (team_id); + +-- A name identifies an integration (and a switch) within its team, so a client +-- that manages them declaratively can look one up by name instead of listing +-- and matching. +CREATE UNIQUE INDEX integrations_team_name_key ON integrations (team_id, name); +CREATE UNIQUE INDEX deadman_switches_team_name_key ON deadman_switches (team_id, name); + +CREATE INDEX invites_team_idx ON invites USING btree (team_id); + +CREATE INDEX notifications_incident_idx ON notifications USING btree (incident_id, id DESC); + +CREATE INDEX notifications_pending_idx ON notifications USING btree (send_after) WHERE (sent_at IS NULL); + +CREATE INDEX oidc_logins_expires_idx ON oidc_logins USING btree (expires_at); + +CREATE INDEX schedule_entries_date_idx ON schedule_entries USING btree (date); + +CREATE UNIQUE INDEX schedule_entries_team_date_idx ON schedule_entries USING btree (team_id, date); + +CREATE INDEX service_account_keys_service_account_id_idx ON service_account_keys USING btree (service_account_id); + +CREATE INDEX service_accounts_team_id_idx ON service_accounts USING btree (team_id); + +CREATE INDEX team_members_user_idx ON team_members USING btree (user_id); + +CREATE INDEX user_identities_user_idx ON user_identities USING btree (user_id); + +CREATE INDEX users_is_admin_idx ON users USING btree (is_admin) WHERE is_admin; + +ALTER TABLE alerts + ADD CONSTRAINT alerts_integration_id_fkey FOREIGN KEY (integration_id) REFERENCES integrations(id) ON DELETE SET NULL; + +ALTER TABLE alerts + ADD CONSTRAINT alerts_team_id_fkey FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE; + +ALTER TABLE api_keys + ADD CONSTRAINT api_keys_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + +ALTER TABLE deadman_switches + ADD CONSTRAINT deadman_switches_team_id_fkey FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE; + +ALTER TABLE device_logins + ADD CONSTRAINT device_logins_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + +ALTER TABLE escalation_levels + ADD CONSTRAINT escalation_levels_team_id_fkey FOREIGN KEY (team_id) REFERENCES escalation_policies(team_id) ON DELETE CASCADE; + +ALTER TABLE escalation_policies + ADD CONSTRAINT escalation_policies_team_id_fkey FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE; + +ALTER TABLE escalation_targets + ADD CONSTRAINT escalation_targets_level_id_fkey FOREIGN KEY (level_id) REFERENCES escalation_levels(id) ON DELETE CASCADE; + +ALTER TABLE escalation_targets + ADD CONSTRAINT escalation_targets_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + +ALTER TABLE incident_ack_tokens + ADD CONSTRAINT incident_ack_tokens_incident_id_fkey FOREIGN KEY (incident_id) REFERENCES incidents(id) ON DELETE CASCADE; + +ALTER TABLE incident_ack_tokens + ADD CONSTRAINT incident_ack_tokens_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + +ALTER TABLE incident_alerts + ADD CONSTRAINT incident_alerts_alert_id_fkey FOREIGN KEY (alert_id) REFERENCES alerts(id) ON DELETE CASCADE; + +ALTER TABLE incident_alerts + ADD CONSTRAINT incident_alerts_incident_id_fkey FOREIGN KEY (incident_id) REFERENCES incidents(id) ON DELETE CASCADE; + +ALTER TABLE incident_events + ADD CONSTRAINT incident_events_actor_service_account_id_fkey FOREIGN KEY (actor_service_account_id) REFERENCES service_accounts(id) ON DELETE SET NULL; + +ALTER TABLE incident_events + ADD CONSTRAINT incident_events_actor_user_id_fkey FOREIGN KEY (actor_user_id) REFERENCES users(id) ON DELETE SET NULL; + +ALTER TABLE incident_events + ADD CONSTRAINT incident_events_alert_id_fkey FOREIGN KEY (alert_id) REFERENCES alerts(id) ON DELETE SET NULL; + +ALTER TABLE incident_events + ADD CONSTRAINT incident_events_incident_id_fkey FOREIGN KEY (incident_id) REFERENCES incidents(id) ON DELETE CASCADE; + +ALTER TABLE incident_events + ADD CONSTRAINT incident_events_service_account_id_fkey FOREIGN KEY (service_account_id) REFERENCES service_accounts(id) ON DELETE SET NULL; + +ALTER TABLE incident_events + ADD CONSTRAINT incident_events_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL; + +ALTER TABLE incidents + ADD CONSTRAINT incidents_acknowledged_by_fkey FOREIGN KEY (acknowledged_by) REFERENCES users(id) ON DELETE SET NULL; + +ALTER TABLE incidents + ADD CONSTRAINT incidents_acknowledged_by_service_account_id_fkey FOREIGN KEY (acknowledged_by_service_account_id) REFERENCES service_accounts(id) ON DELETE SET NULL; + +ALTER TABLE incidents + ADD CONSTRAINT incidents_assigned_to_fkey FOREIGN KEY (assigned_to) REFERENCES users(id) ON DELETE SET NULL; + +ALTER TABLE incidents + ADD CONSTRAINT incidents_team_id_fkey FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE; + +ALTER TABLE integrations + ADD CONSTRAINT integrations_team_id_fkey FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE; + +ALTER TABLE invites + ADD CONSTRAINT invites_created_by_fkey FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL; + +ALTER TABLE invites + ADD CONSTRAINT invites_team_id_fkey FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE; + +ALTER TABLE notifications + ADD CONSTRAINT notifications_incident_id_fkey FOREIGN KEY (incident_id) REFERENCES incidents(id) ON DELETE CASCADE; + +ALTER TABLE notifications + ADD CONSTRAINT notifications_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL; + +ALTER TABLE schedule_entries + ADD CONSTRAINT schedule_entries_team_id_fkey FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE; + +ALTER TABLE schedule_entries + ADD CONSTRAINT schedule_entries_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + +ALTER TABLE service_account_keys + ADD CONSTRAINT service_account_keys_service_account_id_fkey FOREIGN KEY (service_account_id) REFERENCES service_accounts(id) ON DELETE CASCADE; + +ALTER TABLE service_accounts + ADD CONSTRAINT service_accounts_created_by_fkey FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL; + +ALTER TABLE service_accounts + ADD CONSTRAINT service_accounts_team_id_fkey FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE; + +ALTER TABLE sessions + ADD CONSTRAINT sessions_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + +ALTER TABLE team_members + ADD CONSTRAINT team_members_team_id_fkey FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE; + +ALTER TABLE team_members + ADD CONSTRAINT team_members_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + +ALTER TABLE user_identities + ADD CONSTRAINT user_identities_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + +ALTER TABLE users + ADD CONSTRAINT users_invited_via_fkey FOREIGN KEY (invited_via) REFERENCES invites(id) ON DELETE SET NULL; diff --git a/internal/models/alert.go b/internal/models/alert.go index 01047e8..c6e0356 100644 --- a/internal/models/alert.go +++ b/internal/models/alert.go @@ -33,7 +33,7 @@ type Alert struct { // refreshed. The sweeper stale-dates against it (see expireStale), API // clients render it, and GET /api/alerts is ordered by it. Anything that // stops the webhook handler from advancing it on a re-send is a breaking - // change — see "received_at is a liveness heartbeat" in the README and + // change — see "received_at is a liveness heartbeat" in docs/api.md and // TestWebhook_ResendBumpsReceivedAt. ReceivedAt time.Time `json:"received_at"` @@ -52,7 +52,7 @@ type Alert struct { // inferred. Under "expiry" nothing ever reported an end, so EndsAt is only // an upper bound (see expireStale) and ReceivedAt is the more truthful // signal. Treat the value set as open — see "resolution_source says how much - // to trust ends_at" in the README, and TestWebhook_ResolvedSetsSource / + // to trust ends_at" in docs/api.md, and TestWebhook_ResolvedSetsSource / // TestExpiry_StaleFiringAlert. ResolutionSource *string `json:"resolution_source,omitempty"` diff --git a/internal/models/team.go b/internal/models/team.go index 8bedf25..0ed6365 100644 --- a/internal/models/team.go +++ b/internal/models/team.go @@ -9,6 +9,10 @@ type Team struct { Name string `json:"name"` CreatedAt time.Time `json:"created_at"` + // ExternalID identifies a team managed by automation; see handleCreateTeam. + // Shown to instance service accounts and admins only. + ExternalID *string `json:"external_id,omitempty"` + // Role is the caller's own role in this team, populated when a team is // listed for a particular person. Empty when nobody in particular is // asking, as in the admin listing. diff --git a/internal/oidc/grants.go b/internal/oidc/grants.go index 2a67a65..4de53a1 100644 --- a/internal/oidc/grants.go +++ b/internal/oidc/grants.go @@ -102,6 +102,3 @@ func rank(role string) int { } return 0 } - -// HigherRole reports whether role a outranks role b. -func HigherRole(a, b string) bool { return rank(a) > rank(b) } diff --git a/internal/web/static/js/format.js b/internal/web/static/js/format.js index 9bf994f..98be815 100644 --- a/internal/web/static/js/format.js +++ b/internal/web/static/js/format.js @@ -123,7 +123,7 @@ export function initial(name) { // convention. It comes from Prometheus's externalLabels, so it is on every // alert; an incident carries it only when it is in Alertmanager's group_by, // which is also what keeps two clusters' identical alerts from merging into one -// incident (see the README, "Several clusters, one team"). +// incident (see docs/incidents.md, "Several clusters, one team"). export const ORIGIN_LABEL = 'cluster'; export function originOf(labels) { -- 2.52.0 From eb63e5e138606d047165e7ed18bbd4d2967a408a Mon Sep 17 00:00:00 2001 From: Niklas Ye Date: Fri, 9 Oct 2026 15:17:02 +0200 Subject: [PATCH 3/4] Build and scan with Go 1.26.9 govulncheck in the security job reports ten standard-library vulnerabilities (net/http, mime/multipart, crypto/tls), all fixed in 1.26.9. The workflows pinned golang:1.26.6-bookworm. Claude-Session: https://claude.ai/code/session_016mBLURvJoMuUEr9cB2RpUN --- .gitea/workflows/ci.yaml | 4 ++-- .gitea/workflows/release.yaml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml index 3111081..09cd03d 100644 --- a/.gitea/workflows/ci.yaml +++ b/.gitea/workflows/ci.yaml @@ -35,7 +35,7 @@ jobs: # Runs inside the toolchain image rather than installing Go per job. Note this puts # the job on the dind bridge, which cannot reach github.com or get.helm.sh -- # proxy.golang.org and git.ryuvia.com are reachable, which is all this job needs. - image: golang:1.26.6-bookworm + image: golang:1.26.9-bookworm # act_runner destroys a job's own volumes when it finishes, so without these every # run re-downloads the whole module graph. The names must appear in the runner's # container.valid_volumes allowlist (charts/act-runner in the k8s repo); unlisted @@ -101,7 +101,7 @@ jobs: security: runs-on: ubuntu-latest container: - image: golang:1.26.6-bookworm + image: golang:1.26.9-bookworm volumes: - go-mod-cache:/go/pkg/mod - go-build-cache:/root/.cache/go-build diff --git a/.gitea/workflows/release.yaml b/.gitea/workflows/release.yaml index 50bd5ff..c4ded87 100644 --- a/.gitea/workflows/release.yaml +++ b/.gitea/workflows/release.yaml @@ -30,7 +30,7 @@ jobs: test: runs-on: ubuntu-latest container: - image: golang:1.26.6-bookworm + image: golang:1.26.9-bookworm volumes: - go-mod-cache:/go/pkg/mod - go-build-cache:/root/.cache/go-build @@ -71,7 +71,7 @@ jobs: needs: test runs-on: ubuntu-latest container: - image: golang:1.26.6-bookworm + image: golang:1.26.9-bookworm volumes: - go-mod-cache:/go/pkg/mod - go-build-cache:/root/.cache/go-build -- 2.52.0 From 01922291f600d302fe61ed3654fb28061f2bb1f3 Mon Sep 17 00:00:00 2001 From: Niklas Ye Date: Fri, 9 Oct 2026 15:27:45 +0200 Subject: [PATCH 4/4] Satisfy gosec on the proxy count and the request log G115: the trusted-proxy count is stored as an int64 instead of narrowing it to int32. G706: the request logger and serverError quote the request method and route; the logger's remaining taint comes from the wrapped response writer, so it carries a justified nosec like the other quoted log lines. Claude-Session: https://claude.ai/code/session_016mBLURvJoMuUEr9cB2RpUN --- internal/api/auth.go | 2 +- internal/api/helpers.go | 2 +- internal/api/middleware.go | 2 +- internal/api/router.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/api/auth.go b/internal/api/auth.go index 100acfb..38feff9 100644 --- a/internal/api/auth.go +++ b/internal/api/auth.go @@ -132,7 +132,7 @@ func purgeRateLimits(ctx context.Context, db *sql.DB) { // trustedProxies is how many X-Forwarded-For hops clientAddr trusts. Set once // by NewRouter from config. -var trustedProxies atomic.Int32 +var trustedProxies atomic.Int64 // clientAddr is the address a login is counted against. Behind the gateway // RemoteAddr is the gateway itself, so the client address is read from diff --git a/internal/api/helpers.go b/internal/api/helpers.go index 1b73b51..2ae751e 100644 --- a/internal/api/helpers.go +++ b/internal/api/helpers.go @@ -77,7 +77,7 @@ func serverError(w http.ResponseWriter, r *http.Request, err error) { if rc := chi.RouteContext(r.Context()); rc != nil && rc.RoutePattern() != "" { route = rc.RoutePattern() } - log.Printf("%s %s: %v", r.Method, route, err) + log.Printf("%s %s: %v", strconv.Quote(r.Method), strconv.Quote(route), err) respond(w, http.StatusInternalServerError, errResp("internal error")) } diff --git a/internal/api/middleware.go b/internal/api/middleware.go index a9e0fc6..462b386 100644 --- a/internal/api/middleware.go +++ b/internal/api/middleware.go @@ -447,6 +447,6 @@ func requestLogger(next http.Handler) http.Handler { if status == 0 { status = http.StatusOK } - log.Printf("%s %s %d %dB %s", r.Method, route, status, ww.BytesWritten(), time.Since(start).Round(time.Millisecond)) + log.Printf("%q %q %d %dB %s", r.Method, route, status, ww.BytesWritten(), time.Since(start).Round(time.Millisecond)) // #nosec G706 -- method and route are %q-quoted, the route is a registered pattern, the rest are numbers }) } diff --git a/internal/api/router.go b/internal/api/router.go index 14ff537..aceecd1 100644 --- a/internal/api/router.go +++ b/internal/api/router.go @@ -23,7 +23,7 @@ func NewRouter(db *sql.DB, notify NotifyConfig, cfg config.Config, version strin // One limiter each, both process-wide for the life of the router: login // counts failed passwords, sign-up counts account creation, and mixing the // two would let a burst of sign-ups lock somebody out of logging in. - trustedProxies.Store(int32(cfg.TrustedProxies)) + trustedProxies.Store(int64(cfg.TrustedProxies)) loginLimit := newLoginLimiter(db) signupLimiter := newLoginLimiter(db) oidcLimit := newLoginLimiter(db) -- 2.52.0