
Domain Web
Install when you are building async Rust HTTP services and want domain rules for state, handlers, security, and observability aligned to axum-style stacks.
Overview
domain-web is an agent skill most often used in Build (also Ship) that applies Rust web-domain constraints for async HTTP services, shared state, and type-safe request handling.
Install
npx skills add https://github.com/actionbook/rust-skills --skill domain-webWhat is this skill?
- Maps five domain rules (stateless HTTP, concurrency, latency, security, observability) to Rust design choices
- Async-by-default rule: handlers must not block; CPU work goes to spawn_blocking
- State guidance: Arc and Arc<RwLock<T>> for thread-safe shared application state
- Request-scoped lifecycle via extractors and ownership—no request-local globals
- Type-safe input validation, JWT/session/CORS/rate-limiting called out as security implications
- Five domain rules mapped to design constraints (stateless HTTP, concurrency, latency SLA, security, observability)
- Three critical constraint blocks: async by default, state management, request lifecycle
Adoption & trust: 840 installs on skills.sh; 1.2k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
You are starting a Rust web API but lack a concise checklist tying HTTP realities—concurrency, latency, and validation—to ownership and async patterns.
Who is it for?
Indie builders adding REST or WebSocket APIs in Rust who already picked axum/actix and want constraint-driven review criteria.
Skip if: Teams building only CLI tools, frontends without a Rust server, or greenfield projects where SKILL.md’s web-handler async rules do not apply.
When should I use this skill?
Use when building web services; matches Cargo.toml globs and web/HTTP/API keywords (axum, middleware, JWT, CORS, WebSocket).
What do I get? / Deliverables
After applying the skill, handler design, state sharing, and tracing choices align with non-blocking async Rust web stacks before you wire routes and middleware.
- Constraint-aligned handler and state design
- Review notes on async, ownership, and tracing gaps
Recommended Skills
Journey fit
Spans multiple journey phases - primary shelf plus alternate fits below.
Canonical shelf is Build because the skill encodes Layer 3 web-service design constraints (handlers, extractors, shared state) while implementing backends. Backend is the right subphase: REST/GraphQL/WebSocket servers, middleware, auth, and routing—not frontend UI work.
Where it fits
Sketch Axum router layout with Arc-wrapped app state and extractor-based auth before coding handlers.
Review whether inputs are validated at extractors and JWT/session flows match the skill’s security constraints.
Audit handlers for blocking calls that would stall the async runtime under concurrent load.
How it compares
Use as a domain-constraint checklist alongside framework tutorials—not instead of official axum or tower documentation.
Common Questions / FAQ
Who is domain-web for?
Solo and indie developers shipping Rust HTTP services who want fast, opinionated constraints for async handlers, shared state, and security-minded extractors.
When should I use domain-web?
During Build when structuring routes and app state; during Ship when reviewing blocking handlers, CORS/auth, or missing request tracing before release.
Is domain-web safe to install?
Treat it as procedural guidance tied to Cargo.toml globs; review the Security Audits panel on this Prism page before trusting any third-party skill in your repo.
SKILL.md
READMESKILL.md - Domain Web
# Web Domain > **Layer 3: Domain Constraints** ## Domain Constraints → Design Implications | Domain Rule | Design Constraint | Rust Implication | |-------------|-------------------|------------------| | Stateless HTTP | No request-local globals | State in extractors | | Concurrency | Handle many connections | Async, Send + Sync | | Latency SLA | Fast response | Efficient ownership | | Security | Input validation | Type-safe extractors | | Observability | Request tracing | tracing + tower layers | --- ## Critical Constraints ### Async by Default ``` RULE: Web handlers must not block WHY: Block one task = block many requests RUST: async/await, spawn_blocking for CPU work ``` ### State Management ``` RULE: Shared state must be thread-safe WHY: Handlers run on any thread RUST: Arc<T>, Arc<RwLock<T>> for mutable ``` ### Request Lifecycle ``` RULE: Resources live only for request duration WHY: Memory management, no leaks RUST: Extractors, proper ownership ``` --- ## Trace Down ↓ From constraints to design (Layer 2): ``` "Need shared application state" ↓ m07-concurrency: Use Arc for thread-safe sharing ↓ m02-resource: Arc<RwLock<T>> for mutable state "Need request validation" ↓ m05-type-driven: Validated extractors ↓ m06-error-handling: IntoResponse for errors "Need middleware stack" ↓ m12-lifecycle: Tower layers ↓ m04-zero-cost: Trait-based composition ``` --- ## Framework Comparison | Framework | Style | Best For | |-----------|-------|----------| | axum | Functional, tower | Modern APIs | | actix-web | Actor-based | High performance | | warp | Filter composition | Composable APIs | | rocket | Macro-driven | Rapid development | ## Key Crates | Purpose | Crate | |---------|-------| | HTTP server | axum, actix-web | | HTTP client | reqwest | | JSON | serde_json | | Auth/JWT | jsonwebtoken | | Session | tower-sessions | | Database | sqlx, diesel | | Middleware | tower | ## Design Patterns | Pattern | Purpose | Implementation | |---------|---------|----------------| | Extractors | Request parsing | `State(db)`, `Json(payload)` | | Error response | Unified errors | `impl IntoResponse` | | Middleware | Cross-cutting | Tower layers | | Shared state | App config | `Arc<AppState>` | ## Code Pattern: Axum Handler ```rust async fn handler( State(db): State<Arc<DbPool>>, Json(payload): Json<CreateUser>, ) -> Result<Json<User>, AppError> { let user = db.create_user(&payload).await?; Ok(Json(user)) } // Error handling impl IntoResponse for AppError { fn into_response(self) -> Response { let (status, message) = match self { Self::NotFound => (StatusCode::NOT_FOUND, "Not found"), Self::Internal(_) => (StatusCode::INTERNAL_SERVER_ERROR, "Internal error"), }; (status, Json(json!({"error": message}))).into_response() } } ``` --- ## Common Mistakes | Mistake | Domain Violation | Fix | |---------|-----------------|-----| | Blocking in handler | Latency spike | spawn_blocking | | Rc in state | Not Send + Sync | Use Arc | | No validation | Security risk | Type-safe extractors | | No error response | Bad UX | IntoResponse impl | --- ## Trace to Layer 1 | Constraint | Layer 2 Pattern | Layer 1 Implementation | |------------|-----------------|------------------------| | Async handlers | Async/await | tokio runtime | | Thread-safe state | Shared state | Arc<T>, Arc<RwLock<T>> | | Request lifecycle | Extractors | Ownership via From<Request> | | Middleware | Tower layers | Trait-based composition | --- ## Related Skills | When | See | |------|--