core: implement real-time events via Supabase Realtime#91
Open
Godfrey-Delight wants to merge 2 commits into
Open
core: implement real-time events via Supabase Realtime#91Godfrey-Delight wants to merge 2 commits into
Godfrey-Delight wants to merge 2 commits into
Conversation
Adds real-time notifications via Supabase Realtime (replication on `loan_index`/`payment_index`) and a standalone WebSocket gateway (port 3005), so loan status changes and payment confirmations broadcast immediately instead of requiring polling. Includes indexer event handlers wiring `LOAN_CREATED`/`LOAN_REPAID`/`LOAN_DEFAULTED` to broadcasts, and an integration guide for clients. Closes StepFi-app#30
EmeditWeb
requested changes
Jul 21, 2026
EmeditWeb
left a comment
Member
There was a problem hiding this comment.
Review verdict: ❌ Request changes (security — data leak)
The implementation is clean and well-tested (11 tests pass, no any), but the design leaks sensitive financial data.
The gateway is unauthenticated and unscoped. src/realtime/realtime.gateway.ts:
wss.on('connection', ...)accepts any client that reachesWEBSOCKET_PORT— no JWT/token verification on the handshake.broadcast()sends every message to every connected client (this.wss.clients.forEach(... client.send(message))) — no per-user rooms/scoping.
And the payloads are per-user financial data. From realtime.handler.ts → realtime.service.ts:
loan.status_changed→{ loanId, userWallet, principalAmount, interestAmount, dueDate }payment.confirmed→{ loanId, txHash, amount, paidAt }
So any anonymous client connecting to the WebSocket port receives every user's loan creations (wallet + amounts + due date), repayments, and defaults. That's a privacy/data-exposure vulnerability for a lending app.
Required before merge:
- Authenticate the WS handshake (verify the same JWT used for HTTP; reject unauthenticated upgrades).
- Scope delivery per user — only send a user events for their own wallet (rooms/subscriptions keyed to the authenticated wallet), or restrict broadcasts to genuinely public aggregate data.
- Prefer the NestJS WebSocket adapter over a raw
wsserver on a separate port, so guards/CORS/origin checks apply consistently.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🔗 Related Issue
Closes #30
🔖 Title
Implementation of real-time events via Supabase Realtime
📝 Description
Adds real-time notifications via Supabase Realtime (replication on
loan_index/payment_index) and a standalone WebSocket gateway (port 3005), so loan status changes and payment confirmations broadcast immediately instead of requiring polling. Includes indexer event handlers wiringLOAN_CREATED/LOAN_REPAID/LOAN_DEFAULTEDto broadcasts, and an integration guide for clients. Closes #30🔄 Changes Made
loan_indexandpayment_indexrealtime.service.tsbroadcast helpersLOAN_CREATED/LOAN_REPAID/LOAN_DEFAULTED, plus integration guide📸 Screenshots (if applicable)
🗒️ Additional Notes