fix(focas): refuse String on PMC/PARAM/MACRO in the factory, editor and CLI (R07:U8)
FocasDataType.String was authorable on any address, but no area read returns text: PMC fell through to a byte read, PARAM to Int32, MACRO to a double, and the String node received a boxed number at Good. One rule, FocasTagDefinitionFactory.DescribeDataTypeMismatch, now backs every path: - FromTagConfig rejects the pair, so the driver skips + reports it (BadNodeIdUnknown, never a Good number) and Inspect names the reason at deploy; - FocasTagConfigModel.Validate refuses it on the typed fields; - the AdminUI editor only offers String where it is readable and shows the rule's text inline (kept visible for a loaded blob that already carries it); - the CLI read/subscribe/probe/write commands refuse it at the boundary. String stays valid on FIXED: paths (Identity/Program name/mode text) and is ignored on ALARM: tags; an unparseable address keeps its own diagnosis. Razor change (FocasTagConfigEditor.razor) needs the Wave 4 live check. Refs #740 Claude-Session: https://claude.ai/code/session_01Ub9hGmYLQvn9XETzw7CMsT
This commit is contained in:
+16
-2
@@ -15,8 +15,22 @@
|
||||
</div>
|
||||
<div class="col-md-3"><label class="form-label">Data type</label>
|
||||
<select class="form-select form-select-sm" value="@_m.DataType" @onchange="@(e => Update(() => _m.DataType = ParseEnum(e.Value, FocasDataType.Int32)))">
|
||||
@foreach (var v in Enum.GetValues<FocasDataType>()) { <option value="@v">@v</option> }
|
||||
</select></div>
|
||||
@foreach (var v in Enum.GetValues<FocasDataType>())
|
||||
{
|
||||
@* String is only readable from the fixed tree (FocasTagDefinitionFactory.DescribeDataTypeMismatch):
|
||||
offered there, and kept visible when a loaded blob already carries it so the select never lies. *@
|
||||
if (v != FocasDataType.String || _m.DataType == FocasDataType.String
|
||||
|| FocasTagDefinitionFactory.DescribeDataTypeMismatch(v, _m.Address) is null)
|
||||
{
|
||||
<option value="@v">@v</option>
|
||||
}
|
||||
}
|
||||
</select>
|
||||
@if (FocasTagDefinitionFactory.DescribeDataTypeMismatch(_m.DataType, _m.Address) is { } typeError)
|
||||
{
|
||||
<div class="form-text text-danger small">@typeError</div>
|
||||
}
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="focas-writable" disabled checked="false" />
|
||||
|
||||
@@ -80,6 +80,10 @@ public sealed class FocasTagConfigModel
|
||||
// ahead of the parse consult below and is never replaced by it.
|
||||
if (FocasAddress.TryParse(Address) is null) return DescribeUnparseableAddress(Address);
|
||||
|
||||
// The driver's own address/data-type rule (String only on FIXED: paths) — checked on the typed fields so a
|
||||
// model built in the editor is judged too, not only a loaded blob the parse gate below can see.
|
||||
if (FocasTagDefinitionFactory.DescribeDataTypeMismatch(DataType, Address) is { } typeError) return typeError;
|
||||
|
||||
// Parse-gate backstop. ⚠️ It gates on the PARSE VERDICT, never on Inspect being non-empty: FOCAS's
|
||||
// inspector emits advisories for blobs the reader ACCEPTS (an unparseable address, an authored
|
||||
// 'writable':true on a read-only wire), and promoting those to authoring errors would make the modal
|
||||
|
||||
Reference in New Issue
Block a user