Skip to content

Common Module (common)

common is a standalone crate providing logging, standardized errors, CLI parsing, and the ports and adapters for configuration and permissions. It has no domain logic and no hardware dependencies; it is the cross-cutting utility layer that keeps the hexagon pure.

Key principle: common is pure Rust: no unsafe code, no FFI, no platform-specific dependencies. It can be compiled and tested on any platform.

common has no feature flags. It contains only portable, cross-platform code. Unlike other domain crates, its adapters are always compiled (not feature-gated) since they provide essential cross-cutting functionality.

AdapterImplements PortPurpose
FileConfigAdapterConfigProviderParses static configuration files (TOML, JSON, YAML)
SQLitePermissionAdapterPermissionManagerSQLite storage for user-granted permissions

At the foundation of the dependency graph, common acts as a shared utility layer. The composition root (pai-engine) and core depend on it directly. Together with Core, it forms the hardware-agnostic “hexagon”. All other domain crates safely rely on common (often transitively through Core) for shared logging and error traits.

Like other domain crates, common follows the Hexagonal Architecture pattern. For an overview of this structure, see Engine Domains.

Key difference from other crates: The adapters in common are always compiled (not feature-gated), since they provide essential cross-cutting functionality needed by all domain crates.

ComponentResponsibility
LoggerCentralized, thread-safe tracing and logging facility used by all crates
ErrorTypesGlobal, standardized error definitions for consistent error handling across domain boundaries
ArgParseCommand-line argument parsing for the engine executable
  • Contract: Defines how system and hardware configuration is retrieved.
  • Adapter: FileConfigAdapter: Parses static configuration files from the local filesystem (e.g., hardware.toml).
  • Supported formats: TOML, YAML, or JSON. The adapter must detect the format automatically (via file extension or content sniffing) or be configured explicitly at initialization.
  • Domain crates depend only on the ConfigProvider trait; they never depend on file formats or filesystem details.

PermissionManager Port & SQLitePermissionAdapter

Section titled “PermissionManager Port & SQLitePermissionAdapter”
  • Contract: The critical contract for the HITL security concept. Resolves whether an action is “Allowed”, “Denied”, or “Ask”.
  • Adapter: SQLitePermissionAdapter: Connects to a local SQLite database to persistently store and retrieve user-granted permissions and preferences.
  • Domain crates call the trait only; they do not depend on SQLite or any specific storage implementation.
  • Not feature-gated. The PermissionManager port and its adapter are always compiled. Making the permission system optional would weaken the HITL security guarantee: every build must enforce permission checks. For testing, a MockPermissionAdapter (always returns “Allowed”) can be injected via the composition root; the port itself is never conditionally compiled.