← Anomaly Upload Validator

Anomaly Upload Validator · Specification artifact

Product Requirements Document

What the tool had to do and the constraints it worked inside.

This page is rendered from that DOCX. Same document, same words.

Anomaly Upload Validator — Product Requirements Document

Platform A · Internal Tool · v3.1.4 · September 2026

Document Information

Document Information
PropertyDetail
Product NameAnomaly Upload Validator
Versionv3.1.4 (current; working file v9.1.4)
Document StatusCurrent — reflects delivered functionality through v3.1.4
AuthorEngineering
Last UpdatedSeptember 2026
Distributiondata coordinators and engineering staff

Executive Summary

The Anomaly Upload Validator is a browser-based internal tool that automates the pre-upload preparation of inspection datasets for Platform A. It accepts raw Input Source exports in CSV or XLSX format, validates them against the Platform A upload specification, converts field values across three nomenclature systems (Input Source → Platform A → Platform B), enables human-in-the-loop resolution of unmatched values, and produces a formatted multi-tab XLSX working document ready for upload.

The tool is distributed as a single self-contained HTML file requiring no installation, no server, and no authentication. All data processing runs client-side — no inspection data is transmitted externally.

Problem Statement

Background

Platform B wind farm asset owners engage both Platform A and third-party inspector Input Source for blade inspections. When third-party-sourced data needs to be ingested into Platform A and submitted to Platform B, it must pass through two conversion layers and conform to the Platform A upload specification.

Problems Identified

Impact: Each failed upload or conversion error requires manual rework estimated at 30–90 minutes per dataset.

Goals & Success Metrics

Goals & Success Metrics
GoalSuccess MetricPriority
Eliminate manual pre-upload field checking100% of required fields validated automaticallyMust Have
Automate field value conversionZero manual conversion steps for known field valuesMust Have
Structured resolution for unknown valuesAll unmatched values surfaced with dropdown resolutionMust Have
Support multiple source dataset formatsHandles all known Input Source export structuresMust Have
Zero installation / zero IT dependencyRuns in any modern browser from a shared Drive linkMust Have
Keep data internalNo inspection data transmitted outside local machineMust Have
Engineering can extend conversion mappingsNew rows in Conversions tab update formulas automaticallyShould Have
Operational visibilityCompliance score, anomaly count, turbine count, site breakdown per runShould Have

Users & Personas

Data Coordinator (Primary User)

Receives raw Input Source exports from clients and prepares them for upload to Platform A. Non-technical. Needs clear pass/fail feedback without reading code or formulas.

Engineering / Data Lead (Secondary User)

Owns the conversion mapping tables and is responsible for extending them when new damage types or component combinations appear. Comfortable with spreadsheets. Needs to update the Conversions tab without breaking the output.

Operations Manager (Stakeholder)

Needs confidence that data being uploaded to Platform A and onward to Platform B is accurate and complete. Reviews compliance scores and flags for escalation.

Scope

In Scope — v3.1.4

Added since v2.1:

Out of Scope — v3.1.4

Functional Requirements

FR-01 File Ingestion

Functional Requirements
#RequirementPriority
FR-01.1Accept CSV (UTF-8) and XLSX / XLS file formatsMust Have
FR-01.2Files may be submitted via drag-and-drop or file browser dialogMust Have
FR-01.3First sheet of any XLSX file shall be used as the data sourceMust Have
FR-01.4Filename and row count shall be displayed on successful loadMust Have
FR-01.5Error message shall be displayed if file is empty or unparseableMust Have
FR-01.6No file data shall be transmitted to any external serverMust Have
FR-01.7A date shall be ingested from its underlying value rather than from the parser's display formatting, so that the calendar date is identical in every timezone (v3.0)Must Have
FR-01.8An ingested date shall be normalised to YYYY-MM-DD, retaining a time of day only where the source cell carries one (v3.0)Must Have

FR-02 Column Normalisation

Functional Requirements
#RequirementPriority
FR-02.1Apply a column alias map to normalize variant column names before validationMust Have
FR-02.2Aliases shall include: Date→Inspection Date, Blade Chamber→BladeChamber, Chord (%)→Chord(%), Turbine Serial Number→Serial Number, Links→Source ImagesMust Have
FR-02.3Unrecognized column names shall be passed through unchangedMust Have
FR-02.4Columns shall be matched by content as well as by name. The alias map is a fallback, not the primary mechanism (v2.3)Must Have
FR-02.5Matching shall run two passes: header alias first, in priority order, then a data-shape fingerprint for any field still unmatchedMust Have
FR-02.6A field shall bind by data shape when at least 70% of sampled values in a candidate column match that field's expected shapeMust Have
FR-02.7Where one alias matches several columns, the candidate whose values best fit the field shall win; where shape cannot separate them, the column with more distinct values shall winMust Have
FR-02.8The header row shall be detected automatically within the first 25 rows, so a file carrying a metadata preamble above its header is ingested without manual editingMust Have
FR-02.9A confirmation panel shall show which input column bound to each canonical field, and whether it bound by name or by shapeShould Have

