ADR-262: The field writers write into the workspace, and a redirect is refused before the card
- Status
-
Accepted
- Date
-
2026-11-05
- Amends
-
ADR-260 (its consequence that only
update_writes into a workspace), ADR-135 (its refusal of every draft workspace, for the writers named here), ADR-084 and ADR-134 (every declared write suspends: not a call its tool refuses whatever is decided)content_ element - Authors
-
Netresearch DTT GmbH
Context
ADR-260 let update_ write a workspace
version in the draft workspace a run was started in and left every other
writer refusing a draft workspace — after the approval card had been shown
and approved. Five more writers change fields of an existing record:
update_ (pages), set_
(sys_), set_ and
update_ (sys_), and publish_
(hidden of pages or tt_). Each table declares
ctrl., so the DataHandler started with a user in a draft
workspace stores a version (TYPO3 14.3.10 and 13.4.37,
Data, the branch around
workspace and workspace).
sys_ needed a measurement of its own, because file metadata
is read through FAL rather than as a record. Measured on 2026-11-05 against
TYPO3 14.3.10, as a non-admin editor with a page mount and a file mount who
is a member of the workspace:
- the DataHandler stores a version (
t3ver_,wsid t3ver_) and leaves the live row;oid Workspace, the Workspaces module's query, lists that version for the editor, on their page tree and over all their mounts — core adds root levelService:: select Versions In Workspace () 0to the page list for tables that ignore the root-level restriction "(e.g. FAL records)";- in a frontend request previewing the workspace,
Metareturns the version's values (EXT:frontend'sData Repository:: find By File Uid () Fileoverlays it); outside the frontend it returns the live row.Metadata Overlay Aspect
The redirect writers create_, update_ and
disable_ write sys_, which core does not version
(versioning false). In a draft workspace the DataHandler either
refuses such a write or — where the workspace allows live editing, or the
table versioning — writes the live row at once,
past the workspace (Backend).
They refused, too, after the card.
clear_ writes no record. Core's Data
does not consult the workspace, and the caches it empties are not kept per
workspace.
Decision
The five field writers write into the run's workspace, as
update_ does under ADR-260: they refuse a
draft workspace only where the run did not record it, read the record, the
card's current values and the read-back through the workspace overlay
(fetch, or for the file metadata the live row overlaid
with its version), name the workspace on the card, and end their answer with
"Stored as a draft in the workspace …; live stays unchanged until that
workspace is published", so the model does not tell the editor the change is
live. publish_ in a draft workspace clears the flag in the
record's version: visitors see the record once the workspace is published.
File metadata is versioned rather than refused: the version is created,
listed in the Workspaces module, and previewed in the frontend, which is
what an editor's own save in the file list produces.
The field writers also ask the helper below for the table they write: where an installation takes the versioning off one of these tables, the DataHandler would write the live row in a draft workspace, and the writer refuses instead of reporting a draft.
A call its tool refuses whatever is decided does not wait for approval.
A tool may implement Refuses:
refusal answers with the refusal or
null. Wherever the loop asks whether a call needs approval — the approval
scan, the proposal of a guided process, the calls settled beside that
proposal, and the calls run on the resume after a question was answered —
it asks Tool and then this method; a
refusal means no suspension, and the call goes to the tool. The tool's
execute asks the same method first and returns its refusal unchanged,
so skipping the approval can never lead to a write. A method that throws
counts as no refusal: the call waits for approval as before.
The redirect writers refuse in a draft workspace before the card, with
refuse of
Writes: in a draft workspace a table whose
versioning is not true is refused, whatever the workspace or the table
allow — a change there would go live, and an editor working in a draft
workspace asked for a draft. So is a versioned table that sets
versioning: TYPO3 13.4 edits its live rows in a
workspace as well (workspace asks that flag
before the versioning there; 14.3 asks it for tables without versioning
only). The answer names the workspace and the table
and says the change can only be made in the live workspace.
In a turn that suspends for another call the refused call's card says so. A turn is approved as one (ADR-132): when another call of the turn needs approval, the refused call is pending too, and its card shows the refusal in the card's language instead of the change. The line depends on the workspace and the table only, so the card is the same when the run resumes (ADR-184). Approving the turn runs the other call and the refused one, which refuses; declining it gives every call the denial.
:php:`ToolApprovalRule` stays context-free. The registry's boot validation, the Governance simulator and the unattended filter ask whether a tool needs approval in general, and for these tools it does.
clear_ is unchanged.
Consequences
✓ An editor in a draft workspace can let the chat change page metadata, an image's alternative text on one use or on the file, a file's title, description and copyright, and unhide a page or an element; each change waits in the Workspaces module, live stays as it was.
✓ A redirect asked for in a draft workspace no longer shows an approval card that can only end in a refusal.
✓ Another writer that cannot write in the run's context — a table core does not version — implements the interface with the same helper.
✗ set_ reads the reference and the record
it sits on in the workspace, but that record's page and the inline owners
above it are read live. A reference whose page, or an owner above its
record, is new in the workspace is refused as not found.
✗ Outside the frontend core shows a file's live metadata: the file list and the image's fallback text in a backend form show the live text until the workspace is published. The metadata version is edited in the file list's metadata form, which overlays it.
✗ Where an installation takes the versioning off one of the field writers' tables, their card still names the workspace, and the write is refused after the approval; a stock TYPO3 versions all four tables.
✗ A declined turn gives the refused call the denial, as every other call of the turn; the model reads "declined" rather than the refusal's reason, and learns that reason only when it asks again.
✗ The other writers — create, attach, move, copy, delete, localize, replace a reference, the social image — still refuse a draft workspace after the card.