ADORSYS-GIS / ADORSYS-GIS/lightbridge-authz
[Story]: An auth-health Grafana dashboard — can people log in right now, and if not, why?
- Lingua principale
- Rust
- Stelle
- 0
- Fork
- 1
- Merge medio
- 6h 42m
- PR unite (30g)
- 246
Descrizione
## User Story
**As** whoever is on call,
**I want** one dashboard answering *"can people log in right now, and if not, why?"*,
**so that** an auth outage is a glance rather than a three-hour investigation.
## Source of truth (links)
Parent epic #638. #623 (3h32m outage whose signature was in Loki the whole time), #637 (the `reason=` field this depends on), `docs/architecture/auth-flows.md` §3a (the state machine the reasons map onto).
## Context
The 2026-09-01 outage had an unmistakable signature, sitting in Loki, unseen for 3h32m:
```
rp leg failure reason="begin_device_failed" <- repeating
token-exchange refreshed access token <- healthy throughout
```
**Fresh logins broken, refreshes fine.** Two series on one graph. Refreshes kept working because they never touch the RP leg, which is exactly why "the service looks busy and healthy" was so misleading.
## Acceptance Criteria
A `GrafanaDashboard` CR, managed like the existing 32, with at minimum:
- [ ] **Fresh logins vs refreshes** over time, as two series. This one panel makes #623 obvious. It is the reason this story exists; if only one panel ships, it is this one.
- [ ] **Refresh refusals by `reason`** — the `reason=` field from #637: `jwt_verification_failed`, `wrong_client`, `absolute_cap_exceeded`, `context_not_found`, `account_suspended`, `unknown_token`, `revoked`, `expired`. This is what turns "users are being logged out" into a cause.
- [ ] **RP-leg failures by `reason`** — `begin_device_failed`, `callback_completion_failed`, `callback_state_mismatch`, etc.
- [ ] **Signing-key age**, per `purpose`. Rotation is age-driven (`max_key_age_days`); a key about to roll is worth seeing before it does.
- [ ] **Discovery/JWKS reachability** — the failure mode behind #623, where `discover()` failed on every call.
- [ ] Every panel documents its LogQL/PromQL inline, so it can be re-derived when a field name changes.
## Out of Scope
- GenAI usage/cost — that is #581 and the existing 32 dashboards.
- Per-user analytics. This is service health; if it starts answering "who did what", it has drifted.
- Alerting (story 3), though panels should be shaped so alerts can reuse their queries.
## Dependencies
**#637 must be deployed** or the refusal-by-reason panel is empty — the field will not exist in Loki yet. The fresh-logins-vs-refreshes panel works today, from data already collected.
## Test Plan / Verification evidence
Replay each of the epic's three incidents against the dashboard and show it would have been caught:
1. Induce a discovery failure in staging -> fresh logins drop, refreshes flat.
2. Revoke a chain -> the refusal panel shows `revoked`.
3. Present a token signed by the wrong key -> `jwt_verification_failed`.
Paste screenshots or panel JSON with real data. **A dashboard that renders is not the same as a dashboard that would have caught the outage** — the acceptance evidence is the replay, not the render.
## AI Usage Declaration
AI (Claude Opus 5, Claude Code) diagnosed the incidents this dashboard is derived from and drafted this story.
- [x] The panel list comes from what was actually needed during three real investigations, not from a generic dashboard template.
- [x] The dependency on #637 is stated, including which panel is empty without it.
- [x] `reason` values are the real emitted strings, read from the merged implementation.
## Human verification completed
- [ ] Owner confirms the panel list and that health, not analytics, is the boundary.
Guida per i contributori
Apri la guida per i contributori
Valutazione
Questa issue non è ancora stata valutata.