Files
strangler-fig-demo/docs/adr/ADR-003-ownership-is-taken-per-case.md
T
ehoandClaude Sonnet 5 a6a1abbe9c feat: implement strangler-fig-demo Session 1 (backend + smoke script)
Builds the four-seam, three-write-path reference demo backend: case-framework
(seam D stand-in), legacy-backend/frontend (SQL Server, seams A/B/C targets),
and new-backend (Domain/Application/Infrastructure.*/Api implementing the
source resolver, take/release-ownership, write-through translator, and owned
assessment flow), wired together via docker-compose with a plain placeholder
frontend standing in for the Angular portal until Session 2.

All 11 Architecture.Tests pass and scripts/smoke.sh passes end-to-end against
a fresh `docker compose up`, covering acceptance criteria 1-3 and 7-22.

Fixes two real domain bugs found only once the stack ran for real: the BSN
eleven-proof checksum trivially passes all-zero digits, and the adoption
mapper silently treated a partial legacy address as absent instead of failing
loudly. Also fixes several environment-specific integration issues (rootless
Podman/SELinux bind-mount permissions, a buildah NuGet layer-caching bug,
SqlClient's invariant-globalization incompatibility, and an nginx path-prefix
mismatch for the legacy frontend).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 07:57:26 +02:00

3.2 KiB

ADR-003: Ownership is taken per case for now — bulk migration is a later, separate capability

Status

Accepted (interim). Superseded in part once bulk migration tooling (see "Future work" below) ships.

Context

The end state for at least some processes — registration cases among them — is a bulk cutover: migrate the whole remaining population in one operation and retire the legacy path for that process on a clean date. That is a real, wanted outcome, not something this design argues against.

What this system cannot do is wait for that bulk-migration tooling to exist before shipping anything of business value. Building a safe bulk migration requires solving problems this demo deliberately defers: what happens to rows that fail adoption (four such failure modes already exist in the seed data — contact, BSN, motivation, and partial-address invariant violations), how a partially-failed batch is reported and retried, and how the cutover is scheduled and communicated. None of that should block getting the read ACL, write-through ACL, and take-ownership mechanics themselves live and earning their keep.

Decision

Ship now with ownership taken one legacy case at a time, via POST /api/worklist/legacy/{aanvraagId}/take-ownership (§7.5), triggered by an explicit user action in the portal. This is the interim mechanism, not the final one for every process.

This is deliberately the right building block either way:

  • It is the same adoption logic (mapping, invariant validation, case-framework correlation, atomic persistence, migratie-vlag flip) that a future bulk tool would need to call in a loop — building it per-case first means the bulk tool is an orchestration layer on top of already-proven logic, not a parallel implementation to keep in sync.
  • It gives a real, visible answer today for what a bulk migration would otherwise discover the hard way: which legacy rows fail adoption and why (surfaced here as a named 422 per case, not a batch-job log line).
  • The read ACL (seam A) and write-through ACL (seam B) must work correctly for a partially-adopted population regardless of how adoption happens — that requirement doesn't change once bulk tooling exists.

Consequences

  • Until bulk tooling exists, full legacy retirement for a process happens case-by-case, which is slower than a scheduled cutover — accepted as the cost of shipping the seam mechanics now rather than waiting.
  • Reversal (§7.6) stays per-case and gated on domain_writes_since for the same reason a bulk reversal would be unsafe absent a sync (docs/sync-not-implemented.md): undoing adoption after edits would silently discard them.
  • This demo's non-goals (§3) exclude building the bulk migration tool itself — that's future work, not a rejected idea.

Future work

A bulk migration tool for a given process (e.g. registration cases) can reuse the same take-ownership handler per legacy id, adding: pre-flight reporting of which rows would fail adoption and why (so the four invariant-failure classes seen here are triaged before cutover, not discovered during it), a scheduled cutover window, and a decision on whether failed rows block the cutover or are carved out and finished by hand.