Skip to main content

systemprompt_analytics/models/
fingerprint.rs

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