fix(drivers): flip runtime tag parsers to strict enum parsing (#457) #465

Merged
dohertj2 merged 1 commits from fix/457-runtime-parsers-strict into master 2026-07-15 11:29:04 -04:00
Owner

Closes #457 (archreview R2-11 Phase C).

Flips all six equipment-tag parsers (Modbus/S7/AbCip/AbLegacy/TwinCAT/Focas) from lenient to strict enum parsing. A present-but-invalid (typo'd) enum now rejects the tag at the runtime resolver — TryParse false -> EquipmentTagRefResolver.TryResolve false -> driver surfaces BadNodeIdUnknown — instead of silently defaulting to a wrong-width Good.

Mechanism: new TagConfigJson.TryReadEnumStrict<TEnum>(root, name, fallback, out value) — absent => fallback, valid => parsed, invalid => returns false. The six parsers swap their ReadEnumOrDefault calls for it (Modbus flips all three enum fields region/dataType/byteOrder; the rest flip dataType). The lenient ReadEnumOrDefault primitive stays for any future lenient caller.

Acceptance item 1 (fleets deploy clean under Error mode): this is the operator rollout step — a fleet that deploys clean under Deployment:TagConfigValidationMode=Error has, by construction, no typo'd enums and is safe on the flip. The Error-mode deploy gate is unchanged and unit-proven (AdminOperationsActorTagConfigGateTests).

Regression coverage (item 2):

  • Six *EquipmentTagParserStrictnessTests inverted from Freeze_typo_* (froze lenient) to Typo_*_rejects_the_tag + Valid_*_still_parses.
  • TagConfigJsonTests.TryReadEnumStrict_rejects_only_invalid matrix.
  • Driver-level end-to-end proof: AbCipEquipmentTagTests.Driver_read_of_a_typod_dataType_ref_surfaces_BadNodeIdUnknown drives the real AbCipDriver.ReadAsync through resolve->status.

Golden parity corpus has no typo'd enums (no-op there). Full solution builds clean; all six driver suites + Core.Abstractions + parity + deploy-gate tests green.

Closes #457 (archreview R2-11 Phase C). Flips all six equipment-tag parsers (Modbus/S7/AbCip/AbLegacy/TwinCAT/Focas) from lenient to **strict** enum parsing. A present-but-invalid (typo'd) enum now rejects the tag at the runtime resolver — `TryParse` false -> `EquipmentTagRefResolver.TryResolve` false -> driver surfaces **`BadNodeIdUnknown`** — instead of silently defaulting to a wrong-width `Good`. **Mechanism:** new `TagConfigJson.TryReadEnumStrict<TEnum>(root, name, fallback, out value)` — absent => fallback, valid => parsed, invalid => returns false. The six parsers swap their `ReadEnumOrDefault` calls for it (Modbus flips all three enum fields region/dataType/byteOrder; the rest flip dataType). The lenient `ReadEnumOrDefault` primitive stays for any future lenient caller. **Acceptance item 1 (fleets deploy clean under `Error` mode):** this is the operator rollout step — a fleet that deploys clean under `Deployment:TagConfigValidationMode=Error` has, by construction, no typo'd enums and is safe on the flip. The `Error`-mode deploy gate is unchanged and unit-proven (`AdminOperationsActorTagConfigGateTests`). **Regression coverage (item 2):** - Six `*EquipmentTagParserStrictnessTests` inverted from `Freeze_typo_*` (froze lenient) to `Typo_*_rejects_the_tag` + `Valid_*_still_parses`. - `TagConfigJsonTests.TryReadEnumStrict_rejects_only_invalid` matrix. - **Driver-level end-to-end proof:** `AbCipEquipmentTagTests.Driver_read_of_a_typod_dataType_ref_surfaces_BadNodeIdUnknown` drives the real `AbCipDriver.ReadAsync` through resolve->status. Golden parity corpus has no typo'd enums (no-op there). Full solution builds clean; all six driver suites + Core.Abstractions + parity + deploy-gate tests green.
dohertj2 added 1 commit 2026-07-15 11:28:54 -04:00
fix(drivers): flip runtime tag parsers to strict enum parsing (#457)
v2-ci / build (pull_request) Successful in 4m12s
v2-ci / unit-tests (pull_request) Failing after 10m15s
e8db0a683f
R2-11 Phase C. All six equipment-tag parsers (Modbus/S7/AbCip/AbLegacy/
TwinCAT/Focas) now read enum fields via the new TagConfigJson.TryReadEnumStrict:
absent -> fallback, valid -> parsed, present-but-invalid (typo) -> TryParse
returns false -> EquipmentTagRefResolver.TryResolve false -> driver surfaces
BadNodeIdUnknown, instead of the old lenient path that silently defaulted a
typo to a wrong-width Good.

Modbus flips all three enum fields (region/dataType/byteOrder); the other five
flip dataType. The deploy-time Deployment:TagConfigValidationMode=Error gate is
unchanged and remains the operator pre-flight.

Coverage:
- Six *EquipmentTagParserStrictnessTests inverted from Freeze_typo_* (lenient)
  to Typo_*_rejects_the_tag + Valid_*_still_parses.
- TagConfigJsonTests.TryReadEnumStrict_rejects_only_invalid matrix.
- Driver-level end-to-end proof:
  AbCipEquipmentTagTests.Driver_read_of_a_typod_dataType_ref_surfaces_BadNodeIdUnknown
  drives the real AbCipDriver.ReadAsync through resolve->status.

Golden parity corpus has no typo'd enums, so the flip is a no-op there.
Full solution builds clean; all six driver suites + core + parity + gate green.
dohertj2 merged commit c417502db1 into master 2026-07-15 11:29:04 -04:00
Sign in to join this conversation.