---
title: "ADR-047: FAL tools"
manual: "TYPO3 LLM Extension"
version: "0.35"
permalink: "https://docs.typo3.org/permalink/netresearch/nr-llm:adr-047@0.35"
source: "Adr/Adr047FalTools.rst"
modified: "2026-09-16T22:09:16+00:00"
---

# ADR-047: FAL tools

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

## Context

The tool family covered records, schema, configuration and code — but not
the File Abstraction Layer. The recurring questions "which storages exist?",
"what is in this folder?", "find that PDF", "where is this image used?" and
"why is this image broken?" had a single narrow answer
(`read_fal_asset_meta`, one file by uid) and no navigation around it.

FAL output egresses to the external LLM provider, so the family needs one
shared containment: storage scoping. A single allow-list in one place beats
five copies of the same intersection logic.

## Decision

Five read-only built-in tools in the NEW group `files` — the first group
added since the initial taxonomy (ADR-043); third-party extensions remain
advised to use their extension key as group:

-   **`list_fal_storages`**

    The effective storages with uid, name, driver and status flags. The
    server-side base path is never part of the output.

-   **`browse_fal_folder`**

    One folder's subfolders (with file count) and files (size, MIME type),
    resolved exclusively through the storage API. Identifiers are
    storage-relative; entries are capped.

-   **`search_fal_files`**

    Substring search over file name and default-language metadata
    title/alternative. The model-chosen query is LIKE-escaped (literal
    `%`/`_`), missing files are excluded, results are capped.

-   **`get_fal_references`**

    `sys_file_reference` usages of one file as `table:uid (field)` —
    hidden references marked, deleted ones invisible. The output states
    explicitly that soft references (RTE links, plain URLs) are not tracked,
    so "no references" is never read as "safe to delete".

-   **`find_missing_files`**

    `sys_file` rows with `missing = 1` in the effective storages, with
    the total count always reported alongside the capped listing.

## Access model

All five share `FalStorageGate`: the configured storage allow-list
(default `[1]`), intersected for non-admins with the storages reachable
through their file mounts
(`BackendUserAuthentication::getFileStorages()`, verified identical on
13.4 and 14). Fail-closed: no backend user or an empty intersection yields
the neutral denial. A file or folder outside the gate is indistinguishable
from a missing one — the same neutrality contract as
`read_fal_asset_meta`. `get_fal_references` additionally drops rows
whose referencing table fails `TableReadAccessService` for non-admins.
`browse_fal_folder` enforces FOLDER-level file-mount boundaries on top:
for non-admins it sets `ResourceStorage::setEvaluatePermissions()`, so
the core mount checks apply to every folder read. The mounts themselves are
attached by the core `StoragePermissionsAspect` only inside a backend
request — in any other context (CLI, scheduler) non-admin folder access
therefore fails CLOSED (denied) rather than mount-blind.
Server paths never egress: listings use storage-relative identifiers, and
`list_fal_storages` omits the base path by design.

## Consequences

-   The FAL gap in the tool taxonomy is closed with navigation
    (storages → folders → files), search, usage and integrity tools.
-   The new `files` group can be disabled centrally, per configuration and
    per run like every other group (ADR-043).
-   `get_fal_references` reads `sys_file_reference` only; soft-reference
    tracking (`sys_refindex`) is a possible later extension if "is this
    file really unused?" needs a stronger answer.
