Commit Graph
1525 Commits
Author SHA1 Message Date
gorkem-bwl e760db1192 fix(monitors): correct proxy transport and error attribution
Second review round found two blocking defects, both verified against a stub
proxy rather than inferred.

HttpsProxyAgent was used for every target, and it always issues CONNECT:

    PROXY RECEIVED: "CONNECT example.com:80 HTTP/1.1"

Squid's stock ACL permits CONNECT only to 443, so every http:// monitor would
have broken the moment HTTP_PROXY was set — in exactly the hardened networks
this feature targets. Plain-http targets now use http-proxy-agent, which
sends an absolute-URI request. The agent cache keys on target scheme.

A refused CONNECT is replayed onto the socket, so the proxy's own status was
parsed as the target's: a proxy ACL denial reported "the site returned 403",
and a monitor whose customUpCodes included 403 or 407 was marked UP while the
target was never reached. Proxy-tunnel rejections are now detected via the
agent's proxyConnect event and reported as a network error naming the proxy.
The listener is per request and removed in a finally block, so a failure
cannot be attributed to a concurrent check.

Also from review:

- The fallback for an invalid PROXY_MONITOR_TYPES no longer fires when every
  entry was a deliberate but unproxyable type ("ping,port"). Falling back
  there would have proxied http and pagespeed, which the operator never
  nominated. Typos still fall back; unproxyable lists stay empty and warn.
- Dropped the now-redundant strict/insecure agent split: TLS is applied per
  request, and Node already separates socket pools by TLS options, so the
  split only doubled tunnels to the proxy.
- Renamed to ProxyPolicy.ts to match the PascalCase peers in the directory.
- The warning no longer echoes the raw config value.

Adds 9 tests covering scheme selection, tunnel rejection, and the narrowed
fallback. Verified by reverting: the tunnel-failure test fails without the fix.
2026-08-20 10:58:55 -04:00
gorkem-bwl 3b03850a3b fix(monitors): keep ignoreTlsErrors effective for proxied checks
Review found that the proxy path silently dropped ignoreTlsErrors.
rejectUnauthorized was passed to the HttpsProxyAgent constructor, where it
governs the socket to the proxy rather than the tunnelled handshake with the
target. Verified directly: the value lands in connectOpts, while the target
handshake reads got's per-request https options, which were unset and so
defaulted to strict.

The consequence was worse than a no-op. A monitor with ignoreTlsErrors
against a self-signed endpoint works today; configuring a proxy would have
made it fail verification, flip to down and fire a false incident with
notifications. Stating the option per request fixes it, and the agent cache
keeps its TLS split so a relaxed agent is never shared with a strict monitor.

Also from review:

- A fully-invalid PROXY_MONITOR_TYPES disabled proxying entirely, which in a
  restricted-egress deployment would take every HTTP monitor down at once —
  the exact failure the parser was meant to prevent. It now falls back to the
  defaults and warns loudly. "none" remains the way to disable deliberately.
- The "none" sentinel only matched when it was the sole entry, so "none,http"
  half-enabled proxying. It is now honoured wherever it appears.
- "unknown" is a real MonitorType but never a deliberate choice, so it is
  reported as a typo rather than as an unproxyable type.
- Dropped the unused warning field from ProxyResolution.
- Documented that lowercase proxy variables are honoured and take precedence,
  which matters on base images that already set them.

Adds 10 tests, including the request-level TLS assertions the previous suite
lacked. Verified by reverting the fix: both TLS tests fail without it.
2026-08-20 10:46:25 -04:00
gorkem-bwl 705c19f7c8 feat(monitors): route checks through an outbound HTTP proxy
Deployments with restricted egress could not run checks at all: got does not
read HTTP_PROXY/HTTPS_PROXY (unlike curl or axios), and NODE_USE_ENV_PROXY
only affects Node's built-in fetch, which got does not use. Even a correctly
built proxy agent was discarded, because HttpProvider overwrote
options.agent on every request.

Proxy selection is resolved per check and applied where the agent is chosen.
NO_PROXY handling is delegated to proxy-from-env rather than reimplemented,
so wildcards, host lists and port-qualified entries behave exactly as
operators expect from curl.

Infrastructure monitors are excluded by default. Hardware and pagespeed
checks both delegate to HttpProvider, so a naive global proxy would also
capture Capture agents — which normally sit on the internal network, where
proxying them fails or hairpins. PROXY_MONITOR_TYPES is the escape hatch for
deployments whose agents genuinely are behind the proxy, and accepts "none"
to disable proxying without unsetting the environment variables. Values that
are not real monitor types, or that open raw sockets and cannot be proxied
(ping, port, docker, grpc, websocket, dns, game), are dropped and logged so
a typo cannot silently disable proxying.

