fix(rbac): gate Contracts/Rate Cards reads and financial reports like Invoices #271
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/PMS-350-rbac-finance-gates"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
External review found a technician could reach Contracts, Rate Cards, and the financial reports that Invoices already restricts to finance roles, plus export the billing CSV through a side-door that skipped the report's own gate. Audit Log, the user list, and invitations were already gated; this closes the remaining server-side holes so every billing / financial surface enforces the same RequireFinance check Invoices uses, returning the identical 403 AppError envelope the SPA already renders.
Contracts: the create/update/delete handlers already carried RequireFinance, but the read handlers (list_contracts, get_contract, list_contract_items, get_hour_balance, list_rate_cards, get_rate_card, list_rate_card_items) only had the module-enable gate, so any reports-enabled tenant member could read contract and rate-card data. Add RequireFinance to each read handler so read and write match.
Reports: switch the billing report from RequireManager to RequireFinance so it matches the Invoices gate exactly (finance, not manager), update its descriptor text, and add the same can_manage_billing() check to the billing branch of the CSV export so the export cannot bypass the report's gate.
Add tests/rbac_route_coverage.rs: an HTTP integration test that logs in as every role (super_admin, admin, manager, technician, dispatcher, sales, finance) and walks the protected routes (invoices, contracts, rate-cards, reports/billing, reports/billing/export, invitations, audit-log, auth/users) asserting the exact allow/deny matrix, so a future feature cannot silently re-open a gap.
The sidebar / nav role-reflection acceptance criterion lives in the mokosh-apps SPA repo, not mokosh-server, so it is out of scope for this change.
#PMS-350
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com