App-level navigation pattern per 00-shared/05 (global IA). Leave is a
top-level workspace reachable from the home grid; org-admin surfaces nest
under the same workspace. Routes are client-side names (forward-looking)
until the Flutter client lands; the API surface is authoritative
(leave.controller.ts:25-28, tag leave).
Cancel — status cancelled exists (leave-request.schema.ts:11) but no
endpoint can produce it → no cancel action anywhere in IA.
Request detail — no GET /leave/requests/:id; the client must pass the
whole object from the list (list is the only read surface).
RBAC — approvals UI must hide for non-admins by client role check;
the API would still enforce at leave.service.ts:163-167 (non-admin userId
filter) and :179-180 (self-decision).
Balance for other users — GET /leave/balance/:userId accepts any id;
no server check restricts it (gap — expose only admin/own in client).
Substitutions list for absent teacher — endpoint only lists by
substituteTeacherId (leave.service.ts:275-280); no "who covers me" list
for the absent teacher (gap).