Skip to main content

execsurface_model/
canonical.rs

1//! Backend-independent canonical execution-surface model.
2//!
3//! These types deliberately exclude PIDs, TIDs, timestamps and raw event
4//! sequence numbers.
5
6use serde::{Deserialize, Serialize};
7
8use crate::{FileOperation, SpawnMechanism};
9
10pub const CANONICAL_SURFACE_SCHEMA_VERSION: u32 = 2;
11pub const NORMALIZATION_PROFILE_VERSION: u32 = 2;
12
13#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
14pub struct CanonicalSurface {
15    pub schema_version: u32,
16    pub normalization: NormalizationMetadata,
17    pub effects: Vec<CanonicalEffect>,
18}
19
20#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
21pub struct NormalizationMetadata {
22    pub profile_version: u32,
23    pub semantic_roots: Vec<String>,
24}
25
26#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
27pub struct CanonicalExecutable {
28    pub path: CanonicalPath,
29    pub family: String,
30}
31
32#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
33pub struct CanonicalPath {
34    pub value: String,
35    pub class: PathClass,
36    pub resolution: PathResolution,
37}
38
39#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
40#[serde(rename_all = "snake_case")]
41pub enum PathClass {
42    Workspace,
43    Home,
44    CredentialSensitive,
45    Temp,
46    RunTemp,
47    Cache,
48    System,
49    Device,
50    OutsideDeclaredRoots,
51    Unknown,
52}
53
54#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
55#[serde(rename_all = "snake_case")]
56pub enum PathResolution {
57    Lexical,
58    RelativeUnresolved,
59    ContainsParentTraversal,
60    KernelFdResolved,
61}
62
63#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
64#[serde(tag = "event_type", rename_all = "snake_case")]
65pub enum CanonicalEffect {
66    ProcessSpawn {
67        actor: Option<CanonicalExecutable>,
68        mechanism: SpawnMechanism,
69    },
70    ProcessExec {
71        from: Option<CanonicalExecutable>,
72        executable: CanonicalExecutable,
73    },
74    FilePathAccess {
75        actor: Option<CanonicalExecutable>,
76        execution_chain: Vec<CanonicalExecutable>,
77        operation: FileOperation,
78        target: CanonicalPath,
79        open_intent: Option<OpenIntent>,
80    },
81    FileRename {
82        actor: Option<CanonicalExecutable>,
83        execution_chain: Vec<CanonicalExecutable>,
84        from: CanonicalPath,
85        to: CanonicalPath,
86    },
87    NetworkConnectAttempt {
88        actor: Option<CanonicalExecutable>,
89        execution_chain: Vec<CanonicalExecutable>,
90        endpoint: CanonicalNetworkEndpoint,
91    },
92}
93
94#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
95pub struct OpenIntent {
96    pub read: bool,
97    pub write: bool,
98    pub create: bool,
99    pub truncate: bool,
100    pub append: bool,
101    pub path_only: bool,
102    pub resolve_flags: u64,
103    pub other_flags: u64,
104}
105
106#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
107#[serde(tag = "address_family", rename_all = "snake_case")]
108pub enum CanonicalNetworkEndpoint {
109    Inet { ip: String, port: u16 },
110    Inet6 { ip: String, port: u16 },
111    Unix { path: Option<CanonicalPath> },
112    Other { family: u16 },
113}