FR-03 Column-Level Validation

Functional Requirements
#RequirementPriority
FR-03.1Verify all 18 required field column headers are present (case-sensitive)Must Have
FR-03.2Missing required columns shall be flagged with field name and descriptionMust Have
FR-03.3Missing conditional columns shall be reported as informational (non-blocking)Must Have

FR-04 Row-Level Validation

Functional Requirements
#RequirementPriority
FR-04.1Every data row shall be validated against all required field rulesMust Have
FR-04.2Severity: integer value 1–5 onlyMust Have
FR-04.3Critical: 'Yes' or 'No' (case-insensitive)Must Have
FR-04.4Inspection Date: YYYY-MM-DD format strictly enforcedMust Have
FR-04.5Damage Location: 'Internal' or 'External' (case-insensitive)Must Have
FR-04.6Blade Side: Code 1 / Value 1 / Code 2 / Value 2 / Code 3 / Value 3 / Code 4 / Value 4Must Have
FR-04.7Distance (m), Length (m), Width (m): numeric valuesMust Have
FR-04.8Coordinates: must contain at least three [x,y] bracketed pairsMust Have
FR-04.9Asset and Coordinates: when empty, flag as Check Internally rather than ErrorMust Have
FR-04.10Serial Number: when empty or absent, raise no flag of any kindMust Have

FR-05 Conversion Engine

Functional Requirements
#RequirementPriority
FR-05.1Detect Component+Material vs Component+Element column structure and apply appropriate concatenationMust Have
FR-05.2Detect Type+Subtype vs AnomalyType+Subtype column structure and apply appropriate concatenationMust Have
FR-05.3Concatenation shall use LEN()=0 guard (not ISBLANK) to handle empty string cells correctlyMust Have
FR-05.4Element conversion: Input Source Component → Platform A Element + Platform B Element via lookupMust Have
FR-05.5Anomaly Type conversion: Input Source Damage Type → Platform A Anomaly Type + Platform B Anomaly Type via lookupMust Have
FR-05.6Blade Side conversion: Blade Side → Platform A Blade Side + Platform B Blade Side via lookupMust Have
FR-05.7Floating-point noise in numeric fields shall be cleaned to 4 decimal places on importShould Have
FR-05.8Blade letter shall be extracted from Asset field when Blade column is empty or contains full labelShould Have
FR-05.9Derived column headers shall render both company names as those companies write them (v2.7.1)Must Have

FR-06 Status System

Functional Requirements
#RequirementPriority
FR-06.1Each row issue shall be assigned one of four statuses: Error, Manual Review, Check Internally, WarningMust Have
FR-06.2Error: required field absent or format invalidMust Have
FR-06.3Manual Review: concatenated value not found in conversion lookup tableMust Have
FR-06.4Check Internally: Asset or Coordinates empty — value may exist in internal recordsMust Have
FR-06.5Warning: conditional field populated but format invalidMust Have
FR-06.6Check Internally rows shall be excluded from compliance score denominatorMust Have

FR-07 Manual Review Resolution

Functional Requirements
#RequirementPriority
FR-07.1Each Manual Review row shall display the original unmatched valueMust Have
FR-07.2A dropdown shall present all valid target-platform values for the affected fieldMust Have
FR-07.3On selection, row status updates to Resolved and correct value written to converted datasetMust Have
FR-07.4A progress counter shall show resolved / total Manual Review countMust Have
FR-07.5Export Converted XLSX shall remain disabled until all Manual Reviews are resolvedMust Have

FR-08 Results Dashboard

Functional Requirements
#RequirementPriority
FR-08.1Summary cards: Total Rows, Clean, Errors, Manual Review, Check Internally, WarningsMust Have
FR-08.2Compliance score as percentage with green/amber/red threshold coloringMust Have
FR-08.3Auto-conversion count and Manual Review count as secondary cardsMust Have
FR-08.4Dataset summary: total anomalies, unique turbine count, site count, per-site breakdownMust Have
FR-08.5Issues table filter tabs: All / Errors / Manual Review / Check Internally / WarningsMust Have

