CSV typed-column merge silently rewrites a typo'd enum in the TagConfigJson cell before any gate can see it #553
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found by the #551 work; the CSV analogue of #549 (silent retype instead of a dead tag).
CsvDriverTagMap.ApplyTypedColumnsround-trips the free-formTagConfigJsoncell through the driver model'sFromJson/ToJsonto merge the typed columns — and that lenient load turns"dataType":"Intt16"intoInt16before the #551 import gate (or any later gate) can judge it. The operator's typo is silently replaced by the default; only keys the model does not own (e.g. keys like ModbusstringByteOrderbefore #551, or unknown keys) survive the round-trip to be judged.Related: the MTConnect CSV export writes
driverDataTypeinto the residual cell (the typed map doesn't own it), so a validdriverDataTypere-imports and out-ranks theMtDataTypecolumn at the driver — an operator editsMtDataTypein the exported CSV, re-imports, and the change is silently ignored (#550's editor normalisation only repairs it on the next editor save).Fix direction: validate the raw pre-merge cell (run
TagConfigValidatorover the as-imported blob beforeApplyTypedColumns), and/or make the merge normalise runtime-preferred aliases the same way the editors now do. A rejected row must be an ERROR, not a silent rewrite.FIXED — merged to master as
62fe6c83(branch commitcf2af8a5).Characterization on the current tree first (the issue was filed against pre-#550/#551 analysis), which narrowed the real defect: MTConnect's invalid-alias and invalid-cell cases were already caught (#550 flowing through the #551 gate — MTConnect uses a raw-key map that never round-trips), but the model-backed maps (Modbus/S7) genuinely laundered (
"dataType":"Intt16"→ silentInt16), and the valid-alias case plus the whole export side were still broken:ReadTypedColumnsread only the canonical key, so export printed the ignored value in the typed column and left the winning alias in the residual — actively setting the re-import trap.Fix — evidence preservation, not a second validator:
ModelBackedCsvDriverTagMap.ApplyTypedColumnsrestores the base cell's own tokens over the model's serialisation for every key no non-blank typed column overrode. Fragment + typed-columns composition is byte-identical; nothing in the CSV layer decides validity — the #551 gate (TagConfigValidator→ each model'sValidate()) stays the one authority, now judging unlaundered evidence.CsvTypedColumngainedReadKeys/OwnedJsonKeys— the full ordered spelling set the RUNTIME reads (MTConnectdriverDataType→dataType,fullName→dataItemId→address, mirroringTryFromTagConfig). A firing column clears out-ranking aliases (so an editedMtDataTypegenuinely wins), the export residual strips them, and export cells show the effective value via precedence-orderedReadEffective.TypedOverrodeFallbackextended to the whole owned key set). #549's doctrine is against silent rewrites; every token that reaches the stored blob is judged, and a token the operator overrode is discarded visibly.Falsified: guard neutered → exactly the 7 defect-closing tests red, 8 acceptance controls green, and the #551 gate suites stayed 53/53 green under the neutered build (layer in front of the gate, not a replacement). Verified on the merged tree: AdminUI 1262, MTConnect 534, Modbus 373, S7 285, TwinCAT 205 — all green.
Residual found en route, filed separately: non-enum model-owned keys (e.g. Modbus
address) are judged by the deploy-gateInspectsince #551 but by no authoring model (#554).