docs: archive the finished backlogs (RD-30)

Two backlog trees are complete: `docs/project/backlog/` (75 files, every
WP done) and `docs/project/refactor-backlog-setup/` (the arc before it).
Move both under `docs/project/archive/` with `git mv`, so history stays
intact through `git log --follow`. `SHOWCASE-ROADMAP.md` moves with them,
because it points at the now-archived backlog README.

Add `docs/project/archive/README.md`. It states that these trees are
historical and names the two directories that are still live.

Repoint every inbound reference named in RD-30's Files table: CLAUDE.md,
the root README, both backend READMEs, `LetterHtml.cs`, `a11y.mdx`, the
`document-feature` and `new-ssp` skills, and the readable-codebase PLAN,
README, and RD-19 ticket. Fix two upward-relative links inside the moved
WP files (WP-68, WP-69) that gained a directory level and would otherwise
break. Repoint `.prettierignore`'s two agent-prompt exclusions to their
new path, so prettier keeps leaving those files' exact wording alone.

Mark RD-30 done and check off its acceptance criteria; flip its README
row to done.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
eho
2026-09-08 23:00:38 +02:00
co-authored by Claude Opus 5
parent 097e8468e0
commit 12f17d9d73
161 changed files with 154 additions and 24 deletions
@@ -0,0 +1,59 @@
# WP-49 — OpenZaak zaken read seam (slice 1)
Status: done
Phase: 9 — OpenZaak / ZGW integration
## Why
The POC serves cases from local SQLite. To grow toward production it must be able to source
them from a real ZGW backend (OpenZaak) **without changing the frontend** (BFF-lite, ADR-0001).
The backend had no data-access abstraction to swap behind, no outbound HTTP, and no JWT. This is
the first thin vertical slice: read-only zaken.
## Read first
- [ADR-0005 — OpenZaak behind the BFF](../reference/architecture/0005-openzaak-behind-bff.md)
- [openzaak-integration.md](../reference/openzaak-integration.md)
## Decisions (pre-made, don't relitigate)
- OpenZaak's anti-corruption layer lives in the **BFF**, never the browser.
- Source selected by config (`Zgw:Enabled`, default false) → POC still runs offline.
- Each source maps into the **existing** `ApplicationSummaryDto` → no api-client drift, no FE change.
- Fresh HS256 JWT **per call** (no refresh flow). Hand-rolled (no new NuGet).
- `IZaakSource` is sync (matches the endpoint + local store); OpenZaak source does sync-over-async.
## Files
- `Data/IZaakSource.cs`, `Data/LocalZaakSource.cs`
- `Zgw/{ZgwOptions,ZgwTokenProvider,ZgwZaakMapper,OpenZaakZaakSource}.cs`
- `Program.cs` (DI + resolve `IZaakSource` in `/admin/cases`), `appsettings.json` (`Zgw` section)
- tests: `ZgwTokenProviderTests`, `ZgwZaakMapperTests`, `OpenZaakZaakSourceTests`
## Steps
1. Extract the cases read into `IZaakSource`; `LocalZaakSource` delegates to `ApplicationStore`.
2. Build the `Zgw/` client (options, JWT minter, ZGW→DTO mapper, paginating HTTP source).
3. Wire DI by config; refactor `/admin/cases` to resolve `IZaakSource`.
4. Unit-test the minter, mapper, and source (fixtures + stub `HttpMessageHandler`).
## Acceptance criteria
- [x] `/admin/cases` serves identical DTOs via `LocalZaakSource` (default, offline).
- [x] `OpenZaakZaakSource` follows pagination, resolves+caches zaaktype labels, sends a Bearer token.
- [x] JWT verifies (HS256) with the required claims.
- [x] `dotnet test` green (142); `npm run ci` green with **no api-client drift** (FE untouched).
## Verification
`cd backend && dotnet test`; `npm run ci`; manual: `/beheer/zaken` still lists cases with `Zgw:Enabled=false`.
## Out of scope
Create-zaak (WP-50), Documenten/DRC (WP-51), Notificaties (WP-52), real inbound OIDC/JWT,
OpenZaak in docker-compose.
## Risks
Sync-over-async blocks a thread under load if OpenZaak becomes the default → make the read path
async then (noted at the call site).