systemprompt_analytics/models/
fingerprint.rs1use chrono::{DateTime, Utc};
7use serde::{Deserialize, Serialize};
8use sqlx::FromRow;
9
10#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
11pub struct FingerprintReputation {
12 pub fingerprint_hash: String,
13 pub first_seen_at: DateTime<Utc>,
14 pub last_seen_at: DateTime<Utc>,
15 pub total_session_count: i32,
16 pub active_session_count: i32,
17 pub total_request_count: i64,
18 pub requests_last_hour: i32,
19 pub peak_requests_per_minute: f32,
20 pub sustained_high_velocity_minutes: i32,
21 pub is_flagged: bool,
22 pub flag_reason: Option<String>,
23 pub flagged_at: Option<DateTime<Utc>>,
24 pub reputation_score: i32,
25 pub abuse_incidents: i32,
26 pub last_abuse_at: Option<DateTime<Utc>>,
27 pub last_ip_address: Option<String>,
28 pub last_user_agent: Option<String>,
29 pub associated_user_ids: Vec<String>,
30 pub updated_at: DateTime<Utc>,
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq)]
34pub enum FlagReason {
35 HighRequestCount,
36 SustainedVelocity,
37 ExcessiveSessions,
38 ReputationDecay,
39}
40
41impl FlagReason {
42 pub const fn as_str(&self) -> &'static str {
43 match self {
44 Self::HighRequestCount => "request_count_exceeded_100",
45 Self::SustainedVelocity => "sustained_velocity_10rpm_1hr",
46 Self::ExcessiveSessions => "session_count_exceeded_10",
47 Self::ReputationDecay => "reputation_score_below_threshold",
48 }
49 }
50}
51
52impl std::fmt::Display for FlagReason {
53 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54 write!(f, "{}", self.as_str())
55 }
56}
57
58#[derive(Debug, Clone)]
59pub struct FingerprintAnalysisResult {
60 pub fingerprint_hash: String,
61 pub should_flag: bool,
62 pub flag_reasons: Vec<FlagReason>,
63 pub new_reputation_score: i32,
64 pub should_ban_ip: bool,
65 pub ip_to_ban: Option<String>,
66}