Last updated: 13 Jan 2026
whitehall: 9. Separate configurable document forms and presenters from attribute schema
Status
Accepted
Context
The configurable document schema introduced in ADR-0006 and evolved in ADR-0007 and ADR-0008 defined document properties under schema.properties and grouped UI fields via settings.edit_screens. This conflated three concerns:
- How publishers see and group fields in the UI (form layout and copy).
- How field values are presented to downstream systems (e.g. Publishing API payload mapping and transformations).
- How attributes and validations are defined and enforced.
This coupling made it hard to:
- Group related fields in the UI without affecting payload mapping.
- Present the same attribute differently to publishers and Publishing API. E.g Duration block in topical events holding data for
start_dateandend_datebut needed to be presented as individual fields to publishing API. - Flatten validations while still allowing nested form structures, leading to complex validation logic.
Decision
We refactored the configurable document type schema to separate concerns:
- Introduced a top-level
formshash describing UI forms and their fields (label, description, block type), replacingsettings.edit_screens. - Replaced
schema.propertieswithschema.attributes. The current implementation focuses on simple types (string, integer, date), moving away from nested object properties. In future, we are open to introducing more complex attribute shapes like arrays. - Introduced a top-level
presentershash to describe how attribute values are mapped or transformed for downstream consumers (e.g. Publishing API), helping to decouple UI layout from payload shape. - Moved validation definitions to
schema.validations, listing validators by attribute name. Nested validations within property definitions are no longer used in current schemas to simplify validation logic. - Removed custom nested block content handling for
objecttypes. Object attributes now use Rails' default hash implementation. - Updated the configurable document type JSON schema to validate the new structure and removed obsolete nested-schema code paths.
Consequences
- All configurable document type definitions must use
schema.attributes,forms, andpresenters;settings.edit_screensand nested property validations are no longer supported. - UI layout changes (field grouping, titles, descriptions, block types) can now be made in
formswithout impacting Publishing API payloads, which are defined inpresenters. - Validators will run against the flattened
schema.attributesnamespace. Added tests ensure nested data values stored in block content are preserved when present in the payload. - Future support for genuinely nested attribute schemas or arrays would need a new design rather than reintroducing
objecttypes. - It now becomes easier to present the same attribute differently in the UI and Publishing API (or any other consumer in future) by defining separate mappings in
formsandpresenters.
Example
A configurable document type schema following the new structure will be identical to this:
{
"key": "example_document_type",
"title": "Example Document Type",
"description": "An example document type with configurable forms and presenters",
"forms": {
"documents": {
"fields": {
"body": {
"title": "Body",
"description": "The main content area",
"block": "govspeak"
},
"lead_paragraph": {
"title": "Lead Paragraph",
"description": "A short introduction",
"block": "default_string"
}
}
}
},
"schema": {
"attributes": {
"body": {
"type": "string"
},
"lead_paragraph": {
"type": "string"
},
},
"validations": {
"presence": {
"attributes": ["body", "lead_paragraph"]
},
"length": {
"attributes": ["lead_paragraph"],
"maximum": 255
}
}
},
"presenters": {
"publishing_api": {
"body": "govspeak",
"lead_paragraph": "string"
}
}
}