ADR-044: Error-analysis tools with fail-closed guards
- Status
-
Accepted
- Date
-
2026-07-09
- Authors
-
Netresearch DTT GmbH
Context
The agent can read content and configuration (ADR-042), but the debugging use cases admins actually bring to the playground — "why does this URL answer 500", "how do I fix this PHP error" — need capabilities the tool set lacked: reading the TYPO3 file logs with the failing source code, reading arbitrary project files, searching the code base, and probing a frontend URL. All four egress host-level data to an external LLM provider and take model-chosen (attacker-influenceable) arguments, so each needs a hard, fail-closed containment story.
Decision
Four admin-only tools, two shared guards.
Tools
get_last_exception(groupcode)- Newest error-level entries from the TYPO3 file logs, with the parsed
stack trace and ±6 lines of source context inlined for up to three
project-local frames (vendor/core frames are listed, not expanded).
indexsteps back through older errors,searchfilters. read_source(groupcode)- Line-ranged, line-numbered read of one project file (default 60, max 200 lines).
search_code(groupcode)- Literal-substring (opt-in regex) search over project source files —
a pure-PHP walk, no shell-out — returning
path:linehits under a hard budget (20 000 files / 5 s), reported when exhausted. probe_url(groupsystem)- One GET against the instance's own frontend: status, key headers, timing, a 2 KB tag-stripped body excerpt — and on a 5xx the newest error-log entries from the probe's ±30 s window are appended through the same log parser, so probe and cause arrive in one result.
Consequences
- The "analyse the error" loop closes:
probe_url→ correlated log entry →get_last_exception(full trace + code) →read_source/search_codefor the fix site — without leaving the playground. - All four tools are
requiresAdmin() = trueand live behind the ADR-043 group cascade (new groupcode;probe_urljoinssystem), so one central toggle silences the whole family. settings.phpand other credential carriers are structurally unreadable even for admins — the guard has no bypass parameter by design.probe_urlperforms real frontend requests (cache warm-up, log entries, load); it is deliberately GET-only, single-request, 15 s-capped.