On this page
The Infrastructure Layer provides stateless utilities that domain crates build upon. These crates handle cross-cutting concerns like database access, logging, configuration, and security.
Characteristics
- May have external I/O - Database, network, filesystem
- No business logic - Technical concerns only
- Reusable - Used across all domain crates
- Configuration-driven - Behavior controlled by config
Crates
| Crate | Purpose |
|---|---|
| systemprompt-database | PostgreSQL/SQLx, connection pooling, migrations |
| systemprompt-logging | Tracing setup, structured logging |
| systemprompt-config | Profile-based configuration |
| systemprompt-events | Event bus, SSE, broadcasting |
| systemprompt-security | JWT validation, authentication |
| systemprompt-cloud | Cloud API client, tenant management |
| systemprompt-loader | File discovery, module loading |
Dependency Rules
Infrastructure layer crates:
- Can depend on Shared layer crates
- Can depend on each other within the layer
- Cannot depend on Domain, Application, or Entry crates
Common Patterns
Database Access
use systemprompt_database::DatabasePool;
// Get pool from AppContext
let pool = ctx.database.clone();
// Execute queries with SQLx
let users = sqlx::query_as!(User,
"SELECT * FROM users WHERE tenant_id = $1",
tenant_id
)
.fetch_all(&*pool)
.await?;
Event Publishing
use systemprompt_events::{EventBus, Event};
// Define an event
#[derive(Event)]
struct UserCreated {
user_id: UserId,
email: String,
}
// Publish
events.emit(UserCreated { user_id, email }).await;
// Subscribe
events.subscribe::<UserCreated, _>(|event| async {
println!("User created: {}", event.user_id);
});
Security Middleware
use systemprompt_security::{JwtValidator, Claims};
// Validate JWT from request
let claims: Claims = validator.validate(&token)?;
// Check scopes
if !claims.has_scope("admin") {
return Err(Forbidden);
}
Configuration Loading
use systemprompt_config::Config;
// Load active profile
let config = Config::load()?;
// Access values
let db_host = config.database.host;
let api_port = config.api.port;
Layer Diagram
┌────────────────────────────────────────────────────────────┐
│ INFRASTRUCTURE LAYER │
│ │
│ ┌──────────┐ ┌─────────┐ ┌────────┐ ┌────────┐ │
│ │ database │ │ logging │ │ config │ │ events │ │
│ └──────────┘ └─────────┘ └────────┘ └────────┘ │
│ │
│ ┌──────────┐ ┌───────┐ ┌────────┐ │
│ │ security │ │ cloud │ │ loader │ │
│ └──────────┘ └───────┘ └────────┘ │
│ │
│ ↓ │
│ Depends on SHARED LAYER │
└────────────────────────────────────────────────────────────┘