Repository navigation
Bugfix Issue 1577 Codetracker Invalid Type Warnings
Bug fix — Issue #1577: unregistered Code Tracker types were persisted and generated Event Viewer warnings
The modern Code Tracker BFF accepted arbitrary integer values in the type
field. A crafted create request with type: 6 returned HTTP 200, persisted the
unknown type, and the following list/delete requests dereferenced missing system
metadata. PHP 8.3 recorded ten E_WARNING rows in Event Viewer from
tlCodeTracker.class.php:116,120,124,559,560.
Entry points:
- API:
http://localhost:8082/api/codetracker/index.php - Screen:
http://localhost:8082/gui/templates/codetracker/codetrackerView.html
- Authenticate as
adminwithcodetracker_managementright 51. - POST
{"name":"repro-1577-unknown","type":6,"cfg":""}to the API root. - Request the collection and the returned tracker detail.
- Delete the temporary tracker and inspect Event Viewer.
Measured result: create, list, and delete all returned HTTP 200. Type 6 was persisted even though the registered enabled systems were only type 1 (stash) and type 200 (github). Event Viewer contained ten new warnings generated by the legacy lookups; the browser showed no JavaScript exception.
- The BFF create route previously applied
intval()to any submitted type but never checked it againsttlCodeTracker::getSystems(). - The update route had the same lossy coercion and also did not distinguish an omitted partial-update type from an explicitly supplied value.
-
tlCodeTracker::create()andupdate()persisted the unchecked integer. - Serialization and delete handling then indexed
$systems[$type]and$implementations[$type]without a presence guard. Missing metadata produced the warnings instead of a client error. - The structured 400 response had no UI mapping, so adding BFF validation also required a localized client message.
Why it breaks now: the REST create/update surface was added during the Code Tracker modernization without the validation that the normal type selector makes implicit in the browser. Direct API clients could bypass that UI constraint.
Blast radius: authenticated managers could create an unusable row or change a valid row to an unusable type. Anonymous and view-only requests remained protected by the existing 401/403 gates; those checks execute before the new type validation.
The BFF is the trust boundary, so validation was added there rather than relying on the browser type selector.
-
api/codetracker/index.php:82requires request bodies to be top-level JSON objects. Scalar, list, and malformed bodies return HTTP 400{"status":"error","code":"invalid_body"}instead of reaching array access or producing a PHP error. -
api/codetracker/index.php:91accepts only JSON integers or canonical signed decimal strings. Booleans, floats, null, objects, arrays, and strings with trailing characters are rejected before lossy coercion. -
api/codetracker/index.php:102checks the normalized value againstgetSystems(['status' => 'enabled']). Unknown and disabled systems return HTTP 400 withcode=invalid_typeand the rejected integer. -
api/codetracker/index.php:200validates create input before persistence. -
api/codetracker/index.php:233validates an explicitly supplied update type before loading or changing the tracker. An omitted type remains a valid partial update and retains the stored type. -
gui/templates/codetracker/codetrackerView.html:397mapsinvalid_typetoct.msg.invalidType; the key exists in all 10 modern locale bundles.
Authorization ordering is unchanged: same-origin, authentication, page read rights, and management rights all run before body/type validation.
-
Harden only
tlCodeTracker::getByID()/serialization: this would suppress warnings but still persist an invalid type and leave list/delete behavior ambiguous. The BFF must reject invalid state at ingress. - Accept any registered type, including disabled systems: disabled systems are not usable and should not be creatable through the API. Validation uses the enabled-system set.
-
Coerce with
intval()before validation: values such astrue,1.5, or1junkcan alias a registered integer. Raw values are normalized strictly first. - Treat omitted PUT type as zero and reject it: that would break the existing rename/config-only partial update. Presence is checked separately.
- Return a hardcoded English PHP error: violates the BFF i18n contract and would expose implementation wording in the modern screen.
-
php -l api/codetracker/index.phpandgit diff --check: clean. - Inline JavaScript parses successfully; all 10 locale bundles pass
python3 -m json.tool. - Registered types 1 and 200 retain create, list, detail, update, and delete
behavior. Type transitions
1→200and200→1pass. - Unknown, disabled, malformed, boolean, float, null, and trailing-text type values return HTTP 400 without persistence.
- Omitted PUT type retains the stored type.
- Anonymous invalid create returns 401; a temporary user holding only
codetracker_viewreceives 403 on create and stored-token connection paths. - The create modal displays
Code Tracker type 999 is unknown.and remains open; the collection remains empty. - Event Viewer WARNING/ERROR count remains exactly 10, all created by the
pre-fix reproduction. Rows with
id > 11at levels 2/4: 0. - Regression suite in
tmp/TLU_Test_Cases.md: 8/8 PASS.
Before the fix, Event Viewer shows the ten PHP warnings produced by create, list, and delete operations against the unknown tracker type:

After the fix, the create modal keeps the user's input and displays the localized structured error; the unknown tracker is not added to the table:

-
api/codetracker/index.php— request-shape and enabled tracker-type guards. -
gui/templates/codetracker/codetrackerView.html— structured error rendering. -
gui/templates/i18n/{de,en,es,fr,it,ja,pt,ro,ru,zh}.json— localized message. -
tmp/TLU_Test_Cases.md— Issue #1577 regression suite. -
CHANGELOGand this Wiki/docs mirror.
Issue #1577 is fixed on fix/issue-1577 in commits 4497f11bb (fix) and
f25761c01 (regression suite). The original warning-producing path is rejected
before persistence, normal registered-type behavior is preserved, and no new
Event Viewer warning was generated.