feat(nakui-ui): validación estricta de params del morphism vía FieldKind
Reemplaza la heurística `infer_param_value` por parseo estricto basado en el `FieldKind` declarado en el `FieldSpec` correspondiente. Un Boolean con value "abc" ahora rebota en la UI con mensaje claro en lugar de fallar opacamente dentro del morphism Rhai. Cambios: - Nuevo helper `resolve_param_value(field_name, raw, spec)`: - Required + empty → error con label legible. - Optional + empty → Value::Null. - Spec presente → parse_field_value(spec.kind, raw) estricto. - Spec ausente (módulo mal-formado) → fallback a infer_param_value. - `commit_morphism` simplificado: el loop de params ahora delega al helper, que es testable sin GPUI. - 6 tests nuevos cubriendo: número estricto, boolean rechaza "abc", required vacío, optional vacío → null, fallback a infer sin spec. 22 tests verdes (+6 nuevos). E2E del morphism real `morphism_pipeline_executes_real_sales_vender` sigue verde — la validación estricta no afecta el path correcto, sólo agrega rebotes tempranos a values mal-tipados. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,66 @@ ratio/diff ver `git show <sha>`.
|
||||
|
||||
## 2026-05-09
|
||||
|
||||
### feat(nakui-ui): validación estricta de params del morphism vía FieldKind del FieldSpec
|
||||
Cierra el último trade-off documentado: `infer_param_value` adivinaba
|
||||
el tipo de cada param por la shape del string (i64 → f64 → bool →
|
||||
string). Ahora cuando hay `FieldSpec` declarado, usamos
|
||||
`parse_field_value(spec.kind, raw)` — un Boolean field con value
|
||||
"abc" rebota con mensaje claro en la UI antes de llegar al morphism
|
||||
Rhai (donde el error sería opaco como "Function not found: * ((), ())").
|
||||
|
||||
Cambios:
|
||||
- **Nuevo helper `resolve_param_value(field_name, raw, spec)`**:
|
||||
- Si hay `FieldSpec`: validación de `required` (rebota empty con
|
||||
"param 'X' es obligatorio y está vacío") + parseo estricto via
|
||||
`parse_field_value(spec.kind, raw)`. Errores incluyen el `label`
|
||||
del spec para que el toast sea interpretable.
|
||||
- Si NO hay spec (param declarado en `Action::Morphism.params`
|
||||
que no existe en `form.fields` — módulo mal-formado): fallback
|
||||
a `infer_param_value` como red de seguridad.
|
||||
- Empty + opcional → `Value::Null`.
|
||||
- **`commit_morphism` simplificado**: el loop de params ahora es
|
||||
3 líneas (lookup spec + llamada a `resolve_param_value` +
|
||||
inserción al map). La lógica vive en el helper standalone,
|
||||
testable sin GPUI.
|
||||
|
||||
Tests: 6 nuevos en `tests` mod, todos contra `resolve_param_value`:
|
||||
- `resolve_param_strict_number_parses_i64` — happy path.
|
||||
- `resolve_param_strict_boolean_rejects_non_boolean` — un Boolean
|
||||
con "abc" rebota con mensaje que incluye el label.
|
||||
- `resolve_param_strict_number_rejects_garbage` — Number con "abc"
|
||||
rebota.
|
||||
- `resolve_param_required_empty_rejected` — required vacío rebota
|
||||
con "obligatorio".
|
||||
- `resolve_param_optional_empty_returns_null` — optional vacío
|
||||
→ null.
|
||||
- `resolve_param_no_spec_falls_back_to_infer` — el fallback
|
||||
preserva el comportamiento anterior para back-compat.
|
||||
|
||||
22 tests verdes en nakui-ui (+6). E2E del morphism real
|
||||
(`morphism_pipeline_executes_real_sales_vender`) sigue verde — la
|
||||
validación estricta no rompe el path correcto, sólo agrega rebotes
|
||||
tempranos a values mal-tipados.
|
||||
|
||||
Beneficio operativo:
|
||||
- Mensaje de error en la UI ahora identifica el field problemático
|
||||
por su label legible ("param 'Cantidad': 'abc' no es número")
|
||||
en lugar del error opaco del morphism Rhai.
|
||||
- Errores se ven antes de tocar el log o el store — ningún cambio
|
||||
parcial.
|
||||
- El módulo Nakui ya no tiene que defender contra inputs garbage
|
||||
desde la UI: la metainterfaz se vuelve la primera línea de
|
||||
validación tipada.
|
||||
|
||||
Pendientes futuros (orden de prioridad):
|
||||
- **Confirmación de delete** — modal antes de borrar.
|
||||
- **Snapshot/compaction** del log para repos grandes.
|
||||
- **Edit delta-only** — sólo campos modificados, no todos.
|
||||
- **EntityRef validation post-submit**: hoy `parse_field_value`
|
||||
para EntityRef devuelve string raw; el commit_morphism luego
|
||||
valida como Uuid sólo cuando es input del morphism. Para
|
||||
EntityRef como param, podríamos validar UUID al submit.
|
||||
|
||||
### feat(nakui-ui): FieldKind::EntityRef — selector clickable de records existentes
|
||||
Cierra el principal trade-off documentado del commit anterior:
|
||||
"Inputs UUID a mano (no dropdown)". Los formularios pueden declarar
|
||||
|
||||
Reference in New Issue
Block a user