Agents are cached by proxy URL and TLS mode. Keying on TLS matters: sharing
one agent between a strict monitor and an ignoreTlsErrors monitor would leak
the relaxed setting across monitors. Caching also preserves pooling, so 50
monitors share tunnels instead of dialling the proxy per check.

Both new dependencies were already present transitively (76K total).

Notification providers still call out directly and are unaffected; that is a
known follow-up for the same class of deployment.
2026-08-20 10:39:36 -04:00
Alex Holliday 7fd368def3 update tests 2026-08-19 10:26:17 -07:00
Alex Holliday dd44e6c34f add recent checks for infra monitors 2026-08-19 10:20:21 -07:00
Alex Holliday 2468d3e287 bump dependencies 2026-08-18 11:21:20 -07:00
Alexander Holliday 6eba53d716 Merge pull request #3837 from egeoztass/fix/email-error-propagation
fix: propagate SMTP transport errors from EmailService.sendEmail
2026-08-18 10:36:02 -07:00
Alexander Holliday 8bfb3a7de5 Merge pull request #3838 from egeoztass/fix/matrix-notifications
fix: resolve Matrix room aliases and encode room IDs in the send path
2026-08-18 10:32:45 -07:00
Alexander Holliday 5cca0fb2d3 Merge pull request #3839 from egeoztass/feat/ntfy-authentication
feat: add authentication support to ntfy notifications
2026-08-18 10:30:08 -07:00
Alex Holliday 7478bd7d17 remove duplicate validation 2026-08-17 13:08:43 -07:00
Alex Holliday 7b1d6c763f tighten types, remove duplicate calls 2026-08-17 13:05:03 -07:00
Alex Holliday ff2e1fd648 use reduce 2026-08-17 12:59:23 -07:00
Alex Holliday 9001a8d294 add tests 2026-08-17 12:58:56 -07:00
Alex Holliday ab7f2cd8f4 update openapi docs 2026-08-17 12:36:39 -07:00
Alex Holliday c1f0bf3dd4 wire controller 2026-08-17 12:31:01 -07:00
Alex Holliday 3fc7020a90 move methods to checks, wire up service 2026-08-17 12:26:49 -07:00
Alex Holliday 6f9642c298 tighten timezone validation 2026-08-17 11:48:56 -07:00
Alex Holliday 3a22d3e819 add range buckets for status pages 2026-08-17 11:48:44 -07:00
Alexander Holliday 697574a2a9 Merge pull request #3834 from colinjtsen2010/feat/domain-monitoring
feat: add domain registration expiry monitoring
2026-08-17 10:51:11 -07:00
Alex Holliday 0cbd9ab8a2 point lockfile at official npm registry 2026-08-17 10:49:39 -07:00
egeoztass 099eaa38c3 fix: resolve Matrix room aliases and encode room IDs in the send path
Matrix notifications failed for anyone who entered a room alias. The send
endpoint only accepts a room ID, and an unresolved alias broke the request
outright: the leading "#" opens a URI fragment, so the PUT landed on
/_matrix/client/v3/rooms/ instead of the send endpoint. Element shows users
the alias, so this is the value most people paste in.

- Resolve "#alias:server" through GET /_matrix/client/v3/directory/room/{alias}
  before sending, per the client-server spec
- Percent-encode the room ID in the send path; ":" was previously sent raw
- Strip trailing slashes from the homeserver URL to avoid "//_matrix/..."

Alias resolution failures return false and log, matching how the provider
already handles send failures.

Closes #3478
2026-08-14 17:55:36 +03:00
egeoztass c35b22e1ac fix: propagate SMTP transport errors from EmailService.sendEmail
sendEmail caught transport failures internally and resolved to false or
undefined, so every caller's .catch() was dead code and send failures were
silently suppressed. Password recovery in particular reported "email sent
successfully" while the user received nothing.

sendEmail now throws an AppError carrying the underlying cause, and returns
Promise<string> instead of Promise<string | false | undefined>.

Call sites updated for the new contract:
- UserService.registerUser: the existing .catch() now actually fires
- UserService.requestRecovery: the failure reaches the client instead of a
  misleading success response
- InviteService and the test-email endpoint: keep their user-facing messages
  and attach the SMTP cause
- EmailProvider: catches and returns false, because NotificationsService fans
  providers out through Promise.all and a rejection there would abort the
  other channels' alerts

Closes #3757
2026-08-14 14:11:16 +03:00
egeoztass 1c9739d1da feat: add authentication support to ntfy notifications
ntfy servers that require auth rejected every Checkmate alert because the
provider posted without an Authorization header, so alerts to protected
topics failed silently.

Adds ntfyAuthType ("none" | "token" | "basic"):
- token: Authorization: Bearer <accessToken>
- basic: Authorization: Basic base64(ntfyUsername:accessToken)

Both types store their secret in the existing accessToken field rather than
introducing a new secret, so credential handling stays in one place.

