docs(schema,arch-form-builder): reflect purpose registry v1.0

- SCHEMA.md §3.5.12 header rewritten for the 7-purpose vocabulary and
  `PurposeRegistry`. The `custom_purpose_slug` column is dropped from
  the `form_schemas` table and removed from the index list. The
  `form_submissions.subject_type` note cites
  `PurposeRegistry::allSubjectTypes()` instead of the deleted
  `config/form_subjects.php`.
- ARCH-FORM-BUILDER.md TL;DR updated: goal bullet cites 7 purposes
  (v1.0); §3.2 bullet notes the legacy 22-variant vocabulary is
  retired. §17.3 replaced: the "Custom purposes per organisation"
  section is gone; the new "Purpose registry" section documents the
  seven-slug table, PurposeDefinition shape, PurposeRegistry API,
  MorphMapAlignmentTest guard, the pre-publish binding check, and a
  step-by-step "adding a new purpose" checklist.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-24 14:36:18 +02:00
parent 55ba4f24c0
commit 598593b0db
2 changed files with 88 additions and 25 deletions

View File

@@ -1790,11 +1790,14 @@ Immutable audit record of every email sent. No soft deletes.
## 3.5.12 Form Builder
> Universal form builder — one schema/field/submission/value stack serving
> 22 `FormPurpose` variants from `event_registration` to `incident_report`
> to `signature_contract`. See `/dev-docs/ARCH-FORM-BUILDER.md` v1.2 for
> the authoritative behaviour spec; this section documents the physical
> tables as landed through S1 + S2a + S2b. Where ARCH §4 and the
> migrations disagree, the migrations win (document code-as-built).
> the seven v1.0 `FormPurpose` variants (`event_registration`,
> `artist_advance`, `supplier_intake`, `post_event_evaluation`,
> `incident_report`, `signature_contract`, `user_profile`) registered in
> `config/form_builder/purposes.php` via `PurposeRegistry`. See
> `/dev-docs/ARCH-FORM-BUILDER.md` v1.3 for the authoritative behaviour
> spec; this section documents the physical tables as landed through
> S1 + S2a + S2b + WS-2. Where ARCH §4 and the migrations disagree, the
> migrations win (document code-as-built).
>
> **Legacy tables dropped (S2a):** `registration_form_fields`,
> `person_field_values`, `registration_field_templates` removed by
@@ -1870,8 +1873,7 @@ that aggregates the user's submitted, non-test `form_submissions`.
| `owner_id` | ULID nullable | polymorph target |
| `name` | string | |
| `slug` | string | canonical within organisation |
| `purpose` | string(50) | `FormPurpose` enum value |
| `custom_purpose_slug` | string nullable | required when `purpose = custom` |
| `purpose` | string(50) | Slug matching a key in `PurposeRegistry::all()`; `FormPurpose` enum mirrors the seven v1.0 values |
| `description` | text nullable | |
| `is_published` | bool | default: false |
| `submission_mode` | string(20) | `FormSubmissionMode` enum value |
@@ -1897,7 +1899,7 @@ that aggregates the user's submitted, non-test `form_submissions`.
| `deleted_at` | timestamp nullable | Soft delete |
**Relations:** `belongsTo` organisation, createdBy/lastUpdatedBy/editLockUser (User); `morphsTo` owner; `hasMany` fields, sections, submissions, webhooks
**Indexes:** `(organisation_id, purpose)`, `(owner_type, owner_id)`, `(public_token)`, `(public_token_previous)`, `(custom_purpose_slug)`
**Indexes:** `(organisation_id, purpose)`, `(owner_type, owner_id)`, `(public_token)`, `(public_token_previous)`
**Unique constraint:** `UNIQUE(organisation_id, slug)`
**Global scope:** `OrganisationScope`
**Soft delete:** yes
@@ -2019,7 +2021,8 @@ that aggregates the user's submitted, non-test `form_submissions`.
> One submission per `(schema, subject)` in `single` / `draft_single`
> modes; unbounded in `multiple` mode. Polymorphic `subject_type` /
> `subject_id` (allowed types per `config/form_subjects.php`).
> `subject_id` (allowed types derived from
> `PurposeRegistry::allSubjectTypes()`; WS-2 Q6 consolidation).
> Carries the lifecycle timestamps, review status, optional schema
> snapshot (when `form_schemas.snapshot_mode != 'never'`), locale used,
> idempotency key, anonymisation marker, and a `search_index` text