Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
365 commits
Select commit Hold shift + click to select a range
46f1fbc
CI: phpunit-only job probes an API route for readiness
edwh Jul 16, 2026
8fa9053
phpunit: withoutVite() globally; CI: warm up Discourse before phpunit
edwh Jul 16, 2026
d273802
Plan: four-job CI topology fully green
edwh Jul 16, 2026
75ac046
Phase F prep: make resources/global self-contained (cross-ref traps 1-3)
edwh Jul 16, 2026
ee7d968
F2-3: leaf widget independent of the Vue 2 tree
edwh Jul 16, 2026
a52e5e2
Checklist: F2-3 done
edwh Jul 16, 2026
bf7feb1
Consent-completion page + middleware gate; dev-server allowedHosts; l…
edwh Jul 16, 2026
00babbf
Checklist: F execution batches + G6 via Playwright
edwh Jul 16, 2026
2a7f0a1
C7/D6/E5 e2e suites + the client bugs they caught
edwh Jul 16, 2026
ca61305
F2-4/F2-5: six deep-link routes become thin SPA redirectors (81 tests…
edwh Jul 16, 2026
449c800
Translations check: count SPA usage; toast invite redirect flags
edwh Jul 17, 2026
9aeec96
Lint: drop unused deleteNetworkTagByRow e2e helper
edwh Jul 17, 2026
7871a6f
Devices store: mutate the reactive entry, not the raw fallback object
edwh Jul 17, 2026
8f01ffc
Group map page: Leaflet port of the RES-1995 map (B7)
edwh Jul 17, 2026
0d64034
Taskfile: forward CLI_ARGS to the client Playwright runner
edwh Jul 17, 2026
c0c06d4
Plan: B7/C7/D6/E5 complete; F2 checklist refinements from code verifi…
edwh Jul 17, 2026
07e6abd
Phase F: Laravel becomes API-only; retire the Blade + Vue 2 frontend
edwh Jul 18, 2026
e723aa6
Plan: Phase F cutover complete (07e6abd7cc)
edwh Jul 18, 2026
ede3a3f
G6 visual review: fix broken profile pages, tab i18n key, missing assets
edwh Jul 18, 2026
837d454
Security review: fix device IDOR, open redirect, reset replay, event …
edwh Jul 18, 2026
80674e3
Fix event-visibility gate to resolve bearer/token auth, not just web …
edwh Jul 18, 2026
eb95936
e2e: approve the group before a non-member follows it from its event …
edwh Jul 18, 2026
feabd81
Client CSS: port the brand .panel styles into the global layer (G6 D1)
edwh Jul 18, 2026
8dc51b8
Client: dashboard + fixometer live parity (G6 D2/D3) + CSS consolidation
edwh Jul 18, 2026
be90db0
Retire the legacy global jQuery JS (resources/global/js/app.js)
edwh Jul 18, 2026
a36358b
Client: restore the dashboard "Add Data" group->event picker (G6)
edwh Jul 18, 2026
04f31ec
Drop 4 unused dashboard sidebar lang keys (fix testCheckTranslations)
edwh Jul 18, 2026
109e6c7
Fix build-client vitest: mock fetchMyEvents in dashboard test, unflak…
edwh Jul 18, 2026
291d795
Move admin preview-deploy off Blade to /api/v2 + the SPA
edwh Jul 18, 2026
59f62e5
Fly deploy: build + serve the Nuxt SPA as the origin (fixes localhost…
edwh Jul 18, 2026
974f0ab
Dockerfile.fly: Node 22 (Nuxt 4 needs >=22), was 18 → build failed
edwh Jul 18, 2026
f103de2
Make Sanctum personal_access_tokens migration idempotent (fixes previ…
edwh Jul 18, 2026
895da65
Guard sso_tickets create migration too (same prod drift as personal_a…
edwh Jul 18, 2026
67597e7
Stop the SPA redirect loop: root -> Nitro, catch-all 404s (not redire…
edwh Jul 18, 2026
6ffff0e
Landing page: rebuild to match the live marketing layout
edwh Jul 18, 2026
aa50cf9
Add a repeatable dev-vs-live visual parity harness + audit findings
edwh Jul 18, 2026
982a848
Parity harness: compare new-dev vs old-dev instead of production
edwh Jul 18, 2026
08bf31a
Record 105 confirmed visual parity findings (new-dev vs old-dev)
edwh Jul 18, 2026
773625c
Fix the auth-gating defect class, and pin the auth model in tests
edwh Jul 19, 2026
f180f06
Fix consent page: swapped GDPR labels, age floor, missing intro copy
edwh Jul 19, 2026
030c84f
Restore the Add-event CTA and fix the capped host-permission check
edwh Jul 19, 2026
11c9257
Fixometer records table: keep headers when empty, collapse filters by…
edwh Jul 19, 2026
e389604
Logged-out chrome: impact-stats header + language-bar footer on plain…
edwh Jul 19, 2026
28ebe06
Login panel: black panel links (global), restore "Find out more" CTA
edwh Jul 19, 2026
68460f3
Dashboard: fix "See all groups" link rendering a raw i18n key
edwh Jul 19, 2026
5c1e493
Rebuild registration as the legacy 4-step wizard with DB-backed skills
edwh Jul 19, 2026
87be9bc
Cap container width to Bootstrap 4's 1140px (was BS5's 1320px)
edwh Jul 19, 2026
f3a7a9c
Add the cookie-consent banner (was missing on every page)
edwh Jul 19, 2026
a3b9a07
Add the moderation-queue component + store (Admin/NetworkCoordinator)
edwh Jul 19, 2026
042ea3b
Group edit: relabel the delete-that-archives control to "Archive group"
edwh Jul 19, 2026
7deed2a
Admin PR-preview-deploy tooling: move off the Blade web route to /api…
edwh Jul 19, 2026
2b0d80d
Wire the moderation queues into /party, /group/map and /networks/{id}
edwh Jul 19, 2026
25d6161
Group view: relabel delete-that-archives to "Archive" (same as group/…
edwh Jul 19, 2026
4a7b980
Dashboard: rebuild to match the legacy layout, order, and panels
edwh Jul 19, 2026
a68bb7a
web catch-all: return a 404 response instead of abort(404)
edwh Jul 19, 2026
d418ffd
CI e2e-client: probe /api/v2/session for readiness, not "/"
edwh Jul 19, 2026
3edec3a
e2e: dismiss the dashboard onboarding modal after login
edwh Jul 19, 2026
d3de370
e2e: clear the session in login() so re-login works with the guest gate
edwh Jul 19, 2026
fdb6434
Navbar: drop the duplicate language selector (footer keeps it)
edwh Jul 19, 2026
98a5646
Moderation store: DRY the two queue fetchers into one helper
edwh Jul 19, 2026
1b29a41
Record final re-diff findings (61 non-by-design gaps)
edwh Jul 19, 2026
be722f9
group/nearby: show the set-a-location prompt when the user has no tow…
edwh Jul 19, 2026
5c6bb65
LogoStatsHeader: centre the logo on mobile (stats bar is desktop-only)
edwh Jul 19, 2026
8bc2004
Cookie banner + nav captions: restore legacy Bootstrap-4 styling
edwh Jul 19, 2026
ae3fffa
Dashboard: add the talk doodle to the What's happening heading
edwh Jul 19, 2026
b06364a
Fixometer: legacy +/- filter glyph and light Powered/Unpowered tabs
edwh Jul 19, 2026
8117d29
Re-diff findings: record resolution status for the 2026-07-19 pass
edwh Jul 19, 2026
d471188
Fixometer Repair Records: full feature parity (sort, info rows, two-c…
edwh Jul 19, 2026
83f53d1
Dashboard: live Talk topics in the "What's happening" section
edwh Jul 19, 2026
5f4d69d
Parity: restore "Other groups nearby" tab + footer language-switcher …
edwh Jul 19, 2026
0b6a58c
Dashboard: hide the Add Data card when there's no group+event to add …
edwh Jul 19, 2026
5db7b85
Groups: sort affordance on all columns + restore the heading doodle
edwh Jul 19, 2026
83fe4e5
Login: keep "Create an account" on one line on mobile
edwh Jul 19, 2026
e945653
Dashboard: mobile-collapsible section cards (legacy CollapsibleSection)
edwh Jul 19, 2026
6b45bf3
Group view: restrict the heading image to 67px wide, matching develop
edwh Jul 19, 2026
64ec32f
Group view: render stats as styled cards + add Environmental impact +…
edwh Jul 19, 2026
2318c66
Group view: About | Volunteers two-column layout
edwh Jul 19, 2026
7a21d8b
Detail-page parity: close the 35-gap sweep vs develop (event/network/…
edwh Jul 19, 2026
85a19b8
Detail pages: expose + show the last deferred data (Talk link, networ…
edwh Jul 19, 2026
02eb384
Networks: add the "Download event list" export link (last detail-page…
edwh Jul 19, 2026
4077451
Parity: close 10 client-only gaps from the full-page develop sweep
edwh Jul 19, 2026
cb27b19
Parity: close 5 deferred client-only gaps (admin/create affordances)
edwh Jul 19, 2026
749bd27
Swagger: fix orphaned v2 security scheme + add shared error components
edwh Jul 19, 2026
c40e6b7
Swagger: document the coverage-hole controllers from the API audit
edwh Jul 19, 2026
8ed44d3
Parity: password-reset token validation+email and consent newsletter …
edwh Jul 19, 2026
a52bbd8
Parity: admin user management — create, edit/reset/delete another use…
edwh Jul 20, 2026
0d6d8e5
Parity: per-event stats + filters on the events landing (gaps 17,18)
edwh Jul 20, 2026
d7299cd
Hygiene: delete dead legacy controllers + fix Alert cache invalidation
edwh Jul 20, 2026
20b4764
Swagger: complete per-endpoint docs across the v2 API surface
edwh Jul 20, 2026
e70676b
Swagger/osteel: JSON errors on /api/v2 + correct create-vs-update id …
edwh Jul 20, 2026
a3f6cdc
Hygiene: hoist duplicated getUser() to base controller + document leg…
edwh Jul 20, 2026
af36e46
Hygiene: extract Fixometer::generateHash() for the 24-char token
edwh Jul 20, 2026
1e32f4d
Hygiene: extract requireAdministrator() base helper for the admin gate
edwh Jul 20, 2026
565bd94
Parity (visual): rebuild dashboard + group-view to match develop
edwh Jul 20, 2026
7484985
Parity wave 2: events, groups, fixometer, profile, admin, networks, f…
edwh Jul 20, 2026
6a62fa6
Fix: role and cluster names rendered raw instead of translated
edwh Jul 20, 2026
154483f
Parity: events cluster residuals + attendee email exposure
edwh Jul 20, 2026
b5026b7
Parity: revert 11 admin regressions to this branch's own baseline
edwh Jul 20, 2026
719db94
API: expose discourse_group, per-event group stats, dashboard archive…
edwh Jul 20, 2026
1242901
Parity: wire the canvas share image to the event CO2 card
edwh Jul 20, 2026
bd4a353
i18n: consolidate duplicate "Share this" key onto partials.share_this
edwh Jul 20, 2026
18b75d1
Add parity-fixtures.php to restore capture data after phpunit runs
edwh Jul 20, 2026
ba01038
API: serve share-image backgrounds via /api/v2 so the canvas stays un…
edwh Jul 20, 2026
c1528dd
API: expose image_idxref + auto_approve, fix N+1 on network events
edwh Jul 20, 2026
04fdc5e
Fix: readonly inputs rendered as editable (Bootstrap 5 regression)
edwh Jul 20, 2026
ecce81a
Parity: networks panels + headers, event-create toolbar + date field
edwh Jul 20, 2026
2f01569
Fix: moderation queues silently empty (double-unwrapped response)
edwh Jul 20, 2026
7570385
Parity: navbar shows avatar only, matching develop
edwh Jul 20, 2026
27808eb
a11y: label the account-menu toggle, matching develop
edwh Jul 20, 2026
33cd386
API: fix a second N+1 on event listings; verify image_idxref + auto_a…
edwh Jul 20, 2026
2d1d25e
Fix parity fixtures: create the default 'restarters' network
edwh Jul 20, 2026
660a39b
API: fix withCount silently discarded by a later select()
edwh Jul 20, 2026
d09ff0f
Mobile parity: groups list restacks, and moderation sits above the he…
edwh Jul 20, 2026
80cbc97
Mobile parity: fixometer filter rail and Powered/Unpowered accordion
edwh Jul 20, 2026
3623116
Parity harness: suppress the cookie notice before page scripts run
edwh Jul 20, 2026
fe50364
Mobile parity: group stats use develop's two responsive grids
edwh Jul 20, 2026
3b55301
API: event images and discourse_thread; two "gaps" were already closed
edwh Jul 20, 2026
d262a6a
Parity: drop admin additions the pre-Phase-F baseline never had
edwh Jul 20, 2026
a4e7d90
Parity: remove archive UI from the group edit form
edwh Jul 20, 2026
eccc6e6
Docs: retract the "develop has no bottom nav" finding
edwh Jul 20, 2026
dcb1641
Parity: hide the mobile bottom nav on scroll, as develop does
edwh Jul 20, 2026
08f2bd6
Parity harness: cover the 9 never-captured comparable pages
edwh Jul 20, 2026
45d1287
Parity (visual): restore the action dropdown caret, uppercase and nowrap
edwh Jul 20, 2026
48e00d3
Parity harness: bound the settle wait and raise the suite timeout
edwh Jul 20, 2026
ca0f54b
Parity: event form auto-approve copy, creation confirmation, Duplicate
edwh Jul 20, 2026
b9b6bd5
Parity harness: support per-system paths; recover 2 more pages
edwh Jul 20, 2026
e565478
Fix: share-stats embed URLs must be absolute, not root-relative
edwh Jul 20, 2026
52cf230
Parity harness: fail on blank captures instead of emitting them
edwh Jul 20, 2026
8dcc66b
Findings: record the coverage gap, 3 harness defects, and event-view …
edwh Jul 20, 2026
70044bc
Event view: photos gallery, talk-thread link, inline headcounts, add …
edwh Jul 20, 2026
fcaf41e
Parity (visual): restore the event page's tab panels and stat treatments
edwh Jul 20, 2026
d8702e2
Fix: primary stat card lost the cascade, hiding its count entirely
edwh Jul 20, 2026
776360a
Findings: resolve the event-view diffs; retract two that were wrong
edwh Jul 20, 2026
01b17d3
Findings: 5 real diffs on the network view page
edwh Jul 20, 2026
80679cb
Parity: network page Groups section is a sentence, not a groups browser
edwh Jul 20, 2026
3b21dfe
Parity: moderation queue renders GroupsTable, as develop's does
edwh Jul 20, 2026
0ff83bd
Findings: network moderation diffs resolved; record the missing edit …
edwh Jul 20, 2026
9b35284
Parity (visual): apply .table-section panel to every table develop pa…
edwh Jul 20, 2026
7dae3cd
Parity: build the missing /networks/[id]/edit page
edwh Jul 20, 2026
638e285
Parity: admin Delete moves to the edit form, where develop has it
edwh Jul 20, 2026
e70b214
Parity: restore the network dropdown's "View groups" item and its gate
edwh Jul 20, 2026
7f93ed7
Findings: 3 gaps on /group, incl. a likely-false API blocker
edwh Jul 20, 2026
32da815
Parity: /group uses the real moderation table, and drops the 5-group cap
edwh Jul 20, 2026
e199275
Correct the UserAPI comment that outlived its own slice
edwh Jul 20, 2026
0cfa021
Parity: every moderation queue renders develop's real table; delete t…
edwh Jul 20, 2026
d0d5fdc
Parity: event description gets develop's mobile collapse; clear two s…
edwh Jul 20, 2026
d0f3e80
Findings: 5 diffs on the event edit page
edwh Jul 20, 2026
f2c5783
Parity: event date shows develop's format, not raw ISO
edwh Jul 20, 2026
b41e525
Parity: event edit page gets develop's Details/Photos tabs
edwh Jul 20, 2026
cc3e670
Parity: profile sidebar active tab is amber, and mark-all-read always…
edwh Jul 20, 2026
99496b2
Parity harness: assert the fixtures ran, not tinker's exit code
edwh Jul 20, 2026
47f467d
Close the API gap behind /group's four missing columns
edwh Jul 20, 2026
1b6b616
Fix the N+1 my own commit message claimed wasn't there
edwh Jul 20, 2026
8f311a8
Close the invited-count gap on the events moderation queue
edwh Jul 20, 2026
b7ae450
Parity: close the last three event-edit diffs
edwh Jul 20, 2026
b830236
Fix three bugs the /party comparison exposed
edwh Jul 20, 2026
06e8e8b
Add the event audit-trail endpoint, and fix requireAdministrator for …
edwh Jul 20, 2026
8bf148a
Parity: build the Event log tab - the last recorded "no endpoint" gap
edwh Jul 20, 2026
33e3d5e
Catch unresolvable i18n keys, and fix the two that existed
edwh Jul 20, 2026
367fc04
Parity: venue map preview on the event form
edwh Jul 20, 2026
6239ce2
Group audit endpoint, and stop audit logs leaking API tokens
edwh Jul 20, 2026
d1583c9
Parity: build the Group log tab
edwh Jul 20, 2026
365d98d
Fix data loss: PATCH /api/v2/groups/{id} wiped fields it wasn't sent
edwh Jul 20, 2026
4fa1cdf
Findings: 31-profile-edit compared - 1 diff, amber tab confirmed
edwh Jul 20, 2026
4dc2d7e
Purge API tokens from stored audit URLs; resolver-level fix NOT yet w…
edwh Jul 20, 2026
f0c3049
Revert the audit `resolvers` block - it broke auditing entirely
edwh Jul 20, 2026
4c4313b
Stop audit records storing API tokens - fixed at source this time
edwh Jul 20, 2026
959a839
Parity: label the profile picture field
edwh Jul 20, 2026
d8b312a
Fix: :read-only greyed out every select on the site
edwh Jul 20, 2026
f623e6d
Document /api/v2/moderate/events - it had no OpenAPI annotation
edwh Jul 20, 2026
ce131ed
Findings: profile photo control - the one open difference, with evidence
edwh Jul 20, 2026
c728f2e
Parity: profile photo uses develop's file input + submit
edwh Jul 20, 2026
ba0e318
Correct three comments that outlived the code they described
edwh Jul 20, 2026
beb7ee1
Remove migration narrative from code comments
edwh Jul 21, 2026
a1d5fee
Revert profile photo to Uppy/tus - all uploads go through one path
edwh Jul 21, 2026
6a7c5e0
Fix: partial-PATCH change made group postcode unclearable
edwh Jul 21, 2026
77c70cb
Fix CI: mock leaflet in the EventForm spec
edwh Jul 21, 2026
0cf5101
Fix group header: squished logo, and long names pushing actions down
edwh Jul 21, 2026
f61035b
Profile avatar: serve full size, not the thumbnail
edwh Jul 21, 2026
410faf7
Document /api/v2/moderate/groups - CI phpunit was erroring on it
edwh Jul 21, 2026
3d36209
Remove the invented footer; move its links to the navbar as develop h…
edwh Jul 21, 2026
271998c
Events page: stop showing "none" before the fetch starts, and fix the…
edwh Jul 21, 2026
6c3302d
Fix account dropdown opening off the top of the screen
edwh Jul 21, 2026
b4b67bd
Revert the "Other Links" navbar menu - develop never shows those links
edwh Jul 21, 2026
2b38f4c
Port develop's notifications stylesheet - none of it existed here
edwh Jul 21, 2026
b560d58
Port the remaining cell-* state washes from _events.scss
edwh Jul 21, 2026
fea971c
Match develop's section heading margins on stats blocks
edwh Jul 21, 2026
4e6a574
Fixometer: reserve the real layout while impact stats load
edwh Jul 21, 2026
4bb9653
Port .edit-panel - the class was applied everywhere and styled nowhere
edwh Jul 21, 2026
8928f4d
Port three more classes that were applied in markup but unstyled
edwh Jul 21, 2026
f6e294c
SECURITY: POST /api/v2/users let any authenticated user create an Adm…
edwh Jul 21, 2026
6141926
Bind the event_end_utc comparison instead of interpolating
edwh Jul 21, 2026
f3f074a
Speed up /api/v2/devices: drop the unconditional groups join and the …
edwh Jul 21, 2026
b85ba1d
Remove an N+1 in the user-group changes endpoint
edwh Jul 21, 2026
1bf95e4
Batch the other two Zapier change-feed lookups
edwh Jul 21, 2026
18f1351
Fix mojibake on the preview warming-up page
edwh Jul 21, 2026
3b9d4ce
Restore the dashboard sidebar's intro paragraph
edwh Jul 21, 2026
6073f2a
Restore the device form's five field help popovers
edwh Jul 21, 2026
28afbb5
Restore the invite modals' shareable-link panel, and the starting-soo…
edwh Jul 21, 2026
3755f34
Security: filter the event export by visibility, and stop publishing …
edwh Jul 21, 2026
3ea06d3
Fix the export tests CI caught, including one that asserted the leak
edwh Jul 21, 2026
b1877c9
Restore the per-event stats columns on the group events table
edwh Jul 21, 2026
4078458
Confirm leaving a group, instead of only flipping the button
edwh Jul 21, 2026
4b51309
Restore permanent group deletion for Administrators
edwh Jul 21, 2026
bd77f25
Restore the event invite modal's group member picker
edwh Jul 21, 2026
6274537
Banner an outstanding group invitation on the group page
edwh Jul 21, 2026
05c2b61
Let event photos be removed, and correct five stale "not implemented"…
edwh Jul 21, 2026
950315c
Stop the photo uploader forcing a horizontal scrollbar
edwh Jul 21, 2026
39a5a6e
Fix wrong Follow/Unfollow state, and a stray "None" above the Groups …
edwh Jul 21, 2026
ac4f5a5
Sync nine strings whose English text had drifted from develop
edwh Jul 21, 2026
c84398e
Announce sortable table columns to screen readers
edwh Jul 21, 2026
5375ee5
Finish announcing sortable columns across the remaining four tables
edwh Jul 21, 2026
4d61352
Show stored role names on the admin roles page, not translated labels
edwh Jul 21, 2026
f8771f7
Describe the onboarding slide images instead of marking them decorative
edwh Jul 21, 2026
1eb9863
Punctuate the user filter labels as develop does
edwh Jul 21, 2026
50053aa
Make the mobile collapse control usable by keyboard and screen reader
edwh Jul 21, 2026
87e8b24
Restore the "(if known)" hints on the device brand and model fields
edwh Jul 21, 2026
b771cbd
Fix the overflow test's measurement, and cover mobile
edwh Jul 21, 2026
d5bd3f5
Fix the logged-out nav buttons, a duplicated count, and mobile stat s…
edwh Jul 21, 2026
c3737e8
Match develop's Sign in / Join buttons exactly, not just legibly
edwh Jul 21, 2026
d47d443
Add a Vue 3 tag multiselect, and use it for the event invite modal
edwh Jul 21, 2026
14413c9
Restore per-category cookie consent
edwh Jul 21, 2026
4ac1537
Fix four functional HIGH parity deviations
edwh Jul 21, 2026
b17158c
Fix the remaining functional HIGH deviations
edwh Jul 21, 2026
db30c3e
Make every column of the group events table sortable
edwh Jul 21, 2026
ccc4b84
Parity: fix 88 audited deviations across 12 component areas
edwh Jul 21, 2026
7180064
Parity: correct 11 divergences an adversarial re-verification caught …
edwh Jul 21, 2026
307435d
Fix e2e-client timeout: point network-tag specs at the real component
edwh Jul 22, 2026
084974f
Fix dead-session dashboard error, nav buttons, and language-bar pinning
edwh Jul 22, 2026
9367f0d
Group map: friendlier zero-state with a link to find a group nearby
edwh Jul 22, 2026
c51f096
Integrate PR 887 backend: a group's next event must be approved
edwh Jul 22, 2026
e30f2d3
Integrate PR 887 map wording into 898, reconciling my own earlier keys
edwh Jul 22, 2026
b6dcb00
Integrate PR 887's marker info modal into the clustering map (TDD)
edwh Jul 22, 2026
0c27baf
GroupInfoModal: render group.location.location, not the raw object
edwh Jul 22, 2026
7082bb0
Treat develop as a preview branch; retire the restarters-dev machinery
edwh Jul 30, 2026
3c155bb
Group map feedback: deeper zoom, fewer clusters, separate identical pins
edwh Aug 17, 2026
e7c218e
Render the Map tab in the shared groups tab bar
edwh Aug 17, 2026
996ce52
Tighten identical-location pin split; decluster at max zoom
edwh Aug 17, 2026
df40a22
Restore PR 887's two-tab groups page: Your Groups | Find a group (map)
edwh Aug 17, 2026
632ba9d
Map: size/saturation-tiered cluster bubbles and restart-style SVG pins
edwh Aug 18, 2026
983bb23
Map styling: brand colours and 2px borders for clusters and pins
edwh Aug 19, 2026
e04a3ae
Map palette as SCSS tokens instead of hardcoded hexes
edwh Aug 19, 2026
fde9826
Cluster counts in the brand font (Asap)
edwh Aug 20, 2026
9c4f8d2
Map: zoom with the mouse wheel
edwh Aug 20, 2026
19415ce
Remove translation keys orphaned by the nearby-list page removal
edwh Aug 20, 2026
a26615d
Defuse date time-bombs in the party page specs
edwh Aug 20, 2026
a6ba8df
Distance column in the map's group list, nearest-first by default
edwh Aug 20, 2026
1344766
Place search finds boroughs: merged place-first Photon queries
edwh Aug 20, 2026
a5879a4
Lint: drop unused LATER_* constants from the party view spec
edwh Aug 20, 2026
a9a9279
Repair the stale e2e suite; preserve ?network across the group redirects
edwh Aug 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
308 changes: 241 additions & 67 deletions .circleci/config.yml

Large diffs are not rendered by default.

28 changes: 26 additions & 2 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
node_modules
# Docker only applies a bare directory name at the top level, so `node_modules`
# alone never excluded client/node_modules (~466MB) — it was uploaded to the
# builder on every deploy, CI included. Use ** for anything nested.
**/node_modules
vendor
.git
.env*
Expand All @@ -14,4 +17,25 @@ tests/Browser/screenshots
tests/Browser/console
*.log
.DS_Store
Thumbs.db
Thumbs.db

# Local-only clutter. These never exist in a CI checkout, but a manual
# `flyctl deploy` from a working tree uploads them: together they took the
# build context to 8.1GB / 358k files and made the deploy time out.
.worktrees/
.claude/
.idea/
.vscode/

# Test/report output. All untracked, so a CI checkout never has them, but a
# local deploy would ship ~253MB of screenshots and reports.
playwright-report/
parity-shots/
test-results/
/uploads/

# Root-level database dumps (e.g. restarters-anonymised.sql, ~662MB).
# Anchored to the root on purpose: database/data_updates/*.sql is tracked and
# must stay in the image.
/*.sql
/*.sql.gz
16 changes: 11 additions & 5 deletions .github/workflows/pr-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Deploy: label a PR with 'preview' (or re-push while labeled, or run this
# workflow manually with a PR number). Every deploy waits for
# approval via the 'preview' GitHub Environment — approvers should
# glance at the PR's diff to .github/workflows/, fly.pr.toml,
# glance at the PR's diff to .github/workflows/, fly.preview.toml,
# Dockerfile.fly and docker/*.sh before approving, since the deploy
# runs the PR's own code.
# Cleanup: a 6-hourly sweep destroys apps whose PR is closed or no longer
Expand Down Expand Up @@ -116,7 +116,7 @@ jobs:
- name: Overlay preview infra files from develop if still missing
run: |
git fetch origin develop --depth=1
for f in fly.pr.toml docker/preview-startup.sh; do
for f in fly.preview.toml docker/preview-startup.sh; do
if [ ! -f "$f" ]; then
echo "Branch lacks $f - taking it from develop"
git show origin/develop:"$f" > "$f"
Expand Down Expand Up @@ -153,7 +153,7 @@ jobs:
else
flyctl apps create "$APP" --org "$FLY_ORG"
# Shared read-only credentials (Tigris RO, Drive RO, gate password...)
# Strip comments/blank lines so the fly.pr-secrets.example.env
# Strip comments/blank lines so the fly.preview-secrets.example.env
# template can be filled in and pasted as-is.
echo "$FLY_PREVIEW_SECRETS" | grep -vE '^\s*(#|$)' \
| flyctl secrets import --app "$APP" --stage
Expand All @@ -171,8 +171,14 @@ jobs:
PR="${{ steps.pr.outputs.number }}"
# Shown on the cookie-gate login page so testers know which PR this is.
flyctl secrets set PREVIEW_PR_TITLE="$PR_TITLE" --app "$APP" --stage
sed "s/__PR_NUMBER__/$PR/g" fly.pr.toml > fly.pr.generated.toml
flyctl deploy --config fly.pr.generated.toml --app "$APP" \
# fly.preview.toml is shared with the develop deploy in
# .circleci/config.yml; keep the two substitution lists in step.
sed -e "s|__APP_NAME__|$APP|g" \
-e "s|__APP_TITLE__|Restarters PR #$PR|g" \
-e "s|__BASE_URL__|https://$APP.fly.dev|g" \
-e "s|__SENTRY_ENV__|preview|g" \
fly.preview.toml > fly.preview.generated.toml
flyctl deploy --config fly.preview.generated.toml --app "$APP" \
--remote-only --ha=false
# --ha=false has a history of not reliably keeping one machine.
flyctl scale count 1 --app "$APP" --yes
Expand Down
47 changes: 0 additions & 47 deletions .github/workflows/stop-dev-nightly.yml

This file was deleted.

20 changes: 20 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,29 @@ restarters-anonymised.sql
/.claude/settings.local.json
/public/build/
/storage/api-docs/api-docs.json
/storage/app/tus
/storage/app/tus-cache
/.phpunit.result.cache
/playwright-report/
/events.csv
/public/repair-data*.csv
/uploads/*.jpg
.mcp.json

# Local ralph session log (not for commit)
.claude-session.md
# PHPUnit coverage artifact
/tests/clover.xml

# Visual parity capture output (task parity:capture) - screenshots, never committed
parity-shots/

# Canvas share-image backgrounds (224MB, 267 files). These live in the Laravel
# app at public/images/stats and must NOT be duplicated into the client bundle.
# The client reaches them through an /api/* endpoint so CORS applies and the
# canvas stays untainted - see the stats-share composable.
client/public/images/stats/
parity-fixtures.json

# Generated from fly.preview.toml by CI (and by hand for manual deploys)
fly.*.generated.toml
1 change: 1 addition & 0 deletions .php_cs.cache
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"php":"8.4.21","version":"2.19.1","indent":" ","lineEnding":"\n","rules":{"array_syntax":{"syntax":"short"},"binary_operator_spaces":{"default":"single_space","operators":{"=>":null}},"blank_line_after_namespace":true,"blank_line_after_opening_tag":true,"blank_line_before_statement":{"statements":["return"]},"braces":true,"cast_spaces":true,"class_attributes_separation":{"elements":["method"]},"class_definition":true,"concat_space":{"spacing":"none"},"declare_equal_normalize":true,"elseif":true,"encoding":true,"full_opening_tag":true,"fully_qualified_strict_types":true,"function_declaration":true,"function_typehint_space":true,"heredoc_to_nowdoc":true,"include":true,"increment_style":{"style":"post"},"indentation_type":true,"linebreak_after_opening_tag":true,"line_ending":true,"lowercase_cast":true,"lowercase_constants":true,"lowercase_keywords":true,"lowercase_static_reference":true,"magic_method_casing":true,"magic_constant_casing":true,"method_argument_space":true,"native_function_casing":true,"no_alias_functions":true,"no_extra_blank_lines":{"tokens":["extra","throw","use","use_trait"]},"no_blank_lines_after_class_opening":true,"no_blank_lines_after_phpdoc":true,"no_closing_tag":true,"no_empty_phpdoc":true,"no_empty_statement":true,"no_leading_import_slash":true,"no_leading_namespace_whitespace":true,"no_mixed_echo_print":{"use":"echo"},"no_multiline_whitespace_around_double_arrow":true,"multiline_whitespace_before_semicolons":{"strategy":"no_multi_line"},"no_short_bool_cast":true,"no_singleline_whitespace_before_semicolons":true,"no_spaces_after_function_name":true,"no_spaces_around_offset":true,"no_spaces_inside_parenthesis":true,"no_trailing_comma_in_list_call":true,"no_trailing_comma_in_singleline_array":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"no_unneeded_control_parentheses":true,"no_unreachable_default_argument_value":true,"no_useless_return":true,"no_whitespace_before_comma_in_array":true,"no_whitespace_in_blank_line":true,"normalize_index_brace":true,"not_operator_with_successor_space":true,"object_operator_without_whitespace":true,"ordered_imports":{"sortAlgorithm":"alpha"},"phpdoc_indent":true,"phpdoc_inline_tag":true,"phpdoc_no_access":true,"phpdoc_no_package":true,"phpdoc_no_useless_inheritdoc":true,"phpdoc_scalar":true,"phpdoc_single_line_var_spacing":true,"phpdoc_summary":true,"phpdoc_to_comment":true,"phpdoc_trim":true,"phpdoc_types":true,"phpdoc_var_without_name":true,"psr4":true,"self_accessor":true,"short_scalar_cast":true,"single_blank_line_at_eof":true,"single_blank_line_before_namespace":true,"single_class_element_per_statement":true,"single_import_per_statement":true,"single_line_after_imports":true,"single_line_comment_style":{"comment_types":["hash"]},"single_quote":true,"space_after_semicolon":true,"standardize_not_equals":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"ternary_operator_spaces":true,"trailing_comma_in_multiline_array":true,"trim_array_spaces":true,"unary_operator_spaces":true,"visibility_required":{"elements":["method","property"]},"whitespace_after_comma_in_array":true},"hashes":{"app\/Http\/Controllers\/API\/StatsShareImageController.php":653998297,"tests\/Feature\/Devices\/APIv2StatsShareImageTest.php":3643096653,"routes\/api.php":180907154}}
45 changes: 24 additions & 21 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ task docker:run:artisan -- migrate # Run artisan command
task docker:shell # Open shell in container

# Testing
task docker:test:phpunit # Run PHP tests
task docker:test:jest # Run JS tests
task docker:test:playwright # Run e2e tests
task docker:test:phpunit # Run PHP tests
task docker:test:vitest # Run client (Nuxt) unit tests
task docker:test:playwright:client # Run client e2e tests

# Vite dev server (HMR)
task docker:vite:start # Start Vite in background
Expand Down Expand Up @@ -74,11 +74,9 @@ task docker:shell # Open shell in container
task docker:run:artisan -- migrate # Run artisan commands
task docker:run:bash -- "command" # Run bash commands

# Run Vite for HMR (hot module replacement)
task docker:run:bash -- "npm run dev"

# The application will be available at:
# - Restarters: http://localhost:8001 (Admin: jane@bloggs.net / passw0rd)
# - Frontend (Nuxt SPA, restarters_client): http://localhost:8004 (Admin: jane@bloggs.net / passw0rd)
# - Laravel API: http://localhost:8001
# - phpMyAdmin: http://localhost:8002 (Host: restarters_db, User: root, Pass: s3cr3t)
# - Mailhog: http://localhost:8025
# - Discourse: http://localhost:8003
Expand All @@ -89,11 +87,13 @@ task docker:run:bash -- "npm run dev"
# Install PHP dependencies
composer install

# Install and build frontend assets
npm install
npm run dev # Development build
npm run watch # Watch for changes
npm run production # Production build
# Frontend (Nuxt SPA) — the restarters_client container runs the dev server;
# for local tooling outside Docker:
cd client && npm install && npm run dev

# Widget/wiki assets still built by Laravel-side Vite (rarely needed):
npm install --legacy-peer-deps
npm run build

# Laravel commands
php artisan migrate # Run database migrations
Expand Down Expand Up @@ -121,11 +121,11 @@ export DB_TEST_HOST=restarters_db
# Run specific test method
./vendor/bin/phpunit --filter testMethodName

# Run JavaScript tests
npm run jest
# Run client unit tests (from client/)
cd client && npx vitest run

# Run Playwright end-to-end tests
npm test
# Run client Playwright end-to-end tests
task docker:test:playwright:client
```

### Code Quality
Expand Down Expand Up @@ -168,11 +168,14 @@ npm test
- JSON columns for flexible network_data storage

### Frontend Stack
- **Vue 2** components for interactive features
- **Laravel Mix** for asset compilation
- **Bootstrap 4** for styling
- **SCSS** for styles in `resources/sass/`
- Multiple build targets: main app, global styles, wiki styles
- **Nuxt 4 SPA in `client/`** — Vue 3, Pinia, bootstrap-vue-next (Bootstrap 5),
@nuxtjs/i18n, Vitest; talks to Laravel exclusively via `/api/v2`
- Laravel serves no user-facing pages (see `tests/Feature/ApiOnlyRouteSurfaceTest.php`
for the pinned web-route surface): only the embeddable stats widgets and the
MediaWiki skin assets are still built here (Vite, `resources/global` +
`resources/wiki`, jQuery/Bootstrap 4 only)
- Client translations are exported from `lang/*.php` via
`php artisan translations:export-client` (checked in CI)

### Permission System
- Role-based permissions via custom `app/Role.php` and `app/Permissions.php`
Expand Down
26 changes: 24 additions & 2 deletions Dockerfile.fly
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
# Install composer
COPY --from=composer/composer:2-bin /composer /usr/bin/composer

# Install Node 18
RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - \
# Install Node 22 (Nuxt 4 / nuxi require Node >=22; matches client/Dockerfile
# node:22 and CI cimg/node:22.16. Vite 4 root build is Node-22-compatible too.)
RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
&& apt-get install -y nodejs \
&& apt-get clean && rm -rf /var/lib/apt/lists/*

Expand Down Expand Up @@ -53,6 +54,19 @@
RUN php artisan lang:js --no-lib resources/js/translations.js 2>/dev/null || true
RUN npm run production && rm -f public/hot

# Build the Nuxt SPA (the separate app in client/). `nuxt build` emits a
# standalone Nitro Node server at client/.output that bundles its own runtime
# deps, so production serves the SPA origin via
# `node client/.output/server/index.mjs` (see docker/supervisord-fly.conf).
# apiBase is runtime-overridable (NUXT_PUBLIC_API_BASE), so no API URL is baked
# in here. Drop client/node_modules afterwards — .output is self-contained, and
# this keeps the final-stage `COPY /build` from dragging the dev install in.
WORKDIR /build/client
RUN npm ci --legacy-peer-deps

Check warning on line 65 in Dockerfile.fly

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Omitting "--ignore-scripts" allows lifecycle scripts to run during package installation.

See more on https://sonarcloud.io/project/issues?id=TheRestartProject_restarters.net&issues=AZ-DXVP2gDQPfj9To7kv&open=AZ-DXVP2gDQPfj9To7kv&pullRequest=898
RUN npm run build
RUN rm -rf node_modules
WORKDIR /build

# Generate swagger docs (non-fatal if it fails)
RUN php artisan l5-swagger:generate 2>/dev/null || true

Expand All @@ -77,6 +91,7 @@
util-linux \
default-mysql-client \
rclone \
curl ca-certificates gnupg \
libpng-dev libjpeg62-turbo-dev libfreetype6-dev libzip-dev libicu-dev libxml2-dev \
&& if [ "$STARTUP_SCRIPT" != "startup.sh" ]; then apt-get install -y --no-install-recommends default-mysql-server; fi \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
Expand All @@ -86,6 +101,13 @@
# Install xmlrpc
RUN pecl install channel://pecl.php.net/xmlrpc-1.0.0RC3 && docker-php-ext-enable xmlrpc

# Node 22 (runtime only) — runs the Nuxt Nitro server that serves the SPA origin
# (client/.output, started by supervisord). The .output targets Node >=22, same
# as the builder. This image only needs the node binary to run it.
RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \

Check warning on line 107 in Dockerfile.fly

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Not enforcing HTTPS here might allow for redirections to insecure websites. Make sure it is safe here.

See more on https://sonarcloud.io/project/issues?id=TheRestartProject_restarters.net&issues=AZ-DXVP2gDQPfj9To7ky&open=AZ-DXVP2gDQPfj9To7ky&pullRequest=898
&& apt-get install -y --no-install-recommends nodejs \
&& apt-get clean && rm -rf /var/lib/apt/lists/*

# Configure PHP-FPM to use unix socket.
# The base image ships docker.conf (formerly zz-docker.conf) with:
# listen = 9000 — overrides www.conf (last-file-wins in glob)
Expand Down
Loading
Loading