Julien Gautier 472b2b2c8c
CI / scan (pull_request) Successful in 2m21s
CI / commits (pull_request) Successful in 2m31s
CI / check (pull_request) Successful in 2m40s
CI / a11y (pull_request) Successful in 1m56s
CI / perf (pull_request) Successful in 5m44s
feat(portal-admin): audit log viewer screen
Final piece of the chantier portal-admin per ADR-0020 §"v1 scope"
item 4. The new /audit page consumes GET /api/admin/audit (PR #132),
renders a filter form + paginated results table, and trips the
admin.audit.query deterrent on every fetch.

What lands

- AuditEventsService (apps/portal-admin/src/app/pages/audit/
  audit-events.service.ts): thin HttpClient wrapper around
  GET /api/admin/audit. Builds HttpParams from the filter shape,
  dropping empty strings (Nest's ValidationPipe treats ?foo= as
  invalid). providedIn: 'root' — the audit page is the single v1
  consumer, no per-page DI overhead worth it.

- AuditPage component (apps/portal-admin/src/app/pages/audit/
  audit.ts): signal-driven page composing:
  - Filter form: eventType, actorIdHash, audience, outcome,
    subjectPrefix, createdAtFrom/To (datetime-local → ISO),
    page-size selector (25 / 50 / 100 / 200 matching BFF MAX_LIMIT).
  - Result table: timestamp (locale-formatted), event type,
    audience+outcome with color-coded badges, actor hash + subject
    stacked, trace id, payload disclosure (details/summary).
  - Pagination: previous/next disabled at boundaries, resets
    offset to 0 on every Apply Filters or Reset.
  - States: loading line, empty state, error message (403
    surfaces "you do not have access"; 5xx surfaces a generic
    retry message — raw status leaks to ops via the network tab,
    not to the admin UI).

- Route: /audit, lazy-loaded, title 'Audit log — APF Portal Admin'
  + matching FR translation in messages.fr.xlf
  ('Journal d'audit — Administration APF Portal').

Notes

- @RequireMfa NOT applied to the BFF endpoint in v1 — the admin
  surface already sits behind a freshly-MFA'd session per ADR-0020,
  and the per-query audit row is the deterrent. The endpoint will
  pick up @RequireMfa({ freshness: 600 }) when the security review
  asks for it; the SPA already lives behind the unauthorized
  interceptor so it would gracefully refresh on the 401.
- Page-size cap mirrors the BFF MAX_LIMIT (200). A future caller
  bypassing the SPA cap is still safe because the BFF DTO clamps
  to 200 regardless (PR #132 §AuditReader.findEvents).
- SCSS budget: 4.98 KB / 5 KB warning (1.21 KB transfer). Well
  below the 6 KB error ceiling.
- AdminAuditQuery interface uses `?: T | undefined` so callers can
  build the query object with `undefined` placeholders for absent
  filters under `exactOptionalPropertyTypes: true` — the page does
  exactly that in `buildFilters()`.

Tests: +15 specs (AuditEventsService 3, AuditPage 12: initial query,
filter forwarding, offset-reset on Apply, clearFilters, pagination
disabled at boundaries, outcome-badge variants, payload disclosure
visibility, empty / loading / error states).
2026-05-14 17:44:35 +02:00

Documentation index

This is the entry point to all project documentation. It is maintained automatically: any addition, rename, or removal of a .md file under docs/ must be reflected here in the same change.

Conventions

  • Documentation is written in English.
  • One topic per file. Group related files into a folder when there are three or more.
  • Cross-reference with relative links so they keep working in GitHub, IDEs, and exported sites.
  • For architectural decisions, do not add them here — they belong in decisions/ as MADR 4.0.0 ADRs.

Sections

Daily development

  • development.md — repo layout, prerequisites, initial setup, daily commands, observability dev-loop (Jaeger UI, log ↔ trace correlation), dependency updates (Renovate), conventional commit cycle. Day-to-day reference for working on the project.

Architecture

  • architecture.md — cross-cutting Mermaid diagrams: C4 system context, C4 containers, Nx module boundaries, CI/CD pipeline. Single-decision diagrams (auth sequence, ERD, etc.) live inline in their ADR.

Onboarding & environment

Setup guides for new contributors:

Operations & runbooks

Empty — to be populated when we deploy.

Security, performance, accessibility

Empty — placeholders to be filled with rationale docs alongside their corresponding ADRs.

S
Description
No description provided
Readme 42 MiB
Languages
TypeScript 85.3%
JavaScript 5.4%
SCSS 4.3%
HTML 3.9%
Shell 0.8%
Other 0.3%