# 外部 Synthetic Healthcheck — Worker outage 検知

> **SSoT 参照**: 通知 channel / severity 振り分けは
> [notification-strategy.md](notification-strategy.md) で定義。
> 本 runbook は GH Actions cron 実装 + Discord webhook 配線 + 本格化 (Cloudflare
> Health Checks) 移行手順のみ扱う。
>
> dev fail → P1 (`#p1-ops`)、prod fail → P0 (`#p0-alerts` + `@here`)
> に振り分け済 (commit `956c8c6d`)。`workflow_dispatch` の input
> `force_fail=true` で smoke 発火可。

> 監査 2026-04-29 #1 Operations Critical 対策。  
> 「外部 synthetic 監視ゼロ — Worker outage 検知が user 報告依存」を解消する。

## 現状 (2026-04-29)

- **暫定**: `.github/workflows/synthetic-healthcheck.yml` で 5 分粒度の GH Actions cron 監視を稼働中。失敗時 Discord 通知。
- **本格**: Cloudflare Health Checks (Pro plan 必要 / より高頻度 / 別 region から probe) は未設定 (M-04 manual)。
- **内部 cron warmer** (`api/src/cron/warmer.ts`) は Worker 自身が動いている前提なので、Worker 全停止検知には使えない。

## GH Actions 暫定実装の特性

| 項目 | 値 |
|---|---|
| 監視頻度 | 5 分間隔 (GH Actions cron 最短粒度) |
| 監視 region | GH Actions runner = 現状 `ubuntu-22.04` (US/EU 中心) |
| 失敗判定 | HTTP != 200 OR body の `ok != true` を **連続 2 回** 確認したら通知 (transient flap 対策で 5 秒 sleep + retry) |
| 通知先 | Discord webhook (matrix で `parky-api-dev` は warning 黄色 / `parky-api-prod` は critical 赤 + `@here` mention) |
| 通知先未設定時 | warning ログのみ (workflow は走り続ける) |
| Actions UI | probe 失敗時は最終 step で `exit 1` し job が赤くなる (履歴で過去失敗を辿れる) |

### 本構成の限界

- **GH Actions cron は SLA 緩い** — 5 分後に正確に走る保証はなく、重い時間帯に最大 +10 分遅延する事例あり。本気で 1 分粒度 SLA が必要なら有料 monitor 必須。
- **Region 偏重** — GH Actions runner は US/EU 中心。日本 user が体験する outage を完全に再現できない。
- **GH Actions 自体が落ちると盲目** — GitHub status page は別 channel で監視する想定。

## セットアップ手順 (user manual)

### 1. Discord webhook (notification-strategy.md SSoT 準拠)

5 channel × 1 webhook 構成。本 workflow は severity に応じて 2 本を参照する:

| severity | channel | GH Secret |
|---|---|---|
| `critical` (prod) | `#p0-alerts` | `DISCORD_WEBHOOK_ALERTS` |
| `warning` (dev)   | `#p1-ops`    | `DISCORD_WEBHOOK_OPS` |

Webhook URL の発行 + 1Password 登録 + GH Secret 一括投入手順は
[notification-strategy.md §10 Phase 1](notification-strategy.md) 参照。
旧 `DISCORD_HEALTHCHECK_WEBHOOK_URL` (#system-alerts 単一 webhook) は廃止済。

### 2. 動作確認

- 通常モード: `gh workflow run synthetic-healthcheck.yml --ref main` で手動 dispatch。
  healthz が緑なら Discord には何も出ない (= 正常)。
- smoke モード: `gh workflow run synthetic-healthcheck.yml --ref main -f force_fail=true`
  で probe を skip し Discord notify path を強制発火。alert は subject に `[SMOKE]`
  prefix + 説明 field 付きで投稿される。job 自体は green を維持。
- 既存通知 (実 outage 検知時): subject `[P1] healthcheck FAILED — parky-api-dev (dev)`
  または `[P0] ... — parky-api-prod (prod)` の embed が該当 channel に届く。

## 本格移行 (Cloudflare Health Checks)

GH Actions cron を捨てる必要はないが、以下を追加すると 1 分粒度 + 多 region monitor になる。

### 前提

- Cloudflare **Pro plan 以上** (Health Checks は Free 不可)
- monitor 1 つ = $0 (Pro plan 内)、追加 monitor は $5/mo each (5 個まで Pro 標準)

### 手順

1. Cloudflare Dashboard → **Traffic** → **Health Checks** → **Create**
2. Name: `parky-api-prod-healthz`
3. Target: `api.parky.co.jp/healthz` / Method: `GET` / Interval: `60s` / Expected status: `200`
4. **Notification**: Slack / Discord webhook (Cloudflare → Notifications → New → Webhook)
5. dev も同様に `dev-api.parky.co.jp/healthz` で別 monitor (interval 5min で十分)

### 移行後の役割分担

| 監視 | カバー |
|---|---|
| Cloudflare Health Checks | 1 分粒度の本体 outage 検知 (主役) |
| GH Actions cron | 5 分粒度のバックアップ + Cloudflare 自体の障害時の fallback |
| Sentry alert (M-02) | 5xx burst / error rate spike (機能別 tracking) |

## 関連

- 監査レポート: `.work/parky/2026-04-29_001_parky_comprehensive_evaluation_v2.html`
- M-04 (manual checklist): `.work/parky/2026-04-28_002_parky_manual_action_checklist.html`
- /healthz 実装: `parky/api/src/app-core.ts` (現状は `{ ok: true, time }` のみ。将来 deep health 化で DB ping + R2 ping 追加予定)
