Skip to content

feat(status): surface relevant Cloudflare provider incidents - #1296

Merged
kody-bot merged 6 commits into
mainfrom
cursor/status-cf-incidents-58e2
Aug 7, 2026
Merged

kody-bot merged 6 commits into
mainfrom
cursor/status-cf-incidents-58e2

Conversation

@kentcdodds

@kentcdodds kentcdodds commented Aug 7, 2026 •

Copy link
Copy Markdown
Owner

Related to #1092 (alerting independence).

Summary

During the 2026-08-07 audit-DB probe timeout, Cloudflare had an active R2 availability incident — but the status page couldn't show that context, leaving "is this us or the platform?" unanswerable at a glance.

This PR adds provider-incident context to the status worker (entirely within packages/status/):

  • Filtered fetch of Cloudflare's public Statuspage API (/api/v2/incidents/unresolved.json), keeping only incidents whose components intersect what kody runs on (Workers, D1, R2, KV, Durable Objects, Queues, Vectorize, Email Routing, Access); regional/product noise excluded.
  • Fetched on the existing per-minute cron tick, cached in StatusStore; the render path reads the cache only.
  • Clearly-separated "Provider incidents (Cloudflare)" section on the status page — provider-declared context, never merged into kody's measured component health or uptime numbers; links to cloudflarestatus.com. Hidden when no relevant incidents are active (the expected steady state).
  • Fail-soft everywhere: the fetch never throws (bounded timeout, abort, parse guards return { ok: false }); a stale-but-present cache keeps rendering; the page renders without the section when nothing is available.
  • Alert-email annotation: outage emails gain one line — "Possibly related Cloudflare incident: ()" — when a relevant provider incident is active. Kody's own probes remain the only alerting trigger.
  • Tests for filtering, fail-soft paths, page rendering, and email annotation; readme section added.

Conductor report

Status: in review. Track agent (Grok 4.5) completed the implementation; PR creation was blocked by the Cursor manual-approval gate, so the conductor created this PR from the pushed branch. Track agent resumes the ship-pr deploy loop: CI + AI reviewers → squash-merge → verify the path-filtered status:deploy job and the live page at status.heykody.dev.

Open in Web Open in Cursor 

Summary by CodeRabbit

  • New Features
    • Added Cloudflare incident monitoring to the status page, including affected components, impact, current status, update time, and source links.
    • Added incident context to outage notifications and daily reminders.
    • Provider incidents are cached and displayed separately from measured service health.
  • Bug Fixes
    • Provider monitoring failures now degrade gracefully without suppressing outage alerts or status information.
  • Documentation
    • Documented provider incident monitoring, caching, and fallback behavior.

Fetch Cloudflare's public Statuspage unresolved incidents on the status
worker cron tick, filter to products kody runs on, cache fail-soft, and
render a separate provider section plus outage-email annotations.

Refs #1092
Root vitest console spies fail unexpected console.warn; the fail-soft
Statuspage paths intentionally warn, so the test opts in and asserts.
Complete the opt-in that was partially staged by lint-staged so root
vitest console spies do not fail the intentional warn coverage.

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 38ca4bf. Configure here.

Comment thread packages/status/provider-incidents.ts Outdated
@github-actions

github-actions Bot commented Aug 7, 2026 •

Copy link
Copy Markdown
Contributor

🔎 Preview deployed: https://kody-pr-1296.kody-a99.workers.dev

Worker: kody-pr-1296
D1: kody-pr-1296-db
KV: kody-pr-1296-oauth-kv

Mocks:

@coderabbitai

coderabbitai Bot commented Aug 7, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@cursor[bot], you've reached your PR review limit, so we couldn't start this review.

Next review available in: 1 minute

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 125ecf4d-4ed6-4d23-8040-0cebe7af04f1

📥 Commits

Reviewing files that changed from the base of the PR and between 94ab370 and bb1001e.

📒 Files selected for processing (4)
  • packages/status/provider-incidents.node.test.ts
  • packages/status/provider-incidents.ts
  • packages/status/status-page.node.test.ts
  • packages/status/status-page.ts
📝 Walkthrough

Walkthrough

The status package now fetches and caches relevant Cloudflare incidents. Cached incidents appear on status pages and in outage-related emails. Fetch failures are handled without changing outage detection or notifications.

Changes

Cloudflare incident integration

