5aa1a8b004e9d04466385894bd288026bf135fe8
15 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
f9ed3cf82a |
chore(ci): skip perf and commits gates on Renovate-authored PRs (#23)
## Summary Renovate's dep-bump PRs run the full pipeline today (`check`, `scan`, `commits`, `perf`, `a11y`). Two of those gates have near-zero signal on a typical bump and dominate the wall-clock cost: - **`perf`** — Lighthouse build + 3-iteration median across the critical-routes list. 3-5 min per PR for a metric that is essentially zero on a patch/minor dep bump (the SPA today serves the static placeholder; even with real routes a typical bump stays inside the median noise floor). - **`commits`** — re-validates commit messages that Renovate generates from a Conventional-Commits-conformant template. Tautological. Skip both when the PR author is the `apf-portal-bot` Gitea user. The `push` event on `main` still runs the full pipeline post-merge, so any regression caught by `perf` is detected seconds after merge — fast enough to revert. Net result: Renovate PRs run `check + scan + a11y` only, ≈ 4-5 min faster per PR. ## ADR amendment ADR-0017 is amended in the same change: - "Where Lighthouse CI runs" table now distinguishes human PR / bot PR / push to main / scheduled / local. - New "Pre-merge gating policy: human PRs vs bot PRs" subsection records the rationale and the human-takeover edge case. - §Confirmation entry for `perf` is reworded to reflect the conditional gate. ## Test plan - [ ] After merge, the next Renovate-triggered PR (auto-rebase or new bump) shows only `check`, `scan`, `a11y` queued — no `perf`, no `commits`. - [ ] A human-opened PR (e.g. this one) still queues all 5 gates. - [ ] On `push` to `main` post-merge, the full pipeline runs including `perf`. --------- Co-authored-by: Julien Gautier <julien.gautier@apf.asso.fr> Reviewed-on: #23 |
||
|
|
f58cf13e33 |
fix(ci): give Renovate a git identity and a github.com token (#13)
## Summary First successful Renovate run (after the docker-image fix in #12) extracted 116 deps cleanly but every branch update failed with `fatal: empty ident name not allowed`, then the whole repo aborted on `Lock file error - aborting`. Two root causes: - **No git identity** — the bot user had an email but no **Full Name** on its Gitea profile, so Renovate produced incomplete git authorship. - **No github.com auth** — Renovate could not look up versions of GitHub-hosted Actions (`actions/checkout`, etc.) or `containerbase/node-prebuild` (the Node binary it dynamically fetches for lockfile maintenance) — anonymous rate limit (60 req/h) hit. Fixes: 1. **`renovate.json`** — pin `gitAuthor` explicitly. The Full Name was also set on the bot's Gitea profile for UI consistency, but the override in config means we don't depend on out-of-band UI state. 2. **`.gitea/workflows/renovate.yml`** — pass `RENOVATE_GITHUB_COM_TOKEN` from the new `GITHUBCOM_TOKEN` repo secret (no underscore between GITHUB and COM — Gitea reserves the `GITHUB_*` namespace). 3. **`docs/development.md`** — onboarding procedure now covers both tokens + the Full Name step. ## Manual setup required after merge Already done in this iteration: - Bot's Full Name set in Gitea ("APF Portal Bot"). - `GITHUBCOM_TOKEN` repo secret created with a zero-scope github.com PAT. (If the PAT was leaked during setup, regenerate before merging — the workflow only references the secret name, not the value.) ## Test plan - [ ] After merge, trigger Renovate manually (Actions → Renovate → Run workflow). - [ ] No `empty ident name` warning in the logs. - [ ] No `Lock file error - aborting`; repo finishes with `INFO: Repository finished … "cloned": true`. - [ ] Renovate creates the dependency dashboard issue + the first batch of grouped PRs (Angular, Nx, NestJS, Prisma, …) signed by `apf-portal-bot`. --------- Co-authored-by: Julien Gautier <julien.gautier@apf.asso.fr> Reviewed-on: #13 |
||
|
|
82911f9319 |
chore(ci): set up Renovate dependency automation (#11)
## Summary
Wire up Renovate to keep dependencies fresh without manual triage.
- **Workflow** — `.gitea/workflows/renovate.yml`: cron daily at 03:00 UTC + `workflow_dispatch`, runs on the existing self-hosted runners. Picked 03:00 specifically so Monday's tick sits inside Renovate's default `lockFileMaintenance.schedule` ("before 4am Monday") and triggers the weekly lockfile refresh in passing.
- **Config** — `renovate.json`: `config:recommended` baseline + groupings (Angular, Nx, NestJS, Prisma, Vitest, TypeScript tooling, ESLint, SWC, Tailwind), Conventional-Commits commit messages, OSV.dev as vulnerability source, dependency dashboard issue.
- **Docs** — new §5 in `docs/development.md` covering the bot onboarding (manual, one-shot), how to trigger Renovate manually, how to review its PRs. The placeholder roadmap entry is dropped from §8.
No ADR — Renovate is operational tooling, not an architectural decision (and on Gitea it's the only viable bot anyway, no real alternative to capture).
## Manual setup required after merge
The workflow is wired but inert until the bot is onboarded once on Gitea:
1. Create a non-admin Gitea user `apf-portal-bot`.
2. Add the bot as a **Write** collaborator on this repo.
3. Sign in as the bot, generate a PAT (scopes: read/write `repository`, read/write `issue`, read `user`).
4. Add the PAT as the repo secret `RENOVATE_TOKEN` (Settings → Actions → Secrets).
Detailed steps in [`docs/development.md`](docs/development.md) → "Dependency updates (Renovate)".
## Test plan
- [ ] After bot onboarding, trigger the workflow manually (Repo → Actions → Renovate → Run workflow).
- [ ] First run creates the "Renovate Dependency Dashboard" issue and a batch of grouped PRs (Angular, Nx, …).
- [ ] Each generated PR has CI green (`check`, `scan`, `commits`, `perf`, `a11y`).
- [ ] Commit subject matches `chore(deps): …` / `fix(deps): …` so the `commits` gate doesn't reject.
---------
Co-authored-by: Julien Gautier <julien.gautier@apf.asso.fr>
Reviewed-on: #11
|
||
|
|
02bdd43fa1 |
fix(ci): pin act_runner job image to catthehacker/ubuntu:act-22.04 (#4)
## Summary - Pin `act_runner`'s job container image to `catthehacker/ubuntu:act-22.04` via the `<label>:docker://<image>` format on the runner registration labels. - Update `infra/ci-runners.compose.yml`'s `GITEA_RUNNER_LABELS` for all three runner services, with an inline comment explaining the format requirement. - Amend ADR-0015 §"Runners" to specify the chosen image and explain the docker-suffix syntax trap. ## Motivation The first real PR test of the CI pipeline failed at the very first step: ``` Run actions/checkout@v4 0s Cannot find: node in PATH ❌ Failure - Main actions/checkout@v4 ``` Root cause: `act_runner` registers labels (`self-hosted`, `on-prem`) without a `docker://` image suffix. Without that suffix, act spawns jobs in a minimal default container that has no Node. Every JavaScript action (`actions/checkout`, `actions/setup-node`, `nrwl/nx-set-shas`, the Trivy/gitleaks actions) crashes during the action's launch step. None of the five CI gates can run. `catthehacker/ubuntu:act-22.04` is the de facto image used by `act` upstream and the standard recommendation for self-hosted Gitea Actions runners. It bundles Node, Python, git, common build tools, and the Docker CLI — exactly the assumed environment for GitHub Actions-compatible workflows. ## Implementation notes - The fix lives in `GITEA_RUNNER_LABELS` because that's what `act_runner` reads at registration time. The label-to-image mapping is then persisted in the runner's `data/runner-N/.runner` credential. - For runners **already registered** (i.e. the three currently-running `apf-portal-runner-N`), the persisted credential ignores the new env var. Their labels must be updated through Gitea's UI (Site Administration → Actions → Runners → each runner → edit `Labels`). This is documented in the commit message and is an operational follow-up to merging this PR. - The compose-file change applies the next time a runner is re-registered (e.g. when `data/runner-N/` is wiped or a new fourth runner is added). - ADR-0015 amendment is in-place, status remains `accepted`. The runner-image choice is an implementation detail under the existing decision; no new ADR. ## Verification - [ ] `pnpm ci:check` — n/a, this PR only changes infra and ADR docs, no code paths. - [ ] **Manual:** after merge + Gitea label updates, the next PR's `actions/checkout@v4` step runs without `Cannot find: node in PATH`. ## Related - [ADR-0015 — CI/CD pipeline](docs/decisions/0015-cicd-gitea-actions.md). Amended in §"Runners". - [`infra/README.md`](infra/README.md) — operational doc for the runners; mentions the registration workflow but predates this format requirement. A subsequent docs touch could mirror the new label format there too; deferred to keep this PR scoped to the actual fix. --------- Co-authored-by: Julien Gautier <julien.gautier@apf.asso.fr> Reviewed-on: #4 |
||
|
|
f0b437bdc9 |
Merge pull request 'docs: add docs/architecture.md with C4 contexts, Nx boundaries, and CI/CD pipeline' (#1) from docs/architecture-diagrams into main
Reviewed-on: #1 |
||
|
|
156e7ca2df |
chore: add PR template and document title/body convention
Formalise the PR-flow conventions while we install the PR-flow itself. .gitea/pull_request_template.md auto-populates the PR body in Gitea with five sections: Summary / Motivation / Implementation notes / Verification (with CI-gate checkboxes + ADR/diagram update flags) / Related. Sections can be left blank when irrelevant; the template guides without adding ceremony. Header HTML comment reminds the contributor of the PR title format and links to the full convention. docs/development.md §5 (Conventional commit cycle) gains a 'PR conventions' subsection that: - explains why the PR title format matters (squash-merge subject on main, validated by commitlint in the CI 'commits' job) - separates feature-branch commit hygiene (exploratory OK) from PR title hygiene (must conform) - documents the type vocabulary (feat/fix/docs/style/refactor/perf/ test/build/ci/chore/revert) - proposes an optional scope vocabulary (apps, libs, cross-cutting domains like decisions/docs/ci/deps) - describes the body template No new ADR. The PR title format is derived from ADR-0007 (Conventional Commits at the commit-msg layer) plus ADR-0015 (squash-merge means PR title becomes the commit subject on main). The body template is tactical guidance, not architectural. |
||
|
|
4b8d0789b1 |
docs: add inline OIDC sequence diagram to ADR-0009
Render the OAuth 2.0 Authorization Code + PKCE flow as a Mermaid sequence diagram at the top of the Decision Outcome section. Five participants (user, SPA, BFF, Entra, Redis), thirteen autonumbered steps covering the authorize redirect, the user-side authentication (with the Conditional Access MFA enforcement annotated), the callback, the state verification, the token exchange, the id_token validation pipeline (signature, iss against the tenant allowlist, aud, exp/nbf, amr sanity-check, audience-claim mapping), the encrypted session write to Redis, and the cookie set. Inline rather than in docs/architecture.md per the convention stated at the top of architecture.md: cross-cutting diagrams live in the architecture file, single-decision diagrams live inside the ADR they visualise. ADR-0009 IS the auth flow decision; the sequence diagram belongs here. Cross-references the related ADRs (0010 sessions, 0011 MFA, 0008 audience model) so the diagram reads as the integration point of the security stack rather than as an isolated picture. |
||
|
|
312791b74e |
docs: add docs/architecture.md with C4 contexts, Nx boundaries, and CI/CD pipeline
Cross-cutting visual reference for the architecture, written in Mermaid (text in markdown, rendered natively by Gitea / GitHub / IDE viewers, diffable in PR). Four diagrams that summarise decisions spread across multiple ADRs: 1. C4 level 1 - System Context. The portal as a black box with its workforce/customer/IT/RSSI actors and Entra ID + downstream APIs as external systems. Customer audience and Entra External ID are shown dashed (future scope per ADR-0008's dual-audience design). 2. C4 level 2 - Containers. Browser-side portal-shell, on-prem BFF, Postgres (public + audit schemas), Redis, local OTel Collector, plus external Entra ID and downstream APIs. Annotates the wire protocols (HTTPS + __Host- cookies, OIDC, OBO/signed assertion, OTLP, ioredis with AES-GCM at rest, traceparent end-to-end). 3. Nx module boundaries. The Project graph rendered with the depConstraints from ADR-0003 (scope axis: portal-shell / portal-bff / shared, plus type axis: app / feature / shared). Forbidden directions called out below the diagram. 4. CI/CD pipeline. Local hooks → push → PR → 5 parallel CI jobs (check / scan / commits / perf / a11y) → branch protection → squash-merge → tag → release. Includes the weekly scheduled security-scheduled.yml workflow (full-tree scan + prod Lighthouse). Convention adopted at the top of architecture.md: cross-cutting diagrams live here; single-ADR diagrams live inline in the ADR itself (sequence flows, ERDs, lifecycle diagrams, etc.). The 'To be added' section at the bottom maps each future diagram to where it will land and what triggers its addition. docs/README.md index updated with a new 'Architecture' section linking to architecture.md, and the previous empty 'Architecture' placeholder removed (the placeholder was a tick-the-box section that violated the doc convention 'documentation when genuinely useful, not just to tick a box'). |
||
|
|
7d27cd8773 |
docs: turn development.md §7 into a phase-mapped roadmap
The section was a short bullet list of 'sections to be added' - it underplayed how broad the future content really is, and gave no visibility on what triggers each. Replace it with a structured table that maps every planned section to (a) its ADR phase and (b) the specific implementation work that unlocks it. A contributor reading the doc today now sees: - which dev-loops will exist (auth, sessions, MFA step-up, OTel, audit, downstream APIs, component patterns, a11y, perf debugging, Renovate, release, GitLab migration, architecture diagrams) - under which ADR each lands - what concrete event in the codebase makes each section real Plus the explicit policy: each entry stays a subsection of this doc until we have at least three substantial sub-topics, at which point the file is split into docs/development/ with an index. Avoids creating empty placeholder files (per CLAUDE.md: 'documentation when genuinely useful, not just to tick a box') while signalling the future structure clearly. Cross-references each row to its triggering ADR so the table doubles as a 'what's pending implementation' radar. Foreshadows the §7 → file split that will happen once content density justifies it. |
||
|
|
b69d3a2206 |
docs: add development.md as the day-to-day reference for working on apf_portal
A new contributor (or returning lead) opening the repo gets: - the final repo layout, with one-line annotations per top-level dir - the prerequisite tooling list (Node 24 LTS, pnpm 10, mkcert, optional local Trivy/gitleaks, Docker for Postgres) - the fresh-clone setup steps (clone, pnpm install, prisma generate, sanity check) - the daily commands organised by intent: serve, test (incl. single file), lint, build, generate (apps / libs / components), Prisma, the four ci:* scripts that mirror the CI gates - the conventional commit cycle end-to-end (branch naming, hook enforcement, PR gates, squash-merge, release tagging) - a 'where to look' table cross-linking the project rules (CLAUDE.md), the ADRs, the setup guides, and the personal notes - an explicit 'to be added' section listing what the doc will grow into (local infra Docker Compose, auth dev-loop, component patterns, debugging tips, release workflow, Renovate policy) The doc is intentionally non-exhaustive at v1 - it captures what a contributor needs today and is structured to grow as the workflow sharpens. Indexed in docs/README.md under a new 'Daily development' section, separate from the one-off onboarding guides under docs/setup/. |
||
|
|
c66ef4c7a4 |
docs: amend ADR-0016 to defer the spartan-ng library, keep its philosophy
@spartan-ng/brain and @spartan-ng/cli are currently at 0.0.1-alpha.681
- pre-1.0, which trips the project rule against pre-1.0 dependencies
("Pre-1.0 dependencies and one-maintainer projects are rejected unless
an ADR justifies the exception", per CLAUDE.md). ADR-0016 originally
adopted spartan-ng with the copy-paste mitigation; the alpha state was
not anticipated when the ADR was written.
Amend ADR-0016 with a dated note: the spartan-ng *library* is
deferred until it reaches 1.0.0. The spartan-ng *philosophy* -
headless primitives on Angular CDK, Tailwind utility CSS, copy-paste
components owned in-source - is unchanged. Components for v1 are
written in-house in libs/shared/ui/, on Angular CDK directly. The
spartan-ng project is consulted for design inspiration (component
patterns, ARIA usage, theming) without taking the dependency.
CLAUDE.md Architecture section adjusted accordingly: 'Angular CDK +
TailwindCSS' (spartan-ng deferred), with the philosophy still in
effect.
The amendment is structured as an in-place '> Amended on YYYY-MM-DD'
block in the Component stack section, consistent with how ADR-0001's
recent path-relocation amendment was handled. Status remains
'accepted' - the design intent did not change, only the dependency
selection.
The argumentaire in notes/argumentaire-stack-ui-spartan-cdk-tailwind.md
is left as-is (gitignored, personal). It still serves to explain to
the dev team why we are NOT adopting React-side libs - the conclusion
section now reads as "we apply the same philosophy via CDK + Tailwind
in-house, deferring the lib until it stabilises".
|
||
|
|
0e58e32d29 |
chore: relocate ADRs from decisions/ to docs/decisions/ to consolidate documentation
Move the ADR folder under docs/ alongside the rest of the project
documentation. Convention (flat folder, globally-sequential 4-digit
numbering, tags-based categorization, MADR 4.0.0 format) is unchanged
- only the path moved.
- git mv decisions docs/decisions preserves history for all 18 ADRs +
README + template (19 files renamed in this commit).
- ADR-0001 amended in-place with a dated note documenting the
relocation. Status remains 'accepted' - the location detail
changed, the decision did not.
- All cross-references updated:
- CLAUDE.md (~17 ADR links + 3 mentions of decisions/ in the Project
rules section)
- docs/README.md (now references decisions/ as a sibling under docs/)
- docs/setup/03-angular-nx-monorepo.md (paths shortened from
../../decisions/ to ../decisions/, since setup/ and decisions/ are
now both inside docs/)
- docs/decisions/0003 ../CLAUDE.md adjusted to ../../CLAUDE.md
(one extra level of nesting)
- docs/decisions/template.md mention of the README path
- notes/asvs-level-decision-briefing-rssi.md mention of the index
Sanity verified: every ADR link in CLAUDE.md, docs/setup/03, and
docs/decisions/0001 resolves to an existing file. pnpm nx run-many
-t lint passes on 8 projects.
|
||
|
|
880c7ded6b |
chore: rename project from adastra_portal to apf_portal
The host organisation - APF France Handicap - was confirmed on 2026-04-30. Update all in-repo references to use apf_portal (snake_case in prose) and apf-portal (kebab-case workspace name and repo URL). Touched: CLAUDE.md, ADRs 0001/0002/0003/0015, and the Nx bootstrap setup guide. The historical name is preserved as a single sentence in ADR-0003 as a self-validating example of the function-prefixed naming convention designed exactly for this scenario - the apps (portal-shell, portal-bff) and the lib conventions (feature-<name>, shared-<scope>) were unaffected by the rename, which was the explicit point of ADR-0003. Memory state aligned out-of-band: project_adastra.md retired, project_apf_portal.md created with the expanded APF context (host org, health + financial data scope, ASVS L3 pending RSSI input, UI stack decision spartan-ng + CDK + Tailwind, expanded phase-3 status). Pending follow-ups (user-side, not in this commit): - rename the Gitea repo julien/adastra_portal -> julien/apf_portal - git remote set-url origin gitea@git.unespace.com:julien/apf_portal.git - optionally rename the local working directory ~/Works/adastra_portal/ -> ~/Works/apf_portal/ |
||
|
|
084ff5c3bf |
docs: add ADR-0007 for pre-commit hooks and align documentation references
- decisions/0007-pre-commit-hooks-and-conventional-commits.md formalizes Husky + lint-staged + commitlint with Conventional Commits as the local quality-gate baseline. - decisions/README.md index updated. - docs/setup/03 section 8 rewritten to reference the ADR and document the full hook setup (pre-commit, commit-msg, commitlint config). - docs/setup/03 future-work table 'ADR(s)' column removed; future ADR numbers are now assigned at the moment each ADR is written, not pre-reserved. - CLAUDE.md aligned: pre-allocated phase-2 ADR numbers replaced by phase references; a pointer to ADR-0007 added under 'Local quality gates'. |
||
|
|
79eee77594 |
chore: initialize repository with project rules, docs, and phase-1 ADRs
Set up the foundation for the adastra-portal project: - CLAUDE.md captures durable project rules (quality bar, security/perf/a11y as first-class, language, commit conventions, ADR proactivity). - docs/ and decisions/ scaffolding with maintained indexes (docs/README.md and decisions/README.md), MADR 4.0.0 template, and tag vocabulary. - Phase-1 ADRs (0001-0006) lock structural choices: ADR usage, Nx monorepo with the apps preset, naming convention (adastra-portal / portal-shell / portal-bff), Angular CSR/zoneless/Signals/Vitest, NestJS over Express, PostgreSQL with Prisma. - docs/setup/ guides translated to English. - .gitignore covers Node/Nx artifacts and the personal notes/ scratchpad. The Nx workspace itself is not yet bootstrapped; that step is gated on a revised setup guide aligned with the ADRs. |