@checkstack/incident-backend 1.10.0 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,421 @@
1
1
  # @checkstack/incident-backend
2
2
 
3
+ ## 1.12.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 43e4484: Incidents and maintenance: richer, safer update timelines.
8
+
9
+ - **Markdown updates and descriptions.** Update messages and descriptions now
10
+ render sanitized Markdown (bold, links, lists) everywhere they appear -
11
+ detail pages, editors, the shared status-update timeline, and the public
12
+ status page (which stays sanitized via `rehype-sanitize`). An "Markdown
13
+ supported" hint is shown under the update composer.
14
+ - **Edit and delete published updates.** New `editUpdate` / `deleteUpdate`
15
+ procedures let a manager correct or remove an update in place; edited updates
16
+ are marked "edited". Editing the `statusChange` of the latest update
17
+ re-derives the incident/maintenance status. Deletion is irreversible and, on
18
+ the AI path, always routes through propose/apply. Both procedures are
19
+ object-scoped on the owning incident/maintenance (`idParam`), so team-scoped
20
+ managers can use them without a global rule.
21
+ - **Edit the published time of an update.** `editUpdate` now accepts an optional
22
+ `createdAt`, and the update editor exposes a date/time picker (the same
23
+ `DateTimePicker` used for maintenance windows) when editing an existing update.
24
+ Re-timing an update re-orders the timeline and re-derives the incident/
25
+ maintenance status (the header still follows the latest status-bearing
26
+ update), so moving an update never leaves the header and timeline diverged.
27
+ - **Per-update edit history (GitHub-style "history of edits").** Each in-place
28
+ edit now archives the prior version of the update into a new durable
29
+ `edit_history` `jsonb` column (a snapshot of message, status, visibility, and
30
+ the published time it carried, plus when it was superseded). The shared status
31
+ timeline turns the "edited" marker into an "edited (N)" disclosure that
32
+ expands to show those prior versions. History is **manager-facing only**: the
33
+ read path attaches `editHistory` solely for the manager audience and strips it
34
+ for public / logged-in readers, so a version that was `internal` before being
35
+ made `public` can never leak its prior internal content. A no-op edit
36
+ (nothing actually changed) neither archives a snapshot nor marks the update
37
+ "edited". Adds a forward-only, additive migration to each backend
38
+ (`edit_history jsonb NOT NULL DEFAULT '[]'`, backfilling existing rows).
39
+ We framed this as "either a delayed publish with undo OR a history of
40
+ edits"; edit history satisfies the ask, so undo-send / delayed-publish is
41
+ intentionally **deferred** (it would need a queue-delay + pending state and is
42
+ redundant with history).
43
+ - **Status updates are now editable from the editor dialog too, via one shared
44
+ implementation.** The status-updates surface (add / edit / delete an update,
45
+ including its published time and edit history) is extracted into a single
46
+ `IncidentUpdatesSection` / `MaintenanceUpdatesSection` used by BOTH the detail
47
+ page and the create/edit editor dialog, so the two surfaces can no longer
48
+ drift. Previously the editor dialog showed a read-only timeline with no way to
49
+ edit an existing update.
50
+ - **Editable hotlinks.** Added-links can now be edited in place (label, URL, and
51
+ visibility where applicable) instead of only added/removed. The shared
52
+ `LinksEditor` gains an inline edit affordance, backed by a new `updateLink`
53
+ procedure on incidents and maintenances and `updateSystemLink` on catalog
54
+ systems (so system links are editable too). Each is object-scoped on its
55
+ parent (`incidentId` / `maintenanceId` / `systemId`) with the same anti-spoof
56
+ WHERE-clause scoping as the remove path, so a link id cannot be paired with a
57
+ foreign parent the caller happens to manage. No migration is needed (the
58
+ columns already exist).
59
+ - **Per-update / per-link visibility.** A new shared visibility level
60
+ (`public` / `logged_in` / `internal`) can be set on both updates and hotlinks
61
+ via the same three-way visibility select in the editor (the update composer
62
+ previously exposed only a binary public/internal toggle, so `logged_in` was
63
+ unreachable for updates even though the backend already accepted and filtered
64
+ it). Filtering is enforced SERVER-SIDE on every read path: anonymous callers
65
+ and the public status-page projection see only `public`; authenticated
66
+ non-managers additionally see `logged_in`; managers see everything. Updates
67
+ still default to `public`, and `internal` updates never broadcast a
68
+ notification. Adds a forward-only migration to each backend (new visibility
69
+ enum + column, plus a nullable `edited_at` on updates).
70
+ - **"Keep Current" shows the current status**, e.g. "Keep Current
71
+ (Investigating)".
72
+ - **Status colors.** Adds a blue `--status-info` token and a shared
73
+ `StatusPillTone` / `pillToneStyles` in `@checkstack/ui`; incident "monitoring"
74
+ and maintenance "scheduled" now read as informational (blue) instead of grey.
75
+ The incident severity ramp is now blue(minor) -> amber(major) -> red(critical):
76
+ a minor incident uses the blue `info` hue instead of grey, with no minor/major
77
+ amber collision. This corrected ramp now also applies on the public status
78
+ page (active-incident cards, severity pills, and the incident detail page) and
79
+ in the system-detail active-incidents panel, which both previously still
80
+ rendered `minor` grey.
81
+ - **Logged-out overview.** Incidents and maintenance now expose a public,
82
+ read-gated overview page and sidebar entry (the manage-gated config page is
83
+ renamed "Manage ..."), so anonymous visitors who hold the default read rule
84
+ can browse them.
85
+
86
+ Thanks to [@stuajnht](https://github.com/stuajnht) for the valuable feedback.
87
+
88
+ - 43e4484: Include the latest incident and maintenance update text in subscriber
89
+ notifications. The update message is now escaped, single-lined, truncated, and
90
+ appended to the notification body as a blockquote, so subscribers see WHAT
91
+ changed rather than a generic "has been updated"/"has been scheduled".
92
+ Message-only updates (no status change) now notify too, and an incident's
93
+ initial message is carried into its "reported" notification. Maintenance now has
94
+ full parity with incidents: its update text reaches subscribers, internal-only
95
+ operator notes never notify or leak text, and a completion note is carried into
96
+ the "completed" notification.
97
+
98
+ The escaping/truncation helper (`sanitizeUpdateMessage` /
99
+ `buildUpdateMessageSuffix`) now lives in `@checkstack/notification-common` so
100
+ both domain backends share one implementation.
101
+
102
+ Thanks to [@stuajnht](https://github.com/stuajnht) for the valuable feedback.
103
+
104
+ - 43e4484: Count incident-forced downtime against SLOs. When an incident forces a system to
105
+ degraded/unhealthy via its health override, that downtime is now recorded as an
106
+ SLO downtime event for each of the system's objectives (consuming the error
107
+ budget and appearing in the downtime history) and is closed when the incident is
108
+ resolved, deleted, or its override is cleared - and only once the system's health
109
+ checks are also healthy. Downtime is never double-counted with a concurrent
110
+ health-check outage, and one cause never closes downtime the other is still
111
+ holding open (resolving an incident while checks still fail, or checks recovering
112
+ while an override is still active, both leave the outage open).
113
+
114
+ Adds a nullable `source` column (`healthcheck` | `incident`, NULL read as
115
+ `healthcheck`) to `slo_downtime_events` and a `DowntimeSource` schema in
116
+ slo-common, so the cause of each downtime event is recorded and the orphan
117
+ self-heal skips incident-owned events. incident-backend now emits an
118
+ `incident.lifecycle.changed` hook (contract in incident-common) on every incident
119
+ lifecycle change - including override-only edits that the reactive `incident`
120
+ entity change does not surface - which slo-backend subscribes to with
121
+ exactly-once delivery to reconcile downtime.
122
+
123
+ - 43e4484: Status pages can now publish only a subset of catalog environments. The page
124
+ builder gains a "Published environments" picker (empty = all environments, the
125
+ backward-compatible default). When a non-empty set is selected, the page omits
126
+ status, incidents, maintenances and uptime for systems that belong to none of
127
+ the selected environments.
128
+
129
+ - Status pages store an optional `publishedEnvironmentIds` set (new nullable
130
+ `published_environment_ids` column; NULL = all environments, so existing pages
131
+ are unchanged) exposed on `StatusPage`, `createStatusPage`, and
132
+ `updateStatusPage`.
133
+ - The scope is threaded onto `WidgetResolveContext.publishedEnvironmentIds` as
134
+ opaque strings and passed identically to `resolvePublic`,
135
+ `resolveScopedSystems`, and `resolveScopedSystemsDetailed` (and the email
136
+ subscribe clamp + fan-out), so what a page shows, offers for subscription, and
137
+ emails about all agree.
138
+ - Health widgets recompute per environment: they read the per-environment health
139
+ matrix and roll up only the selected environments. `getBulkRunStats` and
140
+ `getRunStats` gain an optional `environmentIds` filter so uptime counts only
141
+ runs recorded in the selected environments.
142
+ - Incident and maintenance widgets filter their feed and scope by intersecting
143
+ each item's affected systems with the environment-visible systems. Incidents
144
+ and maintenance windows carry no environment of their own, so a system in
145
+ several environments makes its items visible on a page publishing ANY of them
146
+ (the multi-environment caveat).
147
+
148
+ ### Patch Changes
149
+
150
+ - 43e4484: Batch hot-path scoped-db reads/writes into single transactions to cut per-query round-trips.
151
+
152
+ The scoped-db proxy wraps every standalone query in its own `BEGIN → SET LOCAL search_path → query → COMMIT`, so a path issuing N sequential queries paid N round-trips and checked out a connection N times. These reads/writes now run under one `withScopedTransaction`, collapsing the batch to a single `SET LOCAL` on one connection. Behavior is unchanged:
153
+
154
+ - healthcheck: `getSystemHealthOverview`'s `1 + N·(2+E)` read fan-out.
155
+ - incident/maintenance: `getIncident`/`getMaintenance` (4 reads), `getManyEntityStates`, `listOpenIncidentsBySystem` / `getActiveMaintenancesBySystem`, `getMaintenanceWindowsForRange`; the `list*` / `*ForSystem` per-row `N+1` system lookups collapsed to a single set-based `inArray` read; maintenance `transitionStatus` update+insert made atomic; `addUpdate`/`editUpdate`/`addLink` use `.returning()` instead of a follow-up re-select.
156
+ - ai: `appendMessage`, memory `saveOrUpdate`.
157
+ - notification: `resolveInheritedGroups`.
158
+ - status-page: subscriber `verify` (4 reads) and `unsubscribe` (3 reads).
159
+ - announcement: `getActiveAnnouncements` / `dismissAnnouncement` / `createAnnouncement`.
160
+ - gitops: `upsertProvenance`.
161
+
162
+ - 43e4484: Eliminate N+1 RPC fan-outs in the public status-page widget resolvers.
163
+
164
+ Each of these widgets renders a PUBLIC page, so every per-item RPC was real
165
+ external DB load. Three bulk-by-id endpoints replace the per-item fetches:
166
+
167
+ - `healthcheck-common`: new `getBulkRunStats({ systemIds, startDate, endDate,
168
+ maxBuckets })` -> `{ stats: Record<systemId, RunStats> }`. The `systemHealth`
169
+ widget's uptime column now issues ONE request for all systems instead of one
170
+ `getRunStats` per system. Systems with no runs in the window are omitted, so
171
+ the resolver's output is unchanged.
172
+ - `incident-common`: new `getBulkIncidentUpdates({ incidentIds })` ->
173
+ `{ updates: Record<incidentId, IncidentUpdate[]> }`. The incidents widget now
174
+ fetches every selected incident's update timeline in ONE request instead of
175
+ one `getIncident` per incident.
176
+ - `maintenance-common`: new `getBulkMaintenanceUpdates({ maintenanceIds })` ->
177
+ `{ updates: Record<maintenanceId, MaintenanceUpdate[]> }` (symmetric with the
178
+ incident endpoint) for the maintenance widget.
179
+
180
+ The new update endpoints apply the same per-item audience filter as
181
+ `getIncident` / `getMaintenance`, so internal/logged-in updates and author
182
+ identity never leak to a non-manager caller. Each endpoint is keyed by the
183
+ resource id and gated with the record post-filter (`recordKey`) matching the
184
+ single endpoint's read scope, mirroring `getBulkSystemHealthStatus` /
185
+ `getBulkIncidentsForSystems`. Widget DTO output is unchanged - this is a pure
186
+ request-count optimization.
187
+
188
+ - 43e4484: Status page enhancements:
189
+
190
+ - Group-status widget can collapse its member rows while every member is
191
+ operational (auto-expanding on any issue or maintenance).
192
+ - New "Announcements" status-page widget, contributed fully externally by the
193
+ announcement plugin: it surfaces active `visibility: "all"` announcements
194
+ through a public-safe DTO (title/message/severity/timestamps only) and never
195
+ affects the page status rollup.
196
+ - Incident and maintenance widgets can scope by catalog GROUPS with per-system
197
+ exceptions. Scope is resolved at read time (`(systemIds ∪ members(groupIds)) −
198
+ excludedSystemIds`), so members added to a group later are reflected
199
+ automatically. The builder gets a nested group/system picker.
200
+ - Incident and maintenance items on a public page link to dedicated public
201
+ detail pages, gated server-side to items the page's published widgets actually
202
+ surface (no enumeration, no internal-field leak). The custom-domain public
203
+ bundle gains a minimal in-memory router for the two detail pages.
204
+ - Fix the custom-domain "Cannot connect to Checkstack backend" screen: a
205
+ configured-but-not-servable custom domain now serves the lean public
206
+ "not available" page instead of the admin shell; the public bundle skips the
207
+ cross-origin `/api/config` probe; CORS admits resolved custom domains; the
208
+ request origin is normalized for proxy scheme/port variance; and re-saving an
209
+ unchanged custom domain no longer clears its verification.
210
+ - Anonymous email subscriptions (double opt-in) for incident updates, opt-in per
211
+ status page (`emailSubscriptionsEnabled`, default off): a new
212
+ `status_page_subscribers` table, public subscribe/verify/unsubscribe
213
+ procedures with constant-time responses that fail closed when the page has not
214
+ enabled subscriptions, and team-scoped admin list/remove + an enable toggle in
215
+ the builder. Emails are delivered through a new `sendRawEmail` primitive in
216
+ notification-backend that sends to an arbitrary external address (no auth
217
+ account) via every enabled email strategy (SMTP), with a mandatory unsubscribe
218
+ link.
219
+ - Incident/maintenance update fan-out to subscribers via a new
220
+ `notificationAudienceExtensionPoint` in notification-backend. Every
221
+ notification funnelled through `notifyForSubscription` (incident, maintenance,
222
+ health - all unchanged) now also invokes each registered audience sink exactly
223
+ once, enriched with the affected systems and their catalog groups (resolved
224
+ from notification-backend's own resource-parent graph, never a domain import).
225
+ status-page-backend contributes a sink that, AT SEND TIME, matches each
226
+ notification's affected systems against the systems each published + public +
227
+ email-enabled page currently surfaces in its incident/maintenance widgets
228
+ (honoring group membership and per-system exclusions) and emails that page's
229
+ verified subscribers. Send-time scoping against the live layout is the privacy
230
+ boundary: a page only ever emails about systems its widgets surface right now.
231
+ Because `notifyForSubscription` is a single-pod point RPC, each notification
232
+ fans out exactly once cluster-wide.
233
+ - Subscriber reconcile on page deletion: the subscriber FK is `ON DELETE
234
+ CASCADE` and page deletion also explicitly purges subscribers (invalidating
235
+ pending verify/unsubscribe tokens) - no orphan rows, no post-deletion send.
236
+ Removing all systems from a page or disabling email is intentionally NOT a
237
+ prune: send-time scoping plus the email-enabled gate make those subscribers
238
+ dormant with no data loss, and re-enabling restores the audience without a
239
+ re-subscribe.
240
+ - Send-time scoping is single-source: the fan-out asks each event-feed widget for
241
+ its CURRENT effective system scope (the same live catalog group expansion the
242
+ widget renders from) instead of a parallel copy of group membership, so it can
243
+ never over- or under-deliver relative to what the page shows.
244
+ - `sendRawEmail` in notification-backend is now `userType: "service"` (was an
245
+ authenticated procedure gated on `notification.send`). Sending to an arbitrary
246
+ address is an open-relay / email-bomb primitive, so it is callable only by a
247
+ trusted backend-to-backend caller (the status-page subscriber mailer), never by
248
+ an end user.
249
+ - Incident/maintenance widgets gain an optional per-system PUBLIC label override
250
+ (`systemLabels`), the same override path the system-health widget uses, so the
251
+ public incident/maintenance detail pages present clean labels instead of raw
252
+ catalog names.
253
+ - The anonymous subscribe endpoint adds a coarse per-page quota (max new
254
+ subscribers per rolling hour, counted over durable rows so it holds across
255
+ pods) on top of the per-(page,email) cooldown, capping verification-email
256
+ amplification. The quota is CONFIGURABLE per status page (new nullable
257
+ `email_subscribers_hourly_quota` column; null uses the default of 50, so
258
+ existing pages are unchanged), validated as a positive integer up to 5000,
259
+ editable in the builder next to the email opt-in toggle and gated by the same
260
+ page-manage capability.
261
+ - Email verification is now per-page configurable and backed by a platform-global
262
+ once-per-address registry:
263
+ - New `email_verification_required` column (boolean, default true) on
264
+ `status_pages`, exposed on the admin StatusPage DTO + `updateStatusPage`
265
+ input (same page-manage gate) with a builder toggle. When OFF, a new
266
+ subscriber is created active immediately - no verification email, and the
267
+ address is NOT written to the global registry (the operator's trust choice
268
+ for e.g. an internal page).
269
+ - New `status_page_verified_emails` table: one row per normalized address that
270
+ has completed verification on ANY page. When a verification-required page is
271
+ subscribed by an already-globally-verified address, the row is created active
272
+ immediately and a COURTESY email (with one-click unsubscribe) is sent instead
273
+ of a verification email, so a malicious add is always caught. `verify` upserts
274
+ the address into this registry and activates every other pending row for the
275
+ same address in one update (confirm once, all pages).
276
+ - Fan-out is unchanged: it still gates on the per-row `verified` flag; the
277
+ registry only governs whether a NEW subscribe short-circuits to active.
278
+
279
+ BREAKING CHANGE: `sendRawEmail` is now service-only. Any (non-existent in-tree)
280
+ authenticated caller must invoke it through a trusted service client instead.
281
+
282
+ Thanks to [@stuajnht](https://github.com/stuajnht) for the valuable feedback.
283
+
284
+ - Updated dependencies [43e4484]
285
+ - Updated dependencies [43e4484]
286
+ - Updated dependencies [43e4484]
287
+ - Updated dependencies [43e4484]
288
+ - Updated dependencies [43e4484]
289
+ - Updated dependencies [43e4484]
290
+ - Updated dependencies [43e4484]
291
+ - Updated dependencies [43e4484]
292
+ - Updated dependencies [43e4484]
293
+ - Updated dependencies [43e4484]
294
+ - Updated dependencies [43e4484]
295
+ - Updated dependencies [43e4484]
296
+ - Updated dependencies [43e4484]
297
+ - Updated dependencies [43e4484]
298
+ - Updated dependencies [43e4484]
299
+ - Updated dependencies [43e4484]
300
+ - Updated dependencies [43e4484]
301
+ - Updated dependencies [43e4484]
302
+ - Updated dependencies [43e4484]
303
+ - Updated dependencies [43e4484]
304
+ - Updated dependencies [43e4484]
305
+ - Updated dependencies [43e4484]
306
+ - Updated dependencies [43e4484]
307
+ - Updated dependencies [43e4484]
308
+ - @checkstack/ai-backend@0.10.10
309
+ - @checkstack/automation-backend@0.11.1
310
+ - @checkstack/catalog-common@2.7.0
311
+ - @checkstack/catalog-backend@1.7.0
312
+ - @checkstack/backend-api@0.31.1
313
+ - @checkstack/incident-common@1.10.0
314
+ - @checkstack/notification-common@1.6.0
315
+ - @checkstack/status-page-backend@0.5.0
316
+ - @checkstack/status-page-common@0.6.0
317
+ - @checkstack/command-backend@0.2.22
318
+ - @checkstack/integration-backend@0.7.4
319
+
320
+ ## 1.11.0
321
+
322
+ ### Minor Changes
323
+
324
+ - f93ee7a: Fix a class of 403s where team-scoped managers were blocked from endpoints they
325
+ needed. A repo-wide audit of every `instanceAccess: { global: true }` procedure
326
+ found more instances of the same bug behind the health-check editor fix: an
327
+ endpoint on a team-scopable resource type, gated so only the GLOBAL access rule
328
+ (never a team grant) authorizes it.
329
+
330
+ Automation: the editor utilities and catalogs (`validateDefinition`,
331
+ `listTriggers`, `listActions`, `listArtifactTypes`, `listAutomationGroups`,
332
+ `listAutomationTemplates`, `renderTemplate`, `testScript`) now use `typeScoped`
333
+ so a team-scoped automation manager can author without the global rule. The run
334
+ endpoints (`listRuns`, `getRun`, `cancelRun`, `getRunScopeForReplay`) are scoped
335
+ to their parent automation via `parentScope` on `automationId`; `getRun`,
336
+ `cancelRun`, and `getRunScopeForReplay` now take the owning `automationId`
337
+ (always available in the run URL/editor) and the handler filters the run fetch by
338
+ it, so a run id cannot be paired with a foreign automation the caller happens to
339
+ hold a grant on. The two migration-admin endpoints stay `global: true` (genuine
340
+ platform-admin actions).
341
+
342
+ Health check: `validateConfiguration` (editor deep-validate) and
343
+ `getPlatformNotificationDefaults` (fetched on every assignment-editor mount) move
344
+ to `typeScoped`. The paired WRITE `setPlatformNotificationDefaults` stays
345
+ `global: true` on purpose - it rewrites instance-wide defaults for every team, so
346
+ a single team grant must not authorize it. Because that write stays global-only,
347
+ the assignment editor's "Notification defaults" button is now gated on the global
348
+ `configuration.manage` rule (`healthcheck-frontend`), so a team-scoped manager no
349
+ longer sees an editor whose Save always 403'd.
350
+
351
+ Anomaly: the anomaly settings panels embedded in the health-check editor
352
+ (`updateAnomalyConfig` / `getAnomalyConfig` and `updateAnomalyAssignmentConfig` /
353
+ `getAnomalyAssignmentConfig`) were authorized against the non-team-scopable
354
+ `anomaly_feed` type (via `global: true` or an `idParam` that could never match a
355
+ team grant), so a team-scoped manager who owns the check/system saw "Save
356
+ Defaults" / "Save Exceptions" buttons whose Save always 403'd. They now
357
+ `parentScope` on the owning health-check configuration (`healthcheck.healthcheck`)
358
+ and catalog system (`catalog.system`) respectively, so managing the check/system
359
+ authorizes reading and editing its anomaly settings. The frontend needed no
360
+ change: those buttons were already disabled for non-managers, and the panels are
361
+ only reachable inside the manager-gated editor. Also, the automation "New
362
+ automation" template picker (`automation-frontend`) gated its page on the bare
363
+ global manage rule; it now uses the create capability, so a team-scoped creator
364
+ (whom the route already reveals the page to) is no longer shown a blocked page.
365
+
366
+ Incident & maintenance: `removeLink` was `global: true` because its input carried
367
+ only the link id. It now takes the owning `incidentId` / `maintenanceId`
368
+ (mirroring `addLink`), authorizes per-instance via `idParam`, and the service
369
+ scopes the delete by that parent id so a link cannot be removed by pairing its id
370
+ with a different incident/maintenance the caller manages. The AI `removeLink`
371
+ tools carry the parent id too.
372
+
373
+ BREAKING CHANGES: `automation.getRun`, `automation.cancelRun`,
374
+ `automation.getRunScopeForReplay`, `incident.removeLink`, and
375
+ `maintenance.removeLink` now require a parent id (`automationId` /
376
+ `incidentId` / `maintenanceId`) in their input. Endpoints previously gated by a
377
+ global rule alone now also accept the owning team's grant; no endpoint became
378
+ more permissive for a user who lacks both the global rule and a relevant team
379
+ grant.
380
+
381
+ Not team-scopable, so intentionally left `global: true` (verified by the audit):
382
+ catalog environments, anomaly config, SLO list/streak/milestone reads and
383
+ health-check history/stats (their read rules are public/default), and every
384
+ hand-rolled HTTP route (global admin/infra or already team-aware).
385
+
386
+ ### Patch Changes
387
+
388
+ - Updated dependencies [f93ee7a]
389
+ - Updated dependencies [f93ee7a]
390
+ - Updated dependencies [8aae4e2]
391
+ - Updated dependencies [d0eddc9]
392
+ - Updated dependencies [d0eddc9]
393
+ - Updated dependencies [f93ee7a]
394
+ - Updated dependencies [f93ee7a]
395
+ - Updated dependencies [d0eddc9]
396
+ - Updated dependencies [d0eddc9]
397
+ - Updated dependencies [d0eddc9]
398
+ - Updated dependencies [f93ee7a]
399
+ - @checkstack/common@0.22.0
400
+ - @checkstack/catalog-common@2.6.3
401
+ - @checkstack/ai-backend@0.10.9
402
+ - @checkstack/backend-api@0.31.0
403
+ - @checkstack/automation-common@0.10.0
404
+ - @checkstack/automation-backend@0.11.0
405
+ - @checkstack/incident-common@1.9.0
406
+ - @checkstack/auth-common@0.13.0
407
+ - @checkstack/ai-common@0.6.6
408
+ - @checkstack/cache-api@0.3.19
409
+ - @checkstack/catalog-backend@1.6.9
410
+ - @checkstack/command-backend@0.2.21
411
+ - @checkstack/integration-backend@0.7.3
412
+ - @checkstack/integration-common@0.9.8
413
+ - @checkstack/notification-common@1.5.3
414
+ - @checkstack/signal-common@0.2.17
415
+ - @checkstack/status-page-backend@0.4.8
416
+ - @checkstack/status-page-common@0.5.3
417
+ - @checkstack/cache-utils@0.2.24
418
+
3
419
  ## 1.10.0
4
420
 
5
421
  ### Minor Changes
@@ -0,0 +1,4 @@
1
+ CREATE TYPE "incident_content_visibility" AS ENUM('public', 'logged_in', 'internal');--> statement-breakpoint
2
+ ALTER TABLE "incident_links" ADD COLUMN "visibility" "incident_content_visibility" DEFAULT 'public' NOT NULL;--> statement-breakpoint
3
+ ALTER TABLE "incident_updates" ADD COLUMN "visibility" "incident_content_visibility" DEFAULT 'public' NOT NULL;--> statement-breakpoint
4
+ ALTER TABLE "incident_updates" ADD COLUMN "edited_at" timestamp;
@@ -0,0 +1 @@
1
+ ALTER TABLE "incident_updates" ADD COLUMN "edit_history" jsonb DEFAULT '[]'::jsonb NOT NULL;