From c46b800d56bbc1b5a778caa0bd1d55990c87e523 Mon Sep 17 00:00:00 2001 From: Kelvin Steiner Date: Thu, 9 Oct 2025 13:55:30 -0300 Subject: [PATCH] docs: add guideline to avoid Rust keywords as field names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added explicit rules to both CLAUDE.md and CONTRIBUTING.md prohibiting the use of Rust keywords (type, use, trait, impl, etc.) as struct field names, especially in public APIs. Problem: Rust keywords require the r# prefix (e.g., r#type), which causes serialization inconsistencies across language bindings: - Polkadot.js converts to r_type or rType - Serde serializes as type - Creates confusion and breaks API consistency Solution: Use alternative names like kind, variant, scope, category, or mode instead. This guideline applies to all public structs, especially those in api crates and types exposed to external clients. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- CLAUDE.md | 23 +++++++++++++++++++++-- CONTRIBUTING.md | 5 +++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index bb0cbc70..1ddb5d73 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -26,16 +26,19 @@ Torus is a stake-driven peer-to-peer network built on Substrate. The blockchain The `permission0` pallet manages delegated permissions and access control within the Torus network. Key components: **Core Permission Types** (`pallets/permission0/src/permission.rs`): + - `PermissionContract` - Main permission structure with delegator, recipient, scope, duration, and enforcement - `PermissionId` - Unique permission identifier (H256 hash) - `PermissionScope` - Defines what actions the permission covers - `NamespaceScope` - Defines namespace path permissions for delegation **Permission Scopes** (`pallets/permission0/src/permission/`): + - `pallets/permission0/src/permission/curator.rs` - `CuratorPermissions` and `CuratorScope` types - `pallets/permission0/src/permission/emission.rs` - `EmissionAllocation`, `DistributionControl`, and `EmissionScope` types **Implementation Handlers** (`pallets/permission0/src/ext/`): + - `pallets/permission0/src/ext/curator_impl.rs` - Functions for curator permission enforcement - `pallets/permission0/src/ext/emission_impl.rs` - Functions for emission permission enforcement - `pallets/permission0/src/ext/namespace_impl.rs` - Functions for namespace permission enforcement @@ -77,6 +80,7 @@ cargo build --release # Build the node - **MUST ALWAYS** use `ensure!` macro for validation, NEVER `assert!` - **MUST ALWAYS** use the `?` operator for error propagation - **MUST ALWAYS** use pattern matching with proper error handling: + ```rust let Some(value) = some_option else { return Err(Error::::SomeError.into()); @@ -132,17 +136,32 @@ cargo build --release # Build the node - **MUST ALWAYS** use proper type conversions with `.try_into()` and handle errors - **MUST NEVER** use `as` for lossy numeric conversions +### API Design - MANDATORY + +- **MUST NEVER** use Rust keywords as struct field names (e.g., `type`, `use`, `trait`, `impl`) +- **PROBLEM**: Rust keywords require `r#` prefix (e.g., `r#type`), causing serialization inconsistencies: + - Polkadot.js converts to `r_type` or `rType` + - Serde serializes as `type` + - Creates confusion and breaks API consistency across language bindings +- **MUST ALWAYS** use alternative names: `kind`, `variant`, `scope`, `category`, `mode`, etc. +- **APPLIES TO**: All public structs, especially those in `api` crates and types exposed to external clients + ### Common Code Patterns - REQUIRED - **MUST ALWAYS** emit events after successful state changes: + ```rust Pallet::::deposit_event(Event::::SomethingHappened(who, what)); ``` + - **MUST ALWAYS** validate string data is UTF-8: + ```rust ensure!(core::str::from_utf8(bytes).is_ok(), Error::::InvalidUtf8); ``` + - **MUST ALWAYS** check bounds before operations: + ```rust ensure!(value <= T::MaxValue::get(), Error::::ValueTooLarge); ``` @@ -169,10 +188,10 @@ cargo build --release # Build the node - **MUST NEVER** use repetitive and redundant comments within code - **MUST NEVER** ignore compiler or clippy warnings with `#[allow(...)]` -### Before committing: +### Before committing 1. **MUST** run `cargo fmt` 2. **MUST** run `just check` and fix all warnings 3. **MUST** run `just test` and ensure all pass 4. **MUST** run `cargo xtask coverage` to verify coverage -5. **MUST** test runtime upgrades if storage changed \ No newline at end of file +5. **MUST** test runtime upgrades if storage changed diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 17e3084f..b82c5b1b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -67,6 +67,11 @@ Be idiomatic. Use `Iterator`s, `Result`s, etc. PLEASE. Take a look at [Rust's AP - the WASM runtime that Substrate runs on cannot unwind, so panics in functions like `on_initialize` will halt the chain (been there - more than once); - use `Option` and `Result` types properly for error handling. NEVER allow `unused_must_use`. NEVER; - always prefer panic-free functions and treat all potential errors (`checked_div` in favor of `/`, etc.). +- **Avoid Rust keywords as field names:** + - Never use Rust keywords (`type`, `use`, `trait`, `impl`, etc.) as struct field names, especially in public APIs; + - keywords require the `r#` prefix in Rust (e.g., `r#type`), which causes serialization inconsistencies across language bindings; + - Polkadot.js may convert `r#type` to `r_type` or `rType`, while Serde serializes it as `type`, creating confusion; + - use alternative names like `kind`, `variant`, `scope`, `category`, or `mode` instead. ## Storage modifications and migrations