Files
slp-modular-cms/aidlc-docs/features/gitea-deployment-workflow/operations/plans/monitoring-setup-plan.md
T
SluijsensandClaude Sonnet 5 56f4f6fe0f
Continuous Integration / config (pull_request) Successful in 9s
Continuous Integration / backend-build (pull_request) Successful in 4m27s
Continuous Integration / vulnerability-scan (pull_request) Successful in 4m10s
Continuous Integration / backend-test (pull_request) Canceled after 0s
Continuous Integration / frontend-build (pull_request) Canceled after 0s
Continuous Integration / frontend-test (pull_request) Canceled after 0s
Continuous Integration / frontend-lint (pull_request) Canceled after 0s
Continuous Integration / publish-test (pull_request) Canceled after 0s
Continuous Integration / publish-production (pull_request) Canceled after 0s
Continuous Integration / deploy-test (pull_request) Canceled after 0s
Continuous Integration / deploy-production (pull_request) Canceled after 0s
Continuous Integration / frontend-prepare (pull_request) Canceled after 50s
Adds Monitoring Setup docs and deploy-scp troubleshooting/debug fixes
Monitoring Setup: operations/plans/monitoring-setup-plan.md and
operations/monitoring/monitoring-instructions.md, covering Sentry alert
rules on the security_event tag, UptimeRobot's 6 liveness monitors, and
the two new Umami website entries for the admin SPA.

deployment-instructions.md gains a missing Observability__Environment
host var (without it, both environments would tag Sentry events as
"Production"), the nginx client_max_body_size fix for the 413 seen on
publish-test/production artifact uploads, and two troubleshooting notes
on Gitea Actions re-run behaviour: re-running deploy-test/production
alone loses the run's uploaded artifact, and re-running all jobs on an
existing (rather than a brand new) run can replay stale secrets.

deploy-scp.yaml: step names no longer show literal unresolved
${{ inputs.* }} text (Gitea doesn't interpolate that context in step
names), and a temporary debug step logs PI_MAIN_USERNAME/PASSWORD
length plus a username equality check to diagnose a persistent
Permission denied during the SSH steps, without ever logging the
secret values themselves.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015FffvxxJp5wG34Ru48GBig
2026-07-29 19:39:44 +02:00

6.5 KiB
Raw Blame History

Monitoring Setup Plan

Context already established (not re-asked)

The observability stack and what it must cover were already decided in Requirements Analysis and built during Construction (U4) — this stage is about configuring the real external services and writing the operational documentation, not re-deciding the approach:

  • Stack: Sentry (backend Sentry.AspNetCore + frontend @sentry/react), self-hosted Umami analytics, UptimeRobot uptime monitoring (D-18, D-24, requirements.md § "Monitoring and observability")
  • Sentry projects: one project for the whole CMS, environment tag distinguishes test/production (D-19) — so one DSN, reused by both environments and both frontend/backend
  • Sentry is optional by design: an absent DSN disables it cleanly, console logging stays active (BR-U4-08) — nothing breaks if a value is left blank temporarily
  • Alertable events already exist in code: six security_event tag values are emitted today — failed_login, authorization_denied, master_api_key_rejected, admin_bypass_rejected, rate_limit_triggered, migration_failure (SecurityEvents.cs). Alert rules must filter on the security_event tag, not message text (nfr-design-patterns.md Pattern 6) — this is explicitly named as Operations — Monitoring Setup work in logical-components.md (FR-19)
  • UptimeRobot scope: /health, / (public website) and /admin, per environment — 6 monitors total (D-23)
  • Umami scope: reuse the existing self-hosted instance at analytics.slpsoftware.nl, add new website entries for this CMS rather than standing up a new instance (D-24/ASM-05). Both the admin SPA (via VITE_UMAMI_WEBSITE_ID_<ENV>, built by this pipeline) and the public website (via the separate website-workspace, FR-09/FR-16, out of this pipeline's scope) are measured (D-25) — this stage only configures the admin SPA's two website entries; the public website's Umami wiring belongs to whichever website workspace serves it
  • Health endpoint: liveness only, no DB check, already built and already on the AvailabilityMiddleware bypass list (D-21) — nothing left to build, only to point UptimeRobot at
  • Log retention deviation: accepted knowingly (DEV-01) — Sentry's ~30-day retention against the 90-day SECURITY-14 minimum. No action here beyond documenting it.

Question 1: Include Monitoring Setup?

Given U4 built all the alertable-event plumbing specifically so that Operations could wire up real alert rules and monitors on top of it, declining this stage would leave that code inert — events would be emitted into a Sentry project that doesn't exist yet, with no alert rule reading the tag, and no UptimeRobot monitor watching /health. Recommended: A.

A) Yes — configure the real services and document it (Recommended) B) No — monitoring is handled elsewhere or not needed C) Not sure — suggest an approach and I'll decide

