TestLink Error Page Modernized - sebiboga/testlink-upgraded GitHub Wiki
Legacy controller error.php (the root-level general purpose error page) + Smarty
template gui/templates/dashio/feedback/error.tpl.
With the TODO ledger empty and every ASIDE entry already mapped to a modern
.html + BFF, the largest remaining legacy gap was the only top-level page that
still rendered legacy Smarty HTML: error.php. It is reached from
lib/functions/csrf.php — csrfguard_start() redirects to error.php?code=1
(No CSRFName found…) or error.php?code=2 (Invalid CSRF token) — and from
any stale ?code= deep link. It required no session (it never called
testlinkInitPage()), so an anonymous visitor must still be able to open it.
| Layer | File |
|---|---|
| Screen |
gui/templates/feedback/error.html (Dashio standalone HTML/JS/CSS) |
| BFF |
api/error/index.php (GET ?code=<int>, session-optional) |
| Legacy |
error.php → GET/HEAD-only 302 shim (the renderer is gone) |
| Wiring |
$actions->errorPage in lib/functions/common.php; both lib/functions/csrf.php redirects switched to the modern screen |
| i18n |
err.* (12 keys) + footers.errorPage in all 10 bundles |
-
Message mapping — code
1→csrf_name_missing/err.csrfMissing("No CSRFName found, probable invalid request."); code2→csrf_token_invalid/err.csrfInvalid("Invalid CSRF token"); any other or missing code →generic/err.generic("Rocket Raccoon is watching You", the legacy default, TICKET 4977). -
No rights gate — like the legacy page, any visitor may open it; the BFF
returns the session state (
auth.logged_in) so the screen offers Home to a session holder and Home + Go to Login to an anonymous visitor. -
Deep links — legacy
error.php?code=Nstill resolves (302 togui/templates/feedback/error.html?code=N). - State cards for 400/403/405/500 with the BFF machine
codeshown; loading spinner, Retry, locale switcher, footer.
-
?code[]=x(array) and non-numericcode→400 INVALID_CODEat the API andcode=0in the shim (the #1886 / #1893 defect class: never coerced to a sink). - JSON headers and method/code validation are sent before the DB connect; the DB is connected lazily (guarded) only for the login fallback, so a DB outage still yields clean JSON (this is the error page) and never echoes driver text.
-
Cache-Control: no-store,X-Content-Type-Options: nosniff, JSON-only. - Non-GET/HEAD →
405 METHOD_NOT_ALLOWED; foreign-origin POST →403viabffSameOriginGuard(). - Stable machine
error_codereturned alongside the localizedmessage_key, so callers/tests assert the path without matching English text. - The message is localized client-side (i18n) — the legacy page was hardcoded English regardless of the user's locale.
-
API (
tmp/vy_1895.sh, 21/21 PASS): shim redirects (code 2 / none / array / non-numeric), 405 POST, HEAD, BFF mapping for codes 1/2/99/none, 400 on array/non-numeric, 403 foreign-origin POST, 405 same-origin POST, anonauth.logged_in=false,$actions->errorPagepresent, bothcsrf.phpredirects switched, no Smarty render left inerror.php, 13 keys × 10 bundles,ai/verify_i18n_coverage.shPASS. -
Browser (headless Chrome): logged-in
?code=1→ 302 → "No CSRFName found, probable invalid request." + switcher; RO fully localized ("Nu s-a găsit CSRFName, cerere probabil invalidă.");?code=99→ "Rocket Raccoon is watching You"; anonymous isolated context shows "Go to Login"; console clean. - Event Viewer: 0 new ERROR/WARNING (only the admin LOGIN audit row).
- Suite
## Issue #1895appended totmp/TLU_Test_Cases.md; suite gateTLU_REQUIRE_SUITE="Issue #1895" bash ai/verify_test_suites.shPASS.
CSRF failure (code 1, logged in) — the legacy default message:

Localized (Română) — the message, actions and footer all translate:

Generic code (unknown code → "Rocket Raccoon is watching You"):

Anonymous visitor — "Go to Login" is offered alongside Home:
