Skip to content

feat(phase-2): wire notify() into admin controllers (#70)#76

Merged
sacha-l merged 1 commit into
developfrom
feat/notify-triggers-p2-04
May 18, 2026
Merged

feat(phase-2): wire notify() into admin controllers (#70)#76
sacha-l merged 1 commit into
developfrom
feat/notify-triggers-p2-04

Conversation

@sacha-l
Copy link
Copy Markdown
Collaborator

@sacha-l sacha-l commented May 18, 2026

Summary

  • Add notifyProjectTeam(projectId, eventType, sourceId, payload) to notification.service.js — fetches the project, fills projectName into the payload, and fans notify(...) out to every non-null team-member wallet. Fully guarded: a project-fetch failure resolves to [], never throws.
  • Wire three admin trigger points: updateApplicationStatus (on a submitted → accepted/rejected transition), approveM2, and requestChanges. Each fires notifyProjectTeam after the success response is sent, inside a try/catch that logs via logger.error.
  • source_id per spec §4.2: application id for accept/reject; project id for m2_approved; ${projectId}:${changeRequestDate} for m2_changes_requested (reusing the timestamp already written to the DB).
  • Added a minimal getById to program-application.repository.js + service pass-through, used to read the application's prior status so the notify only fires on a genuine submitted → transition.

Closes #70

Test plan

  • cd server && npm test — pass (14 files, 121 tests)
  • cd client && npm run build — pass
  • cd client && npm run lint — pass (zero warnings)

UI verification (stadium-tester)

Not applicable — server-only issue. Issue #70 wires service calls into admin controllers; it has no client surface. All five ## Test scenarios are HTTP/DB-state assertions, covered by Vitest controller tests, mapped 1:1:

Issue scenario Test
PATCH application submitted → accepted writes notifications for every team wallet; HTTP response unchanged program-application.test.js — "calls notifyProjectTeam with application_accepted when submitted → accepted"
POST M2 approve writes notifications for every team wallet (m2_approved, source_id=projectId) project.controller.test.jsapproveM2 notify case
POST M2 request-changes writes notifications with feedback in payload (m2_changes_requested, source_id=projectId:iso) project.controller.test.jsrequestChanges notify case
Simulated provider failure does not change the HTTP response or roll back DB state program-application.test.js + project.controller.test.js — "still returns 200 even when notifyProjectTeam rejects"
PATCH submitted → submitted (no real change) writes no notifications program-application.test.js — "does not call notifyProjectTeam when new status is submitted"

Failure-isolation is additionally covered by notifyProjectTeam fan-out tests in notification.service.test.js (null wallets skipped, no team members → [], getProjectById throwing → []) and a new case proving a failing prior-status lookup still returns 200.

Preview

N/A — no client surface affected.

Backlog items logged

One non-blocking observation from the pre-PR review, appended to docs/improvement-backlog.md:

  • Pre-existing console.log calls in project.controller.js (lines 75, 188) — predate Phase 2, left untouched per minimal-diff; flagged for a logger cleanup pass.

Pre-PR review found 1 blocker, fixed before this PR: the prior-status getById lookup ran inside the main try block, so a Supabase transport error there would have 500'd the admin action. It is now wrapped in its own try/catch — a lookup failure degrades to "skip the notify gate," and the status update + response proceed normally. A regression test covers this path.

Invariants verified

  • BYPASS_ADMIN_CHECK still false (no client/admin-page change)
  • Admin routes still use auth.middleware.js (no route changes — handler bodies only)
  • No new console.log in client (no client changes); new server code uses logger
  • No new Mongoose imports in server/api/** (Supabase via repositories)
  • ESM import syntax only; no require()
  • No import cycle — notification.service.jsproject.service.js is one-directional

After a successful DB write, three admin actions now fan out a
notification to every team-member wallet of the affected project:
application accept/reject, M2 approve, and M2 request-changes.

The notify call runs after the HTTP response is sent and is fully
isolated — the prior-status lookup, the team fan-out, and the send
are each guarded so a failure logs an error but never changes the
response or rolls back the underlying admin action.

Closes #70
@vercel
Copy link
Copy Markdown

vercel Bot commented May 18, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
stadium Building Building Preview, Comment May 18, 2026 6:20pm

@sacha-l sacha-l marked this pull request as ready for review May 18, 2026 19:27
@sacha-l sacha-l merged commit df5b69f into develop May 18, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

revamp-P2-04: trigger points — wire notify() into admin controllers

1 participant