e1e7f93545
Task #112 — locks in RBAC, transactional safety, and the router.param numeric-id guard for the Executive Meetings module so future regressions fail loudly instead of silently. What was added (all in artifacts/api-server/tests/executive-meetings.test.mjs): 1. "Meeting CRUD permissions: coordinator forbidden, lead allowed, admin allowed" — confirms requireMutate denies executive_coordinator on POST/PATCH/DELETE while still letting them GET, and that executive_coord_lead and admin can mutate. 2. "Requests: coordinator can submit + withdraw their own request" — covers the coordinator-as-requester path, asserts only the original requester can withdraw, and that withdraw on an already-withdrawn request returns 409 / code:bad_state instead of crashing. 3. "Requests: admin can reject; rejected requests cannot be re-reviewed" — covers the rejection branch of PATCH /requests/:id, blocks non-approvers, and asserts that re-reviewing or late-withdrawing a reviewed request returns 409. 4. "Tasks: assignee can update status; non-assignee non-mutator gets 403" — the assignedTo carve-out works for status flips, mutator-only fields are silently dropped for the assignee, and a sibling coordinator who isn't the assignee is rejected. 5. "Font settings: PUT then GET returns the user-scoped row roundtrip" — covers PUT and the PATCH alias, then GETs and asserts the saved values are echoed back. 6. "router.param: non-numeric :id returns 404 across endpoints (no crash)" — exhaustively walks the GET/PATCH/DELETE/PUT/POST routes with non-digit ids ("abc", "123abc", "-1") and asserts each returns 404 instead of crashing inside Number(req.params.id). 7. "Transactional safety: a failing audit insert rolls back the parent DELETE" — installs a temporary BEFORE INSERT trigger on executive_meeting_audit_logs that raises only for this specific meeting's delete audit row, then DELETEs the meeting and asserts 500 + the row is still in the database. Trigger is dropped in a finally so other tests are unaffected. Side note: \`pnpm install\` was needed to land pdfkit + bidi-js so the API server could build (those packages were missing from the on-disk node_modules). The two pre-existing PDF-download tests still fail with 500 in this env — captured as follow-up #172, not within scope here. Replit-Task-Id: c0ece8b6-6584-4c4c-9655-a158be6db9f0