# AeroFind v1.0 — Release Notes
**Release Date:** April 8, 2026  
**Type:** Patch + Bug Fix Release  
**Status:** ✅ Production Stable — Recommended for all deployments

---

## What's New in v1.0

This release focuses on codebase integrity and production reliability. Eight critical bugs discovered during comprehensive code audit have been resolved, each affecting live system stability.

---

## 🐛 Bug Fixes

### Critical — Runtime Errors

**1. Fatal null dereference in `manage.php`**  
BDO Priority Logic block accessed `$report['temp_country']` and `$report['country']` _before_ the `if (!$report)` guard, causing a PHP fatal error whenever an invalid or missing management token was used. Fixed by moving the logic block to after the 404 early-exit.

**2. Null dereference in `NearestAirportFinder::resolvePassengerAirport()`**  
Two separate code paths in `flights.php` called `$coords['lat']` directly after `geocodeZip()` without checking for a null return. If Nominatim was unreachable or the ZIP was unknown, this caused a fatal crash. Both paths now have null guards.

**3. SQL reserved word collision in `getWorldTracerConfig`**  
Raw query used `WHERE key = 'worldtracer_api_key'` — `key` is a reserved word in MySQL, causing a SQL syntax error on strict MySQL 8+ servers. Fixed to `` WHERE `key` = 'worldtracer_api_key'``.

### Logic Errors

**4. Operator precedence bug in `purgeOldData`**  
L&F item count string: `$stmtDelLost->rowCount() + $stmtDelFound->rowCount() . " L&F Item(s)"` — PHP string concatenation binds before addition, producing `"0L&F Item(s)"` always. Fixed by adding parentheses around the addition.

**5. Missing receiver name in `createDPDLabel`**  
DPD shipment used `$addr['name']` for the receiver, but `getSmartAddress()` never returns a `name` key. This sent a blank receiver name to DPD. Fixed to use `$report['full_name'] ?? $report['first_name'] . ' ' . $report['last_name']`.

**6. SQL injection via `exec()` in `purgeOldData`**  
Task messages delete used raw string interpolation in `exec()`: `"... WHERE date(created_at) <= '$targetDate'"`. Replaced with a proper parameterized `prepare()->execute()` call. Although `$targetDate` was regex-validated, this is correct defensive practice.

**7. Unprotected `ALTER TABLE` in `initSchema`**  
`ALTER TABLE bdo_couriers ADD COLUMN IF NOT EXISTS is_long_haul ...` was called without a try/catch, unlike all surrounding migration calls. Older MySQL versions not supporting `IF NOT EXISTS` on `ALTER TABLE` would throw a fatal exception and abort schema initialization. Wrapped in try/catch.

**8. Duplicate sentence in `unmatchItems` email**  
"We will notify you immediately if we find a new potential match." appeared twice consecutively in the unmatch apology email. Duplicate removed.

---

## 📦 Full Feature Set (Stable in v1.0)

| Module | Status |
|--------|--------|
| PIR Submission (multi-bag, multi-flight, documents, PDF) | ✅ Stable |
| WorldTracer Bridge (PIR, BDO, RUSH, void, auto-sync) | ✅ Stable |
| DPD Integration (shipment, PDF label, tracking sync) | ✅ Stable |
| BDO Decision Engine (tier-1 local, tier-2 long-haul, RUSH intl) | ✅ Stable |
| Rush Flight Intelligence (AviationStack dual-tier + hub fallback) | ✅ Stable |
| Cabin L&F Terminal (lost/found match, passenger notifications) | ✅ Stable |
| Staff Portal (role-based, inline edit, task management) | ✅ Stable |
| Admin Panel (company, airlines, couriers, API keys, email toggles) | ✅ Stable |
| Passenger Self-Service Portal (token-auth address update) | ✅ Stable |
| Public Bag Tracker (tag / WT ref / ID lookup) | ✅ Stable |
| Multi-language UI — EN / DE / ES / NO | ✅ Stable |
| GDPR Purge (auto + manual, file cleanup, 7-day safety) | ✅ Stable |
| Audit Log System (per-report, per-item, immutable) | ✅ Stable |
| ZIP Geocode Cache (Nominatim + haversine) | ✅ Stable |
| PDF Generation (DomPDF, repeating footer, page breaks) | ✅ Stable |
| Static Report Rebuild (`dbRebuildReportHTML`) | ✅ Stable |

---

## 🚀 Deployment Requirements

| Requirement | Minimum |
|-------------|---------|
| PHP | 8.1+ |
| Database | MySQL 8.0+ or MariaDB 10.4+ |
| PHP Extensions | pdo, pdo_mysql, curl, gd, mbstring |
| Optional APIs | AviationStack, WorldTracer, DPD account |

### Upgrade from v1.3.x
1. Replace all PHP files except `db_config.php`
2. Schema migrations run automatically on first request via `initSchema()`
3. No manual SQL migration required

---

## 📋 Changelog Summary

| Version | Date | Type |
|---------|------|------|
| **v1.0** | Apr 8, 2026 | Bug Fix |
| v1.3.0 | Apr 7, 2026 | Bug Fix |
| v1.2.0 | Apr 7, 2026 | Feature + Fix |
| v1.1.0 | Apr 6, 2026 | Feature |
| v1.0.0 | Apr 1, 2026 | Initial Release |

---

*AeroFind v1 — Built for the ground. Designed for the passenger.*
