knowdit_kg_model/db/semantic_node.rs
1use sea_orm::entity::prelude::*;
2
3use super::category::DeFiCategory;
4
5/// One node in the semantic graph.
6///
7/// A row here is one of:
8/// - **Canonical**: no outgoing `semantic_merge` edge points away from
9/// `self.id`. Canonical rows are the targets returned to LLM linkers and
10/// the per-finding mapper, and are the only nodes that participate in
11/// global-link writes to `semantic_finding_link`.
12/// - **Raw / merged-away**: there is a row in `semantic_merge` with
13/// `from_semantic_id = self.id`. The node has been folded into another
14/// canonical node and is retained as historical provenance. Raw rows can
15/// still hold `semantic_finding_link` rows produced by the in-project
16/// linking step (which runs before merge collapses anything).
17///
18/// Project provenance is recorded in the `project_semantic` join table —
19/// a canonical merged node can originate from many historical projects, so
20/// the column-on-row form did not fit. There is intentionally no scalar
21/// `project_id` here.
22#[sea_orm::model]
23#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize, DeriveEntityModel)]
24#[sea_orm(table_name = "semantic_node")]
25pub struct Model {
26 #[sea_orm(primary_key)]
27 pub id: i32,
28 /// Short canonical name, e.g. "Constant Product AMM Swap"
29 #[sea_orm(column_type = "Text")]
30 pub name: String,
31 #[sea_orm(column_type = "Text")]
32 pub definition: String,
33 #[sea_orm(column_type = "Text")]
34 pub description: String,
35 /// The primary DeFi business category of this semantic.
36 pub category: DeFiCategory,
37
38 #[sea_orm(has_many)]
39 pub functions: HasMany<super::semantic_function::Entity>,
40 #[sea_orm(has_many, via = "semantic_finding_link")]
41 pub findings: HasMany<super::audit_finding::Entity>,
42 #[sea_orm(has_many, via = "project_semantic")]
43 pub projects: HasMany<super::project::Entity>,
44}
45
46impl ActiveModelBehavior for ActiveModel {}