systemprompt_analytics/models/
fingerprint.rs1use 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}