Add a multi-stage Dockerfile for the BFF (.NET 10 sdk -> aspnet runtime, curl for the healthcheck) and infra/docker-compose.yml running it with a /health healthcheck. `docker compose up --wait` gates on the container reporting healthy, which is the compose-up smoke test. Document the path in the README. Verified: image builds; `docker compose up -d --build --wait` reports the container Healthy; host curl http://localhost:8080/health -> 200 Healthy. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
194 lines
8.5 KiB
Markdown
194 lines
8.5 KiB
Markdown
# register-reference
|
|
|
|
A reference application demonstrating how to build a Dutch government **register** (a BIG-style professional register) on top of unforked **Common Ground** modules — OpenZaak, Open Notificaties, Objecten, Open Klant — with loose coupling, modern workflow tooling, and data-governance ready integration points.
|
|
|
|
This repository is the runnable companion to Respellion's Foundations playbook entry on Common Ground architecture for non-municipal contexts (CIBG, DUO, RVO, and similar uitvoeringsorganisaties).
|
|
|
|
> **Status:** under active development. See [BACKLOG.md](BACKLOG.md) for the current iteration.
|
|
|
|
---
|
|
|
|
## Start here
|
|
|
|
| Document | Purpose |
|
|
|---|---|
|
|
| **[docs/PRD.md](docs/PRD.md)** | What we're building and why. Goals, non-goals, architecture summary, scope. Read once at project start. |
|
|
| **[CLAUDE.md](CLAUDE.md)** | How we work. Engineering principles, TDD/DDD/BDD discipline, non-negotiable architectural rules, Gitea conventions. Read every task. |
|
|
| **[BACKLOG.md](BACKLOG.md)** | Iteration plan. A curated mirror of the active Gitea milestone — Gitea Issues are the system of record. |
|
|
| **[docs/architecture/](docs/architecture/)** | Diagrams (Mermaid sources) and ADRs. Start with `adr-0001-loose-coupling.md`. |
|
|
| **[docs/runbooks/](docs/runbooks/)** | Operational guides: local startup, seeding, common failures, CI debugging. |
|
|
|
|
The day-to-day operational pages — environment URLs, known issues right now, on-call notes — live in the **Gitea Wiki** for this repository. The wiki points at `docs/` for anything authoritative.
|
|
|
|
---
|
|
|
|
## What this application demonstrates
|
|
|
|
- A **BIG-style professional register** modelled on Dutch public-sector patterns, with four end-user portals: self-service, openbaar register, behandel-portal, beheer-portal.
|
|
- **Common Ground modules as upstream peers** — never forked, reached only via documented APIs (ZGW, NRC events).
|
|
- **An Anti-Corruption Layer** that confines all ZGW knowledge to one place, so the rest of the codebase stays domain-shaped rather than municipality-shaped.
|
|
- **BPMN + DMN workflows via Flowable** as a separate, swappable module — using the external-task job-worker pattern so BPMN models never reach into OpenZaak.
|
|
- **A read projection** as the public-facing data path, decoupled from the authoritative modules.
|
|
- **Synthetic data and mock identity** (Keycloak realms standing in for DigiD, eHerkenning, eIDAS, and a medewerker IdP) so the whole system runs locally without external dependencies.
|
|
- **TDD, DDD, BDD, mutation testing, ADRs, and Conventional Commits** as enforced defaults — encoded in CI.
|
|
- **Gitea-native delivery**: source, issues, milestones, project boards, releases, container registry, packages, wiki, and Actions.
|
|
|
|
For the architecture rationale, see [docs/PRD.md §3](docs/PRD.md) and [docs/architecture/](docs/architecture/).
|
|
|
|
---
|
|
|
|
## Local quickstart
|
|
|
|
**Prerequisites**
|
|
|
|
- Docker Engine (or Docker Desktop) with Compose v2
|
|
- ~8 GB free RAM, ~10 GB free disk
|
|
- Bash or PowerShell
|
|
|
|
**Bring the stack up**
|
|
|
|
```bash
|
|
git clone https://gitea.respellion.local/respellion/register-reference.git
|
|
cd register-reference
|
|
cp .env.example .env # edit if you change ports
|
|
docker compose -f infra/docker-compose.yml up -d
|
|
```
|
|
|
|
Health checks should be green within ~3 minutes on a developer machine. If something fails, see [docs/runbooks/local-startup.md](docs/runbooks/local-startup.md).
|
|
|
|
> **Wired today (Iteration 0):** only the placeholder BFF is in `infra/docker-compose.yml` so far. Bring it up and smoke-test its health endpoint:
|
|
>
|
|
> ```bash
|
|
> docker compose -f infra/docker-compose.yml up -d --build --wait
|
|
> curl http://localhost:8080/health # -> Healthy
|
|
> ```
|
|
>
|
|
> `--wait` exits non-zero unless the container reports healthy, so this doubles as the compose-up smoke test. The remaining services and the URLs below land in later slices.
|
|
|
|
**Default URLs**
|
|
|
|
| Service | URL |
|
|
|---|---|
|
|
| Self-Service portal | http://localhost:4200 |
|
|
| Openbaar register | http://localhost:4201 |
|
|
| Behandel-portal | http://localhost:4202 |
|
|
| Beheer-portal | http://localhost:4203 |
|
|
| BFF | http://localhost:5000 |
|
|
| OpenZaak | http://localhost:8000 |
|
|
| Open Notificaties | http://localhost:8001 |
|
|
| Flowable | http://localhost:8080 |
|
|
| Keycloak | http://localhost:8180 |
|
|
| MkDocs site (after build) | http://localhost:8000/docs/ |
|
|
|
|
Test credentials, BSNs, and personas: see [docs/synthetic-data.md](docs/synthetic-data.md).
|
|
|
|
**Re-seed synthetic data**
|
|
|
|
```bash
|
|
./tools/seed.sh # or pwsh ./tools/seed.ps1
|
|
```
|
|
|
|
---
|
|
|
|
## Repository layout
|
|
|
|
```
|
|
register-reference/
|
|
├── apps/ # Angular portals (Nx monorepo)
|
|
│ ├── self-service/
|
|
│ ├── openbaar/
|
|
│ ├── behandel/
|
|
│ └── beheer/
|
|
├── libs/ # shared Angular libs (UI, auth, generated API client)
|
|
├── services/ # .NET services
|
|
│ ├── bff/
|
|
│ ├── domain/ # BIG Domain Service
|
|
│ ├── acl/ # Anti-Corruption Layer (the only code that knows ZGW)
|
|
│ ├── event-subscriber/
|
|
│ └── projection-api/
|
|
├── workflows/ # BPMN + DMN sources
|
|
├── infra/ # docker-compose, Keycloak, OpenZaak, Flowable, seed
|
|
├── tests/
|
|
│ ├── acceptance/ # Gherkin / Reqnroll BDD scenarios
|
|
│ └── e2e/ # Playwright
|
|
├── docs/ # versioned documentation (MkDocs source)
|
|
├── .gitea/ # Gitea Actions workflows, issue/PR templates
|
|
├── CLAUDE.md # working agreements
|
|
├── BACKLOG.md # iteration plan (mirror of active milestone)
|
|
└── README.md
|
|
```
|
|
|
|
Full description in [docs/PRD.md §9](docs/PRD.md).
|
|
|
|
---
|
|
|
|
## Working in this repository
|
|
|
|
**Source of truth for work:** Gitea Issues + Milestones for this repository. `BACKLOG.md` is a mirror.
|
|
|
|
**Branching:** trunk-based. Short-lived branches off `main`, named `<type>/<issue-number>-<short-slug>` (e.g. `feat/14-acl-default-fill`).
|
|
|
|
**Commits:** Conventional Commits, referencing the Gitea issue:
|
|
|
|
```
|
|
feat(acl): default-fill bronorganisatie (refs #14)
|
|
```
|
|
|
|
The merging PR closes the issue via `closes #14` in the squash-commit body.
|
|
|
|
**Pull Requests:** the unit of review. Squash-merged. PR template enforces the Definition of Done checklist from [CLAUDE.md §3](CLAUDE.md).
|
|
|
|
**Releases:** CalVer (`YYYY.MM.PATCH`), tagged on `main`, changelog generated by `git-cliff`, published as a Gitea Release with container images in the Gitea Container Registry.
|
|
|
|
See [CLAUDE.md](CLAUDE.md) for the full working agreements, the architectural non-negotiables, and the rules Claude Code follows on every task.
|
|
|
|
---
|
|
|
|
## Testing
|
|
|
|
- **Unit tests** — dominant. .NET (xUnit) and Angular (Vitest / Testing Library).
|
|
- **Integration tests** — Testcontainers-driven, exercising real OpenZaak, Flowable, NRC.
|
|
- **Acceptance tests** — Gherkin scenarios in `tests/acceptance/`, one per user-visible flow.
|
|
- **End-to-end** — Playwright, expanding slice by slice from the walking-skeleton happy path.
|
|
- **Mutation testing** — Stryker.NET and Stryker, baseline-ratcheted on `main`.
|
|
|
|
Run everything:
|
|
|
|
```bash
|
|
./tools/test-all.sh
|
|
```
|
|
|
|
Run a focused slice (example):
|
|
|
|
```bash
|
|
dotnet test services/acl
|
|
```
|
|
|
|
---
|
|
|
|
## Contributing
|
|
|
|
1. Find or open a Gitea issue using one of the templates in `.gitea/ISSUE_TEMPLATE/` (`slice.md`, `bug.md`, `adr-proposal.md`).
|
|
2. Assign yourself, move it to "In progress" on the milestone's project board.
|
|
3. Branch off `main`, follow the [CLAUDE.md](CLAUDE.md) working agreements (TDD: red commit → green commit → refactor commit).
|
|
4. Open a PR using the template, link the issue, ensure the Gitea Actions pipeline is green.
|
|
5. Squash-merge once approved. The merging commit closes the issue.
|
|
|
|
If a task pushes against any of the architectural rules in [CLAUDE.md §8](CLAUDE.md), **stop and open an `adr-proposal` issue first.** That conversation is more important than the code.
|
|
|
|
---
|
|
|
|
## License and attribution
|
|
|
|
Respellion-authored code is licensed under [EUPL-1.2](LICENSE). Upstream Common Ground modules retain their own licences (typically EUPL-1.2 or MIT — see each module's repository).
|
|
|
|
This reference application is **not** an official product of CIBG, DUO, VNG Realisatie, or any government body. It is a Respellion playbook artefact illustrating an architectural pattern.
|
|
|
|
---
|
|
|
|
## Contact
|
|
|
|
- Issues, questions, proposals: open a Gitea issue on this repository.
|
|
- Architectural discussion: start with an `adr-proposal` issue.
|
|
- Anything sensitive: contact Respellion through the channel in `docs/runbooks/contact.md`.
|