a2ui-project / a2ui-project/a2ui

Component schema validation silently ignores primitive type mismatches

Đang mở
#1,899 1 bình luận 0 reaction 1 người được giao Được @andrewkolos nhận Xem trên GitHub
component: genui P2 status: first-line-handled type: bug
Ngôn ngữ chính
TypeScript
Star
16.4k
Fork
1.3k
Merge trung bình
2 ngày 13 giờ
Pull request đã merge (30 ngày)
134

Mô tả

_↴ Ported from [flutter/genui#954](https://github.com/flutter/genui/issues/954) — originally opened by [andrewkolos](https://github.com/andrewkolos) on 2026-06-03._
_Original labels: front-line-handled_
_Original assignees: [andrewkolos](https://github.com/andrewkolos)_

---

Currently, GenUI uses a bespoke JSON Schema walker ([`_validateInstance`](https://github.com/flutter/genui/blob/c79062b7094eacc6e849ed97b8b507aa50237f02/packages/genui/lib/src/model/ui_models.dart#L235-L300) inside [`SurfaceDefinition.validate`](https://github.com/flutter/genui/blob/c79062b7094eacc6e849ed97b8b507aa50237f02/packages/genui/lib/src/model/ui_models.dart#L155)) to validate incoming components.

While this custom validator correctly enforces structural keywords like `const`, `enum`, `required`, and `properties`, it doesn't consider `type`.Because `type` is not validated, per-property primitive-type mismatches silently pass the validation layer.

Example: suppose a `MyButton` component expects a `label` of type `string` and a `width` of type `integer`, the following malformed component will successfully pass validation:
```json
{"id": "btn", "component": "Button", "label": 42, "width": "two"}
```
This bad data lands in [`ComponentModel.properties`](https://github.com/flutter/genui/blob/c79062b7094eacc6e849ed97b8b507aa50237f02/packages/a2ui_core/lib/src/core/component_model.dart#L22) with the wrong types, silently corrupting the data model and eventually causing a crash at render time when the Flutter widget expects a `String` but finds an `int`.

Also, here's a failing test that captures the issue:

```dart
// in ui_models_test.dart
test('validate enforces primitive types (this will fail due to the bug)', () {
final component = const Component(
id: 'test',
type: 'Text',
// oopsies, text is a number
properties: {'text': 42},
);
final surfaceDefinition = SurfaceDefinition(
surfaceId: 's1',
components: {'test': component},
);

final schema = S.object(
properties: {
'components': S.list(
items: S.object(
properties: {
'component': S.string(constValue: 'Text'),
'text': S.string(), // Validator should enforce this.
},
),
),
},
);

expect(
() => surfaceDefinition.validate(schema),
throwsA(isA()),
);
});
});
```

Initially, I was confused as to why we aren't using the `json_schema_builder` package to validate these components. However, I there are a few reasons:

1. `Schema.validate()` is async. [`SurfaceController.handleMessage`](https://github.com/flutter/genui/blob/c79062b7094eacc6e849ed97b8b507aa50237f02/packages/genui/lib/src/engine/surface_controller.dart#L101) is a synchronous `void` function responding to `Stream.listen(...)`. Going async would ripple through callers and could involve a good amount of refactoring.
2. The global catalog schema defines many things (`{components, styles, functions}`). If we feed a component payload directly to the package, it will fail because `styles` and `functions` are missing. The hand-rolled implementation in `SurfaceDefinition.validate` drills down into the `oneOf` branch and validates the component against *only* its specific sub-schema.
3. The current implementation throws an [`A2uiValidationException`](https://github.com/flutter/genui/blob/c79062b7094eacc6e849ed97b8b507aa50237f02/packages/genui/lib/src/model/ui_models.dart#L366) containing a formatted `path` on the first failure, which is optimized for relaying over our protocol back to the server.

## Fixes

Band-aid fix: extend the `_validateInstance` method to explicitly check the `type` keyword (and ideally `additionalProperties`).

Proper fix (maybe): Delegate entirely to `json_schema_builder` to close all spec gaps. This will require:
- Make `SurfaceController.handleMessage` async.
- Writing an adapter to translate `ValidationError` lists into `A2uiValidationException`s.

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Hướng nghiên cứu

The validation logic is in packages/genui/lib/src/model/ui_models.dart, specifically the _validateInstance function. Start by examining how it currently walks the schema and where the 'type' keyword is ignored. The failing test in ui_models_test.dart shows the expected behavior. To fix, extend _validateInstance to check primitive types, or research integrating the json_schema_builder package, considering the async and error translation challenges outlined.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
dart, json, typescript
Lĩnh vực
backend-api-design
Loại issue
Lỗi
Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức độ hoạt động
Ít trao đổi
Độ rõ ràng
Đặc tả rõ ràng
Mức phù hợp với người mới
40/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.