---
title: "ADR-046: History, URL and validation tools"
manual: "TYPO3 LLM Extension"
version: "0.35"
permalink: "https://docs.typo3.org/permalink/netresearch/nr-llm:adr-046@0.35"
source: "Adr/Adr046HistoryUrlAndValidationTools.rst"
modified: "2026-09-16T22:09:16+00:00"
---

# ADR-046: History, URL and validation tools

-   *Status:* Accepted
-   *Date:* 2026-07-09
-   *Deciders:* nr_llm maintainers

## Context

The schema tools ([ADR-045](https://docs.typo3.org/permalink/netresearch/nr-llm:adr-045@0.35)) let an agent *retrieve* structure
and reason over it. Three recurring editor/integrator questions still had no
tool: "who changed this record?", "which page serves this URL?", and "is this
TCA/TypoScript actually broken?". The last two are *deterministic* questions —
an LLM guessing at brace balance or showitem consistency over retrieved text
is unreliable where an exact scanner exists.

For TCA validation the core `TcaMigration` was considered and rejected:
it only emits messages while migrating the **raw, pre-boot** TCA; at runtime
`$GLOBALS['TCA']` is already migrated, so replaying it reports nothing.
Structural checks over the live TCA are implemented directly instead.

For TypoScript the core include-tree scanner
(`IncludeTreeSyntaxScannerVisitor`, with
`SysTemplateTreeBuilder`/`IncludeTreeTraverser`) is reused — the
same code path the backend's TypoScript module uses to mark broken syntax.
These classes are `@internal`; the risk is accepted because the surface
used is tiny, covered by functional tests, and verified identical on 13.4
and 14.

## Decision

Four read-only built-in tools:

-   **`get_record_history` (group `content`)**

    One record's `sys_history` newest-first: timestamp, resolved backend
    username, action, and per modification the changed fields as
    `old → new` pairs. Answers "wer hat die Überschrift geändert".

-   **`resolve_url` (group `structure`)**

    URL → page mapping via the real `SiteMatcher`/`PageRouter` — site,
    language, page uid/title/slug, route arguments. Routing only, no HTTP;
    the complement of `probe_url` (which fetches but does not explain).

-   **`validate_tca` (group `structure`)**

    Structural checks over the live TCA: `ctrl.label`/`ctrl.type` must
    name defined columns, `foreign_table` must reference TCA tables,
    `types`/`palettes` showitem entries must reference defined columns
    and palettes, flex `ds_pointerField` is flagged on v14+ (removed
    there).

-   **`check_typoscript` (group `configuration`)**

    Constants and setup include trees of a page's sys_template chain run
    through the core syntax scanner: invalid lines, unbalanced braces,
    `@import` matching no file — each with source and line number.

## Access model

`get_record_history` and `validate_tca` reuse
`TableReadAccessService` (ADR-042): the sensitive-table denylist holds
for every user including admins; non-admins additionally pass
`tables_select`, and `get_record_history` also requires page-show on
the record's page (the per-row gate of `read_records`, fail-closed for
unresolvable records). History values of credential-like fields are
withheld (the *fact* of the change stays visible). `resolve_url` needs no host
allowlist — `SiteMatcher` only knows this instance's sites, so foreign
hosts cannot match by construction; non-admins must hold page-show on the
resolved page, with the same neutral denial as `get_page_content`.
`check_typoscript` is **admin-only** like `get_typoscript`, and reports
source + line number + error kind only — the offending line's content is
never echoed, because a broken constants line may carry an API key.

## Consequences

-   The four remaining diagnostic use-cases named in the tool-expansion plan
    (record attribution, URL mapping, TCA and TypoScript validation) are
    covered by deterministic tools instead of model guesswork.
-   `check_typoscript` depends on `@internal` core classes; a core
    refactoring may require adaptation. The functional tests pin the observable
    behaviour, so a break surfaces in CI, not at runtime.
-   `validate_tca` intentionally implements a *small* rule set with exact
    semantics rather than replicating the Extension Scanner; new rules can be
    added as they prove useful.