X) Other (please describe after Answer: tag below)

Question 2: Monitoring Method

Confirms the stack already decided in Requirements Analysis — asked per the mandatory format, not because it's genuinely open.

A) Sentry + self-hosted Umami + UptimeRobot, exactly as scoped above (Recommended) B) Something else entirely — describe below

X) Other (please describe after Answer: tag below)


The remaining questions are the genuinely open items — real account/service facts that only you know, which nothing in Construction could decide for you.

Question 3: Sentry Project

Does a Sentry project for this CMS already exist (e.g. created ad hoc while testing U4 locally), or does this stage need to walk through creating one from scratch?

A) Already exists — I'll provide the DSN after Answer: below B) Doesn't exist yet — walk me through creating one (org, project platform picks for .NET + React, where to find the DSN afterward) C) Not yet, and I'd rather set it up myself later — document it as a TODO with exactly which Gitea secrets/variables need the DSN once it exists

X) Other (please describe after Answer: tag below)

Answer:A — DSN to be added directly to the Gitea secret/variable once shared (kept out of this doc)

Question 4: Sentry Alert Rule Thresholds

FR-19 requires alert rules for repeated auth failures and authorization violations, filtering on the security_event tag (values: failed_login, authorization_denied, master_api_key_rejected, admin_bypass_rejected, rate_limit_triggered; migration_failure is Critical-level and worth its own always-fire rule regardless of count). What threshold should the repeated-failure rules use?

A) A single reasonable default for all of them (e.g. 20 occurrences in 5 minutes) — document it as a starting point, tune later from real traffic (Recommended) B) I'll specify exact thresholds per event type — describe below C) No count threshold — alert on every occurrence of each of the six (noisier, but nothing is ever missed)

X) Other (please describe after Answer: tag below)

Question 5: UptimeRobot Account and Alert Contacts

6 monitors are needed (/health, /, /admin × test/production). Do you have an UptimeRobot account already (e.g. from the reference SlpSoftware project), and where should alerts go?

A) Existing account, reuse it — alert contact(s): describe after Answer: below (email, and/or any other channel already configured there) B) Need a new account/monitor group set up from scratch — walk me through it C) Not sure yet — document the 6 monitors' exact URLs and recommended check interval as a checklist, I'll create them myself

X) Other (please describe after Answer: tag below)

Answer:A — existing account, alert contact to be confirmed

Question 6: Umami Website Entries (Admin SPA)

Two new website entries are needed on the existing analytics.slpsoftware.nl instance — one per environment — to obtain the VITE_UMAMI_WEBSITE_ID_TEST/_PRODUCTION values the CI workflow already expects as Gitea variables (continuous_integration.yaml reads vars.VITE_UMAMI_WEBSITE_ID_TEST/ _PRODUCTION).

A) I have access to the Umami instance — I'll create the two entries and provide the website IDs after Answer: below B) Walk me through creating them (Umami's own UI/API steps) C) Not yet — document it as a TODO with the exact variable names the pipeline expects, I'll fill them in before the first real deploy

X) Other (please describe after Answer: tag below)

Answer:A — website IDs to be added directly to Gitea variables once created (kept out of this doc)