Julien Gautier f9a061e6f8
CI / commits (pull_request) Successful in 2m18s
CI / check (pull_request) Successful in 2m57s
CI / scan (pull_request) Successful in 3m5s
CI / a11y (pull_request) Successful in 3m11s
Docs site / build (pull_request) Successful in 3m24s
CI / perf (pull_request) Successful in 6m57s
feat(ci): catalogue-drift gate for @RequirePrivilege/@RequireRole literals (ADR-0025)
Phase 3 of the ADR-0025 phasing per its §"More Information" §347:
a small CI gate that asserts every string literal passed to the
authorization decorators belongs to the closed catalogue declared
in libs/shared/auth/src/lib/authorization.types.ts.

The TypeScript signature on the decorators already enforces this
at compile time — the new gate is defence-in-depth against escape
hatches (`as Privilege` casts, hand-edits to the type union
without updating the runtime constant). It runs in <1s, so it
rides the existing `check` CI job rather than starting its own.

Implementation:
- scripts/check-catalogue-drift.mjs: TypeScript compiler API.
  Parses authorization.types.ts to extract the catalogue arrays,
  walks every .ts file under apps/ and libs/, finds each
  CallExpression whose callee identifier matches @RequirePrivilege
  or @RequireRole, validates every string-literal argument.
  Non-literal args (variable indirection) are skipped on purpose —
  the TypeScript signature catches them at compile time and the
  gate's value-add is on literal misspellings. Generated gRPC
  stubs under apps/portal-bff/src/grpc/gen are skipped (their
  `roles[]` field is a wire-format unrelated to the catalogue).
  Reports grouped by file with line:column for each violation,
  exits 1 on drift.
- scripts/check-catalogue-drift.spec.mjs: 13 tests via node:test
  (built-in, no Vitest dependency). Covers catalogue parsing,
  file-level violation detection, workspace-wide aggregation,
  skipped folders, gen-stub exclusion, line/column reporting.
- package.json: ci:catalogue-drift + ci:catalogue-drift:test
  scripts.
- .gitea/workflows/ci.yml: the `check` job now runs the gate's
  unit tests (first, to fail fast if the gate itself is broken)
  then the gate against the live workspace.

Self-tested by injecting `RequirePrivilege('Portal.RogueDrift')`
and `RequireRole('rogue-role-x')` into an existing spec — both
caught with file:line:column and exit code 1.

Test plan:
- pnpm ci:catalogue-drift:test: 13/13 green.
- pnpm ci:catalogue-drift: clean (4 privileges, 24 roles).
- pnpm nx affected -t format:check lint test build: no project affected (script lives outside Nx).
2026-05-24 00:59:57 +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%