From a35a7dcaad30e17ecfd0368a0a57588237648fec Mon Sep 17 00:00:00 2001 From: Florent Clairambault Date: Tue, 25 Aug 2026 00:00:56 +0000 Subject: [PATCH 1/2] chore(release): v0.18.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 7b51ca08b..5e39b9417 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.17.0" + ".": "0.18.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index f7f40f61a..5dfcf15ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [0.18.0](https://github.com/fclairamb/solidping/compare/v0.17.0...v0.18.0) (2026-08-25) + + +### Features + +* Discord bot, audit log, SLO burn-rate alerts, path tracing, support inbox, status-page branding & private pages ([#246](https://github.com/fclairamb/solidping/issues/246)) ([87b33d7](https://github.com/fclairamb/solidping/commit/87b33d70e126be02f3aef8275708310e415fcb6a)) + + +### Bug Fixes + +* **slack:** register the login callback in the prod manifest ([#251](https://github.com/fclairamb/solidping/issues/251)) ([32fae86](https://github.com/fclairamb/solidping/commit/32fae86cc55e78180e4febb53df03e5dbe394f59)) + ## [Unreleased] From 7f0740c69af4a201ad71a166c5b9dfbaef969fc8 Mon Sep 17 00:00:00 2001 From: Florent Clairambault Date: Tue, 25 Aug 2026 02:02:27 +0200 Subject: [PATCH 2/2] docs(changelog): polish v0.18.0 release notes Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 71 ++++++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5dfcf15ef..12f0e0b8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,53 +5,42 @@ ### Features -* Discord bot, audit log, SLO burn-rate alerts, path tracing, support inbox, status-page branding & private pages ([#246](https://github.com/fclairamb/solidping/issues/246)) ([87b33d7](https://github.com/fclairamb/solidping/commit/87b33d70e126be02f3aef8275708310e415fcb6a)) +* **discord:** a first-class Discord bot, not just a webhook. Install it into a server, map servers to organizations, and get incidents as bot-owned threads that edit in place and carry acknowledge and comment buttons. Org members map to Discord identities so on-call mentions reach the right person, comments posted in the thread are ingested back onto the incident through a Gateway supervisor, slash-command and mention dispatch is transport-agnostic, and every inbound interaction is Ed25519-verified with stale and unsigned requests rejected. Ships with a bot settings panel and a server-admin page in the dashboard ([#246](https://github.com/fclairamb/solidping/issues/246)) ([87b33d7](https://github.com/fclairamb/solidping/commit/87b33d70e126be02f3aef8275708310e415fcb6a)) +* **audit:** an organization audit log. Every session-minting path, membership change, token operation, config apply, and escalation / on-call / maintenance / integration / status-page mutation emits a typed event carrying actor metadata and a normalized source address. Payload redaction fails closed on anything it does not recognize, failed logins are flood-controlled, and retention is swept by a cleanup job. The events API gained family, type, actor, target and admin-only IP filters plus working cursors; the dashboard gained an admin-gated audit page; and every event family has a human identity in all four locales ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **slo:** burn-rate alerting on SLOs. Define an alert policy over an SLO and get paged when the error budget burns too fast, evaluated over multiple windows against a shared evaluator. Burn incidents are a distinct incident kind rather than a check failure, with their own lifecycle entry points, their own email and Slack templates, and a periodic sweep job. The dashboard gained an SLO alerting section, a burning badge and a policy edit route ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **diagnostics:** MTR-style path tracing on network failures. A pure-Go path prober with a privilege ladder traces the route when a network-reachability failure opens an incident, so the incident shows where the packets actually stopped. Exposed as an org-level default plus a per-check policy, rendered on the incident and on the onset result page, and pinned never-public ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **support:** a support inbox. Inbound human messages are captured from email, WhatsApp, Telegram, SMS, Slack DMs and Discord DMs into threads and messages, with idempotent capture, abuse ceilings and a mailbox mirror. Replies go back out through per-provider adapters and take their delivery status from the existing provider callbacks, and instance support Reply-To is classified fail-closed per template. Ships with a retention job, org-deletion detach, an OpenAPI-documented API and a `/support` inbox in the dashboard ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **email:** the JMAP inbox consumer is safe to run more than once — inbound mail is deduplicated by `Message-ID` before insert, claimed by archiving it before processing, and the consumer runs under a Postgres advisory lock ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **status-pages:** branding and private pages. Upload a per-page logo and favicon (gated by a white-label entitlement), password-protect a page behind an unlock cookie, and let visitors subscribe over webhook or Slack. Branding moved into settings, and public assets are authorized by file topic ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **incidents:** screenshots of what the browser saw. Browser checks can opt into capturing a screenshot on failure, persisted when the incident opens and rendered in the dashboard. Built on a new generic attachment rail (`files.topic` / `files.details`) with an agent upload endpoint, an out-of-band upload frame, a bounded TTL'd capture LRU for deported agents, orphan reaping, and attachments pinned out of public payloads ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **incidents:** acknowledgement now has a face. The acknowledging actor is resolved and exposed, every paged channel is notified that the incident was acknowledged (Telegram included), and the dashboard and the organization events feed both name who acknowledged it ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **incidents:** flapping is visible. `flap_level` is recorded and exposed on create and reopen, checks carry a live `flapState`, and the dashboard shows a flapping state on check detail plus a "flapping ×N" badge on the incidents list and detail, alongside the actual reopen-cooldown window ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **incidents:** check groups are handled as groups. Active group incidents are closed and member-row incident binding stopped, status pages consolidate group members into a single public entry, the dashboard groups active incidents by check group at read time, and hard children are re-evaluated when a parent incident opens ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **custom-domain:** an explicit custom-domain lifecycle — a stored-cert handshake, a legible 503 while the domain is not ready, a grace and re-promotion sweep, a demotion alert (including demotions reached through Verify), and DNS diagnostics surfaced in the dashboard ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **regions:** a server-scope region migration API with stale-region reconciliation at startup, plus ghost-region detection behind `GET /system/regions/health` ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **watchdog:** the platform monitors itself. A detector package feeds per-detector anomaly gauges through Prometheus, driven by an hourly platform-watchdog job with delivery and parameter validation ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **auth:** flagged accounts are forced through a password rotation, with a dedicated rotation screen in the dashboard ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **auth:** stale SSO provider links heal themselves. A soft-deleted organization used to leave its Discord guild or Slack team link alive, which permanently bricked login for everyone in that guild — the stale link is now cleared and re-linked on the next sign-in, and the same fallback covers user links across all nine connectors ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **import:** UptimeRobot as an import source, with a golden-tested converter and a dashboard source picker ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **performance:** result and chart queries seek instead of scan. Result blobs are skipped when unrequested, the keyset cursor seeks by row value, the chart fetch is split at the raw/rollup boundary into parallel tier queries (and still seeks on SQLite), a per-check per-tier recent-results filter cannot ask for a mixed tier, status-page response times are fetched per check and per tier instead of scanning results, raw-tier queries are clamped to the retention band and report the effective window, and status-page cache directives derive from page visibility ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **dash0:** faceted status and type filters on the checks list, a check filter on the incidents list, documentation links across SLOs, badges, discovery, events and dependencies, incident timestamps rendered in local time with UTC on hover, invitation email delivery status led by the address with the link as fallback, and every auth method a session can carry is labelled ([#246](https://github.com/fclairamb/solidping/issues/246)) ### Bug Fixes +* **audit:** every session-minting path is recorded, not just password logins; redaction fails closed on unrecognized payload value types and keeps pointer-valued fields; the events cursor gained a uid tie-break; the OAuth grant path is audited and the guard widened past the auth package; and an OAuth grant presented by the wrong client is recorded as token misuse ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **traceroute:** an HTTP response stall is no longer labelled a connect timeout, the connection phase resets at dial start so a redirect chain keeps a real connect timeout, a panic on either trace goroutine is recovered, the per-check policy survives export, import and clone, and an agent-uploaded capture is stamped with the probing region ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **support:** `SP_SUPPORT_RETENTION_DAYS=0` genuinely means keep forever, an abuse-ceiling drop counts as throttled rather than failed, and the re-scan path fails closed with the dedup lookup scoped to the org index ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **charts:** the tier merge is keyed on org and check so navigation cannot serve stale rows, the seam is anchored on the bucket edge with the chart window resolved once, and same-`period_start` rollup points get a uid DESC tie-break ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **status-pages:** public incident history is cached by visibility, and public pages no longer vary on `Cookie` ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **notifications:** browser push notifications are incident-aware, escalation Slack DMs address the check by name and number with an incident link, and the agent websocket subscribes to `check.created` before announcing the connection ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **checks:** the 100th auto-slugged check for one host no longer 500s, and `validating` is accepted in the status filter ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **db:** generic attachments moved out of the already-released migration 014 into a new 015 ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **config:** a hostname-derived worker slug is slugified instead of refused, and the fixed-point property holds by construction ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **dash0:** the login page no longer unmounts mid-org-picker redirect, `apiFetch` tolerates an empty body under any status rather than only 204, breadcrumb leaves resolve for every Organization tab and deep route, the SSL check type is labelled TLS across all surfaces, and an empty check duration renders a literal em dash ([#246](https://github.com/fclairamb/solidping/issues/246)) +* **docs:** the API reference index is served at `/docs/api` ([#246](https://github.com/fclairamb/solidping/issues/246)) * **slack:** register the login callback in the prod manifest ([#251](https://github.com/fclairamb/solidping/issues/251)) ([32fae86](https://github.com/fclairamb/solidping/commit/32fae86cc55e78180e4febb53df03e5dbe394f59)) -## [Unreleased] - - -### Features - -* **discord:** a first-class Discord bot, not just a webhook. Install it into a server, map servers to organizations, and get incidents as bot-owned threads that edit in place and carry acknowledge and comment buttons. Org members map to Discord identities so on-call mentions reach the right person, comments posted in the thread are ingested back onto the incident through a Gateway supervisor, slash-command and mention dispatch is transport-agnostic, and every inbound interaction is Ed25519-verified with stale and unsigned requests rejected. Ships with a bot settings panel and a server-admin page in the dashboard -* **audit:** an organization audit log. Every session-minting path, membership change, token operation, config apply, and escalation / on-call / maintenance / integration / status-page mutation emits a typed event carrying actor metadata and a normalized source address. Payload redaction fails closed on anything it does not recognize, failed logins are flood-controlled, and retention is swept by a cleanup job. The events API gained family, type, actor, target and admin-only IP filters plus working cursors; the dashboard gained an admin-gated audit page; and every event family has a human identity in all four locales -* **slo:** burn-rate alerting on SLOs. Define an alert policy over an SLO and get paged when the error budget burns too fast, evaluated over multiple windows against a shared evaluator. Burn incidents are a distinct incident kind rather than a check failure, with their own lifecycle entry points, their own email and Slack templates, and a periodic sweep job. The dashboard gained an SLO alerting section, a burning badge and a policy edit route -* **diagnostics:** MTR-style path tracing on network failures. A pure-Go path prober with a privilege ladder traces the route when a network-reachability failure opens an incident, so the incident shows where the packets actually stopped. Exposed as an org-level default plus a per-check policy, rendered on the incident and on the onset result page, and pinned never-public -* **support:** a support inbox. Inbound human messages are captured from email, WhatsApp, Telegram, SMS, Slack DMs and Discord DMs into threads and messages, with idempotent capture, abuse ceilings and a mailbox mirror. Replies go back out through per-provider adapters and take their delivery status from the existing provider callbacks, and instance support Reply-To is classified fail-closed per template. Ships with a retention job, org-deletion detach, an OpenAPI-documented API and a `/support` inbox in the dashboard -* **email:** the JMAP inbox consumer is safe to run more than once — inbound mail is deduplicated by `Message-ID` before insert, claimed by archiving it before processing, and the consumer runs under a Postgres advisory lock -* **status-pages:** branding and private pages. Upload a per-page logo and favicon (gated by a white-label entitlement), password-protect a page behind an unlock cookie, and let visitors subscribe over webhook or Slack. Branding moved into settings, and public assets are authorized by file topic -* **incidents:** screenshots of what the browser saw. Browser checks can opt into capturing a screenshot on failure, persisted when the incident opens and rendered in the dashboard. Built on a new generic attachment rail (`files.topic` / `files.details`) with an agent upload endpoint, an out-of-band upload frame, a bounded TTL'd capture LRU for deported agents, orphan reaping, and attachments pinned out of public payloads -* **incidents:** acknowledgement now has a face. The acknowledging actor is resolved and exposed, every paged channel is notified that the incident was acknowledged (Telegram included), and the dashboard and the organization events feed both name who acknowledged it -* **incidents:** flapping is visible. `flap_level` is recorded and exposed on create and reopen, checks carry a live `flapState`, and the dashboard shows a flapping state on check detail plus a "flapping ×N" badge on the incidents list and detail, alongside the actual reopen-cooldown window -* **incidents:** check groups are handled as groups. Active group incidents are closed and member-row incident binding stopped, status pages consolidate group members into a single public entry, the dashboard groups active incidents by check group at read time, and hard children are re-evaluated when a parent incident opens -* **custom-domain:** an explicit custom-domain lifecycle — a stored-cert handshake, a legible 503 while the domain is not ready, a grace and re-promotion sweep, a demotion alert (including demotions reached through Verify), and DNS diagnostics surfaced in the dashboard -* **regions:** a server-scope region migration API with stale-region reconciliation at startup, plus ghost-region detection behind `GET /system/regions/health` -* **watchdog:** the platform monitors itself. A detector package feeds per-detector anomaly gauges through Prometheus, driven by an hourly platform-watchdog job with delivery and parameter validation -* **auth:** flagged accounts are forced through a password rotation, with a dedicated rotation screen in the dashboard -* **auth:** stale SSO provider links heal themselves. A soft-deleted organization used to leave its Discord guild or Slack team link alive, which permanently bricked login for everyone in that guild — the stale link is now cleared and re-linked on the next sign-in, and the same fallback covers user links across all nine connectors -* **import:** UptimeRobot as an import source, with a golden-tested converter and a dashboard source picker -* **performance:** result and chart queries seek instead of scan. Result blobs are skipped when unrequested, the keyset cursor seeks by row value, the chart fetch is split at the raw/rollup boundary into parallel tier queries (and still seeks on SQLite), a per-check per-tier recent-results filter cannot ask for a mixed tier, status-page response times are fetched per check and per tier instead of scanning results, raw-tier queries are clamped to the retention band and report the effective window, and status-page cache directives derive from page visibility -* **dash0:** faceted status and type filters on the checks list, a check filter on the incidents list, documentation links across SLOs, badges, discovery, events and dependencies, incident timestamps rendered in local time with UTC on hover, invitation email delivery status led by the address with the link as fallback, and every auth method a session can carry is labelled - - -### Bug Fixes - -* **audit:** every session-minting path is recorded, not just password logins; redaction fails closed on unrecognized payload value types and keeps pointer-valued fields; the events cursor gained a uid tie-break; the OAuth grant path is audited and the guard widened past the auth package; and an OAuth grant presented by the wrong client is recorded as token misuse -* **traceroute:** an HTTP response stall is no longer labelled a connect timeout, the connection phase resets at dial start so a redirect chain keeps a real connect timeout, a panic on either trace goroutine is recovered, the per-check policy survives export, import and clone, and an agent-uploaded capture is stamped with the probing region -* **support:** `SP_SUPPORT_RETENTION_DAYS=0` genuinely means keep forever, an abuse-ceiling drop counts as throttled rather than failed, and the re-scan path fails closed with the dedup lookup scoped to the org index -* **charts:** the tier merge is keyed on org and check so navigation cannot serve stale rows, the seam is anchored on the bucket edge with the chart window resolved once, and same-`period_start` rollup points get a uid DESC tie-break -* **status-pages:** public incident history is cached by visibility, and public pages no longer vary on `Cookie` -* **notifications:** browser push notifications are incident-aware, escalation Slack DMs address the check by name and number with an incident link, and the agent websocket subscribes to `check.created` before announcing the connection -* **checks:** the 100th auto-slugged check for one host no longer 500s, and `validating` is accepted in the status filter -* **db:** generic attachments moved out of the already-released migration 014 into a new 015 -* **config:** a hostname-derived worker slug is slugified instead of refused, and the fixed-point property holds by construction -* **dash0:** the login page no longer unmounts mid-org-picker redirect, `apiFetch` tolerates an empty body under any status rather than only 204, breadcrumb leaves resolve for every Organization tab and deep route, the SSL check type is labelled TLS across all surfaces, and an empty check duration renders a literal em dash -* **docs:** the API reference index is served at `/docs/api` - ## [0.17.0](https://github.com/fclairamb/solidping/compare/v0.16.2...v0.17.0) (2026-08-20)