Skip to content

Status

What is built in tCAD, what is a named placeholder, and what has never been run. The complete and honest inventory: 24 placeholder tabs, no browser surface, no framework integrations, and nothing yet exercised in game with a player.

tCAD was a Cloudflare Workers web application until October 2026. It is now a FiveM resource, and that re-platform is in progress. This page is the inventory, and it is deliberately specific rather than reassuring.

Read it before you deploy. Nothing elsewhere in these docs describes a capability this page does not confirm.

⛔ Nothing in this resource has run in game with a player

This is the single most important line on the page, and it has to stay prominent precisely because everything around it is green.

What has been run:

  • a real FXServer, started on loopback, with tLib and tCAD loaded, and 35 domain assertions passing against both storage backends;
  • the built UI bundle, rendered and driven in Chromium 103.0.5058.0 — the Chromium FiveM's CEF actually is — asserting against the live DOM rather than a screenshot;
  • unit suites in TypeScript and five Lua suites in a real Lua VM;
  • every gate's negative control, each proven able to fail.

What has never been run, written and entirely unexercised:

The client scriptclient/cl_main.lua in its entirety
The keybindOpening the CAD with the key or /tcad from a game client
NUI focusSetNuiFocus, and therefore whether the cursor and keyboard behave
The NUI callbackThe panel's half of the round trip
The client→server hopA request leaving a real client and reaching the server
The assignment toastThe in-world notice a unit gets
The update checkWired for this release and not exercised before it

A headless Chromium is not CEF, and a console command has no player. The quantity of evidence listed above is not a substitute for a game client, and a reader skimming for confidence should stop here.

What is built and measured

The transportOne net event in, one reply out, one push channel. No HTTP, no origin, no cookies
The authority modelServer-side, every request, against ACE. An operation cannot be registered without naming a permission or declaring itself open — the registration raises otherwise
Both storage backendsJSON and SQL behind one contract, each passing the same 35 assertions in a real FXServer
Durable persistenceTemp file → fsync → rename, with a .bak rotation, through a Node bridge. Asserted separately from behaviour
The dispatch boardCalls, units, timelines, a map overlay, server-derived age and SLA marking
Ten department tabsListed below
Three administration sectionsOverview, Catalogues, Audit
Localisation467 strings across 22 sections, with the owner's overrides merged key by key
The export surface17 exports, with the forbidden-prefix refusal asserted at boot

Department tabs: ten built, twenty-four placeholders

A placeholder here is not a blank screen. Each one names the server operation it is waiting for, with the payload and the permission that operation should carry — so the ask is a work order rather than a shrug.

Built

ViewTabs
DispatchBoard
Law enforcementDashboard, NCIC, Warrants, Roster
Fire & EMSRoster
CivilianHome, Roster
BusinessRoster
JudicialWarrants queue, Roster

The law-enforcement Dashboard is real but partial, and it says so on itself: every tile is backed by an operation that exists, and the panel at its foot is an inventory of what a dashboard would normally carry and this one cannot. There is no "arrests this week" tile because nothing counts arrests.

The civilian Home tab is built; two of its four lists — licences and weapons — are not. Neither the records nor the staff-managed catalogue each needs exists.

⛔ Placeholders

ViewTabs not built
Law enforcementDuty board, Reports, Alerts (BOLOs), ALPR, Pre-plans, Fleet, Messages, Review
Fire & EMSDashboard, Duty board, ePCR, Narcotics, Pre-plans, Reports, Fleet, Messages, Review
CivilianAnalytics, Messages
BusinessDashboard, Queue, Messages, Settings
JudicialMessages

Four of those are worth calling out because the CAD has something adjacent and it is not the same thing:

  • Duty board. The Roster answers "who is on duty now". A duty board answers "who is scheduled for Friday night", and nothing on the server models it.
  • ALPR. The manual NCIC plate lookup is built. Automatic plate-reader hits are not — nothing produces them, and nothing delivers them.
  • Alerts / BOLOs. A vehicle carries a BOLO flag, settable by a holder of tcad.civilian.edit. The standing-alert record does not exist. The flag and the record are not the same thing.
  • Fleet. Not the same as a civilian vehicle registration. A fleet vehicle belongs to a department and is signed out by a unit; pointing this tab at the civilian registrations would show an officer their own car.

Messages appears in all six views and is one absence, not six: there is no messaging between units at all.

Administration: three built, six gaps

SectionState
OverviewBuilt. The inventory itself
CataloguesBuilt. One registry-driven editor for every catalogue the server publishes
AuditBuilt. Who changed which catalogue entry. ⛔ No retention — the log grows for ever
StructureNot built. Agencies and departments
LookupsNot built. Thirteen further lookup tables
GeographyNot built. Postals, zones, address flags
ApparatusNot built. The apparatus roll and its inspection checklists
ScheduledNot built. Recurring calls — and it needs a server-side ticker that does not exist
SettingsNot built. CAD policy, the active AOP, timers

Each unbuilt section is named on the Overview screen with the operations it needs.

⛔ No browser or desktop surface

Config.exposeWeb exists in config.lua and defaults to false. There is no surface behind it. Setting it to true today does not produce a usable page.

It is documented because it is in the file, and because turning it on would be a meaningful security decision if the surface existed — tLib's HTTP router adds no authentication of its own, so hidden is not authenticated. Until then, treat tCAD as in-game only.

⛔ No framework integrations

No ESX, no QBCore, no qbx_core, no integration file and no detection. What exists is two optional hooks — a display name and a callsign formatter — with worked examples for ESX and QBCore written into the file as comments. Integration has the full list of what tCAD does not integrate with, including inventory, billing, jail and Discord roles.

Known open questions

These are recorded as unknowns rather than as risks that have been priced.

Crash consistency of the write pathUnprovable from inside a process: demonstrating atomicity under power loss needs a crash, not a test. The .bak rotation is kept as the recovery path rather than replaced by confidence in the rename
The SQL adapter has no unit test coverageIt is the largest file in the resource. It is proven by the 35-assertion self-test against a live database, not by a suite. Stubbing the database exports would mean testing the stub
Overlay dismissal and focusEscape and an outside press dismiss no overlay, and focus never enters an opened one — so keyboard selection in a menu does not work, though pointer selection does. The symptoms are isolated and reproducible; the mechanism inside the UI stack is not understood, and no speculative patch was invented on the strength of a hypothesis
No audit retentionThe catalogue audit log grows without bound. The fix is a server-side timer with a configured age; a button an administrator presses is not a retention policy
Two map assets have no backupThe 3D map and its node data are large, are not in version control, and exist on one disk. This is a risk to the project, not to your install — a release archive ships them

How to read the gates

If you build from source, bun run verify is twelve stages. What they do and do not prove:

StageProves
lint, lint:solidStatic. lint:solid catches the Solid mistakes that are silent at runtime
buildThe bundle built. Close to nothing about whether it works
controlsEvery other gate is still able to fail. A gate nobody has watched fail is an assertion
typecheckTypes
test, test:luaPure logic, both languages. Nothing about rendering or the client hop
renderThe built bundle mounts and runs in Chromium 103, asserted against the DOM
screensThe department views mount, are not the placeholder, and each asks for its own data
admin-proofThe administration subtree renders and is gated by the server's answer
map:proofThe map actually draws — sampled from the composited canvas, so it spans fetch, decode and draw
waypoint-proofThe committed waypoint index snaps under a real synthetic press
smoke (separate)A real FXServer loads the resource and the domain behaves. Server-side only

None of the twelve is in-game evidence, and bun run verify says nothing about CEF, the keybind, or a player.

Was this page helpful?