ExfilGuardian
Conventions

Code Style

Patterns and anti-patterns for Rust and TypeScript

Rust

Module Structure

mod.rs should only contain pub mod declarations:

// Good
pub mod analyzer;
pub mod baseline;

// Bad - no logic in mod.rs
pub mod analyzer;
pub fn some_function() { }

Error Handling

  • thiserror for library errors (engine)
  • anyhow for application errors (api, cli)
  • Always use ? - never unwrap() in production
// Library
#[derive(Debug, thiserror::Error)]
pub enum ExfilError {
    #[error("Capture error: {0}")]
    Capture(String),
}

// Application
fn load_config(path: &str) -> anyhow::Result<AppConfig> {
    let content = std::fs::read_to_string(path)
        .context("Failed to read config")?;
    Ok(serde_yaml::from_str(&content)?)
}

Import Order

// 1. Standard library
use std::sync::Arc;

// 2. External crates
use serde::{Deserialize, Serialize};

// 3. Workspace crates
use exfil_engine::common::types::ThreatEvent;

// 4. Current crate
use crate::handlers::threats;

Functions

  • Max 40 lines per function
  • Return Result<T> over panicking
  • Document public APIs with ///

Protobuf

Style

  • One .proto per service/domain (exfil.proto)
  • Messages: PascalCase, fields: snake_case
  • Always specify field numbers explicitly
  • Use bytes for raw payloads, string for text
service ExfilService {
  rpc StreamPackets(stream NetworkPacket) returns (StreamResponse);
}

message NetworkPacket {
  uint32 protocol   = 1;
  uint32 local_ip   = 2;
  uint32 remote_ip  = 3;
  bytes  payload    = 7;
}

TypeScript

Component Structure

// 1. Imports
import { useState } from "react";

// 2. Types
interface ThreatListProps {
  filter?: string;
}

// 3. Named export
export function ThreatList({ filter }: ThreatListProps) {
  return <div>{/* ... */}</div>;
}

Rules

  • Server Components by default - "use client" only for interactivity
  • Named exports - no export default except page.tsx/layout.tsx
  • No barrel files - no index.ts re-exporting
  • Biome for linting: bun run check, bun run format

On this page