Files
sides/CHANGELOG.md

87 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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-interpolated `CAST('$dateFilter' AS date)` and `AND s.stationid = '{$stationFilter}'` with `?` bindings, eliminating SQL injection vectors
- **F-02** Parameterized SQL queries in `WaterLevelController::index()` — replaced `WHERE s.stationid = '{$stationFilter}'` and `AND w.datetime = '{$sqlDate}'` with `?` bindings
- **F-06** Fixed XSS risk in `stationmgmt.blade.php` — replaced `{!! $types ... !!}` with `e()` escaping for translation strings inside badge HTML
- **F-07** Standardized password policy in `AdminController` — both `storeUser()` and `updatePassword()` now use `Password::defaults()` instead of `min:6`
- **F-10** Stopped leaking internal exception messages to users — `AdminController` catch blocks now log errors via `Log::error()` and return `__('toast.error')` generic messages; added `toast.error` translation keys for EN and BM
- **F-23** Added `Referrer-Policy: strict-origin-when-cross-origin` and `Content-Security-Policy` headers to Nginx config; changed existing headers to `always` directive
- **F-24** Added `url` validation rule for `cctv_link` in both `storeStation()` and `updateStation()`; removed hardcoded `http://` prefix from CCTV link in `cctv.blade.php`
### Reliability
- **F-09** Added error handling to `FcmService::__construct()` — validates credentials file existence, catches `JsonException` on parse, logs errors, and returns status 500 in `sendToTopic()` when credentials are unavailable
- **F-11** Added required parameter validation to `WaterLevelController::wlHistory()`, `WaterLevelController::exportHistoricalWl()`, `RainfallController::historicalRainfall()`, and `RainfallController::exportHourlyRainfallExcel()` — all now validate `station`, `startdate`, and `enddate` before use
- **F-12** Wrapped `AdminController::storeStation()`, `storeUser()`, and `updateUsers()` write operations in `DB::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`, and `threshold.blade.php`
### Performance
- **F-13** Created migration `2026_05_28_000000_add_performance_indexes.php` adding 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.example` with all documented environment variables (APP, DB, SESSION, CACHE, QUEUE, MAIL, FIREBASE, FCM, POSTGRES, PGADMIN)
- Created `src/.env` with populated values: generated `APP_KEY`, set `DB_*` matching docker-compose PostgreSQL service, set `FIREBASE_PROJECT_ID=sides-b4abb`, set `FIREBASE_CREDENTIALS` path
- Created root `.env` for docker-compose with `POSTGRES_DB`, `POSTGRES_USER`, `POSTGRES_PASSWORD`, `PGADMIN_EMAIL`, `PGADMIN_PASSWORD`
- Added `src/.gitignore` and root `.gitignore` to exclude `.env` from version control
### Deployment
- **F-19** Removed redundant `COPY ./src /var/www/html` line from `Dockerfile` — kept only `COPY --chown=www:www ./src /var/www/html`; removed commented-out dead lines (`RUN curl`, `RUN tar`, `COPY fileni`)
- Fixed `docker-compose.yml` PostgreSQL data directory from `/var/lib/postgres/data` to `/var/lib/postgresql/data` and added `PGDATA` env var
- Set non-empty `POSTGRES_PASSWORD` and `DB_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_20260528` into the live `sides` database:
- `users`: 4 rows (admin, imam14, ijantck, jpskedah)
- `station`: 9 rows (KBLG0025KBLG0033)
- `rainfall`: 91,829 rows
- `waterlevel`: 137,956 rows
- `notification`: 128 rows
- Made `users.email` column nullable in migration `0001_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 infrastructure
- `INTEGRATIONS.md` — Firebase FCM, PostgreSQL, S3 filesystem, database queue/cache/session
- `ARCHITECTURE.md` — MVC pattern, raw SQL over Eloquent, Breeze auth, FCM push alerts
- `STRUCTURE.md` — Directory tree, 12 migrations, 8+ tables, dual layout system
- `CONVENTIONS.md` — Raw SQL patterns, PSR-12, localization (en/bm), Blade conventions
- `TESTING.md` — PHPUnit, near-zero coverage (2 example tests only), no CI
- `CONCERNS.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 |