anti-brigading system - detection engine, phantom voting, ALTCHA adaptive difficulty, honeypot fields, admin security dashboard, auto-learning
This commit is contained in:
@@ -7,6 +7,26 @@ import { cleanExpiredChallenges } from "../routes/passkey.js";
|
||||
import { cleanupExpiredTokens } from "../lib/token-blocklist.js";
|
||||
import { getPluginCronJobs } from "../plugins/loader.js";
|
||||
import { cleanupViews } from "../lib/view-tracker.js";
|
||||
import {
|
||||
takeVoteSnapshots,
|
||||
scanVoteVelocity,
|
||||
scanPostVelocity,
|
||||
scanIdentityClusters,
|
||||
scanInflectionPoints,
|
||||
scanCohortArrivals,
|
||||
scanReferrerConcentration,
|
||||
scanPostSimilarity,
|
||||
recalculateBoardBaselines,
|
||||
scanVoterOverlap,
|
||||
scanOutboundLinks,
|
||||
scanCommentVoteRatio,
|
||||
scanVoteDistribution,
|
||||
compareSeasonalBaseline,
|
||||
pruneOldSnapshots,
|
||||
pruneOldAnomalyEvents,
|
||||
scanOffHoursActivity,
|
||||
buildVoterGraph,
|
||||
} from "../services/detection-engine.js";
|
||||
|
||||
export function startCronJobs() {
|
||||
// prune old activity events - daily at 3am
|
||||
@@ -108,6 +128,53 @@ export function startCronJobs() {
|
||||
// clean expired view-tracker entries - every 5 minutes
|
||||
cron.schedule("*/5 * * * *", () => { cleanupViews(); });
|
||||
|
||||
// --- anti-brigading detection jobs ---
|
||||
|
||||
// every 5 min: snapshots + velocity scans
|
||||
cron.schedule("*/5 * * * *", async () => {
|
||||
await takeVoteSnapshots().catch(() => {});
|
||||
await scanVoteVelocity().catch(() => {});
|
||||
await scanPostVelocity().catch(() => {});
|
||||
});
|
||||
|
||||
// every 10 min: identity clustering
|
||||
cron.schedule("*/10 * * * *", async () => {
|
||||
await scanIdentityClusters().catch(() => {});
|
||||
});
|
||||
|
||||
// every 15 min: inflection point detection
|
||||
cron.schedule("*/15 * * * *", async () => {
|
||||
await scanInflectionPoints().catch(() => {});
|
||||
});
|
||||
|
||||
// every 30 min: cohort arrivals, referrer analysis, post similarity
|
||||
cron.schedule("*/30 * * * *", async () => {
|
||||
await scanCohortArrivals().catch(() => {});
|
||||
await scanReferrerConcentration().catch(() => {});
|
||||
await scanPostSimilarity().catch(() => {});
|
||||
});
|
||||
|
||||
// hourly: baselines, overlap, links, comment ratio, off-hours, voter graph
|
||||
cron.schedule("0 * * * *", async () => {
|
||||
await recalculateBoardBaselines().catch(() => {});
|
||||
await scanVoterOverlap().catch(() => {});
|
||||
await scanOutboundLinks().catch(() => {});
|
||||
await scanCommentVoteRatio().catch(() => {});
|
||||
await scanOffHoursActivity().catch(() => {});
|
||||
const boards = await prisma.board.findMany({ select: { id: true } }).catch(() => [] as { id: string }[]);
|
||||
for (const b of boards) {
|
||||
await buildVoterGraph(b.id).catch(() => {});
|
||||
}
|
||||
});
|
||||
|
||||
// daily at 3am: distribution, seasonal, pruning
|
||||
cron.schedule("0 3 * * *", async () => {
|
||||
await scanVoteDistribution().catch(() => {});
|
||||
await compareSeasonalBaseline().catch(() => {});
|
||||
await pruneOldSnapshots().catch(() => {});
|
||||
await pruneOldAnomalyEvents().catch(() => {});
|
||||
});
|
||||
|
||||
// register plugin-provided cron jobs (min interval: every minute, reject sub-minute)
|
||||
for (const job of getPluginCronJobs()) {
|
||||
if (!cron.validate(job.schedule)) {
|
||||
|
||||
Reference in New Issue
Block a user