Skip to main content

safe_migrate/report/
violations.rs

1// FILE: ./src/report/violations.rs
2
3#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
4pub enum OperationKind {
5    DropColumn,
6    DropTable,
7    DropIndex,
8    DropView,
9    DropMaterializedView,
10    DropFunction,
11    DropProcedure,
12    DropSchema,
13    DropDatabase,
14    DropSequence,
15    DropDomain,
16    DropPublication,
17    DropTrigger,
18    DropPolicy,
19    AddColumn,
20    AlterColumnType,
21    AddConstraint,
22    CreateIndex,
23    CreateTable,
24    CreateView,
25    CreateFunction,
26    CreateProcedure,
27    AlterFunction,
28    AlterProcedure,
29    RefreshMaterializedView,
30    AttachPartition,
31    DetachPartition,
32    VacuumFull,
33    Grant,
34    RevokeGrant,
35    AlterType,
36    CreateTrigger,
37    CreatePolicy,
38    DisableTrigger,
39    EnableTrigger,
40    RenameTable,
41    OpaqueSql,
42    Other(String),
43}
44
45impl std::fmt::Display for OperationKind {
46    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47        match self {
48            OperationKind::DropColumn => write!(f, "drop_column"),
49            OperationKind::DropTable => write!(f, "drop_table"),
50            OperationKind::DropIndex => write!(f, "drop_index"),
51            OperationKind::DropView => write!(f, "drop_view"),
52            OperationKind::DropMaterializedView => write!(f, "drop_materialized_view"),
53            OperationKind::DropFunction => write!(f, "drop_function"),
54            OperationKind::DropProcedure => write!(f, "drop_procedure"),
55            OperationKind::DropSchema => write!(f, "drop_schema"),
56            OperationKind::DropDatabase => write!(f, "drop_database"),
57            OperationKind::DropSequence => write!(f, "drop_sequence"),
58            OperationKind::DropDomain => write!(f, "drop_domain"),
59            OperationKind::DropPublication => write!(f, "drop_publication"),
60            OperationKind::DropTrigger => write!(f, "drop_trigger"),
61            OperationKind::DropPolicy => write!(f, "drop_policy"),
62            OperationKind::AddColumn => write!(f, "add_column"),
63            OperationKind::AlterColumnType => write!(f, "alter_column_type"),
64            OperationKind::AddConstraint => write!(f, "add_constraint"),
65            OperationKind::CreateIndex => write!(f, "create_index"),
66            OperationKind::CreateTable => write!(f, "create_table"),
67            OperationKind::CreateView => write!(f, "create_view"),
68            OperationKind::CreateFunction => write!(f, "create_function"),
69            OperationKind::CreateProcedure => write!(f, "create_procedure"),
70            OperationKind::AlterFunction => write!(f, "alter_function"),
71            OperationKind::AlterProcedure => write!(f, "alter_procedure"),
72            OperationKind::RefreshMaterializedView => write!(f, "refresh_materialized_view"),
73            OperationKind::AttachPartition => write!(f, "attach_partition"),
74            OperationKind::DetachPartition => write!(f, "detach_partition"),
75            OperationKind::VacuumFull => write!(f, "vacuum_full"),
76            OperationKind::Grant => write!(f, "grant"),
77            OperationKind::RevokeGrant => write!(f, "revoke_grant"),
78            OperationKind::AlterType => write!(f, "alter_type"),
79            OperationKind::CreateTrigger => write!(f, "create_trigger"),
80            OperationKind::CreatePolicy => write!(f, "create_policy"),
81            OperationKind::DisableTrigger => write!(f, "disable_trigger"),
82            OperationKind::EnableTrigger => write!(f, "enable_trigger"),
83            OperationKind::RenameTable => write!(f, "rename_table"),
84            OperationKind::OpaqueSql => write!(f, "opaque_sql"),
85            OperationKind::Other(s) => write!(f, "{}", s),
86        }
87    }
88}
89
90#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
91pub enum ObjectKind {
92    Table,
93    Index,
94    View,
95    MaterializedView,
96    Function,
97    Procedure,
98    Trigger,
99    Sequence,
100    Schema,
101    Role,
102    Publication,
103    Subscription,
104    Database,
105    Domain,
106    Policy,
107    Type,
108    Unknown,
109}
110
111impl std::fmt::Display for ObjectKind {
112    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
113        match self {
114            ObjectKind::Table => write!(f, "table"),
115            ObjectKind::Index => write!(f, "index"),
116            ObjectKind::View => write!(f, "view"),
117            ObjectKind::MaterializedView => write!(f, "materialized view"),
118            ObjectKind::Function => write!(f, "function"),
119            ObjectKind::Procedure => write!(f, "procedure"),
120            ObjectKind::Trigger => write!(f, "trigger"),
121            ObjectKind::Sequence => write!(f, "sequence"),
122            ObjectKind::Schema => write!(f, "schema"),
123            ObjectKind::Role => write!(f, "role"),
124            ObjectKind::Publication => write!(f, "publication"),
125            ObjectKind::Subscription => write!(f, "subscription"),
126            ObjectKind::Database => write!(f, "database"),
127            ObjectKind::Domain => write!(f, "domain"),
128            ObjectKind::Policy => write!(f, "policy"),
129            ObjectKind::Type => write!(f, "type"),
130            ObjectKind::Unknown => write!(f, "object"),
131        }
132    }
133}
134
135/// ViolationTier represents the severity of a finding.
136/// Tier1 is declared first so `derive(Ord)` sorts it before Tier2 and Tier3.
137#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, serde::Serialize)]
138pub enum ViolationTier {
139    Tier1, // HALT — Access Exclusive / data-destructive, sorts first
140    Tier2, // WARN — Share Row Exclusive / cautious
141    Tier3, // SAFE — informational / low risk, sorts last
142}
143
144#[derive(Debug, Clone, serde::Serialize)]
145pub struct Violation {
146    #[serde(skip)]
147    pub source_range: Option<rowan::TextRange>,
148    pub rule_id: &'static str,
149    pub operation_kind: OperationKind,
150    pub object_kind: ObjectKind,
151    pub object_name: String,
152    pub tier: ViolationTier,
153    pub reason: String,
154    pub recipe: &'static str,
155    pub dedup_key: Option<String>,
156    pub sql: Option<String>,
157}