dpp-rules
Pure #![no_std], zero-dependency EU ESPR cross-field regulatory rules.
These are rules that JSON Schema cannot express — "fibre percentages must sum to ~100%", "SVHC concentration > 0.1% triggers disclosure", "surfactant band must be one of the four EU-standard labels". They live here, once, and are consumed by both dpp-domain (standalone validation, no Wasm host) and the Wasm sector plugins (via dpp-plugin-sdk::rules). Every regulatory rule has exactly one implementation.
See docs/architecture/SECTOR-MODEL-CONSOLIDATION.md §7 for the design rationale.
No-std constraint
This crate must remain #![no_std] + alloc with zero dependencies. That is the whole reason C1 extracted it from dpp-domain: sector plugins compile to wasm32-wasip1 and cannot pull in the heavier domain crate. If a rule needs std or an external crate, the rule is in the wrong place.
The CI cargo check target verifies this. Do not break it.
Module structure
Active sectors are batteries, textiles, and electronics. All others have placeholder modules with field documentation; rules will be added as the delegated acts finalise and the sector plugins mature.
Adding a rule
- Find the right module (sector + sub-concern). If the rule applies to more than one sector, it belongs in
chemicals/orcommon/, not under any single sector. - Write a pure function with primitive borrowing inputs (
&str,f64,&[T]). No owned allocations in function arguments. - Return
Result<(), String>for validators,boolfor predicates. - Add a
#[cfg(test)] mod testsblock in the same file. - If the symbol needs to be accessible from
dpp-domainordpp-plugin-sdkcallers without the module path, add apub useline inlib.rs. - Run
cargo test -p dpp-rulesand thencargo test --workspacebefore committing.
Invariants
| Rule | Rationale |
|---|---|
#![no_std] + alloc only |
Wasm sector plugins consume this crate; std is unavailable in wasm32-wasip1 |
Zero [dependencies] in Cargo.toml |
Keeps the plugin graph lean; any dep here becomes a dep of every plugin |
| Primitive borrowing inputs | Callers adapt their own types; this crate depends on neither dpp-domain structs nor serde_json::Value |
| One implementation per rule | The only acceptable duplication is a pub use re-export in lib.rs |
Repairability scoring → dpp-calc |
EN 45554 A–E grade calculation belongs to the calculator crate; only field-level validations live here |
SVHC → chemicals/ |
REACH Art. 33 is cross-sector; it must never be placed under a single sector module |
common/ threshold |
A helper belongs in common/ only if it is used by ≥ 2 sector modules and has no sector-specific meaning |