Admin guide
For the fleet program administrator: setting up devices and access codes, loading the fleet, changing checklists and rules, backups, resets and troubleshooting. Members should read the user guide.
1. How the system fits together
- The app runs in the browser. Each device keeps its own full copy of the records, so it works offline.
- The server (
api.php) only does two things: it accepts new records and hands out records a device hasn't seen yet. It needs a valid access code for both. - The data is plain text: one file per record type (
records/units.jsonl,inspections.jsonl,lockouts.jsonl…), one record per line. It lives in~/fvm-data, outside the public website folder, so it can't be downloaded from the web. - Records are append-only. Nothing is edited or deleted. Each change is a new record with a unique ID and a SHA-256 fingerprint, and current status (in service, locked out, PM due…) is worked out by replaying the records in order. This gives a complete audit trail.
- Rules are data too. Checklists, inventories, PM intervals and program rules are JSON files in
config/.
Full technical detail: DATA-MODEL.md.
2. First-time setup checklist
- Issue the department's access code(s) — section 3. Retire the test code once real data goes in.
- Review
config/program.jsonagainst your SOPs: lock-out steps, release roles, check-out purposes, the 12-hour pre-trip window — section 7. - Clear any test or demo data from the server and devices — section 9.
- Import the fleet roster from the spreadsheet — section 5.
- Place lock-outs for any units already out of service, and record the last known PM / service test dates so due dates start correctly.
- Hand out the device setup card and the access code.
- Set a backup routine — section 8.
3. Access codes
Give every person their own code (or one per shared station tablet). Everything a code uploads is stamped with its name, and the server logs each upload with the internet address it came from, so changes can be traced. A code can be cut off at once without re-keying anyone else.
Roles
| Role | Can |
|---|---|
| Member | Inspections, check-out / check-in, lock-outs and releases, work orders, PM records. Cannot add or change units — the server refuses those changes. |
| Officer | Everything a member can, plus add / edit units and import the fleet spreadsheet. |
| Administrator | Everything, plus issue, change and deactivate access codes and read the activity log. |
In the app (recommended)
- Connect your own device with an administrator code. Data & settings › Server then shows Manage access codes.
- Issue: enter the person's name, badge ID and role › Issue code. The code is shown once — copy it or press Print slip and hand it over in person. The server keeps only a fingerprint; a lost code can't be looked up, only replaced.
- Deactivate: press Deactivate on the person's row — for a member leaving, a lost phone, or a code that may have spread. Their devices show Access code rejected on the next sync; records already uploaded stay. Reactivate undoes it.
- Change role with the drop-down on the row.
- Recent activity lists every upload (with unit names for fleet changes), code change and refused code, with time and internet address. Use the filter to find, for example, every change to “Engine 9-1”.
You can't deactivate or demote the code you're signed in with, and at least one active administrator code must remain.
From the server shell (backup method)
cPanel › Terminal or SSH, in the program folder:
cd ~/fleet.spcfpd.org
php api.php list-keys # every code: id, name, role, active, last used
php api.php issue-key "Pat Rivera" officer 417 # new code (printed once): name, role, badge ID
php api.php deactivate-key "Pat Rivera" # cut off (name or id)
php api.php reactivate-key "Pat Rivera"
Use the shell if every administrator code is lost: php api.php issue-key "New admin" admin.
4. Setting up devices
- Give each member the device setup card (one printable page) and the access code.
- Server address is
api.php(the default) orhttps://fleet.spcfpd.org/api.php. - Settings — name, member ID, role, server address and code — are stored only in that browser. A new phone, a different browser or a private window starts blank.
- Shared station tablets: leave Your name blank so each member types their own name on each form.
- Data & settings also has Test (checks the code without syncing), Disconnect, and Re-download everything (rebuilds the device's copy from the server).
5. Loading and updating the fleet
From the spreadsheet template
- In the app: Fleet › Import / update from spreadsheet › Download Excel template. It has drop-downs, an Instructions tab and a Unit types tab.
- One row per vehicle. Only Unit name and Unit type are required. Equipment columns:
Y/Nonly where a unit differs from its type's defaults. - Choose the file (.xlsx or .csv). The preview marks each row New, Update, No change or Skipped with the reason. Nothing is saved until you press Import.
- Import on one device only. The others download the units by syncing. Importing the same new file on two devices creates every unit twice.
Updating later
- Download current fleet (CSV) gives the same columns plus a hidden System ID. Edit and re-import it — units match by System ID, then by name, so renames update in place.
- Blank cells keep the current value; they never erase data.
- Asset No. is always the last 6 characters of the VIN. A different value in the sheet is replaced, with a warning. Type one only for units with no VIN.
- Reading .xlsx needs internet the first time (the Excel reader loads from a public CDN). CSV always works offline.
From the district Apparatus Master
The converter turns the Apparatus Master workbook's Fleet Master tab into an import file. It maps Current Assignment to unit name, Chassis Type to unit type, Date Acquired to in-service date and Mileage to odometer, and carries pump hours, priority and notes into Notes:
cd ~/fleet.spcfpd.org
python3 tools/convert_apparatus_master.py ~/fvm-imports/ApparatusMaster.xlsx ~/fvm-imports/fleet-import.xlsx
~/fvm-imports, or the program's private/ folder, which the web server refuses to serve.6. Unit types, retiring and renaming
- Unit type decides the checklist sections, inventory and PM tasks. Types: structure engine, wildland engine, water tender, ladder / aerial, heavy rescue / squad, ambulance (ALS / BLS), medical response vehicle, medical ride share / NEMT, command, utility, and specialty (boat / UTV / trailer).
- Equipment fine-tunes it per unit — a quint is a ladder with a pump; a wildland engine may carry SCBA. Edit it on the unit's Edit page or with Y/N columns in the import.
- Reserve units aren't flagged for missed daily checks. Retired units drop off the board and unit pickers (shown under All incl. retired), lose their action buttons and can't be checked out; their history stays.
- Units are never deleted. Retire a unit that's sold or disposed of.
7. Checklists, inventory, PM and rules
File in config/ | Controls |
|---|---|
program.json | Inspection types and what each covers; result levels; lock-out reasons and required steps; energy sources; who may release a lock-out; check-out purposes; work-order statuses and priorities; the pre-trip window (12 h), expiry warning (30 days) and PM "due soon" thresholds (30 days / 500 mi / 25 h). |
apparatus.json | Unit types, their checklist modules, default equipment, daily-check interval and weekly interval; the equipment list. |
checklists.json | Pass / fail items by section. Flags: crit (failure recommends out of service), freq: "weekly", req (only shown if the unit has that equipment), als / bls, min + unit for readings. |
inventory.json | Stock lists with par levels, expiry tracking and controlled-substance sections. |
pm.json | PM and service-test tasks: interval (months / miles / hours), required equipment, and the standard cited. Edition references marked "verify edition" should be checked against the current NFPA documents your department has adopted. |
- Edit with any text editor (cPanel File Manager works), then check the JSON is valid — a missing comma stops the app from loading. Keep a copy of the file before editing.
- Raise the
versionin the file you changed. Each inspection stores thechecklists.jsonversion it was made with, so later audits know which checklist applied. - Changes reach devices the next time each one opens the app online. Old records are not changed.
- Keep item
ids stable — reports and work-order matching use them. Add new IDs rather than reusing old ones. - After changing unit types or equipment in
apparatus.json, rebuild the import template:python3 tools/make_fleet_template.py.
8. Backups and recovery
Server copy
Back up the whole ~/fvm-data folder — it's the master copy. Your host's account backups include it; for an extra copy:
tar czf ~/fvm-backup-$(date +%F).tar.gz -C ~ fvm-data
Download that file and keep it off the server. Restoring is copying the folder back.
From the app
- Data & settings › Backup file downloads every record on that device as one file. Add a passphrase to encrypt it (AES-256). Import file(s)… loads a backup on any device; records already present are skipped.
- Thumb drive / folder (Chrome or Edge on laptops / Android) keeps a full copy in the same file layout as the server, merging both ways. Useful as an offline master or for moving data without the internet.
- Spreadsheet exports (CSV) — fleet, inspections, defects found, inventory issues, lock-outs, check-outs, work orders, PM and service tests — for reports and audits.
9. Clearing test data / starting over
Because records are never deleted inside the app, clearing test data is done on the server and on each device:
- Server — move the record files into an archive folder (keeps
server.json, so access codes still work):A=~/fvm-data-archive/$(date +%F); mkdir -p "$A" flock ~/fvm-data/.lock sh -c "mv ~/fvm-data/records ~/fvm-data/ids.txt ~/fvm-data/seq.txt ~/fvm-data/fleet.json ~/fvm-data/manifest.json $A/ && mkdir -m 750 ~/fvm-data/records" - Every device that has used the app — Data & settings › Erase this device › Erase local data. This keeps the name, server address and access code. Do it after the server reset and before the device syncs again, otherwise it keeps showing old units and misses the first new records.
- Thumb-drive folders — delete the
FireVehicleMgmtfolder, or it brings old records back. - Import the fleet on one device, then open the app on the others.
10. Updating the program
- The app checks the server first every time it opens, so updated files reach devices on their next online visit; the offline copy is the fallback.
- When changing the program's JavaScript or CSS, raise
CACHEinsw.js(e.g.fvm-v4) and the?v=number onjs/app.jsinindex.html, so every device refreshes its offline copy. - The
.htaccessfile tells browsers not to cache scripts, styles or config, and blocksapi-config.phpand Python tools from the web. Keep it. - Data files are never touched by a program update.
11. Security and accountability
- Access codes are the gate. Anyone with a code can read the fleet records and add records; only officer and administrator codes can change the fleet roster. Issue one code per person and deactivate it the day they leave or lose a phone.
- Names typed on forms aren't verified, the access code is. Each record shows the name entered and, once uploaded, the name of the code that uploaded it (record view › “Uploaded with access code”). The activity log adds the internet address.
- Release authority is by role selection. The app requires a releasing role and records it, but can't check it. Officers should review the Records list for lock-out releases and overrides.
- Integrity. Each record's SHA-256 fingerprint is checked when it's opened. Integrity check failed means the record was altered after signing; investigate.
- The data folder is outside the web root and blocked by
.htaccess. The site must stay on HTTPS. - The records hold no patient information. Keep it that way — use run numbers, not names, in notes.
12. Troubleshooting
| Symptom | Fix |
|---|---|
| Access code rejected | Code mistyped (dashes count; capitals don't) or deactivated. Check Manage access codes; reactivate it or issue a new one. |
| Offline · n waiting for a long time | No connection, or the server is down. Open https://fleet.spcfpd.org/api.php?action=health — it should say "ok":true,"configured":true. Records wait safely on the device. |
| A unit or record is missing on one device | Save & sync now, then Re-download everything. If still missing, the device that created it hasn't uploaded yet — check that device's badge. |
| Units appear twice | The same import ran on two devices. Retire the duplicates (Status: Retired). |
| App shows "Could not load the configuration files" | A JSON file in config/ has a syntax error. Restore your copy or fix the file. |
| Excel import says it can't load the reader | The device is offline. Save the sheet as CSV and import that. |
| Wrong status after a lock-out release | Status follows the newest event. A new inspection or lock-out updates it; old records aren't changed. |
| Storage on a phone filling up | Very unlikely (records are small). If needed: back up, Erase local data, sync again. |
13. Moving to a database later
Each records/*.jsonl file maps one-to-one to a database table, and every record has a unique ID, so loading them is a straight insert that is safe to repeat. Replace api.php with an endpoint that speaks the same two calls (push and pull) and the app doesn't change. That stage is the right time to add per-person sign-in and role-checked lock-out release. Details: DATA-MODEL.md §6–7.