Skip to content

Architecture Decision Records

ADRs document key technical decisions made during StorePredict development.

ADR Title Status Date
001 Use NiceGUI for web framework Accepted 2026-02-18
002 DRR ratios from CSV, not hardcoded Accepted 2026-02-18
003 Column alias dictionaries, not fuzzy matching Accepted 2026-02-18
004 DataFrame as pipeline data format, not dataclass Accepted 2026-02-18
005 Most conservative DRR for multi-workload VMs Accepted 2026-02-18
006 Real objects and sample data for tests, no mocks Accepted 2026-02-18
007 AG Grid for VM review table Accepted 2026-02-18
008 Tab storage for data, user storage for preferences Accepted 2026-02-18
009 Dialog for multi-workload assignment Accepted 2026-02-18
010 Target NiceGUI 3.x, not 2.x Accepted 2026-02-19
011 Substring matching for VM classification Accepted 2026-02-19
012 Priority-ordered rule registry with first-match-wins Accepted 2026-02-19
013 Weighted average DRR, not simple mean Accepted 2026-02-19
014 DRR guard with max(drr, 0.1) Accepted 2026-02-19
015 Canonical DataFrame schema (9 columns) Accepted 2026-02-19
016 Template VM filtering at orchestrator level Accepted 2026-02-19
017 RVTools "MB" values treated as MiB, no conversion Accepted 2026-02-19
018 openpyxl read_only mode for format detection Accepted 2026-02-19
019 Shared _build_liveoptics_df helper (DRY) Accepted 2026-02-19
020 Dark mode in app.storage.user (per-user) Accepted 2026-02-19
021 Dual workload edit mechanism (dropdown + dialog) Accepted 2026-02-19
022 Stats container clear-and-rebuild pattern Accepted 2026-02-19
023 Page routes via module import side-effects Accepted 2026-02-19
024 WorkloadDialog persistent + use-chips props Accepted 2026-02-19
025 PDF with ReportLab Platypus, not WeasyPrint Accepted 2026-02-19
026 Vera TTF fonts for French characters Accepted 2026-02-19
027 PDF in-memory via BytesIO, no temp files Accepted 2026-02-19
028 ui.table for report page, not AG Grid Accepted 2026-02-19
029 Three-layer architecture (pipeline → services → ui) Accepted 2026-02-19
030 Docker Compose single-container deployment Accepted 2026-02-19
031 Server-side file validation with magic bytes Accepted 2026-02-19
032 Log sanitization — never log DataFrame contents Accepted 2026-02-19
033 Context manager for shared layout Accepted 2026-02-19
034 SAP word boundary pattern (exception to substring matching) Accepted 2026-02-19
035 PostgreSQL/MySQL rules before generic SQL Accepted 2026-02-19
036 Citrix VMs default to Full Clone (DRR=8) Accepted 2026-02-19
037 FortiNet detection via OS field Accepted 2026-02-19
038 MkDocs with Material theme for documentation Accepted 2026-02-19
039 uv for Python package management Accepted 2026-02-19
040 pyproject.toml as single configuration file Accepted 2026-02-19
041 Strict mypy with TYPE_CHECKING guards Accepted 2026-02-19
042 Web servers default to content included (DRR=5) Accepted 2026-02-19
043 i18n architecture — per-call locale via t() wrapper with YAML files Accepted 2026-02-20
044 Language switch via full page reload Accepted 2026-02-20
045 ECharts (NiceGUI ui.echart) for interactive web charts Accepted 2026-02-20
046 PDF charts on a dedicated second page Accepted 2026-02-20
047 matplotlib for Sankey diagram in PDF Accepted 2026-02-20
048 AG Grid Community constraint — detail bar instead of master-detail Accepted 2026-02-20
049 AG Grid v34 circular context — event args filter Accepted 2026-02-20
050 Row click = inspect (zoom), bulk button = reclassify Accepted 2026-02-20
051 LLM → keyword extraction → rule suggestion feedback loop Accepted 2026-02-20
052 Flat DRR override for non-PowerStore storage models Accepted 2026-02-20
053 Application-level DRR degradation as CSV subcategory variants Accepted 2026-02-20
054 AI classification toggle is per-session, not a server restart Accepted 2026-02-20
055 Multi-dimensional BFD heuristic for datastore layout engine Accepted 2026-02-21
056 Three fixed layout strategies with tunable parameters Accepted 2026-02-21
057 VMFS datastore layout, not vVol Accepted 2026-02-21
058 Dedicated datastore for mission-critical VMs Accepted 2026-02-21
059 Workload-based IOPS defaults for RVTools sizing Accepted 2026-02-21
060 Stable AG Grid row identity via row_index integer Accepted 2026-02-22
061 Health checks as a pure pipeline module, not a blocking pipeline stage Accepted 2026-02-22
062 Compute presets from CSV, not hardcoded Superseded by 076 2026-02-22
063 TypedDict for NiceGUI page session config dicts Accepted 2026-02-22
064 Datacenter/cluster scope filtering as a dedicated pipeline stage Accepted 2026-02-23
065 Windows Desktop OS fallback → VDI Linked Clone Accepted 2026-02-23
066 Session persistence via self-contained zip archive Accepted 2026-02-24
067 SESSION_ZIP_SENTINEL to distinguish session archives from LiveOptics zips Accepted 2026-02-24
068 Remediation hints as hardcoded English strings Accepted 2026-02-24
069 Standalone concerns export as pure ReportLab Accepted 2026-02-24
070 PLAYWRIGHT_BROWSERS_PATH for non-root Docker execution Accepted 2026-02-25
071 Plotly + Kaleido for PDF charts, Playwright removed Accepted 2026-02-25
072 Auto-detect OS dark mode on first visit Accepted 2026-02-25
073 Open Sans fonts, KPI cards, and PDF visual polish Accepted 2026-02-25
074 Open Sans typography in Excel export and PDF charts Accepted 2026-02-25
075 Runtime Request import for chunked upload endpoint Accepted 2026-02-26
076 Remove compute sizing, redirect to PreSizion Accepted 2026-03-15