FR-09 Exports

Functional Requirements
#RequirementPriority
FR-09.1Validation Report: dated CSV with columns Row, Anomaly ID, Field, Status, DetailMust Have
FR-09.2Converted XLSX: two-tab workbook — Damages Report + ConversionsMust Have
FR-09.3Damages Report tab shall match column order of the amended Format A file exactlyMust Have
FR-09.4Derived columns shall use live VLOOKUP formulas referencing the Conversions tabMust Have
FR-09.5Conversions tab structured in three editable sections: Element/Component, Anomaly Type, Blade SideMust Have
FR-09.6Exported XLSX filename shall incorporate source filename and export dateShould Have
FR-09.7Every column carrying a value on input shall carry it on output. A column whose output header differs from its canonical field name shall still resolve (v3.1)Must Have
FR-09.8The column-width list shall hold exactly one entry per output column, and shall be revised whenever a column is added, removed or inserted (v3.1.1)Must Have
FR-09.9Column widths shall seat the widest value each column can hold, computed from the conversion tables where those define it (v3.1.3, v3.1.4)Should Have

Non-Functional Requirements

Non-Functional Requirements
IDCategoryRequirement
NFR-01DeploymentSingle self-contained HTML file. No server, no installation, no authentication.
NFR-02CompatibilityChrome, Edge, Firefox, Safari — any version released in the last 3 years.
NFR-03Data PrivacyAll processing client-side. No data transmitted to any external endpoint.
NFR-04PerformanceMust handle up to 10,000 rows without browser freezing.
NFR-05DependenciesSheetJS is the only runtime dependency. Loaded from CDN; cacheable for offline use.
NFR-06PortabilityDistributable via shared Drive folder with no configuration required by recipients.
NFR-07MaintainabilityConversion tables, field definitions, and aliases defined as named constants at top of script.
NFR-08Output fidelityExported XLSX formulas must use LEN()=0 guards rather than ISBLANK() for empty-string cells.

Conversion Mapping Summary

Element / Component

Source: Component + Material column (falls back to Component + Element if Material absent)

Derivation: IF(LEN(Material)>0, Component & " - " & Material, IF(LEN(Element)>0, Component & " - " & Element, Component))

Output: Input Source Component → Platform A Element → Platform B Element

[Conversion table removed. The mapping across vendor, platform and client schemas is proprietary and is not distributed with this document.]

Anomaly Type

Source: Type + Subtype column (falls back to Anomaly Type + Subtype if Type absent)

Derivation: IF(LEN(Subtype)>0, Type & " - " & Subtype, Type)

Output: Input Source Damage Type → Platform A Anomaly Type → Platform B Anomaly Type

[Conversion table removed. The mapping across vendor, platform and client schemas is proprietary and is not distributed with this document.]

Blade Side

Source: Blade Side column (direct lookup — no concatenation)

Output: Blade Side → Platform A Blade Side → Platform B Blade Side

[Conversion table removed. The mapping across vendor, platform and client schemas is proprietary and is not distributed with this document.]

Supported Dataset Formats

Supported Dataset Formats
FormatKnown SourceElement ColumnsAnomaly Type ColumnsBlade Column
Format AFormat A (Input Source)Component + MaterialType + SubtypeEmpty — extracted from Asset
Format BFormat B (Input Source)Component + ElementAnomaly Type + Subtype"Blade A" — letter extracted

Assumptions & Constraints

Assumptions

Constraints

Future Considerations

Future Considerations
FeatureDescriptionPriority
Persistent manual review mappingsSave resolved mappings to localStorage for reuse on future runsHigh
Cross-field conditional validationBladeChamber required when Damage Location = InternalHigh
Duplicate anomaly ID detectionFlag rows where ID appears more than onceMedium
Dynamic VLOOKUP range expansionAuto-extend formula ranges when Engineering adds rowsMedium
Audit loggingWrite run summary to a shared Sheet — pending IT approval for API accessMedium
Direct platform uploadSubmit directly to Platform A upload endpointLow
Additional source platform supportExtend alias map and format detection beyond Input SourceLow

Sign-off

Sign-off
RoleNameDateStatus
Product OwnerMay 2026Pending
Engineering LeadMay 2026Pending
Data OperationsMay 2026Pending

Sign-off above covers the v2.1 scope. Versions v2.2 to v3.1.4 have not been through a separate sign-off.

Anomaly Upload Validator · Platform A · Internal Use Only · v3.1.4 · September 2026

← Back to the Anomaly Upload Validator case study