04138b435ab3c0d4fb4f655d67ce02de0c2b7136
13 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
922a44bb50 |
chore(ci): auto-merge low-risk renovate updates (#77)
## Summary After ~10 days of clean Renovate track record (~30 PRs merged without regression beyond the TS/ESLint/webpack-cli majors that the dashboard-approval rule now catches), enable auto-merge on the lowest-risk update types. CI is the gate — `check` / `scan` / `a11y` going red leaves the PR open for manual triage. | Update type | Pre-PR | Post-PR | | - | - | - | | **patch** | manual review | **auto-merge if CI green** | | **pin** (rolling-tag → fixed-version pin) | manual | **auto-merge if CI green** | | **digest** (image digest pin refresh) | manual | **auto-merge if CI green** | | **lockFileMaintenance** (weekly transitive refresh) | manual | **auto-merge if CI green** | | **minor** | manual review (unchanged) | manual review | | **major** | dashboard approval (unchanged) | dashboard approval | `automergeStrategy: "squash"` matches our trunk-based squash-merge convention. `automergeType: "pr"` keeps the PR + CI run as the audit trail (vs branch-direct push), and Gitea auto-merges the PR once green via the bot's existing `repo:write` permission. ## Doc updates - `renovate.json` `dependencyDashboardHeader` — the "Open" row now reflects the new reality: mostly minors, with red patches surfacing briefly when CI fails. - `docs/development.md` §"Reviewing Renovate PRs" gains a bullet describing the auto-merge for contributors landing on the project later. ## Test plan - [ ] CI green on this PR. - [ ] After merge, the next patch-level Renovate run produces a PR that auto-squashes into `main` once CI clears (visible in the merged log; no human action required). - [ ] A patch with red CI stays open in "Open" with the `dependencies` label. - [ ] Minor / major Renovate PRs continue to require human merge. --------- Co-authored-by: Julien Gautier <julien.gautier@apf.asso.fr> Reviewed-on: #77 |
||
|
|
e2dd2e4dd8 |
fix(portal-shell): use .postcssrc.json so tailwind utilities are emitted (#75)
## Summary The portal-shell scaffold shipped a `postcss.config.js`, but `@angular/build` (Angular 17+ esbuild pipeline) does **not** load that file format — it only reads `.postcssrc.json`. Result: the `@tailwindcss/postcss` plugin was never registered, Tailwind ran with no source files visible, generated only its `@theme` block, and dropped every utility class on the floor. The page therefore rendered unstyled — black text on white — even though `nx build` reported success and shipped a 23 KB `styles*.css`. Rename / re-encode the config to `.postcssrc.json`. Same plugin, same options, just the file format Angular's esbuild adapter actually reads. ## Verification | | Before | After | | - | - | - | | Class selectors in `dist/apps/portal-shell/browser/styles*.css` | **0** | **75** (production) | | `.text-3xl`, `.bg-amber-50`, `.font-semibold` etc. emitted | ❌ | ✓ | | Pages render with intended Tailwind layout | ❌ | ✓ | ```bash pnpm exec nx build portal-shell --configuration=production grep -oE '\.[a-zA-Z][a-zA-Z0-9_-]*' dist/apps/portal-shell/browser/styles*.css | sort -u | wc -l # 75 ``` ## Doc update `docs/development.md` repo-layout walkthrough now reads `.postcssrc.json` and explicitly calls out that `postcss.config.js` is ignored by `@angular/build` — so a future contributor reaching for the legacy filename gets a hint instead of a silent failure. ## Test plan - [ ] CI green on this PR. - [ ] Local: bring up the SPA dev server, `localhost:4200` shows the styled layout — header bar with brand link, system-status widget with rounded card, footer with the two language links. - [ ] Production build: `nx build portal-shell --configuration=production` succeeds; `dist/.../styles*.css` contains tens of utility-class selectors (not just `@theme` tokens). --------- Co-authored-by: Julien Gautier <julien.gautier@apf.asso.fr> Reviewed-on: #75 |
||
|
|
288610b9ba |
docs(development): add observability dev-loop section (#73)
## Summary ADR-0012 phase 1 + phase 2 are wired (BFF + SPA), so the "Observability dev-loop" placeholder in the roadmap table now has real content to point at. Promote it from §9 future-work list to a full §5 walkthrough sitting between "Daily commands" and "Dependency updates". ## What §5 covers - **Bringing up the observability stack** — `./infra/local/dev.sh up observability`, with the endpoint table (Jaeger UI, OTLP receiver, BFF stdout, browser DevTools). - **Reading a trace in Jaeger** — service-dropdown filter, span attribute keys to look at (`http.method`, `db.statement`, `service.name`, `trace_id`), the trace-id-as-pivot pattern. - **Correlating a trace with the BFF Pino logs** via `trace_id` and `request_id` (the per-request UUID `nestjs-cls` provides). Concrete `grep` example. - **Reading SPA spans from the browser** — DevTools Network filter on `localhost:4318/v1/traces` + Jaeger UI cross-check. - **Common gotchas** — observability profile not active, CORS pre-flight on `/v1/traces`, `propagateTraceHeaderCorsUrls` mismatches, NODE_ENV mis-set, EADDRINUSE on serve restart. - **What's not in v1** — pointer at the "wired as features land" deltas (CLS keys for session/user/audience, redact list, custom domain spans, prod backend) so a contributor knows what's intentionally not yet there. ## Renumbering The new §5 pushes existing sections down. Final structure: 1. Repo layout / 2. Prerequisites / 3. Initial setup / 4. Daily commands / 5. **Observability dev-loop** / 6. Dependency updates (Renovate) / 7. Conventional commit cycle / 8. Where to look / 9. Roadmap. The "Observability dev-loop" line in §9's roadmap table is removed (now implemented). `docs/README.md` cross-link updated to mention the new section. ## Test plan - [ ] CI green on this PR (`format:check`). - [ ] In a fresh checkout, follow §5's "Bring up the observability stack" verbatim, reach the Jaeger UI, then walk a trace through the `grep` correlation example with a synthetic request — flag any step that's wrong / missing on this real-world rehearsal. --------- Co-authored-by: Julien Gautier <julien.gautier@apf.asso.fr> Reviewed-on: #73 |
||
|
|
fc9b63f24a |
feat(infra): add dev.sh wrapper for the local-dev compose stack (#68)
## Summary Two recurring frictions on the local-dev stack: 1. **Compose-profile asymmetry** — `docker compose down` only operates on services whose profile is currently active. Anything brought up with `--profile X` keeps running unless the same flag is passed on `down`. pgweb and Jaeger silently survived several `down -v` invocations before we noticed (#67 documented the gotcha; this PR makes it impossible to hit if you use the wrapper). 2. **Verbose invocations** — typing `docker compose -f infra/local/dev.compose.yml --profile … <verb>` for routine ops gets old fast. Add [`infra/local/dev.sh`](infra/local/dev.sh) as a thin wrapper. Always passes every profile in scope on teardown / status / log commands, exposes ergonomic verbs: | Command | Effect | | --------------------------------------------- | --------------------------------------------------------------- | | `./infra/local/dev.sh up` | Core only (postgres + redis + otel-collector) | | `./infra/local/dev.sh up all` | Core + every profile | | `./infra/local/dev.sh up dbtools` | Core + pgweb | | `./infra/local/dev.sh up observability` | Core + Jaeger | | `./infra/local/dev.sh down [-v]` | Tear down (every profile in scope, no orphaned services) | | `./infra/local/dev.sh stop <service>` | Stop one service (containers stay around) | | `./infra/local/dev.sh restart <service>` | Restart one service | | `./infra/local/dev.sh status` | `ps` with every profile visible | | `./infra/local/dev.sh logs [service]` | Follow logs | | `./infra/local/dev.sh exec <service> <cmd>` | Run a command inside a container | Anything not matching one of the named verbs is passed through to `docker compose -f dev.compose.yml ...` (with every profile flagged in), so the full Compose surface remains available. ## Doc updates - **`infra/README.md`** — new "Convenience script" subsection with the cheat-sheet table; "First-time setup" rewritten to use the script; the standalone "Profile symmetry" tip from #67 is collapsed into a one-liner since the script now handles it (the note remains as a fallback for direct `docker compose` users). - **`docs/development.md` §3** — points at the script for the typical setup flow. The compose file itself is unchanged. ## Test plan - [ ] `./infra/local/dev.sh help` prints the usage block. - [ ] `./infra/local/dev.sh up` brings up the 3 core services (no pgweb / no jaeger). - [ ] `./infra/local/dev.sh up all` adds pgweb and Jaeger. - [ ] `./infra/local/dev.sh down -v` stops and removes all 5 containers (incl. pgweb and Jaeger), wipes the postgres-data and redis-data volumes. - [ ] `./infra/local/dev.sh stop pgweb` stops just pgweb. - [ ] `./infra/local/dev.sh logs otel-collector` follows that service's logs. - [ ] `./infra/local/dev.sh exec postgres psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "\du"` lists the audit roles. - [ ] `./infra/local/dev.sh stop` (no arg) errors with a clear message. --------- Co-authored-by: Julien Gautier <julien.gautier@apf.asso.fr> Reviewed-on: #68 |
||
|
|
a93b1067e6 |
docs(setup): add psql and redis-cli to prerequisites (#61)
## Summary Verifying the local-dev stack from the host (`docker compose up -d` + `psql ... -c "\du"` / `redis-cli PING`) requires the postgres and redis client binaries on the developer's machine. They were missing from the prereqs table, so `apt install postgresql-client` / `apt install redis-tools` was an implicit step nobody knew to run. Add both to §2's table, with one-line rationale for each. The Docker row is also tightened to point at the actual local-dev stack location ([`infra/local/`](infra/local/)) instead of the placeholder "Postgres + Redis containers" wording from before that recipe existed. `docker compose exec` remains a viable zero-install alternative for developers who prefer not to touch their host. Mentioned only informally — the host-install path is the documented one. ## Test plan - [ ] Fresh-clone a checkout, follow §2 + §3 verbatim, end with a working stack and successful `psql ... -c "\du"` against it. --------- Co-authored-by: Julien Gautier <julien.gautier@apf.asso.fr> Reviewed-on: #61 |
||
|
|
0f00d6d93f |
feat(infra): add local-dev Docker Compose stack (#57)
## Summary Bring up Postgres + Redis + OTel Collector in one command so contributors can run the BFF end-to-end without manually wiring each service. Replaces the throwaway `docker run postgres:17-alpine` one-liner that was in `docs/development.md` §3. ### What lands - **`infra/local/dev.compose.yml`** — three core services (`postgres:17.2-alpine`, `redis:7.4-alpine`, `otel/opentelemetry-collector-contrib:0.115.0`) plus two viewers gated behind Compose profiles: - `--profile dbtools` → `sosedoff/pgweb:0.16.2` (Postgres GUI on port 8081) - `--profile observability` → `jaegertracing/all-in-one:1.62` (Jaeger UI on 16686) - All ports overridable via `.env`. State in named volumes. Healthchecks on data services. - **`infra/local/.env.example`** — credentials + ports template. `POSTGRES_PASSWORD` and `REDIS_PASSWORD` are mandatory (compose refuses to boot without them); other keys default sensibly. - **`infra/local/init/postgres/01-init.sql`** — bootstrap SQL per **ADR-0013**: `audit_owner` / `audit_writer` / `audit_reader` / `audit_archiver` roles + `audit` schema. Default privileges encode the append-only contract (INSERT to writer, SELECT to reader, DELETE to archiver, no UPDATE/TRUNCATE to anyone). Applied on first Postgres boot only; documented re-run procedure. - **`infra/local/otel-collector.yaml`** — pipeline: OTLP gRPC/HTTP → batch → debug exporter (always) + forward to `jaeger:4317`. When the observability profile is off, the Jaeger export logs warn-level retries but doesn't block the debug pipeline. ### Surrounding doc updates - **`infra/README.md`** — new "Local-dev stack" section: service inventory, port table, first-time setup walkthrough, persistence/bootstrap-replay tips. The previous `local/` placeholder line is removed. - **`docs/development.md`** §3 — rewritten to walk through the compose-based setup; cross-links to `infra/README.md` for the full reference. Roadmap entry for "Local infra recipe" removed from §8 (now implemented); "Observability dev-loop" line adjusted to point at the new Jaeger profile. ### Out of scope - **Production parity** — HA Postgres, Redis Sentinel, real OTel backend (Tempo / Loki / etc.) — defer to the on-prem infrastructure ADR (phase 3b). The dev-only nature of this stack is called out explicitly in `infra/README.md`. - **Wiring the BFF** to actually use these endpoints (NestJS config, Prisma datasource URL, OTel SDK init) — that's the **B — Observability foundations** chantier, next up. ## Test plan - [ ] `cd infra/local && cp .env.example .env && docker compose -f dev.compose.yml up -d` → all three core services come up healthy; verify with `docker compose ps`. - [ ] `psql postgres://portal:<pwd>@localhost:5432/portal_dev -c "\dn"` shows the `audit` schema; `\dg` shows the four audit roles. - [ ] `redis-cli -a <pwd> PING` → `PONG`. - [ ] Send a fake OTLP trace via grpcurl → see it printed by `docker compose logs otel-collector`. - [ ] `--profile dbtools up -d` → http://localhost:8081 shows pgweb UI, can navigate to the audit schema. - [ ] `--profile observability up -d` → http://localhost:16686 shows Jaeger UI; collector logs no longer report Jaeger export retries. - [ ] `docker compose down -v` cleanly removes everything; next `up -d` re-runs the bootstrap SQL. --------- Co-authored-by: Julien Gautier <julien.gautier@apf.asso.fr> Reviewed-on: #57 |
||
|
|
f5d3697466 |
fix(deps): revert TS6/ESLint10/webpack-cli7 majors and gate future majors (#43)
## Summary Three Renovate major bumps merged silently because `nx affected` doesn't see deps-only PRs as affecting any project — CI passed trivially, the breakage only surfaced when `nx run-many` was run locally: - **TypeScript 5→6** (#33) — `tsconfig.lib.json` fails with `TS5101: Option 'baseUrl' is deprecated`. Revert to 5.9.x. - **ESLint 9→10** (#36) — `@nx/eslint@22.7.1` not compatible: project graph fails with "Unable to find eslint". Revert eslint, `@eslint/js`, `jsonc-eslint-parser`, `eslint-plugin-playwright` to ESLint-9-compatible versions. - **webpack-cli 5→7** (#34) — webpack-cli 7 removed the `--node-env=production` flag Nx generates. Revert to 5.x. Bonus side-fix: the `ajv@<8.18.0` override added in #42 was over-broad and was forcing ESLint's bundled ajv to v8 (incompatible with ESLint 9's option contract). Narrow the override to `@angular-devkit/core>ajv@<8.18.0` so only the targeted nestjs-prisma chain is bumped. ## Prevention — gate majors behind the dependency dashboard Add a Renovate `packageRule` with `dependencyDashboardApproval: true` for `matchUpdateTypes: ["major"]`. Renovate stops auto-creating PRs for majors; they appear as checkboxes in the dashboard issue, and only get a PR after a human ticks the box (presumably after reading the changelog and confirming Nx-plugin / Angular / NestJS readiness). This is the surgical fix for the gap. The deeper fix (making `nx affected` correctly mark all projects as affected on package.json changes) is a separate investigation worth doing later — but the dashboard gate prevents the same trap regardless. ## Verification Locally on this branch: - `pnpm exec nx run-many -t lint test build --parallel=2` → ✓ 8 projects pass. - `pnpm audit --audit-level=moderate` → 0 vulnerabilities. ## Test plan - [ ] `check` job goes green on this PR (would have caught the regressions if `nx affected` were broader). - [ ] After merge, the next Renovate run does not create new PRs for any major (TS, eslint, webpack-cli, etc.). - [ ] Any pending major in the dashboard issue still appears, but only as a checkbox awaiting approval. ## Out of scope (follow-up) Investigate why `nx affected` misses package.json-only changes. Likely a missing entry in `nx.json` `namedInputs` (`default`) or `targetDefaults`. Worth its own focused PR; the dashboard gate is the conservative fix in the meantime. --------- Co-authored-by: Julien Gautier <julien.gautier@apf.asso.fr> Reviewed-on: #43 |
||
|
|
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
|
||
|
|
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. |
||
|
|
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/. |