# Pupoxide: Technical Context for AI Agents
This document provides a comprehensive technical overview of Pupoxide's internal workings, architecture, and DSL syntax. Use this as a reference when implementing new features or refactoring existing code.
## 1. Core Philosophy
Pupoxide is a Rust-native alternative to Puppet.
* **Declarative**: Describe the *state*, not the *steps*.
* **Idempotent**: Applying the same manifest twice has no side effects.
* **Safe**: Uses Rust's memory safety and a Directed Acyclic Graph (DAG) for execution order.
## 2. Architecture (Hexagonal / Modular Monolith)
The project is divided into three main layers to separate business logic from implementation details.
### Domain Layer (`src/domain/`)
The "Source of Truth". Pure logic, no side effects.
* **Resource**: An enum representing a system component (e.g., `File`).
* Each resource has a unique `id` (e.g., `File[/etc/motd]`) and a list of `dependencies`.
* **backup**: Boolean flag to enable/disable state snapshotting (default: `true`).
* **max_backup_size**: Optional limit in bytes for content snapshots.
* **Ensure**: Enum for desired state (`Present`, `Absent`).
* **ResourceProvider (Port)**: An `async_trait` that must be implemented by Infrastructure adapters.
### Application Layer (`src/application/`)
- `PupoxideEngine`: Interface to Rhai, manages resource collection and include-logic.
- `EnvironmentLoader`: Resolution of manifests and modules within an environment.
- `RollbackEngine`: Logic for generating inverse catalogs based on transaction history and backups.
### Infrastructure Layer (`src/infrastructure/`)
External dependencies and system interactions.
* **FsAdapter**: Handles file system operations (create, delete, permissions). It is responsible for making the resource state real.
---
## 3. DSL Syntax (Rhai-based)
### Object Maps
Resources are defined using Rhai Object Maps (`#{...}`) for readability.
```rust
file("/etc/motd", #{
ensure: "present",
content: "Welcome!",
backup: true,
max_backup_size: 1024 * 1024 // 1MB limit
});
```
### Dependencies
Dependencies can be defined in two ways:
1. **Attribute**: `require: resource_object` or `require: "File[/path]"`
2. **Arrow Operator**: `resource1 -> resource2` (ensures 1 is applied before 2).
### Modules and Environments
* **include("mod_name")**: Loads `modules/mod_name/manifests/init.rhai`.
* **Global Collector**: All resources from the main manifest and all included modules are collected into a single pool and sorted together.
---
## 4. Execution Flow
1. **CLI** receives `--environment` and `--config`.
2. **EnvironmentLoader** finds the site manifest (`site.rhai`).
3. **PupoxideEngine** executes the Rhai scripts.
- Functions like `file()` and `include()` are called.
- Resources populate the **Shared Collector**.
4. **Engine** performs a **Topological Sort** on the collected resources.
5. - **Application Layer**: orchestrates resource collection via Rhai, manages environments, and handles the Transaction lifecycle (Snapshot -> Apply -> Log).
- **Execution Flow**:
1. Agent collects facts and sends them to Master.
2. Master evaluates manifests and returns a compiled `Catalog`.
3. Agent performs a **Snapshot** (collects current state and backups).
4. Agent applies the catalog.
5. Agent logs the **Transaction** for possible future rollback.
## 5. Directory Structure
```text
.
├── environments/
│ └── production/
│ ├── manifests/
│ │ └── site.rhai # Entry point
│ └── modules/
│ └── nginx/
│ └── manifests/
│ └── init.rhai
├── src/
│ ├── domain/ # Logic & Models
│ ├── application/ # Engine & Orchestration
│ ├── infrastructure/ # System Adapters
│ └── interface/ # CLI
└── tests/ # Integration Tests
```
## 6. Development Conventions
* **No Unwraps**: Use `Result` and `DomainError`.
* **Async**: Infrastructure layer is async (Tokio).
* **Idempotency**: Always check existence/state before applying changes.
* **Stable IDs**: Resource IDs must be deterministic (e.g., `Type[Path/Name]`).