Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
eab6d8e
docs: add admin web UI v1 design spec
aaronbrethorst Aug 24, 2026
7af641a
docs: revise admin UI spec per design review (24 findings)
aaronbrethorst Aug 24, 2026
22ac267
docs: add admin web UI implementation plan (18 tasks)
aaronbrethorst Aug 24, 2026
8fc0a19
feat: add users.active flag with soft-deactivate store support
aaronbrethorst Aug 24, 2026
4712a56
test: make DB-backed store tests clean up after themselves (FK-safe o…
aaronbrethorst Aug 24, 2026
c00f136
fix: reject deactivated users at login
aaronbrethorst Aug 24, 2026
2f0744d
feat: add vehicle activate/edit-without-reactivate and admin count qu…
aaronbrethorst Aug 24, 2026
aefb3d1
feat: add trip summaries, trail query, and active-trip-by-vehicle sto…
aaronbrethorst Aug 24, 2026
f764708
feat: add proxy-aware client IP/secure helpers and fail-closed login …
aaronbrethorst Aug 24, 2026
6993cf9
feat: accept session cookie in requireAuth when Authorization header …
aaronbrethorst Aug 24, 2026
55adfd8
feat: add admin session cookie layer, flash messages, and requireAdmi…
aaronbrethorst Aug 24, 2026
49a6a37
feat: session-authenticated admin UI shell with form login, logout, a…
aaronbrethorst Aug 24, 2026
4103a7a
feat: compose handler with CSRF protection, admin bootstrap, and defa…
aaronbrethorst Aug 24, 2026
de186e1
feat: vendor Leaflet and compiled Tailwind CSS; remove CDN dependencies
aaronbrethorst Aug 24, 2026
b0a591f
feat: add live vehicles admin endpoint joining tracker, labels, and a…
aaronbrethorst Aug 24, 2026
6ba0338
feat: add admin trips list and trip trail endpoints
aaronbrethorst Aug 24, 2026
aae8606
feat: dashboard renders live counts, feed health, and recent activity
aaronbrethorst Aug 24, 2026
763e9e7
feat: live map polls real vehicle data; trip trail mode
aaronbrethorst Aug 24, 2026
5a31425
feat: vehicle management pages with create, edit, deactivate, CSV export
aaronbrethorst Aug 24, 2026
d359145
feat: user management pages with CRUD, password change, and vehicle a…
aaronbrethorst Aug 24, 2026
e1a0e83
fix: map assignment conflict/FK errors in userAssignVehicle instead o…
aaronbrethorst Aug 24, 2026
ba71c18
feat: trip history page with filters, search, pagination, and trail l…
aaronbrethorst Aug 24, 2026
54ea2f2
test: admin route wiring coverage; docs: admin UI setup and operations
aaronbrethorst Aug 24, 2026
ffc6065
fix: prevent login limiter map-filling DoS; validate form fields befo…
aaronbrethorst Aug 24, 2026
6f6f21e
docs: note deactivation session window; stabilize trips ordering
aaronbrethorst Aug 24, 2026
18d07d5
fix: run map mode dispatch after let declarations to avoid TDZ Refere…
aaronbrethorst Aug 24, 2026
bf08bb0
simplify: extract shared JWT parse, password/status validation, nulla…
aaronbrethorst Aug 24, 2026
b347175
fix: apply code-review findings — last-admin guard, form validation, …
aaronbrethorst Aug 24, 2026
00009b7
fix: address CodeRabbit review — verify Tailwind binary SHA-256, tole…
aaronbrethorst Aug 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ on:
pull_request:
branches: [main]

permissions:
contents: read

jobs:
ci:
runs-on: ubuntu-latest
Expand All @@ -21,3 +24,14 @@ jobs:

- name: Test
run: go test ./...

- name: Verify committed Tailwind CSS is current
if: runner.os == 'Linux'
run: |
# Pinned to the same tailwindcss release (and SHA-256 from its
# sha256sums.txt) as Makefile's TAILWIND_VERSION — bump together.
curl -fsSL https://github.com/tailwindlabs/tailwindcss/releases/download/v4.2.0/tailwindcss-linux-x64 -o /tmp/tailwindcss
echo "8f65e2d21c675f1e8d265219979d17d10634c1f553a2f583265b7edb28726432 /tmp/tailwindcss" | sha256sum -c -
chmod +x /tmp/tailwindcss
/tmp/tailwindcss -i web/styles/input.css -o /tmp/admin.css --minify
diff -q /tmp/admin.css web/static/css/admin.css || { echo "web/static/css/admin.css is stale — run 'make css' and commit"; exit 1; }
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,6 @@ android/.gradle/
android/build/
android/app/build/
android/local.properties

# Pinned tool binaries (downloaded by `make css`; see Makefile)
.tools/
13 changes: 13 additions & 0 deletions .playwright-mcp/page-2026-08-24T10-03-39-024Z.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
- main [ref=e2]:
- generic [ref=e3]:
- paragraph [ref=e4]: Access
- heading "Transit Tracker" [level=1] [ref=e5]
- paragraph [ref=e6]: Fleet operations sign in
- generic [ref=e7]:
- generic [ref=e8]:
- generic [ref=e9]: Email
- textbox "Email" [ref=e10]
- generic [ref=e11]:
- generic [ref=e12]: Password
- textbox "Password" [ref=e13]
- button "Sign in" [ref=e14]
72 changes: 72 additions & 0 deletions .playwright-mcp/page-2026-08-24T10-03-55-024Z.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
- generic [ref=f1e2]:
- complementary [ref=f1e3]:
- generic [ref=f1e5]:
- generic [ref=f1e6]: 🚌
- generic [ref=f1e7]:
- paragraph [ref=f1e8]: Transit Tracker
- paragraph [ref=f1e9]: Fleet Operations
- navigation [ref=f1e10]:
- link "🗺 Live Map" [ref=f1e11] [cursor=pointer]:
- /url: /admin/map
- generic [ref=f1e12]: 🗺
- text: Live Map
- link "📈 Dashboard" [ref=f1e13] [cursor=pointer]:
- /url: /admin/dashboard
- generic [ref=f1e14]: 📈
- text: Dashboard
- link "🚌 Vehicles" [ref=f1e15] [cursor=pointer]:
- /url: /admin/vehicles
- generic [ref=f1e16]: 🚌
- text: Vehicles
- link "👥 Users" [ref=f1e17] [cursor=pointer]:
- /url: /admin/users
- generic [ref=f1e18]: 👥
- text: Users
- link "🕓 Trips" [ref=f1e19] [cursor=pointer]:
- /url: /admin/trips
- generic [ref=f1e20]: 🕓
- text: Trips
- paragraph [ref=f1e22]: v0.1.0
- main [ref=f1e23]:
- generic [ref=f1e24]:
- generic [ref=f1e25]:
- paragraph [ref=f1e26]: Transit control
- heading "Dashboard" [level=1] [ref=f1e27]
- button "Sign out" [ref=f1e30]
- generic [ref=f1e32]:
- generic [ref=f1e33]:
- generic [ref=f1e34]:
- paragraph [ref=f1e35]: Total Fleet
- paragraph [ref=f1e36]: "1"
- paragraph [ref=f1e37]: Registered vehicles
- generic [ref=f1e38]:
- paragraph [ref=f1e39]: Active Now
- paragraph [ref=f1e40]: "1"
- paragraph [ref=f1e41]: On route
- generic [ref=f1e42]:
- paragraph [ref=f1e43]: Drivers
- paragraph [ref=f1e44]: "0"
- paragraph [ref=f1e45]: Active
- generic [ref=f1e46]:
- paragraph [ref=f1e47]: Active Trips
- paragraph [ref=f1e48]: "1"
- paragraph [ref=f1e49]: In progress
- generic [ref=f1e50]:
- generic [ref=f1e51]: "Feed last updated: just now"
- generic [ref=f1e52]: "Staleness threshold: 5 min"
- generic [ref=f1e53]:
- generic [ref=f1e54]:
- heading "Recent Activity" [level=3] [ref=f1e55]
- link "View all →" [ref=f1e56] [cursor=pointer]:
- /url: /admin/vehicles
- table [ref=f1e58]:
- rowgroup [ref=f1e59]:
- row [ref=f1e60]:
- columnheader "Vehicle" [ref=f1e61]
- columnheader "Route" [ref=f1e62]
- columnheader "Last Update" [ref=f1e63]
- rowgroup [ref=f1e64]:
- row [ref=f1e65]:
- cell "Go Bus 1" [ref=f1e66]
- cell "route-5" [ref=f1e67]
- cell "just now" [ref=f1e68]
56 changes: 56 additions & 0 deletions .playwright-mcp/page-2026-08-24T10-03-59-900Z.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
- generic [ref=f2e2]:
- complementary [ref=f2e3]:
- generic [ref=f2e5]:
- generic [ref=f2e6]: 🚌
- generic [ref=f2e7]:
- paragraph [ref=f2e8]: Transit Tracker
- paragraph [ref=f2e9]: Fleet Operations
- navigation [ref=f2e10]:
- link "🗺 Live Map" [ref=f2e11] [cursor=pointer]:
- /url: /admin/map
- generic [ref=f2e12]: 🗺
- text: Live Map
- link "📈 Dashboard" [ref=f2e13] [cursor=pointer]:
- /url: /admin/dashboard
- generic [ref=f2e14]: 📈
- text: Dashboard
- link "🚌 Vehicles" [ref=f2e15] [cursor=pointer]:
- /url: /admin/vehicles
- generic [ref=f2e16]: 🚌
- text: Vehicles
- link "👥 Users" [ref=f2e17] [cursor=pointer]:
- /url: /admin/users
- generic [ref=f2e18]: 👥
- text: Users
- link "🕓 Trips" [ref=f2e19] [cursor=pointer]:
- /url: /admin/trips
- generic [ref=f2e20]: 🕓
- text: Trips
- paragraph [ref=f2e22]: v0.1.0
- main [ref=f2e23]:
- generic [ref=f2e24]:
- generic [ref=f2e25]:
- paragraph [ref=f2e26]: Transit control
- heading "Live Map" [level=1] [ref=f2e27]
- button "Sign out" [ref=f2e30]
- generic [ref=f2e33]:
- generic [ref=f2e34]:
- generic [ref=f2e35]:
- generic:
- generic:
- generic [ref=f2e36]:
- button "Zoom in" [ref=f2e37] [cursor=pointer]: +
- button "Zoom out" [ref=f2e38] [cursor=pointer]: −
- generic [ref=f2e39]:
- link "Leaflet" [ref=f2e40] [cursor=pointer]:
- /url: https://leafletjs.com
- text: "| © OpenStreetMap contributors © CARTO"
- generic [ref=f2e45]:
- generic [ref=f2e46]:
- paragraph [ref=f2e47]: "0"
- paragraph [ref=f2e48]: Active
- generic [ref=f2e50]:
- paragraph [ref=f2e51]: "0"
- paragraph [ref=f2e52]: Routes
- generic: Active
- heading "Fleet Status" [level=3] [ref=f2e59]
56 changes: 56 additions & 0 deletions .playwright-mcp/page-2026-08-24T10-04-38-299Z.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
- generic [ref=f3e2]:
- complementary [ref=f3e3]:
- generic [ref=f3e5]:
- generic [ref=f3e6]: 🚌
- generic [ref=f3e7]:
- paragraph [ref=f3e8]: Transit Tracker
- paragraph [ref=f3e9]: Fleet Operations
- navigation [ref=f3e10]:
- link "🗺 Live Map" [ref=f3e11] [cursor=pointer]:
- /url: /admin/map
- generic [ref=f3e12]: 🗺
- text: Live Map
- link "📈 Dashboard" [ref=f3e13] [cursor=pointer]:
- /url: /admin/dashboard
- generic [ref=f3e14]: 📈
- text: Dashboard
- link "🚌 Vehicles" [ref=f3e15] [cursor=pointer]:
- /url: /admin/vehicles
- generic [ref=f3e16]: 🚌
- text: Vehicles
- link "👥 Users" [ref=f3e17] [cursor=pointer]:
- /url: /admin/users
- generic [ref=f3e18]: 👥
- text: Users
- link "🕓 Trips" [ref=f3e19] [cursor=pointer]:
- /url: /admin/trips
- generic [ref=f3e20]: 🕓
- text: Trips
- paragraph [ref=f3e22]: v0.1.0
- main [ref=f3e23]:
- generic [ref=f3e24]:
- generic [ref=f3e25]:
- paragraph [ref=f3e26]: Transit control
- heading "Live Map" [level=1] [ref=f3e27]
- button "Sign out" [ref=f3e30]
- generic [ref=f3e33]:
- generic [ref=f3e34]:
- generic [ref=f3e35]:
- generic:
- generic:
- generic [ref=f3e36]:
- button "Zoom in" [ref=f3e37] [cursor=pointer]: +
- button "Zoom out" [ref=f3e38] [cursor=pointer]: −
- generic [ref=f3e39]:
- link "Leaflet" [ref=f3e40] [cursor=pointer]:
- /url: https://leafletjs.com
- text: "| © OpenStreetMap contributors © CARTO"
- generic [ref=f3e45]:
- generic [ref=f3e46]:
- paragraph [ref=f3e47]: "0"
- paragraph [ref=f3e48]: Active
- generic [ref=f3e50]:
- paragraph [ref=f3e51]: "0"
- paragraph [ref=f3e52]: Routes
- generic: Active
- heading "Fleet Status" [level=3] [ref=f3e59]
63 changes: 63 additions & 0 deletions .playwright-mcp/page-2026-08-24T10-05-09-595Z.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
- generic [ref=f4e2]:
- complementary [ref=f4e3]:
- generic [ref=f4e5]:
- generic [ref=f4e6]: 🚌
- generic [ref=f4e7]:
- paragraph [ref=f4e8]: Transit Tracker
- paragraph [ref=f4e9]: Fleet Operations
- navigation [ref=f4e10]:
- link "🗺 Live Map" [ref=f4e11] [cursor=pointer]:
- /url: /admin/map
- generic [ref=f4e12]: 🗺
- text: Live Map
- link "📈 Dashboard" [ref=f4e13] [cursor=pointer]:
- /url: /admin/dashboard
- generic [ref=f4e14]: 📈
- text: Dashboard
- link "🚌 Vehicles" [ref=f4e15] [cursor=pointer]:
- /url: /admin/vehicles
- generic [ref=f4e16]: 🚌
- text: Vehicles
- link "👥 Users" [ref=f4e17] [cursor=pointer]:
- /url: /admin/users
- generic [ref=f4e18]: 👥
- text: Users
- link "🕓 Trips" [ref=f4e19] [cursor=pointer]:
- /url: /admin/trips
- generic [ref=f4e20]: 🕓
- text: Trips
- paragraph [ref=f4e22]: v0.1.0
- main [ref=f4e23]:
- generic [ref=f4e24]:
- generic [ref=f4e25]:
- paragraph [ref=f4e26]: Transit control
- heading "Live Map" [level=1] [ref=f4e27]
- button "Sign out" [ref=f4e30]
- generic [ref=f4e33]:
- generic [ref=f4e34]:
- generic [ref=f4e35]:
- button "🚌" [ref=f4e36] [cursor=pointer]
- generic:
- generic:
- generic [ref=f4e40]:
- button "Zoom in" [ref=f4e41] [cursor=pointer]: +
- button "Zoom out" [ref=f4e42] [cursor=pointer]: −
- generic [ref=f4e43]:
- link "Leaflet" [ref=f4e44] [cursor=pointer]:
- /url: https://leafletjs.com
- text: "| © OpenStreetMap contributors © CARTO"
- generic [ref=f4e49]:
- generic [ref=f4e50]:
- paragraph [ref=f4e51]: "1"
- paragraph [ref=f4e52]: Active
- generic [ref=f4e54]:
- paragraph [ref=f4e55]: "1"
- paragraph [ref=f4e56]: Routes
- generic: Active
- generic [ref=f4e61]:
- heading "Fleet Status" [level=3] [ref=f4e63]
- generic [ref=f4e65]:
- generic [ref=f4e66]: 🚌
- generic [ref=f4e67]:
- paragraph [ref=f4e68]: Go Bus 1
- paragraph [ref=f4e69]: route-5 · Go Driver
78 changes: 78 additions & 0 deletions .playwright-mcp/page-2026-08-24T10-05-27-277Z.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
- generic [ref=f5e2]:
- complementary [ref=f5e3]:
- generic [ref=f5e5]:
- generic [ref=f5e6]: 🚌
- generic [ref=f5e7]:
- paragraph [ref=f5e8]: Transit Tracker
- paragraph [ref=f5e9]: Fleet Operations
- navigation [ref=f5e10]:
- link "🗺 Live Map" [ref=f5e11] [cursor=pointer]:
- /url: /admin/map
- generic [ref=f5e12]: 🗺
- text: Live Map
- link "📈 Dashboard" [ref=f5e13] [cursor=pointer]:
- /url: /admin/dashboard
- generic [ref=f5e14]: 📈
- text: Dashboard
- link "🚌 Vehicles" [ref=f5e15] [cursor=pointer]:
- /url: /admin/vehicles
- generic [ref=f5e16]: 🚌
- text: Vehicles
- link "👥 Users" [ref=f5e17] [cursor=pointer]:
- /url: /admin/users
- generic [ref=f5e18]: 👥
- text: Users
- link "🕓 Trips" [ref=f5e19] [cursor=pointer]:
- /url: /admin/trips
- generic [ref=f5e20]: 🕓
- text: Trips
- paragraph [ref=f5e22]: v0.1.0
- main [ref=f5e23]:
- generic [ref=f5e24]:
- generic [ref=f5e25]:
- paragraph [ref=f5e26]: Transit control
- heading "Live Map" [level=1] [ref=f5e27]
- button "Sign out" [ref=f5e30]
- generic [ref=f5e33]:
- generic [ref=f5e34]:
- generic [ref=f5e35]:
- generic:
- generic:
- img:
- generic [ref=f5e36] [cursor=pointer]
- generic:
- button "🚌" [ref=f5e37] [cursor=pointer]
- button "🚌" [ref=f5e41] [cursor=pointer]
- generic:
- generic:
- generic [ref=f5e45]:
- button "Zoom in" [disabled] [ref=f5e46]: +
- button "Zoom out" [ref=f5e47] [cursor=pointer]: −
- generic [ref=f5e48]:
- link "Leaflet" [ref=f5e49] [cursor=pointer]:
- /url: https://leafletjs.com
- text: "| © OpenStreetMap contributors © CARTO"
- generic [ref=f5e54]:
- generic [ref=f5e55]:
- paragraph [ref=f5e56]: "0"
- paragraph [ref=f5e57]: Active
- generic [ref=f5e59]:
- paragraph [ref=f5e60]: "0"
- paragraph [ref=f5e61]: Routes
- generic: Active
- generic [ref=f5e66]:
- heading "Trip Detail" [level=3] [ref=f5e68]
- generic [ref=f5e70]:
- paragraph [ref=f5e71]: Go Bus 1
- generic [ref=f5e72]:
- strong [ref=f5e73]: Driver
- text: Go Driver
- generic [ref=f5e74]:
- strong [ref=f5e75]: Route
- text: route-5
- generic [ref=f5e76]:
- strong [ref=f5e77]: Status
- text: active
- generic [ref=f5e78]:
- strong [ref=f5e79]: Started
- text: 2026-08-24T03:02:48.4744-07:00
Loading
Loading