conductor/docs/VALIDATION.md

53 lines
3.4 KiB
Markdown

# Project Validation
Conductor uses `shared/schemas/conductor-project.schema.json` plus backend semantic validation as the canonical project-document gate. The same validator is used by JSON Apply, create, update, save, stored-project load checks, and frontend diagnostics.
## Compatibility policy
- This release accepts exactly `schemaVersion: "0.1.0"`.
- Other versions fail with `SCHEMA_VERSION_UNSUPPORTED`; Conductor does not guess, coerce, or migrate them.
- Invalid stored JSON is left untouched and returned as `STORED_PROJECT_INVALID` when loaded. There is no automatic v0.1.0 migration.
- Missing properties remain missing and explicit JSON values—including `null`, empty arrays, and empty objects—are preserved. Validation does not apply schema defaults or mutate documents.
## Result contract
Validation returns `valid`, `errors`, and `warnings`. Every issue has a stable `code`, JSON Pointer-style `path`, actionable `message`, and `severity`.
Errors block Apply and persistence. Warnings identify compatibility-only shapes that remain readable but are not executed: `ComponentEvent.inputMap`, non-empty deprecated `action.responseMapping`, component-level binding references, and `Binding.transform`.
Project create/update failures use:
```json
{
"code": "PROJECT_VALIDATION_FAILED",
"message": "Project document is invalid.",
"errors": [],
"warnings": []
}
```
No database write occurs until parsing, schema validation, and semantic validation all succeed. The database access layer repeats the validation assertion so future callers cannot bypass the route gate.
## Semantic rules
Blocking checks cover:
- unique page, action, binding, and project-wide component identities/names;
- supported page/component events and existing action references;
- existing action, component, variable, binding, and default-page references;
- runtime-supported action-response paths and Table-selection sources, triggers, and component target properties;
- variable default-value type compatibility, while preserving explicit `null`;
- component-specific options, configured values, Table columns, and value types;
- balanced templates, supported component value templates, and declared variables;
- exact schema-version compatibility.
Path parameters follow one contract: frontend runtime interpolation resolves `{{components.<name>.value}}` and `{{variables.<name>}}` inside `pathParameters` values; the backend then substitutes those rendered values into bare URL placeholders such as `{{itemId}}`.
Table selection uses the canonical component binding shape `components.<tableName>.selectedRow``components.<displayName>.value` with trigger `onChange`. The source must resolve to exactly one Table and the target must support runtime `value`. Selecting a row updates only ephemeral Preview state; neither the selected row nor the display value is persisted.
## UI and recovery
Visual Editor, Actions & Bindings, JSON Editor, and Preview display the shared result. A validation/network failure leaves canonical state and JSON Editor draft text unchanged. Save remains dirty after failure. Loading an invalid stored document leaves the currently open project intact. New and Load ask for confirmation before discarding unsaved edits.
Project deletion remains backend-only for v0.1.0. A dedicated Projects screen and deletion control are deferred because project browsing is not yet an implemented MVP surface; the existing API continues to require an explicit project ID.