# Uptime Monitoring — iec-pulse

## Automatic on Every Deploy

Every `tawa deploy` automatically registers an uptime monitor via iec-pulse. No configuration needed — the builder reads your service URL and health endpoint from catalog-info.yaml, and attaches your **org** (from `spec.owner`) so the monitor is scoped to you.

## Org Attribution

The builder includes your owning org slug in the registration payload (`org`, derived from `spec.owner`). iec-pulse stores it on the monitor so per-org status pages can show **only your services**. Older builders that don't send `org` still work — a missing org never overwrites a known one.

## What Gets Monitored

| Check | Interval | Target |
|-------|----------|--------|
| Health endpoint | 30s (prod) / 60s (sandbox) | `https://{service}.tawa.pro{healthEndpoint}` |
| Custom domains | 60s | Each domain from `tawa domain add` |

## Health Endpoint Requirement

Your service **must** expose a health endpoint that returns 2xx. The default path depends on your framework:

| Framework | Default | Override |
|-----------|---------|----------|
| express / fastify / hono | `/health` | `insureco.io/health-endpoint` annotation |
| nextjs | `/api/health` | `insureco.io/health-endpoint` annotation |

## "What's New" — Deploy Changelog on Your Status Page

Every `tawa deploy` also publishes a changelog for your service. It appears on your status page under **What's new** — no wiring, no extra command. The source is picked automatically, so even a vibe-coder who never writes release notes gets one:

| Source (in priority order) | What you do |
|----------------------------|-------------|
| `CHANGELOG.md` in your repo root | Keep a `CHANGELOG.md` (Keep-a-Changelog style — `##` headings + `-` bullets render cleanly). Best control. |
| **Fallback: your git commits** | Nothing. The builder derives a summary from `git log` since your last deploy. **Write decent commit subjects** (`feat: …`, `fix: …`) and they become your changelog for free. |

### How it flows

```
tawa deploy
  └─ builder derives notes  (CHANGELOG.md → else git log since last deploy)
       └─ POST koko /api/plugins/{service}/changelog        (stored once per service, upserted)
            └─ iec-pulse status page reads it → renders "What's new"
```

Koko is the single store — iec-pulse reads it live at `GET /api/plugins/{service}/changelog` (public). Nothing is duplicated. If Koko is unreachable, the status page simply omits the section; deploys are never blocked.

If the service declares [`spec.walkthrough`](catalog-info.md#specwalkthrough--asserted-screenshot-walkthroughs), the builder re-publishes the changelog after the deploy-gated tests pass with the bundle's `walkthroughUrl`, so the same Koko record carries the latest walkthrough for the status page to link from **What's new** (`walkthroughUpdatedAt` says how fresh that link is; a deploy that produces no walkthrough leaves the previous link in place).

A redeploy of the **same commit** with no `CHANGELOG.md` (a config change, a re-roll) derives no new notes, so nothing is re-published — but its walkthrough is still new. The builder attaches just the link to the changelog Koko already holds (`PATCH /api/plugins/{service}/changelog`), leaving the notes and their publish time unchanged; the build log says `Changelog: walkthrough link published (changelog unchanged)`. Only a service with no changelog in Koko at all gets `[warn] … Koko holds none to attach it to`.

**Tips**
- Markdown is rendered as a safe subset (headings, bullet lists, inline `` `code` ``). Raw HTML is escaped.
- Long changelogs are truncated on the page — the full history stays in your repo's `CHANGELOG.md`.
- The panel shows the version (if your `CHANGELOG.md`/manifest carries one) and the deploy time.

## Status & Dashboards

| URL | What |
|-----|------|
| `https://status.insureco.io` | Public status page, no login. `https://status.tawa.pro` is the same page |
| `https://iec-pulse.tawa.pro/dashboard` | Owner dashboard for your org's monitors (Bio-ID login) |
| `GET https://iec-pulse.tawa.pro/api/pulse/status` | JSON status API |

iec-pulse is the whole system: it stores the monitors, runs the checks and serves
the pages.

> **Correction (2026-10-01):** this page listed `https://checkcle.insureco.io` as
> the admin dashboard. CheckCle was the first version of platform monitoring and
> has been retired (insureco/iec-pulse#58). That address no longer exists, and
> `status.insureco.io`, which used to show CheckCle's login, now shows the public
> status page.

## Builder Integration

The builder saves a `pulseMonitorId` on your service record after registering the monitor. This is automatic — you never interact with it directly.

If `IEC_PULSE_URL` is not set on the builder, monitor registration is silently skipped. Deploys are never blocked by pulse failures.

## Adding Non-Tawa Monitors

For a target the builder does not deploy (a Cloudflare Worker, a third-party API,
a managed database), register it with iec-pulse and mark it `unmanaged`, so the
hourly reconcile does not prune it for being absent from Koko:

```bash
curl -X POST https://iec-pulse.tawa.pro/api/pulse/register \
  -H "Authorization: Bearer $PULSE_INTERNAL_KEY" -H 'Content-Type: application/json' \
  -d '{ "serviceName": "relay-inbound", "org": "insureco", "namespace": "external",
        "environment": "prod", "url": "https://relay-inbound.example.workers.dev",
        "healthEndpoint": "/health", "interval": 60, "unmanaged": true }'
```

This is a platform-operator call: it needs the iec-pulse internal key. Optional
`expectStatus` and `expectBodyContains` replace the default "any 2xx is up" rule.
Details are in the iec-pulse README.
