conductor/docs/SCHEMA.md

317 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# SCHEMA.md
# Conductor Project JSON Schema
This document describes the canonical JSON schema for Conductor project definitions and explains how to use it.
---
## Location
```
shared/schemas/conductor-project.schema.json
```
The schema lives in `shared/` so it is accessible to both the backend (Node.js/TypeScript) and any future frontend tooling without duplicating the file.
---
## Purpose
Every Conductor project is represented as a single structured JSON document — the *project definition*. This document is the authoritative source of truth for a project. All editors (Visual Editor, JSON Editor) read from and write to this document. The backend persists it as-is to SQLite.
The JSON schema:
- Documents the exact shape of a valid project definition.
- Enables offline validation during development.
- Drives IDE autocomplete and inline error highlighting when `$schema` is set in a project file.
- Will be used by the backend's validation endpoint (Step 11) to reject malformed saves.
- Makes project definitions portable, diffable in Git, and importable/exportable.
---
## Schema Version
The current schema version is **`0.1.0`** (semver).
Every project definition **must** include a `schemaVersion` field:
```json
{
"schemaVersion": "0.1.0",
"project": { ... }
}
```
Consumers (backend, editor, preview runtime) must check the `MAJOR` version component. A document with a higher major version than the consumer understands should be rejected with a clear error.
---
## Top-Level Structure
| Field | Type | Required | Description |
|-----------------|----------|----------|--------------------------------------------------|
| `schemaVersion` | `string` | ✅ | Schema version in `MAJOR.MINOR.PATCH` format. |
| `project` | `object` | ✅ | Root project object containing all definitions. |
---
## `project` Fields
| Field | Type | Required | Description |
|---------------|----------|----------|----------------------------------------------------------------------|
| `id` | `string` | ✅ | Stable unique identifier (UUID or URL-safe slug). Must not change. |
| `name` | `string` | ✅ | Human-readable display name (1200 characters). |
| `description` | `string` | — | Optional free-text description. Defaults to `""`. |
| `pages` | `array` | ✅ | Ordered list of `Page` objects. May be empty. |
| `actions` | `array` | ✅ | Project-level REST action definitions. May be empty. |
| `bindings` | `array` | ✅ | Project-level binding definitions. May be empty. |
| `variables` | `object` | ✅ | Named global variable declarations. May be empty (`{}`). |
| `settings` | `object` | ✅ | Project display and canvas settings. May be empty (`{}`). |
---
## Key Sub-Types
### `Page`
Represents one view in the project. Required fields: `id`, `name`, `components`.
```json
{
"id": "page_home",
"name": "Home",
"description": "",
"order": 0,
"components": [],
"events": []
}
```
### `Component`
A UI element placed on a page canvas. Required fields: `id`, `type`, `name`, `position`, `size`.
Allowed `type` values:
`Button` · `TextInput` · `TextArea` · `Dropdown` · `Checkbox` · `RadioGroup` · `Label` · `Table` · `JsonViewer` · `StatusPanel` · `Container`
```json
{
"id": "cmp_launch_btn",
"type": "Button",
"name": "launchButton",
"position": { "x": 24, "y": 284 },
"size": { "width": 160, "height": 44 },
"properties": {
"label": "Launch Workflow",
"visible": true,
"disabled": false
},
"events": [
{
"event": "onClick",
"actionId": "action_trigger_workflow"
}
],
"bindings": []
}
```
`ComponentEvent.inputMap` is retained in schema version `0.1.0` for compatibility
but is not consumed by Preview. Request values are configured in REST action
templates using `{{components.<name>.value}}` or `{{variables.<name>}}`.
Visual request-input authoring must write those executed request fields.
### `Action` (REST Action)
A REST API call definition. Required fields: `id`, `name`, `method`, `url`, `authenticationType`.
Allowed `method` values: `GET` · `POST` · `PUT` · `PATCH` · `DELETE`
Allowed `authenticationType` values: `anonymous` · `bearerToken` · `basicAuth` · `apiKeyHeader` · `apiKeyQueryParameter`
```json
{
"id": "action_trigger_workflow",
"name": "Trigger Workflow",
"description": "Calls the Concert RIA API to trigger a workflow run.",
"method": "POST",
"url": "https://api.example.com/workflows/{{workflowId}}/run",
"headers": {
"Content-Type": "application/json",
"Accept": "application/json"
},
"queryParameters": {
"environment": "{{environment}}"
},
"pathParameters": {
"workflowId": "{{workflowId}}"
},
"bodyTemplate": "{\"params\": {{params}}}",
"authenticationType": "bearerToken"
}
```
New response mappings belong in top-level `project.bindings`, not inside the action:
```json
{
"id": "bind_trigger_status",
"source": "actions.action_trigger_workflow.response.body.data.status",
"target": "variables.lastStatus",
"trigger": "onSuccess"
}
```
> **Security note:** Never store actual secret values (passwords, tokens, API keys) in the project definition. The `authenticationType` field declares the authentication strategy only; the backend resolves credentials from server-side secrets at execution time.
#### REST Action Fields
| Field | Type | Required | Description |
|----------------------|----------|----------|-----------------------------------------------------------------------------|
| `id` | `string` | ✅ | Unique identifier within the project. |
| `name` | `string` | ✅ | Human-readable action name shown in the Actions panel. |
| `description` | `string` | — | Optional description of what this action does. |
| `method` | `string` | ✅ | HTTP method: `GET`, `POST`, `PUT`, `PATCH`, or `DELETE`. |
| `url` | `string` | ✅ | Target URL. Use `{{paramName}}` for path parameter placeholders. |
| `headers` | `object` | — | Static request headers. Values may use `{{variableName}}` syntax. |
| `queryParameters` | `object` | — | URL query string parameters. Values may use `{{variableName}}` syntax. |
| `pathParameters` | `object` | — | Path segment substitutions. Keys match `{{paramName}}` in the URL. |
| `bodyTemplate` | `string` | — | Request body template. Use `{{variableName}}` for runtime substitutions. |
| `authenticationType` | `string` | ✅ | Authentication strategy (see allowed values above). Credentials are never stored here. |
| `responseMapping` | `array` | — | Deprecated legacy action-local mappings. New mappings use top-level `project.bindings`. |
### `Binding`
Declares data flow between a source and a target. Required fields: `id`, `source`, `target`.
```json
{
"id": "bind_status_panel",
"source": "variables.lastRunStatus",
"target": "components.statusPanel.message",
"trigger": "onChange"
}
```
### `Variable`
A named global variable. Required field: `type`.
Allowed `type` values: `string` · `number` · `boolean` · `object` · `array`
```json
{
"lastRunStatus": {
"type": "string",
"defaultValue": "",
"description": "Status returned by the most recent workflow trigger."
}
}
```
### `ProjectSettings`
Optional canvas and display configuration.
```json
{
"theme": "system",
"defaultPageId": "page_home",
"canvasWidth": 1280,
"canvasHeight": 900
}
```
---
## Example Files
| File | Description |
|-----------------------------------------------------------------------|-----------------------------------------------------------|
| `examples/project-definitions/valid-minimal.json` | Smallest valid project definition (one empty page). |
| `examples/project-definitions/valid-full.json` | Full example: Concert Workflow Launcher with all features. |
| `examples/project-definitions/valid-rest-actions.json` | Showcases all five authentication types across seven REST actions. No canvas components — validates the action model in isolation. |
| `examples/project-definitions/valid-visual-rest-actions.json` | Slice 2 visual-authoring fixture covering anonymous GET/POST request fields. |
| `examples/project-definitions/invalid-missing-required.json` | Intentionally invalid document showing schema errors. |
---
## Validation
### Using `ajv-cli` (recommended)
Install once globally or run via `npx`:
```bash
# Install globally
npm install -g ajv-cli ajv-formats
# Validate a valid document — should print: valid
ajv validate \
-s shared/schemas/conductor-project.schema.json \
-d examples/project-definitions/valid-minimal.json \
--spec=draft2020
# Validate the full example
ajv validate \
-s shared/schemas/conductor-project.schema.json \
-d examples/project-definitions/valid-full.json \
--spec=draft2020
# Validate the REST actions showcase (all five auth types)
ajv validate \
-s shared/schemas/conductor-project.schema.json \
-d examples/project-definitions/valid-rest-actions.json \
--spec=draft2020
# Validate the intentionally invalid document — should print validation errors
ajv validate \
-s shared/schemas/conductor-project.schema.json \
-d examples/project-definitions/invalid-missing-required.json \
--spec=draft2020
```
### Using VS Code
1. Open any example `.json` file.
2. The `"$schema"` field at the top of the file points to the schema.
3. VS Code will underline validation errors inline and provide autocomplete.
### In the Backend (future — Step 11)
The backend will use [`ajv`](https://ajv.js.org/) at runtime to validate project definitions on save:
```ts
import Ajv from 'ajv';
import schema from '../../shared/schemas/conductor-project.schema.json';
const ajv = new Ajv({ strict: true });
const validate = ajv.compile(schema);
function validateProjectJson(doc: unknown): string[] {
const valid = validate(doc);
if (valid) return [];
return (validate.errors ?? []).map(e => `${e.instancePath} ${e.message}`);
}
```
> This is documented here for reference. The validation endpoint itself is not part of Step 7.
---
## Versioning Policy
| Change type | Version bump |
|----------------------------------------------------|--------------|
| Add optional field | MINOR |
| Add required field or remove existing field | MAJOR |
| Change allowed enum values | MAJOR |
| Clarify description with no structural change | PATCH |
---
## Schema Stability
The schema is currently at **`0.x`** (pre-stable). Breaking changes may occur between minor versions until `1.0.0` is declared.