Skip to content

Add scheduled publishing for incidents and maintenance#396

Merged
jbrooksuk merged 4 commits into
mainfrom
claude/scheduled-incidents-maintenance-0mn6xo
Jul 24, 2026
Merged

Add scheduled publishing for incidents and maintenance#396
jbrooksuk merged 4 commits into
mainfrom
claude/scheduled-incidents-maintenance-0mn6xo

Conversation

@jbrooksuk

Copy link
Copy Markdown
Member

Summary

Adds a published_at timestamp to incidents and schedules so they can be prepared ahead of time and revealed automatically at a future date. While an item's published_at is in the future it is treated as a draft.

  • Hidden from the status page, incident timeline, system-status count, and public reads of the JSON API (guests + read-only tokens).
  • Visible & editable in the Filament dashboard, over the MCP server, and to API tokens with the *.manage ability — parity for management clients.
  • Notifications deferred: subscriber notifications fire at publish time, not at creation.

null = published immediately (backwards compatible); a future value = hidden until then.

How it works

  • A Publishable concern provides published / unpublished scopes and isPublished(). Visibility is evaluated at read time, so items appear the moment their publish time passes — robust even if the scheduler is briefly down.
  • Public read surfaces apply ->published(): API index/show (incidents and schedules), the incident timeline, the status-page schedule block, direct incident/schedule URLs (404 for guests, preview allowed for logged-in staff), and Status::incidents().
  • API read endpoints gate on the *.manage token ability via a new non-throwing tokenCan() helper, so management tokens (and full-privilege first-party sessions) can list/fetch drafts while guests and read-only tokens cannot.
  • Notify actions skip unpublished items; the new cachet:publish-scheduled command (scheduled every minute) dispatches the deferred subscriber notification exactly once, tracked by a published_notified_at column.
  • published_at is exposed for writes and reads across the API request data, JSON:API resources, MCP create/update tools + presenter, and the dashboard forms/tables (with a "scheduled" filter).

Testing

  • New feature/unit tests cover visibility gating (API, status page, timeline), MCP draft exposure, ability-based API access (manage token sees drafts; read-only token and guest do not), the publish command's notify-once behaviour, and the Publishable scopes.
  • Full suite: 898 passed / 0 failures. PHPStan and Pint clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NCuvKjgerpaWvGcmY57G95


Generated by Claude Code

claude added 2 commits July 24, 2026 18:45
Introduce a `published_at` timestamp on incidents and schedules so they
can be prepared ahead of time and revealed automatically at a future date.

While an item's `published_at` is in the future it is treated as a draft:

- Hidden from the status page, incident timeline, system status count and
  the public JSON API (for guests and authenticated callers alike).
- Still fully visible and editable in the Filament dashboard and over the
  MCP server, so operators can manage what they've prepared.
- Subscriber notifications are deferred until publication rather than
  firing at creation time.

Visibility is evaluated at read time via a `Publishable` concern
(`published`/`unpublished` scopes, `isPublished()`), so items appear the
moment their publish time passes. The new `cachet:publish-scheduled`
command (scheduled every minute) dispatches the deferred subscriber
notifications exactly once, tracked by a `published_notified_at` column.

The field is exposed for writes and reads across the API request data,
JSON API resources, MCP create/update tools and presenter, and the
dashboard forms/tables (including a "scheduled" filter).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NCuvKjgerpaWvGcmY57G95
Gate the incident and schedule API read endpoints on the *.manage token
ability rather than hiding unpublished items from every caller. Guests and
read-only tokens still get the published-only view (matching the status
page), while tokens that can manage the resource — and full-privilege
first-party sessions — can list and fetch drafts, giving API management
clients parity with the dashboard and MCP.

Adds a non-throwing tokenCan() helper on GuardsApiAbilities that resolves
the caller through the Sanctum guard, safe to call on the unauthenticated
read routes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NCuvKjgerpaWvGcmY57G95
claude added 2 commits July 24, 2026 20:23
Add the Published At field label/header, the "published" badge placeholder,
the "scheduled" filter label, and the publish helper text to every locale
that carries the incident and schedule language files (de, de_AT, de_CH,
es_ES, fr, ko, nl, ph, pt_BR, zh_CN, zh_TW), matching each locale's existing
terminology.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NCuvKjgerpaWvGcmY57G95
Treat published_at as an always-present timestamp instead of a nullable
sentinel. The migration backfills existing incidents and schedules with
published_at = created_at, and backfills published_notified_at in lockstep
so the publish command never re-announces historical records. Drop the
migration's down() method.

New records default published_at (and, for immediate publication,
published_notified_at) to the creation time via a creating hook, so items
published on creation are never re-announced by cachet:publish-scheduled
while future-dated items still notify when their publish time arrives.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NCuvKjgerpaWvGcmY57G95
@jbrooksuk
jbrooksuk merged commit da5fd96 into main Jul 24, 2026
28 checks passed
@jbrooksuk
jbrooksuk deleted the claude/scheduled-incidents-maintenance-0mn6xo branch July 24, 2026 22:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants