Skip to main content

chainsafe-rust-architect

Architectural guidance for designing Rust crates and systems at ChainSafe (Forest, Mina-rs, ChainBridge Substrate, PINT, other Rust projects). Use this skill whenever the user is starting a new Rust crate, designing a Rust workspace, choosing an async runtime, picking an error model, deciding `unsafe` usage, structuring a Cargo workspace, deciding `pub` vs `pub(crate)`, picking concurrency primitives, or writing an ADR for Rust work. EVEN IF the user does not explicitly say "architecture" — triggers on "design a Rust crate", "new Rust workspace", "Forest module design", "thiserror or anyhow", "async runtime choice", "Tokio vs async-std", "Arc<Mutex<T>> or channel", "public API surface", "is unsafe justified here", "ADR for Rust", "non_exhaustive enum", "workspace layout". Defers to .invariants for invariants themselves; covers what Rust changes about applying them. Do NOT use for line-level Rust coding (use chainsafe-rust-developer) or Rust PR review (use chainsafe-rust-reviewer).

Zur Installation springen

Quellinformationen

Repository
ChainSafe/engineering-handbook
Letzte Quellaktivität
20. Juli 2026 um 11:44
Erkannte Sprache von SKILL.md
Englisch
Sterne
7
Forks
1

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
chainsafe-rust-architect
description
Architectural guidance for designing Rust crates and systems at ChainSafe (Forest, Mina-rs, ChainBridge Substrate, PINT, other Rust projects). Use this skill whenever the user is starting a new Rust crate, designing a Rust workspace, choosing an async runtime, picking an error model, deciding `unsafe` usage, structuring a Cargo workspace, deciding `pub` vs `pub(crate)`, picking concurrency primitives, or writing an ADR for Rust work. EVEN IF the user does not explicitly say "architecture" — triggers on "design a Rust crate", "new Rust workspace", "Forest module design", "thiserror or anyhow", "async runtime choice", "Tokio vs async-std", "Arc<Mutex<T>> or channel", "public API surface", "is unsafe justified here", "ADR for Rust", "non_exhaustive enum", "workspace layout". Defers to .invariants for invariants themselves; covers what Rust changes about applying them. Do NOT use for line-level Rust coding (use chainsafe-rust-developer) or Rust PR review (use chainsafe-rust-reviewer).
metadata
{"type":"role-workflow","language":"rust","role":"architect","source":"languages/rust/architect.md","authored-via":"anthropic-skills:skill-creator (2026-05-27)"}
# Rust Architect Use this when designing Rust systems at ChainSafe — Forest-shaped work or any Rust crate/library/binary. Full reference: [`languages/rust/architect.md`](../../languages/rust/architect.md). ## Key Rust-specific decisions ### Workspace layout ChainSafe Rust projects use Cargo workspaces (Forest is the canonical example): - Root `Cargo.toml` declares workspace members. - Crates split by concern (network, storage, binary, protocol modules). - A `bin/` crate for the executable; a `lib/` crate for the consumable API. - Workspace-level dependency hoisting where possible. ### Error model - **`thiserror` for library crates.** Typed errors callers can match via `#[derive(thiserror::Error)]`. - **`anyhow` for binary crates.** Pass-through errors with `.context(...)` for ergonomics. - **No mixing** within a single crate without reason. - **`?` for propagation.** No `match` arms on trivial pass-through. ### Async runtime - **Pick one.** Tokio for most ChainSafe work (Forest included). Don't mix tokio and async-std in the same workspace. - **`#[tokio::main]` only in the binary crate.** Library crates stay runtime-agnostic where possible. - **Bounded concurrency:** `FuturesUnordered` with limits, `tokio::sync::Semaphore`, `buffer_unordered` on streams. Unbounded futures-spawn is a leak. - **`Send + Sync + 'static` bounds** — design types so they meet what `tokio::spawn` requires. - **Bounded Duration:** Every potentially blocking external `.await` boundary (network I/O, database interaction, channel reads across subsystems) must have a strict timeout boundary. Combine bounded concurrency (caps *how many*) with bounded duration (caps *how long*) to prevent task pool exhaustion. ### Concurrency primitives - **`Arc<Mutex<T>>`** for shared mutable state across tasks. `tokio::sync::Mutex` when locks span `.await`; `std::sync::Mutex` when they don't. - **Channels:** `mpsc` for many-to-one, `broadcast` for one-to-many, `oneshot` for single-response. - **No `std::thread::spawn` in async code.** Use `tokio::task::spawn` or `tokio::task::spawn_blocking`. ### Public API - **`pub(crate)` is the default.** `pub` is a versioning commitment. - **`#[non_exhaustive]`** on enums and structs that may grow. - **Builder pattern** for complex constructors. - **No leaking tokio types in library APIs** unless feature-gated. - **API & storage isolation.** Keep internal domain types separate from external transport layers. Define serde/wire and database DTOs at the boundary and map them explicitly to domain models; don't hang `#[derive(Serialize, Deserialize)]` or storage-schema concerns directly on domain types. External edges only — not between internal modules. ### Feature-gating and compilation boundaries - **Lean defaults.** Keep `default = []` as minimal as possible. Heavy dependencies (tracing subscribers, database drivers, serialization codecs, dev utilities) live behind optional cargo features, not in the default build. - **Environment isolation.** Abstract environment-specific logic — mocks, test vectors, alternative networking layers — behind descriptive gates like `test-utils` or `mock`. Never leak testing dependencies into production builds. - **Conditional compilation.** Apply `#[cfg(feature = "...")]` intentionally on modules and public entry points so that turning a feature off fully removes its artifacts and upstream dependencies from the compilation graph. - **Features are additive.** Cargo unifies feature sets across the workspace, so a feature may only *add* behavior — never remove or swap it. A `mock` gate that replaces real behavior breaks the moment two crates in one build enable different sets; design gates to layer, not to toggle. ### Unsafe - Every `unsafe` block needs a `// SAFETY: ...` comment with the soundness argument. - Justification beyond "performance." - `miri` testing path when possible. - Minimized — wrap the smallest possible code in `unsafe { }`. ## ADR template for Rust work - Public surface — `pub` vs `pub(crate)` vs private. Justify. - Error type — `thiserror` or `anyhow`. Justify. - Async commitments — which runtime, where required, how the API is shaped. - Unsafe — if any, the soundness argument and safety invariants. - Invariants impacted — deep links into `.invariants`. ## Anti-patterns at design time - `unwrap()` in non-test code without `// SAFETY: ...`. - `Box<dyn Error>` as a function's return type when you could be specific. - `String` everywhere when `&str` would do. - Tokio types leaked through public APIs of library crates without feature flags. - `unsafe` without a soundness comment. ## Forest-specific Forest carries [`AI_POLICY.md`](https://github.com/ChainSafe/forest/blob/main/AI_POLICY.md) which sets the security-critical posture for AI-assisted work in a Filecoin client. Architectural decisions on Forest follow that policy — review-time the Rust reviewer skill will enforce. ## Related - Full reference: [`languages/rust/architect.md`](../../languages/rust/architect.md) - Sister roles: `chainsafe-rust-developer`, `chainsafe-rust-reviewer` - Framework: [`invariants/invariants-framework.md`](../../invariants/invariants-framework.md) - Workflow: `chainsafe-research-plan-implement` - Upstream: [Effective Rust](https://effective-rust.com/) · [The Rust Book](https://doc.rust-lang.org/book/)
Auf GitHub ansehen