Incomplete credentials fail the send instead of falling back to an anonymous
post, and validation rejects partial auth config up front so a channel can't
be saved looking authenticated while posting anonymously.

Backend only; frontend follows once this lands.

Closes #3717
2026-08-14 14:01:06 +03:00
Marcos Paulo Diniz d4eaad6170 fix(notifications): route Rocket.Chat links by monitor type
Build title_link from the monitor type (hardware -> infrastructure,
pagespeed -> pagespeed, uptime types -> uptime) and omit it when
clientHost is not configured, instead of always linking to the
infrastructure page.
2026-08-13 11:56:28 -03:00
colinjtsen2010 75516a220d fix: handle IPs, avoid wrong parent-domain lookups, cache whois results
- Bare IP addresses and non-domain hosts (localhost, IPv6) now return a
  null expiry instead of throwing, so they no longer spam error logs.
- Extract the registrable domain with tldts instead of walking up
  hostname labels, so a subdomain can never accidentally return its
  parent domain's expiry date.
- Cache WHOIS lookups per registrable domain (1h positive, 10min
  negative) so visiting details pages does not re-query the registry
  every time.

Addresses review feedback on #3834.
2026-08-13 12:02:49 +08:00
colinjtsen2010 e5959ca91d feat: add domain registration expiry monitoring
Adds a GET /monitors/domain/:monitorId endpoint that looks up the
registrable domain's WHOIS expiry date (walking up from subdomains),
and displays it next to the certificate expiry on the uptime details
page.

Fixes #2094
2026-08-11 00:34:21 +08:00
Marcos Paulo Diniz 8d1fd61bb4 fix(notifications): omit empty incident links 2026-08-07 14:55:05 -03:00
Marcos Paulo Diniz 865fa7cce6 feat(notifications): add rich alert fields 2026-08-07 14:55:05 -03:00
Marcos Paulo Diniz 2c780b8101 feat(notifications): add Rocket.Chat attachments 2026-08-07 14:55:05 -03:00
Marcos Paulo Diniz ee25c6b479 feat(notifications): enrich Rocket.Chat tests 2026-08-07 14:55:05 -03:00
Alexander Holliday 514ee0d30b Merge pull request #3822 from mdiniz97/feat/rocket-chat-notifications
feat: Rocket.Chat notifications
2026-08-05 09:33:42 -07:00
Marcos Paulo Diniz 466d356ad1 refactor(validation): use Zod URL protocols
Refs #3821
2026-08-05 08:34:12 -03:00
Marcos Paulo Diniz 0c184e6d0c fix(notifications): guard incident link
Refs #3821
2026-08-05 08:33:29 -03:00
Alex Holliday 303f47a117 add opt out flag for recent checks 2026-08-04 15:30:34 -07:00
Alex Holliday 5fa74bd883 replace findAll with findAllForScheduling 2026-08-04 15:16:03 -07:00
Alex Holliday 4c8342f379 fix pretty name bug, ordering bug 2026-08-04 14:46:52 -07:00
Alex Holliday dfcb3b4b21 slim check snapshot model/types 2026-08-04 11:27:32 -07:00
Marcos Paulo Diniz 2e19b85a2d docs(notifications): document Rocket.Chat
Refs #3821
2026-08-02 01:59:58 -03:00
Marcos Paulo Diniz 750fc9e238 feat(notifications): add Rocket.Chat provider
Refs #3821
2026-08-02 01:59:11 -03:00
Alexander Holliday 6e6ac5dbf6 Merge pull request #3819 from bluewave-labs/feat/client-side-presentation
feat: client side presentation
2026-07-31 11:52:54 -07:00
Alex Holliday ac251c4d3f update tests 2026-07-31 11:36:20 -07:00
Alex Holliday 8a608961e6 remove server side normalization 2026-07-31 10:31:39 -07:00
Alexander Holliday 955c400731 Merge pull request #3808 from anjupathak03/fix/tag-filtering
test: cover monitor tag filtering
2026-07-31 10:06:59 -07:00
Alexander Holliday 093553f9ba Merge pull request #3818 from bluewave-labs/feat/chart-cleanup
feat: chart cleanup
2026-07-30 12:16:24 -07:00
Alex Holliday 6b4444038c add tests 2026-07-30 11:54:19 -07:00
Alex Holliday c102cd8d26 openapi schemas 2026-07-30 10:35:01 -07:00
Alexander Holliday ff28e74aca Merge pull request #3797 from LvckyAPI/fix-incorrect-status
Fix monitoring status stuck
2026-07-30 09:44:15 -07:00
Alex Holliday 0172272dc3 update tests 2026-07-29 12:33:56 -07:00
Alex Holliday ed54fa4668 first byte to total repsonse 2026-07-29 12:30:18 -07:00
Alex Holliday e3075318b6 denormalize resposne times 2026-07-29 10:57:20 -07:00