-
Notifications
You must be signed in to change notification settings - Fork 0
ops: scheduled live-domain monitor for the deployed product (PT-17) #602
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| name: Live domain monitor | ||
|
|
||
| # PT-17 (2026-07-13 external audit): nothing exercised the deployed product | ||
| # after release, so a broken domain, dead health probe, or lost route could | ||
| # only be discovered by a user. This monitor probes the public domain on a | ||
| # schedule with plain unauthenticated GETs — no secrets, no providers beyond | ||
| # what any anonymous visitor triggers, and no third-party actions. | ||
| # | ||
| # A red run is the alert. Deeper answer-SLO probing stays in the ops-digest | ||
| # workflow (dispatch-only, secret-gated); this one must stay cheap enough to | ||
| # never be worth disabling. | ||
|
|
||
| on: | ||
| schedule: | ||
| - cron: "23 */6 * * *" | ||
| workflow_dispatch: | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| concurrency: | ||
| group: live-domain-monitor | ||
| cancel-in-progress: false | ||
|
|
||
| jobs: | ||
| probe: | ||
| name: Probe public domain | ||
| runs-on: ubuntu-24.04 | ||
| timeout-minutes: 10 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win Align the job timeout with the retry budget. There are eight sequential probes. With Possible fix- timeout-minutes: 10
+ timeout-minutes: 20Alternatively, reduce the per-request retry budget while preserving the desired alert latency. Also applies to: 37-37, 46-46, 63-63, 80-80 🤖 Prompt for AI Agents |
||
| env: | ||
| # Repository variable overrides the default (e.g. a staging cutover). | ||
| LIVE_DOMAIN_URL: ${{ vars.LIVE_DOMAIN_URL || 'https://psychiatry.tools' }} | ||
| steps: | ||
| - name: Root renders the app shell | ||
| run: | | ||
| set -euo pipefail | ||
| body="$(curl -sSL --fail --max-time 30 --retry 2 --retry-delay 10 --retry-all-errors "$LIVE_DOMAIN_URL/")" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift Validate redirect destinations before reporting success.
Also applies to: 46-46, 63-63, 80-80 🤖 Prompt for AI Agents |
||
| echo "$body" | grep -q "Clinical Guide" || { | ||
| echo "::error::Root responded but does not render the Clinical Guide shell" | ||
| exit 1 | ||
| } | ||
|
|
||
| - name: Health endpoint reports ok in live mode | ||
| run: | | ||
| set -euo pipefail | ||
| health="$(curl -sSL --fail --max-time 30 --retry 2 --retry-delay 10 --retry-all-errors "$LIVE_DOMAIN_URL/api/health")" | ||
| echo "$health" | ||
| echo "$health" | grep -q '"status":"ok"' || { | ||
| echo "::error::/api/health did not report status ok" | ||
| exit 1 | ||
| } | ||
| echo "$health" | grep -q '"demoMode":false' || { | ||
| echo "::error::/api/health reports demo mode — live configuration lost" | ||
| exit 1 | ||
| } | ||
|
|
||
| - name: Key routes stay reachable | ||
| run: | | ||
| set -euo pipefail | ||
| # -L follows the /applications -> /tools canonicalisation either side | ||
| # of that redirect landing, so this list survives route renames. | ||
| for route in /privacy /services /forms /differentials /applications; do | ||
| code="$(curl -sSL -o /dev/null -w '%{http_code}' --max-time 30 --retry 2 --retry-delay 10 --retry-all-errors "$LIVE_DOMAIN_URL$route")" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For the key-route probes, and again in the www probe below, a transient HTTP 500/502/503 enters curl's retry path, but this exact Useful? React with 👍 / 👎. |
||
| echo "$route -> $code" | ||
| if [ "$code" != "200" ]; then | ||
| echo "::error::$route returned $code" | ||
| exit 1 | ||
| fi | ||
| done | ||
|
|
||
| - name: WWW and TLS answer | ||
| run: | | ||
| set -euo pipefail | ||
| # Only meaningful for the canonical production domain; an overridden | ||
| # LIVE_DOMAIN_URL (e.g. staging) has no www alias to assert. | ||
| if [ "$LIVE_DOMAIN_URL" != "https://psychiatry.tools" ]; then | ||
| echo "LIVE_DOMAIN_URL overridden; skipping www alias check" | ||
| exit 0 | ||
| fi | ||
| code="$(curl -sSL -o /dev/null -w '%{http_code}' --max-time 30 --retry 2 --retry-delay 10 --retry-all-errors "https://www.psychiatry.tools/")" | ||
| echo "www -> $code" | ||
| if [ "$code" != "200" ]; then | ||
| echo "::error::www.psychiatry.tools returned $code" | ||
| exit 1 | ||
| fi | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Remove the unused repository token permission.
This workflow only performs anonymous HTTP probes and does not checkout code, call GitHub APIs, or use actions. Granting
contents: readis unnecessary; usepermissions: {}instead.As per coding guidelines, GitHub workflow automation must use narrow permissions.
Proposed fix
📝 Committable suggestion
🤖 Prompt for AI Agents
Source: Coding guidelines