feat(abuse-blocker): add backend runtime - #208
Draft
l0nelynx wants to merge 4 commits into
Draft
Conversation
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
This was referenced Aug 15, 2026
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.
Suggested PR title
feat(abuse-blocker): add backend runtimeSummary
This PR adds the backend runtime for the optional
abuseBlockerNode plugin introduced by #207 and implemented on Node in remnawave/node#46.It persists idempotent abuse reports, serializes repeat-offender escalation per user, exposes administrative reporting and manual-review APIs, refreshes Node-local temporary blocks, and integrates alert-level events with the existing Telegram and backend-webhook notification pipelines.
This is PR 3 of 3. It targets
devand is intentionally opened as a Draft until the two shared packages in the dependency chain are published and the registry dependencies and lockfiles can be finalized.Motivation
Node has the connection-level information and must perform low-latency scan detection locally. The backend has the durable, cross-restart state required to track repeated blocking incidents across Nodes and make account-level decisions.
This split keeps high-volume rolling windows in bounded Node RAM while centralizing audit history, repeat-offender policy, notifications, and manual review in PostgreSQL.
Persistence
The migration adds two tables:
AbuseBlockerReportsstores the Node-generatedeventId, user and Node references, severity, score, source IP, action, detection time, and the complete report JSON.AbuseBlockerUserStatestores the durable strike level, last blocking incident, manual-review state, whether the plugin disabled the account, and review timestamps/action.Reports are upserted by
eventId. An updated report may expand evidence, but it does not score or escalate again. Report truncation intentionally leaves strike and manual-review state untouched, and no automatic report retention policy is introduced in this PR.Repeat-offender escalation
Blocking reports are processed in a transaction guarded by a PostgreSQL advisory transaction lock derived from
userId. This serializes concurrent reports for the same user while allowing different users to progress independently.The default chain is:
UsersService, and require manual review.If the gap from the previous blocking incident exceeds the configured repeat window, the chain starts again at strike 1.
The backend consumes the policy snapshot carried by the Node report, including
repeatBlockSecondsandrepeatWindowSeconds, so the escalation decision matches the configuration active when the event was detected.Collection and Node commands
Collection retains the Node plugin's destructive-flush semantics: a batch can be lost if transport fails after Node has returned it.
Administrative API
The authenticated admin API adds routes under
/api/node-plugins/abuse-blockerfor:enableandkeep_disabledreview actions.enableclears plugin strike/review state and enables the user through the standard user service.keep_disabledclears the review workflow while preservingDISABLEDstatus. Existing audit reports are retained for both actions.The current
Usersmodel does not expose a separate UUID column. Therefore, the review route's UUID parameter resolves the existing UUID-shapedvlessUuid. This can be changed to the numeric user ID orshortUuidif maintainers prefer a different public identifier.Notifications
This PR adds:
abuse_blocker;abuse_blocker.report;TELEGRAM_NOTIFY_ABUSE_BLOCKERswitch;Severity behavior is deliberate:
suspiciousreports are database-only;alert, initial block, repeat block, and account-disable events are sent to enabled Telegram/backend-webhook integrations;eventIdupdates and post-disable incidents do not send repeated notifications.Compatibility and release gates
@remnawave/node-plugins@0.7.0.@remnawave/node-contract(expected3.3.0, subject to maintainer release coordination).abuseBlockerremain compatible; the feature is opt-in.Tests
Added nine focused runtime tests covering:
eventIdidempotency;enableand idempotentkeep_disabledreview actions.Local validation:
All nine focused tests, lint, changed-file formatting, production build, both contract typechecks, and Prisma schema validation pass locally. The advisory-lock path is implemented and covered through escalation unit tests; a live PostgreSQL concurrency integration test is not claimed by this Draft.
Dependency chain
@remnawave/node-plugins@0.7.0).Before this Draft is marked ready, the shared packages will be published, registry dependencies and lockfiles will be finalized, the branch will be rebased with signed commits if necessary, and the full repository CI suites will be rerun.