Skip to content

Private Servers Module

Status: shipped (Steps 1–10) Frontend route: /private-servers Backend prefix: /api/v1/private-servers

10-step upgrade modelled on the threats module. Each step ships independently end-to-end (backend + UI) and is independently verifiable.

Translation

This is a condensed English reference. The full Chinese version is the authoritative one — switch to 简体中文 with the language picker (top right).


Purpose

A single workspace for finding the real private servers out of the noisy crawl pool:

  • Discover (queued scans) → Triage (real / suspected / false-positive) → Evidence → Action (takedown / link actor)
  • AI first-pass (rule engine + trust_score) + human final classification — manual decisions always win
  • Tabbed workspace: "Working set / False positive / All" so analysts spend zero time on obvious noise
  • AI summary + live activity feed — same primitives as the threats page
  • Multi-tenant: tenant_admin sees only its portal_publications; super_admin sees the global pool

Step ledger

Step Scope Deliverable
1 KPI rework 5-tile classification strip: confirmed / suspected / unknown / false-positive / new-this-week — bins always sum to total
2 Detail drawer Big screenshot + WHOIS/DNS fold + discovery context + 3 footer actions
3 Manual classification 4-button toolbar in drawer + card corner chip; PATCH /:id/classification jsonb merge
4 Auto rule engine ps_classifier.go (whitelist + keywords + TLD + domain pattern + screenshot + CN) + POST /classify-auto
5 Linked entities GET /:id/links (3 bridges: linked_actor_id / actor reverse / threats promoted) + 3-tab drawer
6 One-click actions PrivateServerLegalModal + PrivateServerLinkActorModal + extended POST /legal-docs/draft + POST /:id/link-actor
7 Scan queue portal_scan_tasks table + POST /scan + GET /scans + worker sync endpoints (/sync/private-server-scans/...) + PrivateServerScanModal
8 Activity + AI summary PrivateServerActivityFeed.tsx + PrivateServerAISummary.tsx + GET /activity + GET /ai-summary
9 Workspace tabs ?classification=csv + ?trust_min=N + trust sort options; 3 workspace tabs ("Working / FP / All")
10 Verification + docs + deploy Routes test + this reference doc + ai-astraweb deploy

Classification taxonomy

The same effective classification drives:

  • The 5-tile Hero KPI strip
  • The 3 workspace tabs
  • The classification filter on the list endpoint
  • The "AI 初评" panel in the drawer
  • The activity feed colour bands

via this single SQL fragment:

COALESCE(
  metadata->>'classification',         -- manual (Step 3)
  metadata->>'classification_hint',    -- auto rule output (Step 4)
  'unknown'
)

Manual decisions always win the auto hint. Re-running classify-auto defaults to only_unclassified=true so it can't clobber human judgement.


Rule-engine weights (Step 4)

Signal Weight
Hostname matches whitelist (4399 / taptap / 18183 / gamersky / bilibili / wikipedia / wemade.com / playmir4.com / …) hard short-circuit → score 5, hint false_positive
Title / first_query contains smoking-gun keyword (私服 / sf / 注册送 / GM后台 / 无限元宝 / 打金服 / …) +30
Hostname stem matches letters+digits[+letters] (e.g. zhaotj / mir4cool / yb235) +15
Low-cost TLD (.top / .xyz / .vip / .club / .online / .site / .cc) +10
Landing-page screenshot captured +10
WHOIS country = CN +5

Buckets after capping to [0,100]: ≥70 confirmed · 40-69 suspected · 20-39 unknown · <20 false_positive.


Open work

  • Scan worker not yet implemented on ai-astrahost — Portal-side API is complete; worker contract documented under "Scan task queue".
  • Evidence creation from the drawer is a no-op pending a separate iteration.
  • AI summary is templated (stats-derived/v1).

For full details (API tables, bridges, time-bucket policy, e2e smoke scripts) switch to 简体中文 in the language picker (top right).