6.1 KiB
6.1 KiB
Changelog
All notable changes to the SIDES project are documented in this file.
[2026-05-28] — Audit Fix, Configuration & Database Recovery
Security
- F-01 Parameterized SQL queries in
RainfallController::index()— replaced string-interpolatedCAST('$dateFilter' AS date)andAND s.stationid = '{$stationFilter}'with?bindings, eliminating SQL injection vectors - F-02 Parameterized SQL queries in
WaterLevelController::index()— replacedWHERE s.stationid = '{$stationFilter}'andAND w.datetime = '{$sqlDate}'with?bindings - F-06 Fixed XSS risk in
stationmgmt.blade.php— replaced{!! $types ... !!}withe()escaping for translation strings inside badge HTML - F-07 Standardized password policy in
AdminController— bothstoreUser()andupdatePassword()now usePassword::defaults()instead ofmin:6 - F-10 Stopped leaking internal exception messages to users —
AdminControllercatch blocks now log errors viaLog::error()and return__('toast.error')generic messages; addedtoast.errortranslation keys for EN and BM - F-23 Added
Referrer-Policy: strict-origin-when-cross-originandContent-Security-Policyheaders to Nginx config; changed existing headers toalwaysdirective - F-24 Added
urlvalidation rule forcctv_linkin bothstoreStation()andupdateStation(); removed hardcodedhttp://prefix from CCTV link incctv.blade.php
Reliability
- F-09 Added error handling to
FcmService::__construct()— validates credentials file existence, catchesJsonExceptionon parse, logs errors, and returns status 500 insendToTopic()when credentials are unavailable - F-11 Added required parameter validation to
WaterLevelController::wlHistory(),WaterLevelController::exportHistoricalWl(),RainfallController::historicalRainfall(), andRainfallController::exportHourlyRainfallExcel()— all now validatestation,startdate, andenddatebefore use - F-12 Wrapped
AdminController::storeStation(),storeUser(), andupdateUsers()write operations inDB::transaction()for atomicity - F-15 Removed all commented-out dead code blocks from
cctvController.php,RainfallController.php,AlertController.php,AppServiceProvider.php,homeapp.blade.php,home.blade.php,usermgmt.blade.php, andthreshold.blade.php
Performance
- F-13 Created migration
2026_05_28_000000_add_performance_indexes.phpadding indexes on:rainfall(stationid),rainfall(timestamp),rainfall(stationid, timestamp)waterlevel(stationid),waterlevel(datetime),waterlevel(stationid, datetime)notification(stationid),notification(timestamp),notification(stationtype)siren(stationid),siren(active_time)
Configuration
- F-18 Created
src/.env.examplewith all documented environment variables (APP, DB, SESSION, CACHE, QUEUE, MAIL, FIREBASE, FCM, POSTGRES, PGADMIN) - Created
src/.envwith populated values: generatedAPP_KEY, setDB_*matching docker-compose PostgreSQL service, setFIREBASE_PROJECT_ID=sides-b4abb, setFIREBASE_CREDENTIALSpath - Created root
.envfor docker-compose withPOSTGRES_DB,POSTGRES_USER,POSTGRES_PASSWORD,PGADMIN_EMAIL,PGADMIN_PASSWORD - Added
src/.gitignoreand root.gitignoreto exclude.envfrom version control
Deployment
- F-19 Removed redundant
COPY ./src /var/www/htmlline fromDockerfile— kept onlyCOPY --chown=www:www ./src /var/www/html; removed commented-out dead lines (RUN curl,RUN tar,COPY fileni) - Fixed
docker-compose.ymlPostgreSQL data directory from/var/lib/postgres/datato/var/lib/postgresql/dataand addedPGDATAenv var - Set non-empty
POSTGRES_PASSWORDandDB_PASSWORD(was empty, causing PostgreSQL 18 to refuse initialization) - Set non-empty
PGADMIN_PASSWORD(was empty, causing pgAdmin to crash)
Database Recovery
- Restored production data from
backup/sides_20260528into the livesidesdatabase:users: 4 rows (admin, imam14, ijantck, jpskedah)station: 9 rows (KBLG0025–KBLG0033)rainfall: 91,829 rowswaterlevel: 137,956 rowsnotification: 128 rows
- Made
users.emailcolumn nullable in migration0001_01_01_000000_create_users_table.php— existing data has NULL emails for admin and jpskedah - Reset all sequence counters to 300,000+ to avoid duplicate key errors from concurrent sensor inserts with explicit IDs
Codebase Assessment
- Created
.planning/codebase/with 7 structured documents:STACK.md— PHP 8.2, Laravel 12, PostgreSQL 18, Docker/Nginx infrastructureINTEGRATIONS.md— Firebase FCM, PostgreSQL, S3 filesystem, database queue/cache/sessionARCHITECTURE.md— MVC pattern, raw SQL over Eloquent, Breeze auth, FCM push alertsSTRUCTURE.md— Directory tree, 12 migrations, 8+ tables, dual layout systemCONVENTIONS.md— Raw SQL patterns, PSR-12, localization (en/bm), Blade conventionsTESTING.md— PHPUnit, near-zero coverage (2 example tests only), no CICONCERNS.md— 26 findings: 3 critical SQL injections, unauthenticated API endpoints, missing indexes, no audit logging, deployment security gaps
Manual-Only Findings (Not Yet Fixed)
These require design decisions or architectural changes:
| # | Finding | Notes |
|---|---|---|
| F-03 | Unauthenticated API alert endpoint | Requires Laravel Sanctum + rate limiting |
| F-04 | API endpoints without authentication | Architectural change across subsystems |
| F-05 | API login without token | Requires Sanctum integration |
| F-08 | Inverted block/unblock logic | Requires UX redesign of checkbox semantics |
| F-14 | Duplicated dashboard query | Requires service class extraction |
| F-20 | PostgreSQL data dir path | Already fixed in this session |
| F-21 | Docker security (Dozzle shell, Filebrowser root, pgAdmin exposed) | Architecture decisions needed |
| F-22 | No Docker health checks | Deployment decisions needed |
| F-25 | No audit logging | Low severity, requires design |
| F-26 | No API rate limiting | Low severity, requires design |