Added three new documents with nine Mermaid diagrams to make the strangler fig strategy visible: - README: container topology diagram at the start, with the proxy entry point and three seams labelled - docs/architecture.md: five diagrams tracing the exact implementation: - The four seams and who holds authority at each boundary - How by-id read goes through the resolver, but list-read bypasses it - Case lifecycle state machine (the strategy in one picture) - Take-ownership sequence with failure windows annotated - Write-through error round-trip showing zero validation logic crossed - docs/playbook.md: how to apply this to a production system: - Write-path decision tree (five read/write patterns) - Cutover ordering diagram (side-effects-free first, least recoverable last) - Seven transferable rules with pointers to the files that demonstrate them - Scope diagram of what's proven vs. left as your decisions Resolved all 13 dangling § citations (to an absent spec doc) by linking to the actual files or dropping them. Replaced portal-frontend/README.md boilerplate with accurate content. All diagrams parse and link-check clean. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
52 lines
2.7 KiB
Markdown
52 lines
2.7 KiB
Markdown
# ADR-002: The write-through translator carries no business rules
|
|
|
|
## Status
|
|
Accepted.
|
|
|
|
## Context
|
|
Seam B lets a user edit a **legacy-owned** case's applicant details (name,
|
|
address, contact) from the new portal, without the new system taking
|
|
ownership of that case. The legacy system remains the authority on this data
|
|
until ownership is explicitly taken ([ADR-003](ADR-003-ownership-is-taken-per-case.md)).
|
|
|
|
It is tempting, once a translation layer exists between the portal's request
|
|
shape and legacy's `PUT /api/aanvragen/{id}/gegevens` shape, to also smuggle
|
|
in a validation shortcut or two — "just check the postcode format here too, it
|
|
saves a round trip." That temptation is exactly what this ADR forecloses.
|
|
|
|
## Decision
|
|
`New.Infrastructure.Legacy`'s write-through translator (the type backing
|
|
`ILegacyCaseGateway.UpdateDetailsAsync`) contains **no business rules**: no
|
|
conditionals on request values, no validation beyond null/shape checks, no
|
|
derived values, no defaulting. It only:
|
|
|
|
1. Maps the portal's 9-field request onto legacy's expected shape.
|
|
2. Calls `PUT legacy-backend/api/aanvragen/{id}/gegevens`.
|
|
3. Maps legacy's response — success, or **every** returned field error via the
|
|
`veld`/`code` → portal-field-path table — back into the portal's error
|
|
shape, including a generic fallback for any unrecognized legacy code
|
|
(logged as a warning, never dropped or guessed at).
|
|
|
|
If a rule needs to be enforced on this data from the new portal, that is a
|
|
signal the capability should be taken into ownership instead, not
|
|
patched into the translator.
|
|
|
|
## Consequences
|
|
- The portal cannot offer a better validation experience than legacy already
|
|
has for this seam — by design. The `Gevalideerd door het legacy systeem`
|
|
notice on the write-through form (`portal-frontend/src/app/case-detail/edit-applicant-details/`)
|
|
exists specifically so the user
|
|
knows why: this is the honest version of a seamless UI, not a limitation to
|
|
hide.
|
|
- Rule 11 in Architecture.Tests (no `New.Api` type both constructs a legacy
|
|
request DTO and touches a `DbContext`) is only a **partial**, structural
|
|
proxy for this constraint — and is already close to vacuous given rule 3
|
|
(legacy DTOs are `internal` to `New.Infrastructure.Legacy` with no
|
|
`InternalsVisibleTo` grant, so `New.Api` cannot even name them). The
|
|
stronger claim this ADR makes — that the translator itself contains no
|
|
conditional business logic — is a **code-review rule**, not a
|
|
machine-enforced one. We say so here rather than implying test coverage
|
|
that does not exist.
|
|
- Any future temptation to "just add one small check" in the translator
|
|
should instead be read as a signal to take that capability into ownership.
|