# Changelog

## 1.0.0 — final release (executed and tested; see TESTING-REPORT.md)

Installed and executed end-to-end on PHP 8.3 + MariaDB 10.11 + Apache/HTTPS with cron, then re-installed from the final ZIP.
Fixes found by that testing:

**Security**
- **Data loss:** `customers/delete` (and 28 other bulk delete/undelete functions across the data models) with an empty id list marked **every** row deleted (CodeIgniter `where_in(NULL)` adds no condition). An empty list now changes nothing.
- **State-changing GET links** (CSRF): test mode on/off (stopped sales being recorded), clone item, inventory counts, bulk delete/undelete, inventory comment edit now require a confirmed POST with the CSRF token.
- **Report SQL injection:** `group_by` from the URL went into the SQL `GROUP BY`; now whitelisted.
- **POS brute force:** 5 failed sign-ins per username (20 per IP) in 15 minutes lock sign-in for 15 minutes.
- **HTTPS:** both apps redirect HTTP → HTTPS (301); the POS now sends HSTS and Permissions-Policy.
- The POS no longer downgrades the Locations page to HTTP for non-Chrome browsers (Secure cookies would sign users out).
- POS `.env` loader stripped no inline comments (`KAABE_SECURE_COOKIES=1  # note` was not `1`).

**Correctness**
- Concurrent sales/purchases (two tills, parallel API calls) could deadlock and fail silently (HTTP 200, sale id −1); saves are now serialised per business and retried.
- Suspending/closing a business now blocks the POS immediately (registry written at once, not after the queue).
- Sales sync: a failed run could stay "running" forever when stored secrets could not be decrypted; runs are always closed and stale runs cleaned; a sale moved to another day no longer stays counted on its old day.
- CSV import reported "Import successful" when a plan limit refused a row (nothing imported); uploads refused by the storage limit reported success. Both now show the plan message.
- API sale at a warehouse returned a fake "TEST MODE" sale; now 403 with a clear error.
- New locations: the creator keeps access to them.
- PHP 8 fatals: closing a register without denominations, public receipt links (`/r/…`), clone employee, 2D barcodes (PDF417/DataMatrix).
- Products without a category could not be edited.
- Adoption rehearsal names collided within the same minute; `kaabe:provision` on a live business now reports SKIP.
- Backups: the tenant registry was skipped under cron; backup files are now private (umask 077).

**Staging preparation (29 Sep 2026)**
- New `scripts/backup-database.sh`: read-only, verified backup of one database (gzip test, SHA-256, dump-completed marker, table count = database). `adopt-existing.sh` now takes this verified backup of the database being adopted before anything else and stops if it cannot be verified (the platform backup did not yet include that database).
- New guides: `STAGING-INMOTION.md`, `STAGING-ACCEPTANCE-CHECKLIST.md`, `PRODUCTION-ADOPTION-GUIDE.md`.
- The integration test scripts are no longer shipped (they contain throw-away test passwords); results remain in `TESTING-REPORT.md`.

**Packaging**
- `platform/vendor` (production libraries) is bundled — no Composer or internet needed to install or upgrade; `upgrade.sh` uses it.
- Documentation rewritten from executed results; `M7_DATA_MAPPING.md`, `M7_MIGRATION_PLAN.md` added at the top level.

## 1.0.0-rc.1 — first release candidate (not yet executed on a server)

**POS (PHP Point of Sale 19.1, patched; all original features kept)**
- **Tenant resolver:** the business is chosen from the sub-domain; there is one database per business with its own database user; credentials were removed from the code; the registry is encrypted (AES-256-GCM).
- **Passwords and sessions:** passwords upgrade from MD5 to bcrypt at the next sign-in; session hardening; CSRF on all forms and AJAX.
- **Plan enforcement:**
  - Module gates in the backend, menus, REST API and inside Sales, covering Appointments, Work Orders, Deliveries, Messages and Price Rules, plus Employees (time clock, commissions), Advanced analytics, Loyalty, API keys and e-commerce channels.
  - Limits: products, users, branches, warehouses, registers, storage, API keys, e-commerce channels.
- **Warehouses:** a location type that cannot sell. The vendor licence server call was replaced by plan limits.
- **Business dashboard** as the home screen.
- **Kaabe tenant migrations #1–#3 (additive):** meta tables, sales indexes for sync.
- **Security `.htaccess`:** `application/`, `database/`, `kaabe/` and dump/log files are blocked.

**Super Admin (Laravel 12)**
- Staff sign-in with 2FA, roles and permissions, audit log.
- Businesses: automatic provisioning (direct MySQL or cPanel UAPI; optional cPanel sub-domain and AutoSSL), retry and reset, branches and users management with temporary passwords.
- Plans, modules, limits and overrides.
- Manual subscriptions and payments (gateway-ready).
- Entitlement delivery (versioned, idempotent, verified).
- Sales sync and monitoring with separate sync-health and activity statuses, and stored alerts.
- CLI installer `kaabe:install` (runs once), `kaabe:backup`, `kaabe:tenants-migrate`, `kaabe:pos-cron`, `kaabe:rehearse`, `kaabe:adopt`.