Layer / File(s) Summary
Incident parsing, fetching, and caching
packages/status/provider-incidents.ts, packages/status/provider-incidents.node.test.ts
Defines incident types and Cloudflare endpoints. Parses relevant unresolved incidents, validates cache data, fetches with timeout and fail-soft handling, and formats annotations.
StatusStore and snapshot wiring
packages/status/status-types.ts, packages/status/status-store.ts
Adds nullable provider incidents to snapshots. The store refreshes and caches incidents, preserves cached data after failed refreshes, and passes incidents to snapshots and alert emails.
Provider incident status-page rendering
packages/status/status-page.ts, packages/status/status-page.node.test.ts
Renders provider incidents in a separate section with escaped details, status, impact, affected components, links, and update times.
Alert email annotations and documentation
packages/status/email-policy.ts, packages/status/email-policy.node.test.ts, packages/status/readme.md
Adds provider annotations to incident-opened and daily-reminder emails, omits them from all-clear emails, and documents the integration behavior.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant StatusStore
  participant CloudflareStatuspage
  participant StatusSnapshot
  participant StatusPage
  participant EmailPolicy
  StatusStore->>CloudflareStatuspage: fetch unresolved provider incidents
  CloudflareStatuspage-->>StatusStore: return relevant incident data
  StatusStore->>StatusSnapshot: store cached provider incidents
  StatusSnapshot->>StatusPage: provide incidents for rendering
  StatusSnapshot->>EmailPolicy: provide incidents for alert composition
  StatusPage-->>StatusSnapshot: render provider incident section
  EmailPolicy-->>StatusSnapshot: append annotations to applicable emails
Loading

Possibly related PRs

  • kentcdodds/kody#1230: Both changes extend the status email and status page paths with provider incident information.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely summarizes the main change: surfacing relevant Cloudflare provider incidents in the status system.
Description check ✅ Passed The description explains the intent and changes in detail, and it summarizes fail-soft behavior, testing scope, and system impact.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/status-cf-incidents-58e2

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Require updatedAt and affectedComponents in parseProviderIncidentCache so
a corrupt meta entry cannot throw during status page HTML rendering.
@kody-bot

kody-bot commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 7, 2026 •

Copy link
Copy Markdown
⚠️ Action not completed

Already reviewed.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
packages/status/status-page.node.test.ts (1)

126-132: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Assert the remaining provider incident metadata.

The fixture includes affectedComponents and updatedAt, but the test does not verify them. Add assertions so the renderer cannot omit these fields without failing the test.

Proposed assertions
 expect(withProvider).toContain('https://stspg.io/r2')
+expect(withProvider).toContain('affects R2')
+expect(withProvider).toContain('updated 2026-08-07T19:00:00.000Z')
 expect(withProvider).toContain('for context only')
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/status/status-page.node.test.ts` around lines 126 - 132, Extend the
withProvider assertions in the status-page rendering test to verify the
fixture’s affectedComponents and updatedAt values are present in the rendered
output. Use the exact expected metadata from the fixture and preserve all
existing assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/status/provider-incidents.ts`:
- Around line 179-181: Update the cache validation around the fetchedAt age
check to reject future-dated records as well as records older than maxAgeMs.
Ensure cache entries are accepted only when fetchedAt is no later than now and
the computed age is within the existing freshness window, while preserving the
incident-array validation and filtering flow.
- Around line 124-127: Update shortlink handling in renderProviderIncident to
validate the trimmed URL before assigning it to href. Allow only HTTPS URLs
whose host matches the expected Cloudflare Statuspage hosts, and use
cloudflareStatusPageUrl for missing, malformed, non-HTTPS, or other-host values.

In `@packages/status/status-page.ts`:
- Line 216: Validate and normalize incident.shortlink in renderProviderIncident
before inserting it into the href: use cloudflareStatusPageUrl when missing, and
replace links whose protocol or host is not an approved Cloudflare Statuspage
URL. Keep escaping the final validated URL with escapeHtml before rendering.
- Line 223: Add a defensive fallback for snapshot.providerIncidents before the
length check in renderStatusPage, treating missing legacy values as null so
accessing length cannot throw; preserve the existing empty-string behavior for
null or empty incident lists.

---

Nitpick comments:
In `@packages/status/status-page.node.test.ts`:
- Around line 126-132: Extend the withProvider assertions in the status-page
rendering test to verify the fixture’s affectedComponents and updatedAt values
are present in the rendered output. Use the exact expected metadata from the
fixture and preserve all existing assertions.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5b8c8df9-ae42-496a-b4c8-8d388cda85a3

📥 Commits

Reviewing files that changed from the base of the PR and between 2ae1ea7 and 94ab370.

📒 Files selected for processing (9)
  • packages/status/email-policy.node.test.ts
  • packages/status/email-policy.ts
  • packages/status/provider-incidents.node.test.ts
  • packages/status/provider-incidents.ts
  • packages/status/readme.md
  • packages/status/status-page.node.test.ts
  • packages/status/status-page.ts
  • packages/status/status-store.ts
  • packages/status/status-types.ts

Comment thread packages/status/provider-incidents.ts Outdated
Comment thread packages/status/provider-incidents.ts Outdated
Comment thread packages/status/status-page.ts Outdated
Comment thread packages/status/status-page.ts Outdated
Sanitize shortlinks to Cloudflare Statuspage HTTPS hosts, reject
future-dated cache entries, and treat missing providerIncidents as absent.
@kody-bot
kody-bot merged commit c0a81c7 into main Aug 7, 2026
10 checks passed
@kody-bot
kody-bot deleted the cursor/status-cf-incidents-58e2 branch August 7, 2026 21:40
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.

3 participants