# Story 11.14: Danfoss Parser Status: done ## Story As a refrigeration engineer, I want Danfoss compressor data integration, so that I can use Danfoss coefficients in simulations. ## Acceptance Criteria 1. **Given** a `DanfossBackend` struct **When** constructed via `DanfossBackend::new()` **Then** it loads the compressor index from `data/danfoss/compressors/index.json` **And** eagerly pre-caches all referenced model JSON files into memory 2. **Given** a valid Danfoss JSON file **When** parsed by `DanfossBackend` **Then** it yields a `CompressorCoefficients` struct with all 10 capacity and 10 power coefficients **And** it supports AHRI 540 format extraction 3. **Given** `DanfossBackend` implements `VendorBackend` **When** I call `list_compressor_models()` **Then** it returns all model names from the pre-loaded cache in sorted order 4. **Given** a valid model name **When** I call `get_compressor_coefficients("some_model")` **Then** it returns the full `CompressorCoefficients` struct 5. **Given** a model name not in the catalog **When** I call `get_compressor_coefficients("NONEXISTENT")` **Then** it returns `VendorError::ModelNotFound("NONEXISTENT")` 6. **Given** `list_bphx_models()` called on `DanfossBackend` **When** Danfoss only provides compressor data here **Then** it returns `Ok(vec![])` (empty list, not an error) 7. **Given** `get_bphx_parameters("anything")` called on `DanfossBackend` **When** Danfoss only provides compressor data here **Then** it returns `VendorError::InvalidFormat` with descriptive message 8. **Given** unit tests **When** `cargo test -p entropyk-vendors` is run **Then** all existing tests still pass **And** new Danfoss-specific tests pass (model loading, error cases) ## Tasks / Subtasks - [x] Task 1: Create sample Danfoss JSON data files (AC: 2) - [x] Subtask 1.1: Create `data/danfoss/compressors/index.json` with sample models - [x] Subtask 1.2: Create `data/danfoss/compressors/model1.json` with realistic coefficients - [x] Subtask 1.3: Create `data/danfoss/compressors/model2.json` as second model - [x] Task 2: Implement `DanfossBackend` (AC: 1, 3, 4, 5, 6, 7) - [x] Subtask 2.1: Create `src/compressors/danfoss.rs` with `DanfossBackend` struct - [x] Subtask 2.2: Implement `DanfossBackend::new()` resolving to `ENTROPYK_DATA` with fallback to `CARGO_MANIFEST_DIR`/data - [x] Subtask 2.3: Implement `load_index()` and `load_model()` pre-caching logic (incorporating fixes from Swep) - [x] Subtask 2.4: Implement `VendorBackend` trait for `DanfossBackend` - [x] Task 3: Wire up module exports - [x] Subtask 3.1: Add `pub mod danfoss;` in `src/compressors/mod.rs` - [x] Subtask 3.2: Re-export `DanfossBackend` in `src/lib.rs` - [x] Task 4: Write unit tests (AC: 8) - [x] Subtask 4.1: Test `DanfossBackend::new()` successfully constructs - [x] Subtask 4.2: Test `list_compressor_models()` returns sorted models - [x] Subtask 4.3: Test `get_compressor_coefficients()` returns valid data - [x] Subtask 4.4: Test `ModelNotFound` error for unknown model - [x] Subtask 4.5: Test `list_bphx_models()` returns empty - [x] Subtask 4.6: Test `get_bphx_parameters()` returns `InvalidFormat` - [x] Task 5: Verify all tests pass (AC: 8) - [x] Subtask 5.1: Run `cargo test -p entropyk-vendors` - [x] Subtask 5.2: Run `cargo clippy -p entropyk-vendors -- -D warnings` - [x] Task 6: Review Follow-ups (AI) - [x] Fix Error Swallowing during JSON deserialization to provide contextual file paths - [x] Fix Path Traversal vulnerability by sanitizing model parameter - [x] Improve Test Quality by asserting multiple coefficients per array - [x] Improve Test Coverage by adding test directly validating `DanfossBackend::from_path()` - [ ] Address Code Duplication with `CopelandBackend` (deferred to future technical debt story) ## Dev Notes ### Architecture **This builds entirely on the `VendorBackend` trait pattern** established in epic 11. Similar to `CopelandBackend` and `SwepBackend`, `DanfossBackend` pre-caches JSON files containing coefficients mapping to `CompressorCoefficients`. ### Project Structure Notes ```text crates/vendors/ ├── data/danfoss/compressors/ │ ├── index.json # NEW: ["model1", "model2"] │ ├── model1.json # NEW: Ahri 540 coefficients │ └── model2.json # NEW: Ahri 540 coefficients └── src/ ├── compressors/ │ ├── danfoss.rs # NEW: main implementation │ └── mod.rs # MODIFY: add `pub mod danfoss;` ├── lib.rs # MODIFY: export DanfossBackend ``` ### Critical Git/Dev Context - Keep error logging idiomatic: use `log::warn!` instead of `eprintln!` (from recent `SwepBackend` fix `c5a51d8`). - Maintain an internal sorted `Vec` for models in the struct to guarantee deterministic output from `list_compressor_models()` without resorting every time (Issue M1 from Swep). - Make sure `data` directory resolution uses standard pattern `ENTROPYK_DATA` with fallback to `CARGO_MANIFEST_DIR` in debug mode. ### Testing Standards - 100% test coverage for success paths, missing files, invalid formats, and `vendor_name()`. - Place tests in `src/compressors/danfoss.rs` in `mod tests` block. ### References - [Source: epics.md#Story-11.14](file:///Users/sepehr/dev/Entropyk/_bmad-output/planning-artifacts/epics.md) - [Source: copeland.rs](file:///Users/sepehr/dev/Entropyk/crates/vendors/src/compressors/copeland.rs) - Primary implementation reference for compressors - [Source: swep.rs](file:///Users/sepehr/dev/Entropyk/crates/vendors/src/heat_exchangers/swep.rs) - Reference for the latest architectural best-practices applied ## Dev Agent Record ### Agent Model Used Antigravity (Gemini) ### Debug Log References ### Completion Notes List - Comprehensive story details extracted from Epic 11 analysis and previously corrected Swep implementation. - Status set to ready-for-dev with BMad-compliant Acceptance Criteria list. - Implemented `DanfossBackend` mimicking the robust pattern of `CopelandBackend`, and applied architectural fixes from `SwepBackend` (idomatic error logging, sorting `list_compressor_models`). - Created Danfoss JSON data files: `index.json`, `SH090-4.json`, `SH140-4.json`. - Integrated `danfoss` module into the vendors crate and re-exported `DanfossBackend` inside `lib.rs`. - Added unit tests mimicking Copeland coverage. Ran `cargo test` and `cargo clippy` to achieve zero warnings with all tests passing. - Advanced story status to `review`. - Code review findings addressed: fixed error swallowing during deserialization, sanitized input to prevent path traversal, added `from_path()` test coverage, and tightened test assertions. Deferred code duplication cleanup. - Advanced story status from `review` to `done`. ### File List - `crates/vendors/data/danfoss/compressors/index.json` (created) - `crates/vendors/data/danfoss/compressors/SH090-4.json` (created) - `crates/vendors/data/danfoss/compressors/SH140-4.json` (created) - `crates/vendors/src/compressors/danfoss.rs` (created) - `crates/vendors/src/compressors/mod.rs` (modified) - `crates/vendors/src/lib.rs` (modified)