# Internal latency SLO board (ops only)

Internal dashboards and alerts for preview / delivery / promote latency. **Not a published customer SLO.** Numeric preview/delivery SLOs stay unpublished until v1 GA (`design-partner-pilot.md`, product preference).

Isolate helpers live in `apps/api/src/observability/latency-slo-board.ts` (`buildInternalSloBoard`, `evaluateLatencyJoinAlerts`). They read aggregation series plus a bounded recent join ring — never promote join fields into `{name}_total` labels.

## Metrics

| Name | Aggregation labels | Sink-only `join` |
| --- | --- | --- |
| `releases.edge_read` | `perspective`, `source`, `kind`, `outcome`, optional `channel` | `releaseId`, `channel`, `requestId`, `locale` |
| `releases.promote_flip` | `op`, optional `channel` | `releaseId`, `channel`, `requestId` |

Structured Workers Logs: `type: "latency"` with `labels`, optional `join`, and `durationMs` as the value. Optional Analytics Engine `METRICS` binding appends join blobs in fixed order: `releaseId`, `channel`, `requestId`, `locale` (null when absent).

## Dashboard panels (internal)

`buildInternalSloBoard()` returns:

- `publication: "internal_only"` and a disclaimer that percentiles are not contractual
- Panels for edge-read and promote-flip isolate p50/p95 snapshots
- `joinCoverage` counts over the recent join ring
- Join-integrity alerts (below)
- Ready-made Workers Logs filter strings in `workersLogsQueries`

Use Cloudflare Workers Logs / `wrangler tail` with those filters. Example:

```bash
# All latency lines
wrangler tail --env <env> --format json --search '"type":"latency"'

# Correlate a promote to delivery samples
# Workers Logs query:
# $json.type == "latency" AND $json.join.releaseId == "<releaseId>"
```

Do **not** copy isolate p50/p95 into marketing, status pages, or pilot decks as an SLO.

## Alerts (join-key hardened)

Alerts are correlation / instrumentation checks — not absolute ms customer budgets:

| Kind | When | Action |
| --- | --- | --- |
| `missing_join_release_id` | `edge_read` hit with `source=release`, or any `promote_flip`, without `join.releaseId` | Fix call sites to pass `joinFromResult` / `releaseId` |
| `promote_without_correlated_reads` | Promote sample's `releaseId` has no recent `edge_read` hit with the same join | Confirm delivery path recorded hits, or query Logs by `join.releaseId` |
| `join_key_used_as_label` | `releaseId` / `requestId` / `locale` appear as counter/series labels | Remove — cardinality must stay bounded |

`channel` may appear on both labels and join (low cardinality). High-cardinality ids must stay sink-only.

## Honesty

- No certification claims; no public “SLO met” marketing from this board.
- PRD §11.1 design targets remain engineering budgets, separate from this ops surface.
- Pilot language: latency is instrumented; customer-facing numbers wait for GA.
