- Working-hours repo accepts nullable staff scope (pgx + memory); staff
rules live in availability_rules and drive public slot generation
- Protected routes for staff working hours, class templates, and class
sessions with tenant-ownership checks and input validation
- Sessions derive endsAt/capacity from templates; list resolves location
names and live booked counts; template delete cascades sessions,
session delete preserves bookings via SET NULL (mirrored in memory)
- Zones page: staff-scope selector on working hours, new Classes tab
with template/session CRUD, CS+EN strings, mobile tab wrapping
- Normalize availability_rules times to HH:MM in the service layer
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Services and staff existed as schema + booking FK targets but had no
management surface. Adds full CRUD: repository (pgx + in-memory with
matching FK semantics), catalog service validation with tenant isolation,
MaxStaff entitlement enforcement, protected API routes, OpenAPI schemas,
and dashboard screens for both entities.
Dashboard summary now resolves staff names on bookings and computes
setup completion from real configured state. Booking modal selects from
the tenant's actual services; blocked days can be scoped per staff member.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>