v4.44.29 FULL FUNCTION / MENU AUDIT + BONUS HOTFIX

FATAL ERROR CONFIRMED:
bonus_recap.php referenced ms.customer_name, but membership_sales has no customer_name column.
Fix: customer identity is resolved through LEFT JOIN members m ON m.id=ms.member_id and m.name.

ADDITIONAL DATA ACCURACY FINDING:
Service bonus query joined bonuses -> transaction_items by barber. A transaction with multiple service rows for the same barber could multiply one bonus row.
Fix: bonus service ledger now reads one row directly from bonuses and uses bonuses.description as item description. No fan-out join.

ACCESS / MENU FINDING:
partials.php exposed staff_income_detail.php and bonus_recap.php to Finance/Finance Auditor, while config/config.php require_login allowlists did not include them. This could redirect a valid menu click back to finance_audit.php.
Fix: canonical require_login allowlists now include staff_income_detail.php and bonus_recap.php.

STATIC VERIFICATION:
- All PHP files pass php -l.
- All menu_link PHP targets exist.
- Local PHP href targets found by static audit exist.
- bonus_recap membership query uses real membership_sales columns and members join.
- Existing v4.44.28 bonus rules retained: service/product bonus requires parent transaction PAID; membership bonus requires membership status=paid and payment_status=paid.
- Historical records are not rewritten.
