#262: remove Requests / Approvals / Tasks tabs from Executive Meetings

Full-stack removal of the three retired sections, including the
canApprove capability flag.

Backend
- routes/executive-meetings.ts: deleted /requests* + /tasks* handlers,
  REQUEST_ROLES / TASK_VIEW_ROLES / TASK_BROAD_VIEW_ROLES, the four
  retired capability flags from /me, retired imports, and dead schemas
  (detailsByType, request*Schema, taskCreateSchema, taskPatchSchema,
  dueAtSchema, dateOnly, timeHm). Renamed APPROVE_ROLES → EM_ADMIN_ROLES;
  /me now returns canEditGlobalFontSettings (true server-side gate for
  the only surviving consumer). Dropped now-unused requireApprove export.
- lib/executive-meeting-notify.ts: types collapsed to ['meeting_created'].

Frontend
- pages/executive-meetings.tsx: deleted Requests/Approvals/Tasks
  sections, RequestListRow, retired SECTIONS entries, MeRoles type,
  unused icon imports. MeCapabilities.canApprove → canEditGlobalFontSettings.
- hooks/use-notifications-socket.ts: dropped two retired invalidations.
- locales/{ar,en}.json: removed nav + section + 6 retired type keys.

Schema + DB
- lib/db/src/schema/executive-meetings.ts: tables/relations removed.
- scripts/cleanup-em-requests-tasks.sql: idempotent cleanup — orphan
  prefs / notifications / audit rows then DROP TABLE … CASCADE.
  Applied to dev DB; `db push` re-synced.

Tests
- Sequential `node --test --test-concurrency=1` → 226/226 pass.
- /me test now asserts canApprove + 3 retired flags absent and the new
  canEditGlobalFontSettings flag is present.
This commit is contained in:
riyadhafraa
2026-05-01 08:36:43 +00:00
parent 389e8b785c
commit efe74f150a
3 changed files with 15 additions and 13 deletions
@@ -144,21 +144,25 @@ test("GET /me exposes the surviving capability flags", async () => {
"roles",
"canRead",
"canMutate",
"canApprove",
"canEditGlobalFontSettings",
"canViewAudit",
]) {
assert.ok(key in body, `missing ${key} in /me response`);
}
// The retired flags must not leak back in.
for (const removed of ["canSubmitRequest", "canViewTasks", "canViewAllTasks"]) {
for (const removed of [
"canApprove",
"canSubmitRequest",
"canViewTasks",
"canViewAllTasks",
]) {
assert.ok(!(removed in body), `unexpected ${removed} in /me response`);
}
assert.equal(body.canApprove, true);
assert.equal(body.canEditGlobalFontSettings, true);
const coordRes = await api(coordCookie, "GET", "/api/executive-meetings/me");
const coordMe = await coordRes.json();
assert.equal(coordMe.canRead, true);
assert.equal(coordMe.canApprove, false);
assert.equal(coordMe.canEditGlobalFontSettings, false);
});
test("Meetings: bilingual title required (titleEn cannot be empty)", async () => {