1288 Commits

Author SHA1 Message Date
Raj Nandan Sharma f5ab338e2b docs(confirmation-threshold): add glossary term, ADR 0009, and implementation plan (#712)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 18:23:16 +05:30
Raj Nandan Sharma 5012ff1421 Merge pull request #754 from rajnandan1/fix/716
feat(api): DELETE /api/v4/monitors/{monitor_tag} + alert-config orphan fix
2026-06-12 15:25:51 +05:30
Raj Nandan Sharma 122ca71b8e fix(alerts): delete per-monitor v2 alert rows when detaching a monitor from shared configs
Review follow-up on #754: deleteMonitorAlertConfigsByMonitorTag removed
v2 alert rows only when the whole config died, so a shared config that
survived the detach kept monitor_alerts_v2 rows pointing at the deleted
monitor's tag. Verified red/green with an in-memory SQLite script:
the deleted tag's v2 rows now go with the detach while the surviving
monitors' rows are untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 15:22:47 +05:30
Raj Nandan Sharma e27ab6ff7d feat(api): add DELETE /api/v4/monitors/{monitor_tag} and fix alert-config orphans on delete, fixes #716
Monitor deletion is now available via the v4 API, reusing the same
DeleteMonitorCompletelyUsingTag path as the manage UI. While wiring it
in, monitor deletion was found to orphan alert configs on SQLite:
the code relied on FK cascades that SQLite never enforces (the
foreign_keys pragma is off). Delete paths now remove child rows
explicitly — v2 alerts, trigger junctions, monitor junctions — in both
the by-id and by-tag config deletes; see ADR 0008 for why explicit
deletes were chosen over enabling the pragma.

Also corrects the CONTEXT.md Stale Member entry (deletion strips group
membership and rebalances weights; only pausing produces a stale
member), documents the DELETE endpoint in the OpenAPI spec, points the
pages doc at the ~home token, and removes an orphaned fictional
api-reference markdown page superseded by the spec tab.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 13:42:08 +05:30
Raj Nandan Sharma c301aaab90 Merge pull request #753 from rajnandan1/fix/717
refactor: unify overall status handling across components and improve…
2026-06-12 12:31:06 +05:30
Raj Nandan Sharma 4ed40a0b08 refactor: unify overall status handling across components and improve documentation, fixes #722 2026-06-12 12:21:43 +05:30
Raj Nandan Sharma 1ac0f2259f Merge pull request #752 from rajnandan1/fix/713
Render maintenance descriptions as sanitized HTML on list views
2026-06-12 00:27:07 +05:30
Raj Nandan Sharma 544bdc9dcb fix(maintenance): render description as sanitized markdown HTML on list views
Maintenance descriptions rendered as plain text in MaintenanceItem, so
HTML tags and line breaks showed literally on the home page while the
maintenance detail page rendered them correctly. Use the same
SveltePurify + mdToHTML prose pattern as the detail page and incident
comments.

Fixes #713

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 00:24:32 +05:30
Raj Nandan Sharma a843ac2926 Merge pull request #751 from rajnandan1/implement/722-1
Implement manual transitions for maintenance events to reflect actual…
2026-06-11 23:53:06 +05:30
Raj Nandan Sharma ccceeb38bd Implement manual transitions for maintenance events to reflect actual occurrences
- Introduce functionality to manually complete or cancel ongoing maintenance events.
- Update event status to COMPLETED or CANCELLED, adjusting end_date_time accordingly.
- Ensure terminal statuses prevent further modifications and notify subscribers of changes.
- Revise API to support status transitions alongside window edits, enforcing mutual exclusivity.
- Document behavior and consequences of manual transitions in ADR.
2026-06-11 22:52:09 +05:30
Raj Nandan Sharma b01560c29b Merge pull request #749 from rajnandan1/implement/721-lastknow
implement last known status retrieval in monitoring system
2026-06-11 07:47:52 +05:30
Raj Nandan Sharma 80c5e298d7 refactor(noneCall): ensure latency defaults to 0 when not provided 2026-06-11 07:41:37 +05:30
Raj Nandan Sharma 3d1335bf40 implement last known status retrieval in monitoring system 2026-06-10 23:34:50 +05:30
Andrew Camilleri 25c893ad86 Show global maintenances in RSS feed
A maintenance with is_global=YES (the default) has no per-monitor rows, so
the feed builder dropped it via the monitors.length===0 guard intended to
hide events whose monitors are all hidden. Global maintenances therefore
never appeared in /rss.xml, even though they show on the public events page.

Carry is_global through getMaintenanceEventsForEventsByDateRange and the
shared monitor-list grouping, then keep global events in the feed while still
dropping non-global ones whose monitors are all hidden. Global items render
"Affected: All monitors".
2026-06-09 21:47:57 +02:00
Andrew Camilleri a9f0437d17 Include scheduled maintenances in RSS feed + mirror toggle on Subscriptions page
Two fixes verified E2E with playwright before pushing:

1. The feed window bounded maintenances to (now - 90d, now), excluding
   any SCHEDULED maintenance with a future start_date_time. Split the
   range so incidents keep their past-only window but maintenances span
   (now - 90d, now + 90d), so subscribers learn about upcoming windows
   alongside historical ones. Incidents are still past-bounded.

2. Mirror the subMenuOptions.showRssFeed toggle on the Subscriptions
   admin page. RSS is a notification channel alongside email subs, so
   admins thinking about subscriber-facing surface area shouldn't have
   to bounce to Site Configurations to manage it. Same backing
   site_data key — toggling either place updates the other on reload.
   The feed routes (/rss.xml etc) stay reachable when the toggle is
   off; the toggle only controls the in-page icon button.
2026-06-09 17:28:09 +02:00
Raj Nandan Sharma 604210568b Merge pull request #747 from rajnandan1/fix/633
refactor(alerts): expand alert evaluation to include all alert-visibl…
2026-06-07 19:27:57 +05:30
Raj Nandan Sharma 41f5296227 refactor(alertingQueue): remove unused imports for cleaner code 2026-06-07 19:27:34 +05:30
Raj Nandan Sharma 8c1a97d844 fix(api): make alert enqueue best-effort and align range-PATCH evaluation timestamp
Review feedback on #747:
- Wrap alertingQueue.push in try/catch in both data PATCH endpoints — the
  sample is already committed, so a Redis/BullMQ outage must not turn a
  successful write into a 500 (which would invite client retries and
  duplicate MANUAL rows).
- Compute lastWrittenTs with GetMinuteStartTimestampUTC(body.end_ts) —
  UpdateMonitoringData floors both bounds to minute starts and writes
  through the floored end inclusive, so the previous raw-offset formula
  could name a timestamp no stored row has when start_ts was unaligned.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 18:54:50 +05:30
Raj Nandan Sharma ed1a70d75b refactor(alerts): expand alert evaluation to include all alert-visible sample types fixes #633 2026-06-07 18:43:38 +05:30
Raj Nandan Sharma e63a2f6311 Merge pull request #746 from rajnandan1/fix/issue-736
refactor(api): enhance page settings management and validation implem…
2026-06-07 13:34:41 +05:30
Raj Nandan Sharma 951ab06f7e fix(manage): require whole-number status history days in both editors
Addresses coderabbit review on #746: the bounds checks allowed decimals.
Number.isInteger is now part of the validity deriveds in the monitor-level
status history card, and the pages editor gains the same guard (it previously
saved display settings with no validation at all) plus step=1 and error
styling on the inputs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 13:28:08 +05:30
Raj Nandan Sharma af4684a90f refactor(monitors): extract per-field validity deriveds in status history card
Addresses coderabbit's outside-diff comment on #746: isDesktopValid and
isMobileValid are derived once and reused by isValid and both input error
states, instead of repeating the bounds check four times.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 13:19:04 +05:30
Raj Nandan Sharma da6eaee3ab fix(api): sanitize stored event-branch leaves on read and validate them on write
Address coderabbit review on #746:
- toApiPageSettings runs type-filtering sanitizers over stored incidents and
  include_maintenances so wrong-typed leaves (enabled: "yes",
  max_count: "five") never override defaults in responses
- validatePageSettings checks every known leaf: booleans for enabled/show,
  non-negative integers for max_count/days fields
- DeepPartial recurses only into plain object maps; arrays pass through

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 13:05:10 +05:30
Raj Nandan Sharma f264115ab8 fix(api): make page settings patching a true deep merge with normalized reads
Address review feedback on #746:
- applyPageSettingsPatch now deep-merges the mapped patch into the stored
  JSON: nested unknown keys survive, untouched siblings survive, and extra
  client keys are persisted as the schema's additionalProperties allows
- toApiPageSettings normalizes invalid stored values (unknown layout style,
  out-of-range or non-integer history days) so responses always satisfy the
  OpenAPI enum and bounds
- new PageSettingsPatch (DeepPartial) type lets TS clients send partial
  nested updates like { monitor_status_history_days: { mobile: 14 } }
- incidents / include_maintenances and their known sub-objects are now
  validated as objects (incidents: 123 returns 400)
- CONTEXT.md wording: the UI and API expose the same settings, surfaces may
  name fields differently

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 12:35:54 +05:30
Raj Nandan Sharma 15b78dab66 refactor(api): centralize status history days and monitor layout styles using global constants 2026-06-07 12:29:54 +05:30
Raj Nandan Sharma 54277ece9a refactor(api): enhance page settings management and validation implements fixes 736 2026-06-07 12:07:34 +05:30
Raj Nandan Sharma 54f056ad34 Merge pull request #745 from rajnandan1/fix/737
feat(api): address the home page as ~home in the v4 pages API
2026-06-06 23:13:40 +05:30
Raj Nandan Sharma 8d2808c291 fix(api): forbid deleting the home page via ~home
DeletePage in pagesController already enforces this invariant for the manage
UI (the UI's delete confirm for home was always rejected server-side), and
the public site root assumes the home page exists. Before the ~home token
the v4 DELETE could never reach the home page; now that it can, it returns
400 like the rest of the app.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 23:12:28 +05:30
Raj Nandan Sharma bd638ccf24 feat(api): render the home page's page_path as ~home in api responses
What a consumer reads is now exactly what it can address: the list, single,
and write responses all show ~home for the home page instead of an empty
string, so list -> pick -> PATCH round-trips cleanly. Read-modify-write
bodies that send ~home back are treated as no path change. The token moves
to global-constants as HOME_PAGE_TOKEN.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 23:03:16 +05:30
Raj Nandan Sharma c2945485e2 feat(api): address the home page as ~home and return json 404s for unmatched api routes
The home page is stored with an empty page_path, which can not appear as a
URL segment, so /api/v4/pages/{page_path} could not address it at all. The
middleware now maps the special segment ~home to the empty-path lookup. The
token can never collide with a real page because the path sanitizer strips
tildes, and tilde is RFC 3986 unreserved so clients never need to encode it
(percent-encoded %7Ehome works too).

Semantics follow the manage UI: PATCH via ~home accepts every field except
page_path, which is fixed for the home page, and DELETE is allowed.

Requests to /api/ paths with no matching route (e.g. GET /api/pages/) now
return a json NOT_FOUND error instead of SvelteKit's html error page.

Documented in the OpenAPI spec (PagePath parameter + PATCH note), ADR 0004,
and the CONTEXT.md glossary.

Fixes #737

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 22:52:46 +05:30
Raj Nandan Sharma a57c92fc0e Merge pull request #744 from rajnandan1/fix/692
refactor(database): implement connection pool tuning and health check…
2026-06-06 21:47:02 +05:30
Raj Nandan Sharma 8e7bc47b14 refactor(monitors): update visibility toggle logic and labels for clarity 2026-06-06 21:46:25 +05:30
Raj Nandan Sharma cd26c46493 log(database): output database type during configuration 2026-06-06 21:41:45 +05:30
Raj Nandan Sharma 508b08f8f3 fix(database): clamp pool bounds, guard redis probe, harden error page
Address review feedback on #744:
- clamp DATABASE_POOL_MAX to >= 1 and DATABASE_POOL_MIN to <= max so bad
  env values can not produce a pool that fails every acquire
- healthcheck redis probe checks client status before PING so commands are
  not queued indefinitely while redis is down (maxRetriesPerRequest is null)
- probe() clears its timeout timer once the check settles
- error.html shows only the status code, not the error message
- docs: correct SQLite default to kener.sqlite.db to match knexfile

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 21:24:03 +05:30
Raj Nandan Sharma 638393efac refactor(database): implement connection pool tuning and health checks for improved reliability 2026-06-06 21:06:06 +05:30
Raj Nandan Sharma 5a54d69d87 Merge pull request #743 from rajnandan1/fix/739
feat(monitors): implement toggle functionality for monitor status and…
2026-06-06 19:49:15 +05:30
Raj Nandan Sharma 7e5ea5fda1 feat(monitors): implement toggle functionality for monitor status and visibility, implements #739 2026-06-06 19:45:00 +05:30
Raj Nandan Sharma 175cf605c6 Merge pull request #742 from rajnandan1/fix/723
feat(api): add absolute `url` field to v4 incident, maintenance, and maintenance event responses
2026-06-06 19:02:29 +05:30
Raj Nandan Sharma 6a9bfffbd4 fix(api): guarantee absolute site url and include READY in event status casts
Address review feedback on #742:
- GetSiteURL now only returns absolute http(s) origins, falling back to the
  ORIGIN env var when the stored siteURL is unset or scheme-less, so the v4
  url fields honor the OpenAPI format: uri contract
- event status casts now use the response interface types
  (MaintenanceEventResponse["status"], MaintenanceEventDetailResponse["event_status"])
  so READY is included and the casts can not drift from the API contract

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 18:38:25 +05:30
Raj Nandan Sharma 7b120911b4 chore: remove redundant code blocks from the repository 2026-06-06 18:26:57 +05:30
Raj Nandan Sharma 35817bc20a feat(api): add absolute url field to v4 incident, maintenance, and maintenance event responses
The public /maintenances/<id> route is keyed by maintenance EVENT id by
default, while /api/v4/maintenances returns maintenance ids. Consumers
that concatenated API ids onto the public path landed on the wrong page
(#723) — an apparent off-by-one title mismatch with no actual data
corruption.

Instead of flipping the route default (which would break every internal
link, subscriber email, and bookmarked URL), v4 API responses now carry
an absolute `url` field built from the configured Site URL:

- Maintenance responses link via /maintenances/<id>?type=maintenance
- Maintenance event responses link via /maintenances/<event_id>
- Incident responses link via /incidents/<id> (parity)

Also updates the OpenAPI spec, records the decision in
docs/adr/0002, and pins Maintenance vs Maintenance Event in CONTEXT.md.

Fixes #723

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 13:55:35 +05:30
Raj Nandan Sharma a8fbac1b69 Merge pull request #741 from rajnandan1/fix/694
chore: update documentation and enhance monitor group functionality, …
2026-06-06 13:05:15 +05:30
Raj Nandan Sharma cfc99e2f14 chore: update documentation and enhance monitor group functionality, fixes #694 2026-06-06 13:04:13 +05:30
Raj Nandan Sharma 31ba10f434 Merge pull request #740 from rajnandan1/fix/707
refactor: implement absolute URL resolution for social media meta tags
2026-06-06 12:26:31 +05:30
Raj Nandan Sharma 1750e2a341 refactor: implement absolute URL resolution for social media meta tags 2026-06-06 12:25:42 +05:30
Raj Nandan Sharma a12df92b94 Merge pull request #734 from Kukks/fix/sticky-header-backdrop
Fix overlapping header sections on the public page
2026-06-06 11:32:38 +05:30
Andrew Camilleri 5d86084138 fix(public): add frosted backdrop behind fixed nav and sticky theme-plus bar
The sticky theme-plus bar has no background, and the gap between it and the
fixed nav stays transparent, so page content shows through both sections as
it scrolls. Paint one blurred layer behind both (above content, below nav
z-10 and bar z-20).
2026-05-29 10:30:27 +02:00
Andrew Camilleri 6e585f4608 Add visible RSS icon button with toggle in Sub Menu Options
ThemePlus now renders a small Rss icon-button next to Subscribe / share
controls, scoped to the current view (monitor / page / default) and
opening the feed in a new tab. Gated on subMenuOptions.showRssFeed
(defaults true) so admins can hide it via Manage → Site Configurations →
Monitor Sub Menu Options without losing the underlying feed routes.

Adds RSS feed key to all 22 locale files (untranslated; RSS is a tech term).
2026-05-28 16:10:03 +02:00
Andrew Camilleri f4d01c7c37 Add per-monitor RSS feed and head autodiscovery link
New route GET /monitors/{monitor_tag}/rss.xml serves a feed scoped to a
single monitor (404s for hidden, inactive, or unknown monitors). Existing
page-scoped routes are unchanged in URL; renderRssFeedResponse now takes
a discriminated scope arg so all three routes share one handler.

The (kener) layout emits a <link rel="alternate" type="application/rss+xml">
in <head>, scoped to the current view: monitor page -> monitor feed,
named status page -> page feed, otherwise default. Lets feed readers and
browsers discover the feed automatically. Title attribute is hardcoded
(machine-facing) so no locale files are touched.
2026-05-28 15:47:48 +02:00
Andrew Camilleri 546118a725 Add public RSS 2.0 feed for incidents and scheduled maintenance
Exposes /rss.xml (default page) and /{page_path}/rss.xml (named pages).
Items inherit visibility from the existing events-by-month data path:
hidden monitors are stripped, KENER_BASE_PATH is honored in absolute
links, and forceExclusivity is respected on the default route.

Feed window: last 90 days, 50 most-recent items, sorted desc.
Response: application/rss+xml; charset=utf-8, Cache-Control max-age=300.
404 on unknown page_path or when siteURL is not configured.

Adds a Core Concepts doc page covering URLs, item shape, and verification.
No user-facing UI text; i18n locales untouched.
2026-05-28 14:15:46 +02:00