docs(timetable): open TECH-OBSERVER-TEST-CONVERGENCE + ART-ADVANCE-SECTION-FK

Two new BACKLOG entries surfaced during Session 3:

- **TECH-OBSERVER-TEST-CONVERGENCE** — track removal of the
  artist_advance.bootstrap_on_org_create config flag once the five
  FormSchema-counting tests are updated to expect the auto-bootstrapped
  schema. Goal: productiegedrag = testgedrag, geen branching.

- **ART-ADVANCE-SECTION-FK** — replace the name-based bridge between
  advance_sections (engagement-scoped) and form_schema_sections
  (org-scoped) with a real FK. Today's name-match works for default-
  seeded schemas but breaks on UI rename and offers no integrity
  guarantee. Includes migration outline (form_schema_section_id
  nullable FK, ArtistEngagement::created provisioning hook,
  best-effort backfill).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-08 23:18:22 +02:00
parent 889441cb39
commit 449581c41e

View File

@@ -676,6 +676,59 @@ voor third-party integraties (ticketing, HR, etc.)
## Technische schuld
### TECH-OBSERVER-TEST-CONVERGENCE — Drop `bootstrap_on_org_create` flag once tests converge
**Aanleiding:** Session 3 introduceerde `OrganisationObserver` om elke nieuwe
organisatie automatisch een `artist_advance` FormSchema te bezorgen
(RFC-TIMETABLE v0.2 D15). Vijf bestaande tests (`FormSchemaTest`,
`FormSchemaApiTest`, `MultiTenancyTest`, twee `ScopeLeakageTest`-cases)
tellen FormSchema-rijen exact en namen aan dat `Organisation::factory()`
geen schema's meebezorgt — de auto-bootstrap brak die assumptie. Quick fix:
`config/artist_advance.php` met `bootstrap_on_org_create` (default `true`,
`phpunit.xml` flipt hem naar `false`); de observer leest de config.
**Wat:** Update de vijf FormSchema-counting tests zo dat ze de auto-
bootstrapped `artist_advance` schema verwachten (filter op `purpose !=
'artist_advance'` of pas counts aan). Verwijder daarna het
`bootstrap_on_org_create` flag, de `phpunit.xml` env-override, en de
config-check in de observer — productiegedrag = testgedrag, geen
branching.
**Prioriteit:** Laag — geen blocker, dedicated test-cleanup pass.
---
### ART-ADVANCE-SECTION-FK — Replace name-based AdvanceSection ↔ FormSchemaSection bridge with FK
**Aanleiding:** Session 3 wirede de portal-flow door een name-match tussen
`advance_sections.name` (engagement-scoped, RFC-TIMETABLE v0.2 §5.3) en
`form_schema_sections.name` (org-scoped, FormBuilder). De seeder
(`ArtistAdvanceDefault`) creëert vijf `FormSchemaSection`-rijen met
deterministische namen; de `EngagementPortalController` filtert
`FormField`-rijen door eerst de `FormSchemaSection` met dezelfde naam te
vinden als de `AdvanceSection`. Werkt vandaag, maar:
1. **Hernoemen breekt**: een organisatie die "Algemeen" hernoemt naar
"Algemene info" via de FormBuilder UI verbreekt de match voor alle
bestaande engagements.
2. **Geen referential integrity**: dubbele/ontbrekende naam-matches
silenten falen i.p.v. een DB-niveau constraint.
3. **Geen migration-pad voor `Custom`-secties**: organisaties die eigen
secties toevoegen aan de FormBuilder schema krijgen geen
corresponderende `AdvanceSection`-rij per engagement.
**Wat:** Voeg `advance_sections.form_schema_section_id` toe (nullable
`foreignUlid`, `nullOnDelete`). Bij `ArtistEngagement::created` (nieuwe
observer of uitbreiding van bestaande) provisionineer één
`AdvanceSection`-rij per `FormSchemaSection` op de org's `artist_advance`
schema, met `form_schema_section_id` gevuld. Migratie voor bestaande
data: best-effort name-match per (organisation_id, schema_id) als
backfill, gevolgd door log-warning voor unmatched rijen. Update
`EngagementPortalController` om via FK te filteren i.p.v. naam.
**Prioriteit:** Middel — relevant zodra UI-rename of `Custom`-secties
voor het eerst in productie aanlopen tegen het bug. Voor pure default
seeded schema's werkt de huidige bridge.
---
### RFC-TIMETABLE-V0.2-DOC-CLEANUP — Strip ARCH-PLANNED-MODULES.md mentions from RFC v0.2
**Aanleiding:** RFC-TIMETABLE v0.2 §1 ("Bron-documenten") en §15