Commit Graph

16 Commits

Author SHA1 Message Date
julien 8bb2d7b43f chore(deps): defer Prisma major updates pending coordinated upgrade ADR (#39)
CI / check (push) Successful in 3m1s
CI / commits (push) Has been skipped
CI / scan (push) Failing after 2m41s
CI / a11y (push) Successful in 2m12s
CI / perf (push) Failing after 2m48s
## Summary
Renovate kept proposing Prisma 7 even though we deliberately downgraded to Prisma 6 in #3 — `nestjs-prisma@0.27.0` is incompatible with Prisma 7's driver-adapter contract, and the upgrade is non-trivial enough to warrant its own ADR rather than a silent Renovate merge.

- **`renovate.json`** — add `enabled: false` packageRule for `matchUpdateTypes: ["major"]` on `prisma`, `@prisma/*`, `nestjs-prisma`. Patch and minor bumps of the 6.x line keep flowing.
- **ADR-0006** — new "Prisma version pin: 6.x in v1" subsection records the narrowing of "latest stable major" to 6.x and the two triggers for revisiting:
  1. `nestjs-prisma` ships a release supporting Prisma 7, or
  2. We decide to drop `nestjs-prisma` for a hand-rolled `PrismaModule`.

  Either path needs its own ADR (schema, client instantiation, request-scoped lifecycle all to re-validate).

## Test plan
- [ ] Once merged, the open Prisma 7 PR can be closed (see closure comment below) and won't be recreated.
- [ ] Next Renovate run confirms no Prisma-major PR is created (check the dependency dashboard issue).
- [ ] Next patch/minor of Prisma 6.x still produces a normal grouped "Prisma" PR.

---------

Co-authored-by: Julien Gautier <julien.gautier@apf.asso.fr>
Reviewed-on: #39
2026-05-06 19:31:48 +02:00
julien f9ed3cf82a chore(ci): skip perf and commits gates on Renovate-authored PRs (#23)
CI / commits (push) Has been skipped
CI / check (push) Successful in 2m20s
CI / scan (push) Failing after 2m34s
CI / a11y (push) Successful in 1m7s
CI / perf (push) Successful in 3m43s
## 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
2026-05-05 16:12:19 +02:00
julien f58cf13e33 fix(ci): give Renovate a git identity and a github.com token (#13)
CI / check (push) Successful in 2m24s
CI / commits (push) Has been skipped
CI / scan (push) Failing after 1m8s
CI / a11y (push) Successful in 1m32s
CI / perf (push) Successful in 2m52s
## 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
2026-05-05 13:47:30 +02:00
julien 82911f9319 chore(ci): set up Renovate dependency automation (#11)
CI / commits (push) Has been skipped
CI / check (push) Successful in 1m21s
CI / scan (push) Failing after 1m27s
CI / a11y (push) Successful in 44s
CI / perf (push) Successful in 2m28s
## 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
2026-05-04 17:37:13 +02:00
julien 02bdd43fa1 fix(ci): pin act_runner job image to catthehacker/ubuntu:act-22.04 (#4)
CI / commits (push) Has been skipped
CI / check (push) Failing after 3s
CI / scan (push) Failing after 9s
CI / a11y (push) Failing after 4s
CI / perf (push) Failing after 4s
## 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
2026-05-04 11:06:56 +02:00
julien 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
CI / check (push) Failing after 5s
CI / commits (push) Has been skipped
CI / scan (push) Failing after 6s
CI / a11y (push) Failing after 2s
CI / perf (push) Failing after 3s
Reviewed-on: #1
2026-05-01 00:45:23 +02:00
Julien Gautier 156e7ca2df chore: add PR template and document title/body convention
CI / check (push) Failing after 5s
CI / commits (push) Has been skipped
CI / scan (push) Failing after 6s
CI / perf (push) Failing after 3s
CI / a11y (push) Failing after 1s
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.
2026-04-30 23:03:13 +02:00
Julien Gautier 4b8d0789b1 docs: add inline OIDC sequence diagram to ADR-0009
CI / commits (pull_request) Failing after 2s
CI / check (pull_request) Failing after 3s
CI / scan (pull_request) Failing after 6s
CI / a11y (pull_request) Failing after 3s
CI / perf (pull_request) Failing after 3s
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.
2026-04-30 21:02:08 +02:00
Julien Gautier 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').
2026-04-30 20:55:21 +02:00
Julien Gautier 7d27cd8773 docs: turn development.md §7 into a phase-mapped roadmap
CI / check (push) Failing after 2s
CI / commits (push) Has been skipped
CI / perf (push) Failing after 12s
CI / a11y (push) Failing after 3s
CI / scan (push) Failing after 1m33s
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.
2026-04-30 20:11:01 +02:00
Julien Gautier b69d3a2206 docs: add development.md as the day-to-day reference for working on apf_portal
CI / check (push) Failing after 2s
CI / commits (push) Has been skipped
CI / perf (push) Failing after 12s
CI / a11y (push) Failing after 2s
CI / scan (push) Failing after 1m44s
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/.
2026-04-30 19:58:37 +02:00
Julien Gautier 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".
2026-04-30 18:59:02 +02:00
Julien Gautier 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.
2026-04-30 18:57:59 +02:00
Julien Gautier 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/
2026-04-30 13:31:38 +02:00
Julien Gautier 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'.
2026-04-29 21:01:49 +02:00
Julien Gautier 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.
2026-04-29 20:43:00 +02:00