Files
apf_portal/apps/portal-admin/src/locale/messages.fr.xlf
T
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

37 lines
1.7 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?xml version="1.0" encoding="UTF-8" ?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" target-language="fr" datatype="plaintext" original="ng2.template">
<body>
<!-- app -->
<trans-unit id="app.skipLink" datatype="html">
<source>Skip to main content</source>
<target>Aller au contenu principal</target>
</trans-unit>
<!-- route -->
<trans-unit id="route.home.title" datatype="html">
<source>APF Portal Admin</source>
<target>Administration APF Portal</target>
</trans-unit>
<trans-unit id="route.audit.title" datatype="html">
<source>Audit log — APF Portal Admin</source>
<target>Journal daudit — Administration APF Portal</target>
</trans-unit>
<!-- page.home -->
<trans-unit id="page.home.title" datatype="html">
<source> APF Portal Admin </source>
<target> Administration APF Portal </target>
</trans-unit>
<trans-unit id="page.home.intro" datatype="html">
<source> Administrative back-office for the APF Portal. The first functional modules — content management, menu administration, user list, audit log viewer — land in upcoming PRs per ADR-0020. </source>
<target> Back-office dadministration pour le portail APF. Les premiers modules fonctionnels — gestion de contenu, gestion du menu, liste des utilisateurs, visualiseur daudit log — arrivent dans les PRs à venir conformément à lADR-0020. </target>
</trans-unit>
<trans-unit id="page.home.status" datatype="html">
<source> Skeleton — coming soon </source>
<target> Squelette — bientôt disponible </target>
</trans-unit>
</body>
</file>
</xliff>