docs: add ADR-0017 for performance budgets (Core Web Vitals + Lighthouse CI + Angular budgets + BFF SLOs)
Pin the perf framework. Front-end metrics tracked at Google Core Web Vitals 'Good' thresholds (LCP <= 2.5s, INP <= 200ms, CLS <= 0.1, plus TBT <= 200ms, TTFB <= 800ms) and Lighthouse Performance >= 90 on critical routes. Lighthouse CI (@lhci/cli) enforces them in CI with median-of-3 runs to mitigate runner variance, on a curated critical-routes list (login, home, accessibility statement, flagship features as they land). Wires into the perf gate slot from ADR-0015. Bundle budgets enforced at nx build via Angular's project.json budgets array, type 'error': initial <= 300 KB gzip, lazy chunks <= 100 KB gzip, per-component CSS <= 6 KB. source-map-explorer wired as an Nx analyze target for diagnosis on budget breaches. Back-end SLOs documented per endpoint family (p95/p99) and observed via the OpenTelemetry spans already shipped by ADR-0012 - advisory in CI (load profile unrepresentative), alerting in production. Quarterly review tightens budgets when achievable. Scheduled weekly Lighthouse run on the prod env via the existing security-scheduled.yml workflow extends coverage beyond PR-time. Explicit a11y/perf trade-off rule: when they conflict, a11y wins (per APF's mission, ADR-0016). The perf budget is then re-evaluated at the next quarterly review. No browser-side RUM SDK in v1 - the OTel browser tracing from ADR-0012 plus scheduled prod Lighthouse runs cover the gap. RUM revisited in v2 if a real incident escapes the existing signal. decisions/README.md index updated. CLAUDE.md gains an explicit 'Performance budgets' line pointing to ADR-0017.
This commit is contained in:
@@ -45,6 +45,7 @@ The structural choices are recorded as ADRs and summarized below. Any change to
|
||||
- **Downstream API access:** unified `DownstreamApiClient` (`@nestjs/axios` + `cockatiel`), per-service `DownstreamApiConfig`; default auth strategy is **OBO via MSAL Node** for Entra-protected APIs (downstream-scoped tokens cached in Redis with AES-256-GCM under a dedicated key); fallback strategy is service credential + signed `X-User-Assertion` JWT (BFF JWKS at `/.well-known/jwks.json`); per-call audience pre-check; no `axios`/`fetch` outside `src/downstream/` — see [ADR-0014](decisions/0014-downstream-api-access-obo-pattern.md).
|
||||
- **CI/CD:** **Gitea Actions** (level-2 implementation; will be superseded by a GitLab migration ADR within 6-18 months). Trunk-based with squash-merge, branch protection on `main`, all CI gates blocking. Thin YAML — orchestration logic lives in `package.json` scripts (`ci:check`, `ci:scan`, `ci:commits`) and Nx targets, runnable locally. Gates: format / lint / type-check / test / build / audit / secret-scan / commit-lint, plus `a11y` (per ADR-0016) and future `perf`. Self-hosted `act_runner` on-prem. Conventional Commits validated locally (hook) and in CI (defense in depth). Required reviewer count = 0 in v1, raised to ≥1 once a second contributor joins. Signed commits recommended, revisited at GitLab migration — see [ADR-0015](decisions/0015-cicd-gitea-actions.md).
|
||||
- **Accessibility:** **WCAG 2.2 AA baseline + targeted AAA** on criteria with high impact for APF's user base (1.4.6 Contrast Enhanced, 2.2.3 No Timing, 2.3.3 Animation, 3.1.5 Reading Level, 1.4.8 Visual Presentation, 2.4.9 Link Purpose, 3.3.5 Help). RGAA 4.1 alignment for French audit. UI stack: **Angular CDK + spartan-ng + Tailwind** (no Angular Material; no React libs). User-preferences panel (contrast / text size / motion / spacing / cognitive simplification / reading focus) persisted in session. Tooling: `@angular-eslint/template/*` lint, `@axe-core/playwright` e2e (blocking on critical/serious), token-contrast CI check, touch-target check (44×44 min). Manual testing cadence with APF's internal user panel before each major release. Public accessibility statement page at `/accessibility` and `/accessibilite` — see [ADR-0016](decisions/0016-accessibility-baseline-wcag-aa-targeted-aaa.md).
|
||||
- **Performance budgets:** Core Web Vitals at Google "Good" thresholds (LCP ≤ 2.5 s, INP ≤ 200 ms, CLS ≤ 0.1, TBT ≤ 200 ms, TTFB ≤ 800 ms), Lighthouse Performance ≥ 90 on critical routes. **Lighthouse CI** (`@lhci/cli`) runs in CI with median-of-3 mitigation, blocking on threshold breach. Angular bundle `budgets` (`type: "error"`): initial ≤ 300 KB gzip, lazy chunks ≤ 100 KB gzip. BFF p95/p99 SLOs per endpoint family observed via OTel (advisory in CI, alerting in prod). Weekly scheduled Lighthouse run on prod env. **a11y wins over perf** when they conflict — see [ADR-0017](decisions/0017-performance-budgets-lighthouse-ci.md).
|
||||
- **Local quality gates:** Husky + lint-staged + commitlint with Conventional Commits — see [ADR-0007](decisions/0007-pre-commit-hooks-and-conventional-commits.md).
|
||||
- **Runtime:** Node.js latest LTS major.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user