ADR-194: Two more metadata fields, one of them a select 

Status

Accepted

Date

2026-09-21

Amends

ADR-135 (the field allow-list of update_page_metadata), ADR-192 (the fields of update_fal_asset_meta)

Authors

Netresearch DTT GmbH

Context 

A live editorial run on the Netresearch demo installation (NEXT-158) ended with two fields an editor could not set through the assistant: the Twitter card type of a page and the copyright notice of an image. Both are descriptive metadata in the sense of ADR-135 — neither decides where a URL points, who sees a record or who may edit it — and both were simply absent from the two writers that own their tables.

The two fields differ from every field the writers had so far.

pages.twitter_card
is a select. EXT:seo declares its items — the empty string, summary and summary_large_image in the versions this repository supports — and an installation may add to them. The DataHandler does not compare a static select's value with its items: without a check any string up to the length bound would be stored, and the backend form would then show it as an invalid value. A length bound, which is all the writer applied so far, says nothing about a select.
sys_file_metadata.copyright
is not core's. It belongs to EXT:filemetadata, and without that extension neither the TCA column nor the database column exists. title and description, the two fields ADR-192 gave the writer, are core's and always there.

Decision 

twitter_card joins the allow-list of update_page_metadata. The list is still intersected with the live TCA, so an installation without EXT:seo is not offered the field. For a select column the writer reads the items the live TCA declares at call time and refuses a value that is not one of them, naming the allowed values in the refusal. The empty string is allowed where an item declares it, and only there; a divider is an entry of items and not a value. The allowed values also appear in the argument's description on the wire, so a model can choose before it calls. They do not appear as a JSON schema enum: the empty string is a legitimate value, and a provider is known to reject a function declaration whose enum holds one.

copyright joins the fields of update_fal_asset_meta, where the live TCA declares the column. Where it does not, the field is neither offered in the tool's specification nor accepted: a call naming it is refused as the unknown argument it is, and the read-back query never names a column the database may not have. The field is handled exactly as description: measured in characters against the tool's own bound of 2000, the TCA max winning where an installation declares one; an empty string clears it; a field left out keeps its value; the field-level grant is checked before anything is written, and a missing grant refuses the whole call.

Nothing else changes: one record per call, live workspace, default language, the approval pause, the neutral refusal for a record the acting user may not reach.

What stays excluded 

og_image and twitter_image stay out of update_page_metadata. They are file references, the risk class ADR-135 keeps out of a scalar writer; a writer of their own is the subject of a separate record.

Consequences 

✓ The two gaps the demo run named are closed within the writers that own the tables, under the review those writers already had.

✓ A select value is checked against what the backend form itself offers, so the tool cannot store what an editor could not pick.

✕ The writer now carries one column-type-specific check. A further select on the allow-list gets it for free; a further column type (check, datetime) would need its own.

✕ The functional tests of both writers need EXT:seo and EXT:filemetadata loaded, which adds both as development requirements of this repository.

Revisit when 

A third column type is proposed for either allow-list, or a select on the list gets itemsProcFunc or a foreign_table — dynamic items the static read cannot see.