Skip to main content

dpp_calc/
lib.rs

1//! EU-methodology compliance calculators for Odal Node.
2//!
3//! Pure, stateless calculation of regulatory metrics from typed inputs. No I/O,
4//! no infrastructure — every function is deterministic and side-effect free.
5//!
6//! **Placement:** these compute *EU methodology* (cradle-to-gate CO₂e, battery
7//! CFB stub) plus a non-regulatory repairability heuristic, so they change when a
8//! regulation changes and therefore live in `dpp-core` under Apache-2.0 — not in
9//! the platform.
10//! The licensing split: the methodology is open; licensed LCI datasets are
11//! never bundled here and are injected at runtime via [`factor::FactorProvider`].
12//!
13//! # Architecture
14//!
15//! ```text
16//! ┌──────────────────────────────────────────────────────────────────────┐
17//! │  dpp-calc (Apache-2.0, open)                                         │
18//! │                                                                      │
19//! │  co2e::calculate()          — cradle-to-gate, operator-supplied EFs  │
20//! │  repairability::calculate() — non-regulatory heuristic → A–E band    │
21//! │  co2e::cfb::calculate_cfb() — STUB → CalcError::NotImplemented       │
22//! │                                                                      │
23//! │  ruleset_registry           — date-based ruleset resolution          │
24//! │  Ruleset / RegulatoryBasis  — legal citation in every ruleset        │
25//! │  FactorProvider             — runtime injection point for LCI data   │
26//! │  CalculationReceipt         — proof-of-calculation envelope          │
27//! └──────────────────────────────────────────────────────────────────────┘
28//! ```
29//!
30//! Every calculator emits a [`receipt::CalculationReceipt`] that records the
31//! input hash, ruleset id + version, factor dataset version and table hash —
32//! ready to be stored in the proof-bound store for notified-body audit.
33//!
34//! # Adding a new sector calculator
35//!
36//! ## New methodology (algorithm not yet in dpp-calc)
37//!
38//! 1. Add `src/{methodology}/` with four files (see `co2e/` or `repairability/`):
39//!    - `mod.rs`        — `pub fn calculate(inputs, ruleset) -> Result<...>` + output types
40//!    - `parameters.rs` — typed input struct (derives `Serialize` for receipt hashing)
41//!    - `thresholds.rs` — `pub trait {Methodology}Ruleset: Ruleset { ... }` + concrete impls
42//!    - `golden_vectors.rs` — `#[cfg(test)]` regression tests
43//! 2. Every `impl RepairabilityRuleset / Co2eRuleset / CfbRuleset` must also
44//!    `impl Ruleset` and fill `regulatory_basis()` with the EU citation.
45//! 3. Add a `resolve_{methodology}()` function to `ruleset_registry/resolve.rs`
46//!    and a `&NewRuleset` row to `all_rulesets()`.
47//! 4. Write golden vectors, including the `all_concrete_rulesets_have_non_empty_regulatory_basis` pattern.
48//! 5. Register the module in `lib.rs`.
49//!
50//! ## New product category on an existing methodology
51//!
52//! 1. Add `impl Ruleset + impl {Methodology}Ruleset` for the new struct in `thresholds.rs`.
53//!    Fill `regulatory_basis` from the product-specific delegated act.
54//! 2. Add a row to the resolver table in `ruleset_registry/resolve.rs` and to
55//!    `all_rulesets()` (one-liner each).
56//! 3. Add golden vectors. Run `cargo test -p dpp-calc`.
57//!
58//! ## Pending delegated act (stub)
59//!
60//! Use `EffectiveDateBound::open(NaiveDate(2100, 1, 1))` as the sentinel and
61//! `regulatory_basis.regulation = "pending — {PEFCR title}"`.
62//! The effective-date guard blocks runtime use; `resolve_*` returns `None` for
63//! all real dates. Keeps the type compile-visible for future plugin wiring.
64//!
65//! ## Superseded ruleset
66//!
67//! - Set `EffectiveDateBound.until` to the last valid day.
68//! - Set `regulatory_basis.superseded_by` to the new ruleset's ID string.
69//! - Keep the row in `ruleset_registry` — receipts reference rulesets by
70//!   ID + version, so removing a row makes old receipts unverifiable.
71
72#![forbid(unsafe_code)]
73
74// Methodology-agnostic spine. Kept private and re-exported below so the internal
75// grouping never leaks: external callers keep using `dpp_calc::error`,
76// `dpp_calc::factor`, `dpp_calc::receipt`, and `dpp_calc::ruleset`.
77mod kernel;
78
79pub mod co2e;
80pub mod repairability;
81pub mod ruleset_registry;
82
83// ── Stable public paths for the spine ────────────────────────────────────────
84pub use kernel::{error, factor, receipt, ruleset};