Without an image suffix on the runner labels, act_runner uses a
minimal default container image that has no Node. Every JavaScript
action (actions/checkout, actions/setup-node, nrwl/nx-set-shas, etc.)
crashes during the action's launch step with `Cannot find: node in
PATH`, blocking every CI gate before any project code runs.
The fix is in the runner registration labels: act_runner accepts the
format `<label>:docker://<image>`, which makes act spawn jobs in the
specified container. catthehacker/ubuntu:act-22.04 is the de facto
standard image for act-compatible runners; it bundles Node, Python,
git, common build tools, and the Docker CLI, matching what GitHub
Actions / Gitea Actions workflows generally assume.
infra/ci-runners.compose.yml: GITEA_RUNNER_LABELS updated for the
three runners, with an inline comment explaining the format trap.
docs/decisions/0015-cicd-gitea-actions.md (§Runners): amend the
runner-image baseline. Previous wording said "a Debian image"
without specifying which; now states catthehacker/ubuntu:act-22.04
explicitly and explains the docker:// suffix requirement. Status
remains 'accepted' - the runner-image choice is implementation detail
under the existing decision.
Already-running runners need their labels updated in the Gitea UI
(Site Administration -> Actions -> Runners -> edit each runner) to
the new format. Compose change applies on next re-registration.
Documented as the operational follow-up.
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.
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.
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').
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.
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/.
@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".
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.
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/
- 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'.
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.