From 85dc4c4f34a3ca7860e49d1d1f54b491fe3eef3d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Feb 2026 07:29:43 +0000 Subject: [PATCH 1/3] Initial plan From 93211a44afc4345280ff4e01c96d728f725aa965 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Feb 2026 07:38:29 +0000 Subject: [PATCH 2/3] feat(api): add missing protocol operations for views, permissions, workflows, realtime, notifications, AI, and i18n Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com> --- .../spec/json-schema/api/AiChatRequest.json | 28 + .../spec/json-schema/api/AiChatResponse.json | 51 + .../json-schema/api/AiInsightsRequest.json | 33 + .../json-schema/api/AiInsightsResponse.json | 53 + .../spec/json-schema/api/AiNlqRequest.json | 27 + .../spec/json-schema/api/AiNlqResponse.json | 32 + .../json-schema/api/AiSuggestRequest.json | 31 + .../json-schema/api/AiSuggestResponse.json | 45 + .../api/CheckPermissionRequest.json | 41 + .../api/CheckPermissionResponse.json | 23 + .../json-schema/api/CreateViewRequest.json | 1797 ++++++++++++++++ .../json-schema/api/CreateViewResponse.json | 1802 +++++++++++++++++ .../json-schema/api/DeleteViewRequest.json | 24 + .../json-schema/api/DeleteViewResponse.json | 29 + .../api/GetEffectivePermissionsRequest.json | 11 + .../api/GetEffectivePermissionsResponse.json | 78 + .../api/GetFieldLabelsRequest.json | 24 + .../api/GetFieldLabelsResponse.json | 53 + .../json-schema/api/GetLocalesRequest.json | 11 + .../json-schema/api/GetLocalesResponse.json | 42 + .../GetNotificationPreferencesRequest.json | 11 + .../GetNotificationPreferencesResponse.json | 70 + .../api/GetObjectPermissionsRequest.json | 19 + .../api/GetObjectPermissionsResponse.json | 92 + .../json-schema/api/GetPresenceRequest.json | 19 + .../json-schema/api/GetPresenceResponse.json | 59 + .../api/GetTranslationsRequest.json | 30 + .../api/GetTranslationsResponse.json | 101 + .../spec/json-schema/api/GetViewRequest.json | 24 + .../spec/json-schema/api/GetViewResponse.json | 1797 ++++++++++++++++ .../api/GetWorkflowConfigRequest.json | 19 + .../api/GetWorkflowConfigResponse.json | 712 +++++++ .../api/GetWorkflowStateRequest.json | 24 + .../api/GetWorkflowStateResponse.json | 113 ++ .../api/ListNotificationsRequest.json | 29 + .../api/ListNotificationsResponse.json | 76 + .../json-schema/api/ListViewsRequest.json | 27 + .../json-schema/api/ListViewsResponse.json | 1800 ++++++++++++++++ .../api/MarkAllNotificationsReadRequest.json | 11 + .../api/MarkAllNotificationsReadResponse.json | 24 + .../api/MarkNotificationsReadRequest.json | 22 + .../api/MarkNotificationsReadResponse.json | 24 + .../spec/json-schema/api/Notification.json | 54 + .../api/NotificationPreferences.json | 60 + .../api/RealtimeConnectRequest.json | 32 + .../api/RealtimeConnectResponse.json | 33 + .../api/RealtimeDisconnectRequest.json | 16 + .../api/RealtimeDisconnectResponse.json | 19 + .../api/RealtimeSubscribeRequest.json | 31 + .../api/RealtimeSubscribeResponse.json | 24 + .../api/RealtimeUnsubscribeRequest.json | 19 + .../api/RealtimeUnsubscribeResponse.json | 19 + .../api/RegisterDeviceRequest.json | 37 + .../api/RegisterDeviceResponse.json | 24 + .../json-schema/api/SetPresenceRequest.json | 56 + .../json-schema/api/SetPresenceResponse.json | 19 + .../api/UnregisterDeviceRequest.json | 19 + .../api/UnregisterDeviceResponse.json | 19 + .../UpdateNotificationPreferencesRequest.json | 70 + ...UpdateNotificationPreferencesResponse.json | 70 + .../json-schema/api/UpdateViewRequest.json | 1802 +++++++++++++++++ .../json-schema/api/UpdateViewResponse.json | 1802 +++++++++++++++++ .../api/WorkflowApproveRequest.json | 33 + .../api/WorkflowApproveResponse.json | 118 ++ .../api/WorkflowRejectRequest.json | 33 + .../api/WorkflowRejectResponse.json | 118 ++ .../spec/json-schema/api/WorkflowState.json | 93 + .../api/WorkflowTransitionRequest.json | 38 + .../api/WorkflowTransitionResponse.json | 118 ++ .../integration/Authentication.json | 146 -- .../integration/FieldTransform.json | 36 - packages/spec/json-schema/qa/TestAction.json | 8 +- .../spec/json-schema/qa/TestActionType.json | 3 +- .../spec/json-schema/qa/TestAssertion.json | 10 +- .../json-schema/qa/TestAssertionType.json | 3 +- .../spec/json-schema/qa/TestScenario.json | 120 +- packages/spec/json-schema/qa/TestStep.json | 30 +- packages/spec/json-schema/qa/TestSuite.json | 129 +- packages/spec/src/api/protocol.zod.ts | 648 ++++++ 79 files changed, 14962 insertions(+), 285 deletions(-) create mode 100644 packages/spec/json-schema/api/AiChatRequest.json create mode 100644 packages/spec/json-schema/api/AiChatResponse.json create mode 100644 packages/spec/json-schema/api/AiInsightsRequest.json create mode 100644 packages/spec/json-schema/api/AiInsightsResponse.json create mode 100644 packages/spec/json-schema/api/AiNlqRequest.json create mode 100644 packages/spec/json-schema/api/AiNlqResponse.json create mode 100644 packages/spec/json-schema/api/AiSuggestRequest.json create mode 100644 packages/spec/json-schema/api/AiSuggestResponse.json create mode 100644 packages/spec/json-schema/api/CheckPermissionRequest.json create mode 100644 packages/spec/json-schema/api/CheckPermissionResponse.json create mode 100644 packages/spec/json-schema/api/CreateViewRequest.json create mode 100644 packages/spec/json-schema/api/CreateViewResponse.json create mode 100644 packages/spec/json-schema/api/DeleteViewRequest.json create mode 100644 packages/spec/json-schema/api/DeleteViewResponse.json create mode 100644 packages/spec/json-schema/api/GetEffectivePermissionsRequest.json create mode 100644 packages/spec/json-schema/api/GetEffectivePermissionsResponse.json create mode 100644 packages/spec/json-schema/api/GetFieldLabelsRequest.json create mode 100644 packages/spec/json-schema/api/GetFieldLabelsResponse.json create mode 100644 packages/spec/json-schema/api/GetLocalesRequest.json create mode 100644 packages/spec/json-schema/api/GetLocalesResponse.json create mode 100644 packages/spec/json-schema/api/GetNotificationPreferencesRequest.json create mode 100644 packages/spec/json-schema/api/GetNotificationPreferencesResponse.json create mode 100644 packages/spec/json-schema/api/GetObjectPermissionsRequest.json create mode 100644 packages/spec/json-schema/api/GetObjectPermissionsResponse.json create mode 100644 packages/spec/json-schema/api/GetPresenceRequest.json create mode 100644 packages/spec/json-schema/api/GetPresenceResponse.json create mode 100644 packages/spec/json-schema/api/GetTranslationsRequest.json create mode 100644 packages/spec/json-schema/api/GetTranslationsResponse.json create mode 100644 packages/spec/json-schema/api/GetViewRequest.json create mode 100644 packages/spec/json-schema/api/GetViewResponse.json create mode 100644 packages/spec/json-schema/api/GetWorkflowConfigRequest.json create mode 100644 packages/spec/json-schema/api/GetWorkflowConfigResponse.json create mode 100644 packages/spec/json-schema/api/GetWorkflowStateRequest.json create mode 100644 packages/spec/json-schema/api/GetWorkflowStateResponse.json create mode 100644 packages/spec/json-schema/api/ListNotificationsRequest.json create mode 100644 packages/spec/json-schema/api/ListNotificationsResponse.json create mode 100644 packages/spec/json-schema/api/ListViewsRequest.json create mode 100644 packages/spec/json-schema/api/ListViewsResponse.json create mode 100644 packages/spec/json-schema/api/MarkAllNotificationsReadRequest.json create mode 100644 packages/spec/json-schema/api/MarkAllNotificationsReadResponse.json create mode 100644 packages/spec/json-schema/api/MarkNotificationsReadRequest.json create mode 100644 packages/spec/json-schema/api/MarkNotificationsReadResponse.json create mode 100644 packages/spec/json-schema/api/Notification.json create mode 100644 packages/spec/json-schema/api/NotificationPreferences.json create mode 100644 packages/spec/json-schema/api/RealtimeConnectRequest.json create mode 100644 packages/spec/json-schema/api/RealtimeConnectResponse.json create mode 100644 packages/spec/json-schema/api/RealtimeDisconnectRequest.json create mode 100644 packages/spec/json-schema/api/RealtimeDisconnectResponse.json create mode 100644 packages/spec/json-schema/api/RealtimeSubscribeRequest.json create mode 100644 packages/spec/json-schema/api/RealtimeSubscribeResponse.json create mode 100644 packages/spec/json-schema/api/RealtimeUnsubscribeRequest.json create mode 100644 packages/spec/json-schema/api/RealtimeUnsubscribeResponse.json create mode 100644 packages/spec/json-schema/api/RegisterDeviceRequest.json create mode 100644 packages/spec/json-schema/api/RegisterDeviceResponse.json create mode 100644 packages/spec/json-schema/api/SetPresenceRequest.json create mode 100644 packages/spec/json-schema/api/SetPresenceResponse.json create mode 100644 packages/spec/json-schema/api/UnregisterDeviceRequest.json create mode 100644 packages/spec/json-schema/api/UnregisterDeviceResponse.json create mode 100644 packages/spec/json-schema/api/UpdateNotificationPreferencesRequest.json create mode 100644 packages/spec/json-schema/api/UpdateNotificationPreferencesResponse.json create mode 100644 packages/spec/json-schema/api/UpdateViewRequest.json create mode 100644 packages/spec/json-schema/api/UpdateViewResponse.json create mode 100644 packages/spec/json-schema/api/WorkflowApproveRequest.json create mode 100644 packages/spec/json-schema/api/WorkflowApproveResponse.json create mode 100644 packages/spec/json-schema/api/WorkflowRejectRequest.json create mode 100644 packages/spec/json-schema/api/WorkflowRejectResponse.json create mode 100644 packages/spec/json-schema/api/WorkflowState.json create mode 100644 packages/spec/json-schema/api/WorkflowTransitionRequest.json create mode 100644 packages/spec/json-schema/api/WorkflowTransitionResponse.json delete mode 100644 packages/spec/json-schema/integration/Authentication.json delete mode 100644 packages/spec/json-schema/integration/FieldTransform.json diff --git a/packages/spec/json-schema/api/AiChatRequest.json b/packages/spec/json-schema/api/AiChatRequest.json new file mode 100644 index 000000000..14c6456af --- /dev/null +++ b/packages/spec/json-schema/api/AiChatRequest.json @@ -0,0 +1,28 @@ +{ + "$ref": "#/definitions/AiChatRequest", + "definitions": { + "AiChatRequest": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "User message" + }, + "conversationId": { + "type": "string", + "description": "Conversation ID for context" + }, + "context": { + "type": "object", + "additionalProperties": {}, + "description": "Additional context data" + } + }, + "required": [ + "message" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/AiChatResponse.json b/packages/spec/json-schema/api/AiChatResponse.json new file mode 100644 index 000000000..ed2a17252 --- /dev/null +++ b/packages/spec/json-schema/api/AiChatResponse.json @@ -0,0 +1,51 @@ +{ + "$ref": "#/definitions/AiChatResponse", + "definitions": { + "AiChatResponse": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Assistant response message" + }, + "conversationId": { + "type": "string", + "description": "Conversation ID" + }, + "actions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Action type" + }, + "label": { + "type": "string", + "description": "Action display label" + }, + "data": { + "type": "object", + "additionalProperties": {}, + "description": "Action data" + } + }, + "required": [ + "type", + "label" + ], + "additionalProperties": false + }, + "description": "Suggested actions" + } + }, + "required": [ + "message", + "conversationId" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/AiInsightsRequest.json b/packages/spec/json-schema/api/AiInsightsRequest.json new file mode 100644 index 000000000..ce75cf880 --- /dev/null +++ b/packages/spec/json-schema/api/AiInsightsRequest.json @@ -0,0 +1,33 @@ +{ + "$ref": "#/definitions/AiInsightsRequest", + "definitions": { + "AiInsightsRequest": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name to analyze" + }, + "recordId": { + "type": "string", + "description": "Specific record to analyze" + }, + "type": { + "type": "string", + "enum": [ + "summary", + "trends", + "anomalies", + "recommendations" + ], + "description": "Type of insight" + } + }, + "required": [ + "object" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/AiInsightsResponse.json b/packages/spec/json-schema/api/AiInsightsResponse.json new file mode 100644 index 000000000..f3910b17e --- /dev/null +++ b/packages/spec/json-schema/api/AiInsightsResponse.json @@ -0,0 +1,53 @@ +{ + "$ref": "#/definitions/AiInsightsResponse", + "definitions": { + "AiInsightsResponse": { + "type": "object", + "properties": { + "insights": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Insight type" + }, + "title": { + "type": "string", + "description": "Insight title" + }, + "description": { + "type": "string", + "description": "Detailed description" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score (0-1)" + }, + "data": { + "type": "object", + "additionalProperties": {}, + "description": "Supporting data" + } + }, + "required": [ + "type", + "title", + "description" + ], + "additionalProperties": false + }, + "description": "Generated insights" + } + }, + "required": [ + "insights" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/AiNlqRequest.json b/packages/spec/json-schema/api/AiNlqRequest.json new file mode 100644 index 000000000..dd642ee3a --- /dev/null +++ b/packages/spec/json-schema/api/AiNlqRequest.json @@ -0,0 +1,27 @@ +{ + "$ref": "#/definitions/AiNlqRequest", + "definitions": { + "AiNlqRequest": { + "type": "object", + "properties": { + "query": { + "type": "string", + "description": "Natural language query string" + }, + "object": { + "type": "string", + "description": "Target object context" + }, + "conversationId": { + "type": "string", + "description": "Conversation ID for multi-turn queries" + } + }, + "required": [ + "query" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/AiNlqResponse.json b/packages/spec/json-schema/api/AiNlqResponse.json new file mode 100644 index 000000000..5dbe89e62 --- /dev/null +++ b/packages/spec/json-schema/api/AiNlqResponse.json @@ -0,0 +1,32 @@ +{ + "$ref": "#/definitions/AiNlqResponse", + "definitions": { + "AiNlqResponse": { + "type": "object", + "properties": { + "query": { + "description": "Generated structured query (AST)" + }, + "explanation": { + "type": "string", + "description": "Human-readable explanation of the query" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score (0-1)" + }, + "suggestions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Suggested follow-up queries" + } + }, + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/AiSuggestRequest.json b/packages/spec/json-schema/api/AiSuggestRequest.json new file mode 100644 index 000000000..30ab8835c --- /dev/null +++ b/packages/spec/json-schema/api/AiSuggestRequest.json @@ -0,0 +1,31 @@ +{ + "$ref": "#/definitions/AiSuggestRequest", + "definitions": { + "AiSuggestRequest": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name for context" + }, + "field": { + "type": "string", + "description": "Field to suggest values for" + }, + "recordId": { + "type": "string", + "description": "Record ID for context" + }, + "partial": { + "type": "string", + "description": "Partial input for completion" + } + }, + "required": [ + "object" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/AiSuggestResponse.json b/packages/spec/json-schema/api/AiSuggestResponse.json new file mode 100644 index 000000000..94f8a17d2 --- /dev/null +++ b/packages/spec/json-schema/api/AiSuggestResponse.json @@ -0,0 +1,45 @@ +{ + "$ref": "#/definitions/AiSuggestResponse", + "definitions": { + "AiSuggestResponse": { + "type": "object", + "properties": { + "suggestions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "value": { + "description": "Suggested value" + }, + "label": { + "type": "string", + "description": "Display label" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score (0-1)" + }, + "reason": { + "type": "string", + "description": "Reason for this suggestion" + } + }, + "required": [ + "label" + ], + "additionalProperties": false + }, + "description": "Suggested values" + } + }, + "required": [ + "suggestions" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/CheckPermissionRequest.json b/packages/spec/json-schema/api/CheckPermissionRequest.json new file mode 100644 index 000000000..fb07a7532 --- /dev/null +++ b/packages/spec/json-schema/api/CheckPermissionRequest.json @@ -0,0 +1,41 @@ +{ + "$ref": "#/definitions/CheckPermissionRequest", + "definitions": { + "CheckPermissionRequest": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name to check permissions for" + }, + "action": { + "type": "string", + "enum": [ + "create", + "read", + "edit", + "delete", + "transfer", + "restore", + "purge" + ], + "description": "Action to check" + }, + "recordId": { + "type": "string", + "description": "Specific record ID (for record-level checks)" + }, + "field": { + "type": "string", + "description": "Specific field name (for field-level checks)" + } + }, + "required": [ + "object", + "action" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/CheckPermissionResponse.json b/packages/spec/json-schema/api/CheckPermissionResponse.json new file mode 100644 index 000000000..dccd60264 --- /dev/null +++ b/packages/spec/json-schema/api/CheckPermissionResponse.json @@ -0,0 +1,23 @@ +{ + "$ref": "#/definitions/CheckPermissionResponse", + "definitions": { + "CheckPermissionResponse": { + "type": "object", + "properties": { + "allowed": { + "type": "boolean", + "description": "Whether the action is permitted" + }, + "reason": { + "type": "string", + "description": "Reason if denied" + } + }, + "required": [ + "allowed" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/CreateViewRequest.json b/packages/spec/json-schema/api/CreateViewRequest.json new file mode 100644 index 000000000..b4792ba0d --- /dev/null +++ b/packages/spec/json-schema/api/CreateViewRequest.json @@ -0,0 +1,1797 @@ +{ + "$ref": "#/definitions/CreateViewRequest", + "definitions": { + "CreateViewRequest": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name (snake_case)" + }, + "data": { + "type": "object", + "properties": { + "list": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 2, + "pattern": "^[a-z][a-z0-9_]*$", + "description": "Internal view name (lowercase snake_case)" + }, + "label": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "grid", + "kanban", + "gallery", + "calendar", + "timeline", + "gantt", + "map" + ], + "default": "grid" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "object" + }, + "object": { + "type": "string", + "description": "Target object name" + } + }, + "required": [ + "provider", + "object" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "api" + }, + "read": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for fetching data" + }, + "write": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for submitting data (for forms/editable tables)" + } + }, + "required": [ + "provider" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "value" + }, + "items": { + "type": "array", + "items": {}, + "description": "Static data array" + } + }, + "required": [ + "provider", + "items" + ], + "additionalProperties": false + } + ], + "description": "Data source configuration (defaults to \"object\" provider)" + }, + "columns": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "width": { + "type": "number", + "exclusiveMinimum": 0, + "description": "Column width in pixels" + }, + "align": { + "type": "string", + "enum": [ + "left", + "center", + "right" + ], + "description": "Text alignment" + }, + "hidden": { + "type": "boolean", + "description": "Hide column by default" + }, + "sortable": { + "type": "boolean", + "description": "Allow sorting by this column" + }, + "resizable": { + "type": "boolean", + "description": "Allow resizing this column" + }, + "wrap": { + "type": "boolean", + "description": "Allow text wrapping" + }, + "type": { + "type": "string", + "description": "Renderer type override (e.g., \"currency\", \"date\")" + }, + "link": { + "type": "boolean", + "description": "Functions as the primary navigation link (triggers View navigation)" + }, + "action": { + "type": "string", + "description": "Registered Action ID to execute when clicked" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + } + ], + "description": "Fields to display as columns" + }, + "filter": { + "type": "array", + "items": {}, + "description": "Filter criteria (JSON Rules)" + }, + "sort": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "field": { + "type": "string" + }, + "order": { + "type": "string", + "enum": [ + "asc", + "desc" + ] + } + }, + "required": [ + "field", + "order" + ], + "additionalProperties": false + } + } + ] + }, + "searchableFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields enabled for search" + }, + "filterableFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields enabled for end-user filtering in the top bar" + }, + "resizable": { + "type": "boolean", + "description": "Enable column resizing" + }, + "striped": { + "type": "boolean", + "description": "Striped row styling" + }, + "bordered": { + "type": "boolean", + "description": "Show borders" + }, + "selection": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "none", + "single", + "multiple" + ], + "default": "none", + "description": "Selection mode" + } + }, + "additionalProperties": false, + "description": "Row selection configuration" + }, + "navigation": { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "page", + "drawer", + "modal", + "split", + "popover", + "new_window", + "none" + ], + "default": "page" + }, + "view": { + "type": "string", + "description": "Name of the form view to use for details (e.g. \"summary_view\", \"edit_form\")" + }, + "preventNavigation": { + "type": "boolean", + "default": false, + "description": "Disable standard navigation entirely" + }, + "openNewTab": { + "type": "boolean", + "default": false, + "description": "Force open in new tab (applies to page mode)" + }, + "width": { + "type": [ + "string", + "number" + ], + "description": "Width of the drawer/modal (e.g. \"600px\", \"50%\")" + } + }, + "additionalProperties": false, + "description": "Configuration for item click navigation (page, drawer, modal, etc.)" + }, + "pagination": { + "type": "object", + "properties": { + "pageSize": { + "type": "integer", + "exclusiveMinimum": 0, + "default": 25, + "description": "Number of records per page" + }, + "pageSizeOptions": { + "type": "array", + "items": { + "type": "integer", + "exclusiveMinimum": 0 + }, + "description": "Available page size options" + } + }, + "additionalProperties": false, + "description": "Pagination configuration" + }, + "kanban": { + "type": "object", + "properties": { + "groupByField": { + "type": "string", + "description": "Field to group columns by (usually status/select)" + }, + "summarizeField": { + "type": "string", + "description": "Field to sum at top of column (e.g. amount)" + }, + "columns": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields to show on cards" + } + }, + "required": [ + "groupByField", + "columns" + ], + "additionalProperties": false + }, + "calendar": { + "type": "object", + "properties": { + "startDateField": { + "type": "string" + }, + "endDateField": { + "type": "string" + }, + "titleField": { + "type": "string" + }, + "colorField": { + "type": "string" + } + }, + "required": [ + "startDateField", + "titleField" + ], + "additionalProperties": false + }, + "gantt": { + "type": "object", + "properties": { + "startDateField": { + "type": "string" + }, + "endDateField": { + "type": "string" + }, + "titleField": { + "type": "string" + }, + "progressField": { + "type": "string" + }, + "dependenciesField": { + "type": "string" + } + }, + "required": [ + "startDateField", + "endDateField", + "titleField" + ], + "additionalProperties": false + }, + "rowActions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Actions available for individual row items" + }, + "bulkActions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Actions available when multiple rows are selected" + }, + "virtualScroll": { + "type": "boolean", + "description": "Enable virtual scrolling for large datasets" + }, + "conditionalFormatting": { + "type": "array", + "items": { + "type": "object", + "properties": { + "condition": { + "type": "string", + "description": "Condition expression to evaluate" + }, + "style": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "CSS styles to apply when condition is true" + } + }, + "required": [ + "condition", + "style" + ], + "additionalProperties": false + }, + "description": "Conditional formatting rules for list rows" + }, + "inlineEdit": { + "type": "boolean", + "description": "Allow inline editing of records directly in the list view" + }, + "exportOptions": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "csv", + "xlsx", + "pdf", + "json" + ] + }, + "description": "Available export format options" + }, + "emptyState": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "message": { + "type": "string" + }, + "icon": { + "type": "string" + } + }, + "additionalProperties": false, + "description": "Empty state configuration when no records found" + } + }, + "required": [ + "columns" + ], + "additionalProperties": false + }, + "form": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "simple", + "tabbed", + "wizard", + "split", + "drawer", + "modal" + ], + "default": "simple" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "object" + }, + "object": { + "type": "string", + "description": "Target object name" + } + }, + "required": [ + "provider", + "object" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "api" + }, + "read": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for fetching data" + }, + "write": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for submitting data (for forms/editable tables)" + } + }, + "required": [ + "provider" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "value" + }, + "items": { + "type": "array", + "items": {}, + "description": "Static data array" + } + }, + "required": [ + "provider", + "items" + ], + "additionalProperties": false + } + ], + "description": "Data source configuration (defaults to \"object\" provider)" + }, + "sections": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "collapsible": { + "type": "boolean", + "default": false + }, + "collapsed": { + "type": "boolean", + "default": false + }, + "columns": { + "type": "string", + "enum": [ + "1", + "2", + "3", + "4" + ], + "default": "2" + }, + "fields": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "placeholder": { + "type": "string", + "description": "Placeholder text" + }, + "helpText": { + "type": "string", + "description": "Help/hint text" + }, + "readonly": { + "type": "boolean", + "description": "Read-only override" + }, + "required": { + "type": "boolean", + "description": "Required override" + }, + "hidden": { + "type": "boolean", + "description": "Hidden override" + }, + "colSpan": { + "type": "integer", + "minimum": 1, + "maximum": 4, + "description": "Column span in grid layout (1-4)" + }, + "widget": { + "type": "string", + "description": "Custom widget/component name" + }, + "dependsOn": { + "type": "string", + "description": "Parent field name for cascading" + }, + "visibleOn": { + "type": "string", + "description": "Visibility condition expression" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "fields" + ], + "additionalProperties": false + } + }, + "groups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "collapsible": { + "type": "boolean", + "default": false + }, + "collapsed": { + "type": "boolean", + "default": false + }, + "columns": { + "type": "string", + "enum": [ + "1", + "2", + "3", + "4" + ], + "default": "2" + }, + "fields": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "placeholder": { + "type": "string", + "description": "Placeholder text" + }, + "helpText": { + "type": "string", + "description": "Help/hint text" + }, + "readonly": { + "type": "boolean", + "description": "Read-only override" + }, + "required": { + "type": "boolean", + "description": "Required override" + }, + "hidden": { + "type": "boolean", + "description": "Hidden override" + }, + "colSpan": { + "type": "integer", + "minimum": 1, + "maximum": 4, + "description": "Column span in grid layout (1-4)" + }, + "widget": { + "type": "string", + "description": "Custom widget/component name" + }, + "dependsOn": { + "type": "string", + "description": "Parent field name for cascading" + }, + "visibleOn": { + "type": "string", + "description": "Visibility condition expression" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "fields" + ], + "additionalProperties": false + } + } + }, + "additionalProperties": false + }, + "listViews": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 2, + "pattern": "^[a-z][a-z0-9_]*$", + "description": "Internal view name (lowercase snake_case)" + }, + "label": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "grid", + "kanban", + "gallery", + "calendar", + "timeline", + "gantt", + "map" + ], + "default": "grid" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "object" + }, + "object": { + "type": "string", + "description": "Target object name" + } + }, + "required": [ + "provider", + "object" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "api" + }, + "read": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for fetching data" + }, + "write": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for submitting data (for forms/editable tables)" + } + }, + "required": [ + "provider" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "value" + }, + "items": { + "type": "array", + "items": {}, + "description": "Static data array" + } + }, + "required": [ + "provider", + "items" + ], + "additionalProperties": false + } + ], + "description": "Data source configuration (defaults to \"object\" provider)" + }, + "columns": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "width": { + "type": "number", + "exclusiveMinimum": 0, + "description": "Column width in pixels" + }, + "align": { + "type": "string", + "enum": [ + "left", + "center", + "right" + ], + "description": "Text alignment" + }, + "hidden": { + "type": "boolean", + "description": "Hide column by default" + }, + "sortable": { + "type": "boolean", + "description": "Allow sorting by this column" + }, + "resizable": { + "type": "boolean", + "description": "Allow resizing this column" + }, + "wrap": { + "type": "boolean", + "description": "Allow text wrapping" + }, + "type": { + "type": "string", + "description": "Renderer type override (e.g., \"currency\", \"date\")" + }, + "link": { + "type": "boolean", + "description": "Functions as the primary navigation link (triggers View navigation)" + }, + "action": { + "type": "string", + "description": "Registered Action ID to execute when clicked" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + } + ], + "description": "Fields to display as columns" + }, + "filter": { + "type": "array", + "items": {}, + "description": "Filter criteria (JSON Rules)" + }, + "sort": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "field": { + "type": "string" + }, + "order": { + "type": "string", + "enum": [ + "asc", + "desc" + ] + } + }, + "required": [ + "field", + "order" + ], + "additionalProperties": false + } + } + ] + }, + "searchableFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields enabled for search" + }, + "filterableFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields enabled for end-user filtering in the top bar" + }, + "resizable": { + "type": "boolean", + "description": "Enable column resizing" + }, + "striped": { + "type": "boolean", + "description": "Striped row styling" + }, + "bordered": { + "type": "boolean", + "description": "Show borders" + }, + "selection": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "none", + "single", + "multiple" + ], + "default": "none", + "description": "Selection mode" + } + }, + "additionalProperties": false, + "description": "Row selection configuration" + }, + "navigation": { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "page", + "drawer", + "modal", + "split", + "popover", + "new_window", + "none" + ], + "default": "page" + }, + "view": { + "type": "string", + "description": "Name of the form view to use for details (e.g. \"summary_view\", \"edit_form\")" + }, + "preventNavigation": { + "type": "boolean", + "default": false, + "description": "Disable standard navigation entirely" + }, + "openNewTab": { + "type": "boolean", + "default": false, + "description": "Force open in new tab (applies to page mode)" + }, + "width": { + "type": [ + "string", + "number" + ], + "description": "Width of the drawer/modal (e.g. \"600px\", \"50%\")" + } + }, + "additionalProperties": false, + "description": "Configuration for item click navigation (page, drawer, modal, etc.)" + }, + "pagination": { + "type": "object", + "properties": { + "pageSize": { + "type": "integer", + "exclusiveMinimum": 0, + "default": 25, + "description": "Number of records per page" + }, + "pageSizeOptions": { + "type": "array", + "items": { + "type": "integer", + "exclusiveMinimum": 0 + }, + "description": "Available page size options" + } + }, + "additionalProperties": false, + "description": "Pagination configuration" + }, + "kanban": { + "type": "object", + "properties": { + "groupByField": { + "type": "string", + "description": "Field to group columns by (usually status/select)" + }, + "summarizeField": { + "type": "string", + "description": "Field to sum at top of column (e.g. amount)" + }, + "columns": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields to show on cards" + } + }, + "required": [ + "groupByField", + "columns" + ], + "additionalProperties": false + }, + "calendar": { + "type": "object", + "properties": { + "startDateField": { + "type": "string" + }, + "endDateField": { + "type": "string" + }, + "titleField": { + "type": "string" + }, + "colorField": { + "type": "string" + } + }, + "required": [ + "startDateField", + "titleField" + ], + "additionalProperties": false + }, + "gantt": { + "type": "object", + "properties": { + "startDateField": { + "type": "string" + }, + "endDateField": { + "type": "string" + }, + "titleField": { + "type": "string" + }, + "progressField": { + "type": "string" + }, + "dependenciesField": { + "type": "string" + } + }, + "required": [ + "startDateField", + "endDateField", + "titleField" + ], + "additionalProperties": false + }, + "rowActions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Actions available for individual row items" + }, + "bulkActions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Actions available when multiple rows are selected" + }, + "virtualScroll": { + "type": "boolean", + "description": "Enable virtual scrolling for large datasets" + }, + "conditionalFormatting": { + "type": "array", + "items": { + "type": "object", + "properties": { + "condition": { + "type": "string", + "description": "Condition expression to evaluate" + }, + "style": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "CSS styles to apply when condition is true" + } + }, + "required": [ + "condition", + "style" + ], + "additionalProperties": false + }, + "description": "Conditional formatting rules for list rows" + }, + "inlineEdit": { + "type": "boolean", + "description": "Allow inline editing of records directly in the list view" + }, + "exportOptions": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "csv", + "xlsx", + "pdf", + "json" + ] + }, + "description": "Available export format options" + }, + "emptyState": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "message": { + "type": "string" + }, + "icon": { + "type": "string" + } + }, + "additionalProperties": false, + "description": "Empty state configuration when no records found" + } + }, + "required": [ + "columns" + ], + "additionalProperties": false + }, + "description": "Additional named list views" + }, + "formViews": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "simple", + "tabbed", + "wizard", + "split", + "drawer", + "modal" + ], + "default": "simple" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "object" + }, + "object": { + "type": "string", + "description": "Target object name" + } + }, + "required": [ + "provider", + "object" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "api" + }, + "read": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for fetching data" + }, + "write": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for submitting data (for forms/editable tables)" + } + }, + "required": [ + "provider" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "value" + }, + "items": { + "type": "array", + "items": {}, + "description": "Static data array" + } + }, + "required": [ + "provider", + "items" + ], + "additionalProperties": false + } + ], + "description": "Data source configuration (defaults to \"object\" provider)" + }, + "sections": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "collapsible": { + "type": "boolean", + "default": false + }, + "collapsed": { + "type": "boolean", + "default": false + }, + "columns": { + "type": "string", + "enum": [ + "1", + "2", + "3", + "4" + ], + "default": "2" + }, + "fields": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "placeholder": { + "type": "string", + "description": "Placeholder text" + }, + "helpText": { + "type": "string", + "description": "Help/hint text" + }, + "readonly": { + "type": "boolean", + "description": "Read-only override" + }, + "required": { + "type": "boolean", + "description": "Required override" + }, + "hidden": { + "type": "boolean", + "description": "Hidden override" + }, + "colSpan": { + "type": "integer", + "minimum": 1, + "maximum": 4, + "description": "Column span in grid layout (1-4)" + }, + "widget": { + "type": "string", + "description": "Custom widget/component name" + }, + "dependsOn": { + "type": "string", + "description": "Parent field name for cascading" + }, + "visibleOn": { + "type": "string", + "description": "Visibility condition expression" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "fields" + ], + "additionalProperties": false + } + }, + "groups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "collapsible": { + "type": "boolean", + "default": false + }, + "collapsed": { + "type": "boolean", + "default": false + }, + "columns": { + "type": "string", + "enum": [ + "1", + "2", + "3", + "4" + ], + "default": "2" + }, + "fields": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "placeholder": { + "type": "string", + "description": "Placeholder text" + }, + "helpText": { + "type": "string", + "description": "Help/hint text" + }, + "readonly": { + "type": "boolean", + "description": "Read-only override" + }, + "required": { + "type": "boolean", + "description": "Required override" + }, + "hidden": { + "type": "boolean", + "description": "Hidden override" + }, + "colSpan": { + "type": "integer", + "minimum": 1, + "maximum": 4, + "description": "Column span in grid layout (1-4)" + }, + "widget": { + "type": "string", + "description": "Custom widget/component name" + }, + "dependsOn": { + "type": "string", + "description": "Parent field name for cascading" + }, + "visibleOn": { + "type": "string", + "description": "Visibility condition expression" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "fields" + ], + "additionalProperties": false + } + } + }, + "additionalProperties": false + }, + "description": "Additional named form views" + } + }, + "additionalProperties": false, + "description": "View definition to create" + } + }, + "required": [ + "object", + "data" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/CreateViewResponse.json b/packages/spec/json-schema/api/CreateViewResponse.json new file mode 100644 index 000000000..e66d6468a --- /dev/null +++ b/packages/spec/json-schema/api/CreateViewResponse.json @@ -0,0 +1,1802 @@ +{ + "$ref": "#/definitions/CreateViewResponse", + "definitions": { + "CreateViewResponse": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name" + }, + "viewId": { + "type": "string", + "description": "Created view identifier" + }, + "view": { + "type": "object", + "properties": { + "list": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 2, + "pattern": "^[a-z][a-z0-9_]*$", + "description": "Internal view name (lowercase snake_case)" + }, + "label": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "grid", + "kanban", + "gallery", + "calendar", + "timeline", + "gantt", + "map" + ], + "default": "grid" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "object" + }, + "object": { + "type": "string", + "description": "Target object name" + } + }, + "required": [ + "provider", + "object" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "api" + }, + "read": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for fetching data" + }, + "write": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for submitting data (for forms/editable tables)" + } + }, + "required": [ + "provider" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "value" + }, + "items": { + "type": "array", + "items": {}, + "description": "Static data array" + } + }, + "required": [ + "provider", + "items" + ], + "additionalProperties": false + } + ], + "description": "Data source configuration (defaults to \"object\" provider)" + }, + "columns": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "width": { + "type": "number", + "exclusiveMinimum": 0, + "description": "Column width in pixels" + }, + "align": { + "type": "string", + "enum": [ + "left", + "center", + "right" + ], + "description": "Text alignment" + }, + "hidden": { + "type": "boolean", + "description": "Hide column by default" + }, + "sortable": { + "type": "boolean", + "description": "Allow sorting by this column" + }, + "resizable": { + "type": "boolean", + "description": "Allow resizing this column" + }, + "wrap": { + "type": "boolean", + "description": "Allow text wrapping" + }, + "type": { + "type": "string", + "description": "Renderer type override (e.g., \"currency\", \"date\")" + }, + "link": { + "type": "boolean", + "description": "Functions as the primary navigation link (triggers View navigation)" + }, + "action": { + "type": "string", + "description": "Registered Action ID to execute when clicked" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + } + ], + "description": "Fields to display as columns" + }, + "filter": { + "type": "array", + "items": {}, + "description": "Filter criteria (JSON Rules)" + }, + "sort": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "field": { + "type": "string" + }, + "order": { + "type": "string", + "enum": [ + "asc", + "desc" + ] + } + }, + "required": [ + "field", + "order" + ], + "additionalProperties": false + } + } + ] + }, + "searchableFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields enabled for search" + }, + "filterableFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields enabled for end-user filtering in the top bar" + }, + "resizable": { + "type": "boolean", + "description": "Enable column resizing" + }, + "striped": { + "type": "boolean", + "description": "Striped row styling" + }, + "bordered": { + "type": "boolean", + "description": "Show borders" + }, + "selection": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "none", + "single", + "multiple" + ], + "default": "none", + "description": "Selection mode" + } + }, + "additionalProperties": false, + "description": "Row selection configuration" + }, + "navigation": { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "page", + "drawer", + "modal", + "split", + "popover", + "new_window", + "none" + ], + "default": "page" + }, + "view": { + "type": "string", + "description": "Name of the form view to use for details (e.g. \"summary_view\", \"edit_form\")" + }, + "preventNavigation": { + "type": "boolean", + "default": false, + "description": "Disable standard navigation entirely" + }, + "openNewTab": { + "type": "boolean", + "default": false, + "description": "Force open in new tab (applies to page mode)" + }, + "width": { + "type": [ + "string", + "number" + ], + "description": "Width of the drawer/modal (e.g. \"600px\", \"50%\")" + } + }, + "additionalProperties": false, + "description": "Configuration for item click navigation (page, drawer, modal, etc.)" + }, + "pagination": { + "type": "object", + "properties": { + "pageSize": { + "type": "integer", + "exclusiveMinimum": 0, + "default": 25, + "description": "Number of records per page" + }, + "pageSizeOptions": { + "type": "array", + "items": { + "type": "integer", + "exclusiveMinimum": 0 + }, + "description": "Available page size options" + } + }, + "additionalProperties": false, + "description": "Pagination configuration" + }, + "kanban": { + "type": "object", + "properties": { + "groupByField": { + "type": "string", + "description": "Field to group columns by (usually status/select)" + }, + "summarizeField": { + "type": "string", + "description": "Field to sum at top of column (e.g. amount)" + }, + "columns": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields to show on cards" + } + }, + "required": [ + "groupByField", + "columns" + ], + "additionalProperties": false + }, + "calendar": { + "type": "object", + "properties": { + "startDateField": { + "type": "string" + }, + "endDateField": { + "type": "string" + }, + "titleField": { + "type": "string" + }, + "colorField": { + "type": "string" + } + }, + "required": [ + "startDateField", + "titleField" + ], + "additionalProperties": false + }, + "gantt": { + "type": "object", + "properties": { + "startDateField": { + "type": "string" + }, + "endDateField": { + "type": "string" + }, + "titleField": { + "type": "string" + }, + "progressField": { + "type": "string" + }, + "dependenciesField": { + "type": "string" + } + }, + "required": [ + "startDateField", + "endDateField", + "titleField" + ], + "additionalProperties": false + }, + "rowActions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Actions available for individual row items" + }, + "bulkActions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Actions available when multiple rows are selected" + }, + "virtualScroll": { + "type": "boolean", + "description": "Enable virtual scrolling for large datasets" + }, + "conditionalFormatting": { + "type": "array", + "items": { + "type": "object", + "properties": { + "condition": { + "type": "string", + "description": "Condition expression to evaluate" + }, + "style": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "CSS styles to apply when condition is true" + } + }, + "required": [ + "condition", + "style" + ], + "additionalProperties": false + }, + "description": "Conditional formatting rules for list rows" + }, + "inlineEdit": { + "type": "boolean", + "description": "Allow inline editing of records directly in the list view" + }, + "exportOptions": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "csv", + "xlsx", + "pdf", + "json" + ] + }, + "description": "Available export format options" + }, + "emptyState": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "message": { + "type": "string" + }, + "icon": { + "type": "string" + } + }, + "additionalProperties": false, + "description": "Empty state configuration when no records found" + } + }, + "required": [ + "columns" + ], + "additionalProperties": false + }, + "form": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "simple", + "tabbed", + "wizard", + "split", + "drawer", + "modal" + ], + "default": "simple" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "object" + }, + "object": { + "type": "string", + "description": "Target object name" + } + }, + "required": [ + "provider", + "object" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "api" + }, + "read": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for fetching data" + }, + "write": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for submitting data (for forms/editable tables)" + } + }, + "required": [ + "provider" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "value" + }, + "items": { + "type": "array", + "items": {}, + "description": "Static data array" + } + }, + "required": [ + "provider", + "items" + ], + "additionalProperties": false + } + ], + "description": "Data source configuration (defaults to \"object\" provider)" + }, + "sections": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "collapsible": { + "type": "boolean", + "default": false + }, + "collapsed": { + "type": "boolean", + "default": false + }, + "columns": { + "type": "string", + "enum": [ + "1", + "2", + "3", + "4" + ], + "default": "2" + }, + "fields": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "placeholder": { + "type": "string", + "description": "Placeholder text" + }, + "helpText": { + "type": "string", + "description": "Help/hint text" + }, + "readonly": { + "type": "boolean", + "description": "Read-only override" + }, + "required": { + "type": "boolean", + "description": "Required override" + }, + "hidden": { + "type": "boolean", + "description": "Hidden override" + }, + "colSpan": { + "type": "integer", + "minimum": 1, + "maximum": 4, + "description": "Column span in grid layout (1-4)" + }, + "widget": { + "type": "string", + "description": "Custom widget/component name" + }, + "dependsOn": { + "type": "string", + "description": "Parent field name for cascading" + }, + "visibleOn": { + "type": "string", + "description": "Visibility condition expression" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "fields" + ], + "additionalProperties": false + } + }, + "groups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "collapsible": { + "type": "boolean", + "default": false + }, + "collapsed": { + "type": "boolean", + "default": false + }, + "columns": { + "type": "string", + "enum": [ + "1", + "2", + "3", + "4" + ], + "default": "2" + }, + "fields": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "placeholder": { + "type": "string", + "description": "Placeholder text" + }, + "helpText": { + "type": "string", + "description": "Help/hint text" + }, + "readonly": { + "type": "boolean", + "description": "Read-only override" + }, + "required": { + "type": "boolean", + "description": "Required override" + }, + "hidden": { + "type": "boolean", + "description": "Hidden override" + }, + "colSpan": { + "type": "integer", + "minimum": 1, + "maximum": 4, + "description": "Column span in grid layout (1-4)" + }, + "widget": { + "type": "string", + "description": "Custom widget/component name" + }, + "dependsOn": { + "type": "string", + "description": "Parent field name for cascading" + }, + "visibleOn": { + "type": "string", + "description": "Visibility condition expression" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "fields" + ], + "additionalProperties": false + } + } + }, + "additionalProperties": false + }, + "listViews": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 2, + "pattern": "^[a-z][a-z0-9_]*$", + "description": "Internal view name (lowercase snake_case)" + }, + "label": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "grid", + "kanban", + "gallery", + "calendar", + "timeline", + "gantt", + "map" + ], + "default": "grid" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "object" + }, + "object": { + "type": "string", + "description": "Target object name" + } + }, + "required": [ + "provider", + "object" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "api" + }, + "read": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for fetching data" + }, + "write": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for submitting data (for forms/editable tables)" + } + }, + "required": [ + "provider" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "value" + }, + "items": { + "type": "array", + "items": {}, + "description": "Static data array" + } + }, + "required": [ + "provider", + "items" + ], + "additionalProperties": false + } + ], + "description": "Data source configuration (defaults to \"object\" provider)" + }, + "columns": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "width": { + "type": "number", + "exclusiveMinimum": 0, + "description": "Column width in pixels" + }, + "align": { + "type": "string", + "enum": [ + "left", + "center", + "right" + ], + "description": "Text alignment" + }, + "hidden": { + "type": "boolean", + "description": "Hide column by default" + }, + "sortable": { + "type": "boolean", + "description": "Allow sorting by this column" + }, + "resizable": { + "type": "boolean", + "description": "Allow resizing this column" + }, + "wrap": { + "type": "boolean", + "description": "Allow text wrapping" + }, + "type": { + "type": "string", + "description": "Renderer type override (e.g., \"currency\", \"date\")" + }, + "link": { + "type": "boolean", + "description": "Functions as the primary navigation link (triggers View navigation)" + }, + "action": { + "type": "string", + "description": "Registered Action ID to execute when clicked" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + } + ], + "description": "Fields to display as columns" + }, + "filter": { + "type": "array", + "items": {}, + "description": "Filter criteria (JSON Rules)" + }, + "sort": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "field": { + "type": "string" + }, + "order": { + "type": "string", + "enum": [ + "asc", + "desc" + ] + } + }, + "required": [ + "field", + "order" + ], + "additionalProperties": false + } + } + ] + }, + "searchableFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields enabled for search" + }, + "filterableFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields enabled for end-user filtering in the top bar" + }, + "resizable": { + "type": "boolean", + "description": "Enable column resizing" + }, + "striped": { + "type": "boolean", + "description": "Striped row styling" + }, + "bordered": { + "type": "boolean", + "description": "Show borders" + }, + "selection": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "none", + "single", + "multiple" + ], + "default": "none", + "description": "Selection mode" + } + }, + "additionalProperties": false, + "description": "Row selection configuration" + }, + "navigation": { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "page", + "drawer", + "modal", + "split", + "popover", + "new_window", + "none" + ], + "default": "page" + }, + "view": { + "type": "string", + "description": "Name of the form view to use for details (e.g. \"summary_view\", \"edit_form\")" + }, + "preventNavigation": { + "type": "boolean", + "default": false, + "description": "Disable standard navigation entirely" + }, + "openNewTab": { + "type": "boolean", + "default": false, + "description": "Force open in new tab (applies to page mode)" + }, + "width": { + "type": [ + "string", + "number" + ], + "description": "Width of the drawer/modal (e.g. \"600px\", \"50%\")" + } + }, + "additionalProperties": false, + "description": "Configuration for item click navigation (page, drawer, modal, etc.)" + }, + "pagination": { + "type": "object", + "properties": { + "pageSize": { + "type": "integer", + "exclusiveMinimum": 0, + "default": 25, + "description": "Number of records per page" + }, + "pageSizeOptions": { + "type": "array", + "items": { + "type": "integer", + "exclusiveMinimum": 0 + }, + "description": "Available page size options" + } + }, + "additionalProperties": false, + "description": "Pagination configuration" + }, + "kanban": { + "type": "object", + "properties": { + "groupByField": { + "type": "string", + "description": "Field to group columns by (usually status/select)" + }, + "summarizeField": { + "type": "string", + "description": "Field to sum at top of column (e.g. amount)" + }, + "columns": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields to show on cards" + } + }, + "required": [ + "groupByField", + "columns" + ], + "additionalProperties": false + }, + "calendar": { + "type": "object", + "properties": { + "startDateField": { + "type": "string" + }, + "endDateField": { + "type": "string" + }, + "titleField": { + "type": "string" + }, + "colorField": { + "type": "string" + } + }, + "required": [ + "startDateField", + "titleField" + ], + "additionalProperties": false + }, + "gantt": { + "type": "object", + "properties": { + "startDateField": { + "type": "string" + }, + "endDateField": { + "type": "string" + }, + "titleField": { + "type": "string" + }, + "progressField": { + "type": "string" + }, + "dependenciesField": { + "type": "string" + } + }, + "required": [ + "startDateField", + "endDateField", + "titleField" + ], + "additionalProperties": false + }, + "rowActions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Actions available for individual row items" + }, + "bulkActions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Actions available when multiple rows are selected" + }, + "virtualScroll": { + "type": "boolean", + "description": "Enable virtual scrolling for large datasets" + }, + "conditionalFormatting": { + "type": "array", + "items": { + "type": "object", + "properties": { + "condition": { + "type": "string", + "description": "Condition expression to evaluate" + }, + "style": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "CSS styles to apply when condition is true" + } + }, + "required": [ + "condition", + "style" + ], + "additionalProperties": false + }, + "description": "Conditional formatting rules for list rows" + }, + "inlineEdit": { + "type": "boolean", + "description": "Allow inline editing of records directly in the list view" + }, + "exportOptions": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "csv", + "xlsx", + "pdf", + "json" + ] + }, + "description": "Available export format options" + }, + "emptyState": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "message": { + "type": "string" + }, + "icon": { + "type": "string" + } + }, + "additionalProperties": false, + "description": "Empty state configuration when no records found" + } + }, + "required": [ + "columns" + ], + "additionalProperties": false + }, + "description": "Additional named list views" + }, + "formViews": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "simple", + "tabbed", + "wizard", + "split", + "drawer", + "modal" + ], + "default": "simple" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "object" + }, + "object": { + "type": "string", + "description": "Target object name" + } + }, + "required": [ + "provider", + "object" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "api" + }, + "read": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for fetching data" + }, + "write": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for submitting data (for forms/editable tables)" + } + }, + "required": [ + "provider" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "value" + }, + "items": { + "type": "array", + "items": {}, + "description": "Static data array" + } + }, + "required": [ + "provider", + "items" + ], + "additionalProperties": false + } + ], + "description": "Data source configuration (defaults to \"object\" provider)" + }, + "sections": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "collapsible": { + "type": "boolean", + "default": false + }, + "collapsed": { + "type": "boolean", + "default": false + }, + "columns": { + "type": "string", + "enum": [ + "1", + "2", + "3", + "4" + ], + "default": "2" + }, + "fields": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "placeholder": { + "type": "string", + "description": "Placeholder text" + }, + "helpText": { + "type": "string", + "description": "Help/hint text" + }, + "readonly": { + "type": "boolean", + "description": "Read-only override" + }, + "required": { + "type": "boolean", + "description": "Required override" + }, + "hidden": { + "type": "boolean", + "description": "Hidden override" + }, + "colSpan": { + "type": "integer", + "minimum": 1, + "maximum": 4, + "description": "Column span in grid layout (1-4)" + }, + "widget": { + "type": "string", + "description": "Custom widget/component name" + }, + "dependsOn": { + "type": "string", + "description": "Parent field name for cascading" + }, + "visibleOn": { + "type": "string", + "description": "Visibility condition expression" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "fields" + ], + "additionalProperties": false + } + }, + "groups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "collapsible": { + "type": "boolean", + "default": false + }, + "collapsed": { + "type": "boolean", + "default": false + }, + "columns": { + "type": "string", + "enum": [ + "1", + "2", + "3", + "4" + ], + "default": "2" + }, + "fields": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "placeholder": { + "type": "string", + "description": "Placeholder text" + }, + "helpText": { + "type": "string", + "description": "Help/hint text" + }, + "readonly": { + "type": "boolean", + "description": "Read-only override" + }, + "required": { + "type": "boolean", + "description": "Required override" + }, + "hidden": { + "type": "boolean", + "description": "Hidden override" + }, + "colSpan": { + "type": "integer", + "minimum": 1, + "maximum": 4, + "description": "Column span in grid layout (1-4)" + }, + "widget": { + "type": "string", + "description": "Custom widget/component name" + }, + "dependsOn": { + "type": "string", + "description": "Parent field name for cascading" + }, + "visibleOn": { + "type": "string", + "description": "Visibility condition expression" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "fields" + ], + "additionalProperties": false + } + } + }, + "additionalProperties": false + }, + "description": "Additional named form views" + } + }, + "additionalProperties": false, + "description": "Created view definition" + } + }, + "required": [ + "object", + "viewId", + "view" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/DeleteViewRequest.json b/packages/spec/json-schema/api/DeleteViewRequest.json new file mode 100644 index 000000000..f7b16a209 --- /dev/null +++ b/packages/spec/json-schema/api/DeleteViewRequest.json @@ -0,0 +1,24 @@ +{ + "$ref": "#/definitions/DeleteViewRequest", + "definitions": { + "DeleteViewRequest": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name (snake_case)" + }, + "viewId": { + "type": "string", + "description": "View identifier to delete" + } + }, + "required": [ + "object", + "viewId" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/DeleteViewResponse.json b/packages/spec/json-schema/api/DeleteViewResponse.json new file mode 100644 index 000000000..70257e2fa --- /dev/null +++ b/packages/spec/json-schema/api/DeleteViewResponse.json @@ -0,0 +1,29 @@ +{ + "$ref": "#/definitions/DeleteViewResponse", + "definitions": { + "DeleteViewResponse": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name" + }, + "viewId": { + "type": "string", + "description": "Deleted view identifier" + }, + "success": { + "type": "boolean", + "description": "Whether deletion succeeded" + } + }, + "required": [ + "object", + "viewId", + "success" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/GetEffectivePermissionsRequest.json b/packages/spec/json-schema/api/GetEffectivePermissionsRequest.json new file mode 100644 index 000000000..ec32f4b6e --- /dev/null +++ b/packages/spec/json-schema/api/GetEffectivePermissionsRequest.json @@ -0,0 +1,11 @@ +{ + "$ref": "#/definitions/GetEffectivePermissionsRequest", + "definitions": { + "GetEffectivePermissionsRequest": { + "type": "object", + "properties": {}, + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/GetEffectivePermissionsResponse.json b/packages/spec/json-schema/api/GetEffectivePermissionsResponse.json new file mode 100644 index 000000000..1e78c1132 --- /dev/null +++ b/packages/spec/json-schema/api/GetEffectivePermissionsResponse.json @@ -0,0 +1,78 @@ +{ + "$ref": "#/definitions/GetEffectivePermissionsResponse", + "definitions": { + "GetEffectivePermissionsResponse": { + "type": "object", + "properties": { + "objects": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "allowCreate": { + "type": "boolean", + "default": false, + "description": "Create permission" + }, + "allowRead": { + "type": "boolean", + "default": false, + "description": "Read permission" + }, + "allowEdit": { + "type": "boolean", + "default": false, + "description": "Edit permission" + }, + "allowDelete": { + "type": "boolean", + "default": false, + "description": "Delete permission" + }, + "allowTransfer": { + "type": "boolean", + "default": false, + "description": "Change record ownership" + }, + "allowRestore": { + "type": "boolean", + "default": false, + "description": "Restore from trash (Undelete)" + }, + "allowPurge": { + "type": "boolean", + "default": false, + "description": "Permanently delete (Hard Delete/GDPR)" + }, + "viewAllRecords": { + "type": "boolean", + "default": false, + "description": "View All Data (Bypass Sharing)" + }, + "modifyAllRecords": { + "type": "boolean", + "default": false, + "description": "Modify All Data (Bypass Sharing)" + } + }, + "additionalProperties": false + }, + "description": "Effective object permissions keyed by object name" + }, + "systemPermissions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Effective system-level permissions" + } + }, + "required": [ + "objects", + "systemPermissions" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/GetFieldLabelsRequest.json b/packages/spec/json-schema/api/GetFieldLabelsRequest.json new file mode 100644 index 000000000..cbbdea1d7 --- /dev/null +++ b/packages/spec/json-schema/api/GetFieldLabelsRequest.json @@ -0,0 +1,24 @@ +{ + "$ref": "#/definitions/GetFieldLabelsRequest", + "definitions": { + "GetFieldLabelsRequest": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name" + }, + "locale": { + "type": "string", + "description": "BCP-47 locale code" + } + }, + "required": [ + "object", + "locale" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/GetFieldLabelsResponse.json b/packages/spec/json-schema/api/GetFieldLabelsResponse.json new file mode 100644 index 000000000..cd0d84940 --- /dev/null +++ b/packages/spec/json-schema/api/GetFieldLabelsResponse.json @@ -0,0 +1,53 @@ +{ + "$ref": "#/definitions/GetFieldLabelsResponse", + "definitions": { + "GetFieldLabelsResponse": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name" + }, + "locale": { + "type": "string", + "description": "Locale code" + }, + "labels": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "label": { + "type": "string", + "description": "Translated field label" + }, + "help": { + "type": "string", + "description": "Translated help text" + }, + "options": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Translated option labels" + } + }, + "required": [ + "label" + ], + "additionalProperties": false + }, + "description": "Field labels keyed by field name" + } + }, + "required": [ + "object", + "locale", + "labels" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/GetLocalesRequest.json b/packages/spec/json-schema/api/GetLocalesRequest.json new file mode 100644 index 000000000..7e587bedb --- /dev/null +++ b/packages/spec/json-schema/api/GetLocalesRequest.json @@ -0,0 +1,11 @@ +{ + "$ref": "#/definitions/GetLocalesRequest", + "definitions": { + "GetLocalesRequest": { + "type": "object", + "properties": {}, + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/GetLocalesResponse.json b/packages/spec/json-schema/api/GetLocalesResponse.json new file mode 100644 index 000000000..b294bcddd --- /dev/null +++ b/packages/spec/json-schema/api/GetLocalesResponse.json @@ -0,0 +1,42 @@ +{ + "$ref": "#/definitions/GetLocalesResponse", + "definitions": { + "GetLocalesResponse": { + "type": "object", + "properties": { + "locales": { + "type": "array", + "items": { + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "BCP-47 locale code (e.g., en-US, zh-CN)" + }, + "label": { + "type": "string", + "description": "Display name of the locale" + }, + "isDefault": { + "type": "boolean", + "default": false, + "description": "Whether this is the default locale" + } + }, + "required": [ + "code", + "label" + ], + "additionalProperties": false + }, + "description": "Available locales" + } + }, + "required": [ + "locales" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/GetNotificationPreferencesRequest.json b/packages/spec/json-schema/api/GetNotificationPreferencesRequest.json new file mode 100644 index 000000000..68ffaa14a --- /dev/null +++ b/packages/spec/json-schema/api/GetNotificationPreferencesRequest.json @@ -0,0 +1,11 @@ +{ + "$ref": "#/definitions/GetNotificationPreferencesRequest", + "definitions": { + "GetNotificationPreferencesRequest": { + "type": "object", + "properties": {}, + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/GetNotificationPreferencesResponse.json b/packages/spec/json-schema/api/GetNotificationPreferencesResponse.json new file mode 100644 index 000000000..df364d51b --- /dev/null +++ b/packages/spec/json-schema/api/GetNotificationPreferencesResponse.json @@ -0,0 +1,70 @@ +{ + "$ref": "#/definitions/GetNotificationPreferencesResponse", + "definitions": { + "GetNotificationPreferencesResponse": { + "type": "object", + "properties": { + "preferences": { + "type": "object", + "properties": { + "email": { + "type": "boolean", + "default": true, + "description": "Receive email notifications" + }, + "push": { + "type": "boolean", + "default": true, + "description": "Receive push notifications" + }, + "inApp": { + "type": "boolean", + "default": true, + "description": "Receive in-app notifications" + }, + "digest": { + "type": "string", + "enum": [ + "none", + "daily", + "weekly" + ], + "default": "none", + "description": "Email digest frequency" + }, + "channels": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "default": true, + "description": "Whether this channel is enabled" + }, + "email": { + "type": "boolean", + "description": "Override email setting" + }, + "push": { + "type": "boolean", + "description": "Override push setting" + } + }, + "additionalProperties": false + }, + "description": "Per-channel notification preferences" + } + }, + "additionalProperties": false, + "description": "Current notification preferences" + } + }, + "required": [ + "preferences" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/GetObjectPermissionsRequest.json b/packages/spec/json-schema/api/GetObjectPermissionsRequest.json new file mode 100644 index 000000000..cb9894f2b --- /dev/null +++ b/packages/spec/json-schema/api/GetObjectPermissionsRequest.json @@ -0,0 +1,19 @@ +{ + "$ref": "#/definitions/GetObjectPermissionsRequest", + "definitions": { + "GetObjectPermissionsRequest": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name to get permissions for" + } + }, + "required": [ + "object" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/GetObjectPermissionsResponse.json b/packages/spec/json-schema/api/GetObjectPermissionsResponse.json new file mode 100644 index 000000000..24837f551 --- /dev/null +++ b/packages/spec/json-schema/api/GetObjectPermissionsResponse.json @@ -0,0 +1,92 @@ +{ + "$ref": "#/definitions/GetObjectPermissionsResponse", + "definitions": { + "GetObjectPermissionsResponse": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name" + }, + "permissions": { + "type": "object", + "properties": { + "allowCreate": { + "type": "boolean", + "default": false, + "description": "Create permission" + }, + "allowRead": { + "type": "boolean", + "default": false, + "description": "Read permission" + }, + "allowEdit": { + "type": "boolean", + "default": false, + "description": "Edit permission" + }, + "allowDelete": { + "type": "boolean", + "default": false, + "description": "Delete permission" + }, + "allowTransfer": { + "type": "boolean", + "default": false, + "description": "Change record ownership" + }, + "allowRestore": { + "type": "boolean", + "default": false, + "description": "Restore from trash (Undelete)" + }, + "allowPurge": { + "type": "boolean", + "default": false, + "description": "Permanently delete (Hard Delete/GDPR)" + }, + "viewAllRecords": { + "type": "boolean", + "default": false, + "description": "View All Data (Bypass Sharing)" + }, + "modifyAllRecords": { + "type": "boolean", + "default": false, + "description": "Modify All Data (Bypass Sharing)" + } + }, + "additionalProperties": false, + "description": "Object-level permissions" + }, + "fieldPermissions": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "readable": { + "type": "boolean", + "default": true, + "description": "Field read access" + }, + "editable": { + "type": "boolean", + "default": false, + "description": "Field edit access" + } + }, + "additionalProperties": false + }, + "description": "Field-level permissions keyed by field name" + } + }, + "required": [ + "object", + "permissions" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/GetPresenceRequest.json b/packages/spec/json-schema/api/GetPresenceRequest.json new file mode 100644 index 000000000..cc88e2a43 --- /dev/null +++ b/packages/spec/json-schema/api/GetPresenceRequest.json @@ -0,0 +1,19 @@ +{ + "$ref": "#/definitions/GetPresenceRequest", + "definitions": { + "GetPresenceRequest": { + "type": "object", + "properties": { + "channel": { + "type": "string", + "description": "Channel to get presence for" + } + }, + "required": [ + "channel" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/GetPresenceResponse.json b/packages/spec/json-schema/api/GetPresenceResponse.json new file mode 100644 index 000000000..ef0f3e4c6 --- /dev/null +++ b/packages/spec/json-schema/api/GetPresenceResponse.json @@ -0,0 +1,59 @@ +{ + "$ref": "#/definitions/GetPresenceResponse", + "definitions": { + "GetPresenceResponse": { + "type": "object", + "properties": { + "channel": { + "type": "string", + "description": "Channel name" + }, + "members": { + "type": "array", + "items": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User identifier" + }, + "status": { + "type": "string", + "enum": [ + "online", + "away", + "busy", + "offline" + ], + "description": "Current presence status" + }, + "lastSeen": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 datetime of last activity" + }, + "metadata": { + "type": "object", + "additionalProperties": {}, + "description": "Custom presence data (e.g., current page, custom status)" + } + }, + "required": [ + "userId", + "status", + "lastSeen" + ], + "additionalProperties": false + }, + "description": "Active members and their presence state" + } + }, + "required": [ + "channel", + "members" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/GetTranslationsRequest.json b/packages/spec/json-schema/api/GetTranslationsRequest.json new file mode 100644 index 000000000..d5beb8f18 --- /dev/null +++ b/packages/spec/json-schema/api/GetTranslationsRequest.json @@ -0,0 +1,30 @@ +{ + "$ref": "#/definitions/GetTranslationsRequest", + "definitions": { + "GetTranslationsRequest": { + "type": "object", + "properties": { + "locale": { + "type": "string", + "description": "BCP-47 locale code" + }, + "namespace": { + "type": "string", + "description": "Translation namespace (e.g., objects, apps, messages)" + }, + "keys": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Specific translation keys to fetch" + } + }, + "required": [ + "locale" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/GetTranslationsResponse.json b/packages/spec/json-schema/api/GetTranslationsResponse.json new file mode 100644 index 000000000..864a9565c --- /dev/null +++ b/packages/spec/json-schema/api/GetTranslationsResponse.json @@ -0,0 +1,101 @@ +{ + "$ref": "#/definitions/GetTranslationsResponse", + "definitions": { + "GetTranslationsResponse": { + "type": "object", + "properties": { + "locale": { + "type": "string", + "description": "Locale code" + }, + "translations": { + "type": "object", + "properties": { + "objects": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "label": { + "type": "string", + "description": "Translated singular label" + }, + "pluralLabel": { + "type": "string", + "description": "Translated plural label" + }, + "fields": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "label": { + "type": "string", + "description": "Translated field label" + }, + "help": { + "type": "string", + "description": "Translated help text" + }, + "options": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Option value to translated label map" + } + }, + "additionalProperties": false + }, + "description": "Field-level translations" + } + }, + "required": [ + "label" + ], + "additionalProperties": false + }, + "description": "Object translations keyed by object name" + }, + "apps": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "label": { + "type": "string", + "description": "Translated app label" + }, + "description": { + "type": "string", + "description": "Translated app description" + } + }, + "required": [ + "label" + ], + "additionalProperties": false + }, + "description": "App translations keyed by app name" + }, + "messages": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "UI message translations keyed by message ID" + } + }, + "additionalProperties": false, + "description": "Translation data" + } + }, + "required": [ + "locale", + "translations" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/GetViewRequest.json b/packages/spec/json-schema/api/GetViewRequest.json new file mode 100644 index 000000000..2a44ef754 --- /dev/null +++ b/packages/spec/json-schema/api/GetViewRequest.json @@ -0,0 +1,24 @@ +{ + "$ref": "#/definitions/GetViewRequest", + "definitions": { + "GetViewRequest": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name (snake_case)" + }, + "viewId": { + "type": "string", + "description": "View identifier" + } + }, + "required": [ + "object", + "viewId" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/GetViewResponse.json b/packages/spec/json-schema/api/GetViewResponse.json new file mode 100644 index 000000000..bd2f76da6 --- /dev/null +++ b/packages/spec/json-schema/api/GetViewResponse.json @@ -0,0 +1,1797 @@ +{ + "$ref": "#/definitions/GetViewResponse", + "definitions": { + "GetViewResponse": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name" + }, + "view": { + "type": "object", + "properties": { + "list": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 2, + "pattern": "^[a-z][a-z0-9_]*$", + "description": "Internal view name (lowercase snake_case)" + }, + "label": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "grid", + "kanban", + "gallery", + "calendar", + "timeline", + "gantt", + "map" + ], + "default": "grid" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "object" + }, + "object": { + "type": "string", + "description": "Target object name" + } + }, + "required": [ + "provider", + "object" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "api" + }, + "read": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for fetching data" + }, + "write": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for submitting data (for forms/editable tables)" + } + }, + "required": [ + "provider" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "value" + }, + "items": { + "type": "array", + "items": {}, + "description": "Static data array" + } + }, + "required": [ + "provider", + "items" + ], + "additionalProperties": false + } + ], + "description": "Data source configuration (defaults to \"object\" provider)" + }, + "columns": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "width": { + "type": "number", + "exclusiveMinimum": 0, + "description": "Column width in pixels" + }, + "align": { + "type": "string", + "enum": [ + "left", + "center", + "right" + ], + "description": "Text alignment" + }, + "hidden": { + "type": "boolean", + "description": "Hide column by default" + }, + "sortable": { + "type": "boolean", + "description": "Allow sorting by this column" + }, + "resizable": { + "type": "boolean", + "description": "Allow resizing this column" + }, + "wrap": { + "type": "boolean", + "description": "Allow text wrapping" + }, + "type": { + "type": "string", + "description": "Renderer type override (e.g., \"currency\", \"date\")" + }, + "link": { + "type": "boolean", + "description": "Functions as the primary navigation link (triggers View navigation)" + }, + "action": { + "type": "string", + "description": "Registered Action ID to execute when clicked" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + } + ], + "description": "Fields to display as columns" + }, + "filter": { + "type": "array", + "items": {}, + "description": "Filter criteria (JSON Rules)" + }, + "sort": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "field": { + "type": "string" + }, + "order": { + "type": "string", + "enum": [ + "asc", + "desc" + ] + } + }, + "required": [ + "field", + "order" + ], + "additionalProperties": false + } + } + ] + }, + "searchableFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields enabled for search" + }, + "filterableFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields enabled for end-user filtering in the top bar" + }, + "resizable": { + "type": "boolean", + "description": "Enable column resizing" + }, + "striped": { + "type": "boolean", + "description": "Striped row styling" + }, + "bordered": { + "type": "boolean", + "description": "Show borders" + }, + "selection": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "none", + "single", + "multiple" + ], + "default": "none", + "description": "Selection mode" + } + }, + "additionalProperties": false, + "description": "Row selection configuration" + }, + "navigation": { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "page", + "drawer", + "modal", + "split", + "popover", + "new_window", + "none" + ], + "default": "page" + }, + "view": { + "type": "string", + "description": "Name of the form view to use for details (e.g. \"summary_view\", \"edit_form\")" + }, + "preventNavigation": { + "type": "boolean", + "default": false, + "description": "Disable standard navigation entirely" + }, + "openNewTab": { + "type": "boolean", + "default": false, + "description": "Force open in new tab (applies to page mode)" + }, + "width": { + "type": [ + "string", + "number" + ], + "description": "Width of the drawer/modal (e.g. \"600px\", \"50%\")" + } + }, + "additionalProperties": false, + "description": "Configuration for item click navigation (page, drawer, modal, etc.)" + }, + "pagination": { + "type": "object", + "properties": { + "pageSize": { + "type": "integer", + "exclusiveMinimum": 0, + "default": 25, + "description": "Number of records per page" + }, + "pageSizeOptions": { + "type": "array", + "items": { + "type": "integer", + "exclusiveMinimum": 0 + }, + "description": "Available page size options" + } + }, + "additionalProperties": false, + "description": "Pagination configuration" + }, + "kanban": { + "type": "object", + "properties": { + "groupByField": { + "type": "string", + "description": "Field to group columns by (usually status/select)" + }, + "summarizeField": { + "type": "string", + "description": "Field to sum at top of column (e.g. amount)" + }, + "columns": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields to show on cards" + } + }, + "required": [ + "groupByField", + "columns" + ], + "additionalProperties": false + }, + "calendar": { + "type": "object", + "properties": { + "startDateField": { + "type": "string" + }, + "endDateField": { + "type": "string" + }, + "titleField": { + "type": "string" + }, + "colorField": { + "type": "string" + } + }, + "required": [ + "startDateField", + "titleField" + ], + "additionalProperties": false + }, + "gantt": { + "type": "object", + "properties": { + "startDateField": { + "type": "string" + }, + "endDateField": { + "type": "string" + }, + "titleField": { + "type": "string" + }, + "progressField": { + "type": "string" + }, + "dependenciesField": { + "type": "string" + } + }, + "required": [ + "startDateField", + "endDateField", + "titleField" + ], + "additionalProperties": false + }, + "rowActions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Actions available for individual row items" + }, + "bulkActions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Actions available when multiple rows are selected" + }, + "virtualScroll": { + "type": "boolean", + "description": "Enable virtual scrolling for large datasets" + }, + "conditionalFormatting": { + "type": "array", + "items": { + "type": "object", + "properties": { + "condition": { + "type": "string", + "description": "Condition expression to evaluate" + }, + "style": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "CSS styles to apply when condition is true" + } + }, + "required": [ + "condition", + "style" + ], + "additionalProperties": false + }, + "description": "Conditional formatting rules for list rows" + }, + "inlineEdit": { + "type": "boolean", + "description": "Allow inline editing of records directly in the list view" + }, + "exportOptions": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "csv", + "xlsx", + "pdf", + "json" + ] + }, + "description": "Available export format options" + }, + "emptyState": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "message": { + "type": "string" + }, + "icon": { + "type": "string" + } + }, + "additionalProperties": false, + "description": "Empty state configuration when no records found" + } + }, + "required": [ + "columns" + ], + "additionalProperties": false + }, + "form": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "simple", + "tabbed", + "wizard", + "split", + "drawer", + "modal" + ], + "default": "simple" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "object" + }, + "object": { + "type": "string", + "description": "Target object name" + } + }, + "required": [ + "provider", + "object" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "api" + }, + "read": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for fetching data" + }, + "write": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for submitting data (for forms/editable tables)" + } + }, + "required": [ + "provider" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "value" + }, + "items": { + "type": "array", + "items": {}, + "description": "Static data array" + } + }, + "required": [ + "provider", + "items" + ], + "additionalProperties": false + } + ], + "description": "Data source configuration (defaults to \"object\" provider)" + }, + "sections": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "collapsible": { + "type": "boolean", + "default": false + }, + "collapsed": { + "type": "boolean", + "default": false + }, + "columns": { + "type": "string", + "enum": [ + "1", + "2", + "3", + "4" + ], + "default": "2" + }, + "fields": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "placeholder": { + "type": "string", + "description": "Placeholder text" + }, + "helpText": { + "type": "string", + "description": "Help/hint text" + }, + "readonly": { + "type": "boolean", + "description": "Read-only override" + }, + "required": { + "type": "boolean", + "description": "Required override" + }, + "hidden": { + "type": "boolean", + "description": "Hidden override" + }, + "colSpan": { + "type": "integer", + "minimum": 1, + "maximum": 4, + "description": "Column span in grid layout (1-4)" + }, + "widget": { + "type": "string", + "description": "Custom widget/component name" + }, + "dependsOn": { + "type": "string", + "description": "Parent field name for cascading" + }, + "visibleOn": { + "type": "string", + "description": "Visibility condition expression" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "fields" + ], + "additionalProperties": false + } + }, + "groups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "collapsible": { + "type": "boolean", + "default": false + }, + "collapsed": { + "type": "boolean", + "default": false + }, + "columns": { + "type": "string", + "enum": [ + "1", + "2", + "3", + "4" + ], + "default": "2" + }, + "fields": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "placeholder": { + "type": "string", + "description": "Placeholder text" + }, + "helpText": { + "type": "string", + "description": "Help/hint text" + }, + "readonly": { + "type": "boolean", + "description": "Read-only override" + }, + "required": { + "type": "boolean", + "description": "Required override" + }, + "hidden": { + "type": "boolean", + "description": "Hidden override" + }, + "colSpan": { + "type": "integer", + "minimum": 1, + "maximum": 4, + "description": "Column span in grid layout (1-4)" + }, + "widget": { + "type": "string", + "description": "Custom widget/component name" + }, + "dependsOn": { + "type": "string", + "description": "Parent field name for cascading" + }, + "visibleOn": { + "type": "string", + "description": "Visibility condition expression" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "fields" + ], + "additionalProperties": false + } + } + }, + "additionalProperties": false + }, + "listViews": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 2, + "pattern": "^[a-z][a-z0-9_]*$", + "description": "Internal view name (lowercase snake_case)" + }, + "label": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "grid", + "kanban", + "gallery", + "calendar", + "timeline", + "gantt", + "map" + ], + "default": "grid" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "object" + }, + "object": { + "type": "string", + "description": "Target object name" + } + }, + "required": [ + "provider", + "object" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "api" + }, + "read": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for fetching data" + }, + "write": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for submitting data (for forms/editable tables)" + } + }, + "required": [ + "provider" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "value" + }, + "items": { + "type": "array", + "items": {}, + "description": "Static data array" + } + }, + "required": [ + "provider", + "items" + ], + "additionalProperties": false + } + ], + "description": "Data source configuration (defaults to \"object\" provider)" + }, + "columns": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "width": { + "type": "number", + "exclusiveMinimum": 0, + "description": "Column width in pixels" + }, + "align": { + "type": "string", + "enum": [ + "left", + "center", + "right" + ], + "description": "Text alignment" + }, + "hidden": { + "type": "boolean", + "description": "Hide column by default" + }, + "sortable": { + "type": "boolean", + "description": "Allow sorting by this column" + }, + "resizable": { + "type": "boolean", + "description": "Allow resizing this column" + }, + "wrap": { + "type": "boolean", + "description": "Allow text wrapping" + }, + "type": { + "type": "string", + "description": "Renderer type override (e.g., \"currency\", \"date\")" + }, + "link": { + "type": "boolean", + "description": "Functions as the primary navigation link (triggers View navigation)" + }, + "action": { + "type": "string", + "description": "Registered Action ID to execute when clicked" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + } + ], + "description": "Fields to display as columns" + }, + "filter": { + "type": "array", + "items": {}, + "description": "Filter criteria (JSON Rules)" + }, + "sort": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "field": { + "type": "string" + }, + "order": { + "type": "string", + "enum": [ + "asc", + "desc" + ] + } + }, + "required": [ + "field", + "order" + ], + "additionalProperties": false + } + } + ] + }, + "searchableFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields enabled for search" + }, + "filterableFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields enabled for end-user filtering in the top bar" + }, + "resizable": { + "type": "boolean", + "description": "Enable column resizing" + }, + "striped": { + "type": "boolean", + "description": "Striped row styling" + }, + "bordered": { + "type": "boolean", + "description": "Show borders" + }, + "selection": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "none", + "single", + "multiple" + ], + "default": "none", + "description": "Selection mode" + } + }, + "additionalProperties": false, + "description": "Row selection configuration" + }, + "navigation": { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "page", + "drawer", + "modal", + "split", + "popover", + "new_window", + "none" + ], + "default": "page" + }, + "view": { + "type": "string", + "description": "Name of the form view to use for details (e.g. \"summary_view\", \"edit_form\")" + }, + "preventNavigation": { + "type": "boolean", + "default": false, + "description": "Disable standard navigation entirely" + }, + "openNewTab": { + "type": "boolean", + "default": false, + "description": "Force open in new tab (applies to page mode)" + }, + "width": { + "type": [ + "string", + "number" + ], + "description": "Width of the drawer/modal (e.g. \"600px\", \"50%\")" + } + }, + "additionalProperties": false, + "description": "Configuration for item click navigation (page, drawer, modal, etc.)" + }, + "pagination": { + "type": "object", + "properties": { + "pageSize": { + "type": "integer", + "exclusiveMinimum": 0, + "default": 25, + "description": "Number of records per page" + }, + "pageSizeOptions": { + "type": "array", + "items": { + "type": "integer", + "exclusiveMinimum": 0 + }, + "description": "Available page size options" + } + }, + "additionalProperties": false, + "description": "Pagination configuration" + }, + "kanban": { + "type": "object", + "properties": { + "groupByField": { + "type": "string", + "description": "Field to group columns by (usually status/select)" + }, + "summarizeField": { + "type": "string", + "description": "Field to sum at top of column (e.g. amount)" + }, + "columns": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields to show on cards" + } + }, + "required": [ + "groupByField", + "columns" + ], + "additionalProperties": false + }, + "calendar": { + "type": "object", + "properties": { + "startDateField": { + "type": "string" + }, + "endDateField": { + "type": "string" + }, + "titleField": { + "type": "string" + }, + "colorField": { + "type": "string" + } + }, + "required": [ + "startDateField", + "titleField" + ], + "additionalProperties": false + }, + "gantt": { + "type": "object", + "properties": { + "startDateField": { + "type": "string" + }, + "endDateField": { + "type": "string" + }, + "titleField": { + "type": "string" + }, + "progressField": { + "type": "string" + }, + "dependenciesField": { + "type": "string" + } + }, + "required": [ + "startDateField", + "endDateField", + "titleField" + ], + "additionalProperties": false + }, + "rowActions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Actions available for individual row items" + }, + "bulkActions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Actions available when multiple rows are selected" + }, + "virtualScroll": { + "type": "boolean", + "description": "Enable virtual scrolling for large datasets" + }, + "conditionalFormatting": { + "type": "array", + "items": { + "type": "object", + "properties": { + "condition": { + "type": "string", + "description": "Condition expression to evaluate" + }, + "style": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "CSS styles to apply when condition is true" + } + }, + "required": [ + "condition", + "style" + ], + "additionalProperties": false + }, + "description": "Conditional formatting rules for list rows" + }, + "inlineEdit": { + "type": "boolean", + "description": "Allow inline editing of records directly in the list view" + }, + "exportOptions": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "csv", + "xlsx", + "pdf", + "json" + ] + }, + "description": "Available export format options" + }, + "emptyState": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "message": { + "type": "string" + }, + "icon": { + "type": "string" + } + }, + "additionalProperties": false, + "description": "Empty state configuration when no records found" + } + }, + "required": [ + "columns" + ], + "additionalProperties": false + }, + "description": "Additional named list views" + }, + "formViews": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "simple", + "tabbed", + "wizard", + "split", + "drawer", + "modal" + ], + "default": "simple" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "object" + }, + "object": { + "type": "string", + "description": "Target object name" + } + }, + "required": [ + "provider", + "object" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "api" + }, + "read": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for fetching data" + }, + "write": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for submitting data (for forms/editable tables)" + } + }, + "required": [ + "provider" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "value" + }, + "items": { + "type": "array", + "items": {}, + "description": "Static data array" + } + }, + "required": [ + "provider", + "items" + ], + "additionalProperties": false + } + ], + "description": "Data source configuration (defaults to \"object\" provider)" + }, + "sections": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "collapsible": { + "type": "boolean", + "default": false + }, + "collapsed": { + "type": "boolean", + "default": false + }, + "columns": { + "type": "string", + "enum": [ + "1", + "2", + "3", + "4" + ], + "default": "2" + }, + "fields": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "placeholder": { + "type": "string", + "description": "Placeholder text" + }, + "helpText": { + "type": "string", + "description": "Help/hint text" + }, + "readonly": { + "type": "boolean", + "description": "Read-only override" + }, + "required": { + "type": "boolean", + "description": "Required override" + }, + "hidden": { + "type": "boolean", + "description": "Hidden override" + }, + "colSpan": { + "type": "integer", + "minimum": 1, + "maximum": 4, + "description": "Column span in grid layout (1-4)" + }, + "widget": { + "type": "string", + "description": "Custom widget/component name" + }, + "dependsOn": { + "type": "string", + "description": "Parent field name for cascading" + }, + "visibleOn": { + "type": "string", + "description": "Visibility condition expression" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "fields" + ], + "additionalProperties": false + } + }, + "groups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "collapsible": { + "type": "boolean", + "default": false + }, + "collapsed": { + "type": "boolean", + "default": false + }, + "columns": { + "type": "string", + "enum": [ + "1", + "2", + "3", + "4" + ], + "default": "2" + }, + "fields": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "placeholder": { + "type": "string", + "description": "Placeholder text" + }, + "helpText": { + "type": "string", + "description": "Help/hint text" + }, + "readonly": { + "type": "boolean", + "description": "Read-only override" + }, + "required": { + "type": "boolean", + "description": "Required override" + }, + "hidden": { + "type": "boolean", + "description": "Hidden override" + }, + "colSpan": { + "type": "integer", + "minimum": 1, + "maximum": 4, + "description": "Column span in grid layout (1-4)" + }, + "widget": { + "type": "string", + "description": "Custom widget/component name" + }, + "dependsOn": { + "type": "string", + "description": "Parent field name for cascading" + }, + "visibleOn": { + "type": "string", + "description": "Visibility condition expression" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "fields" + ], + "additionalProperties": false + } + } + }, + "additionalProperties": false + }, + "description": "Additional named form views" + } + }, + "additionalProperties": false, + "description": "View definition" + } + }, + "required": [ + "object", + "view" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/GetWorkflowConfigRequest.json b/packages/spec/json-schema/api/GetWorkflowConfigRequest.json new file mode 100644 index 000000000..3da0e40fa --- /dev/null +++ b/packages/spec/json-schema/api/GetWorkflowConfigRequest.json @@ -0,0 +1,19 @@ +{ + "$ref": "#/definitions/GetWorkflowConfigRequest", + "definitions": { + "GetWorkflowConfigRequest": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name to get workflow config for" + } + }, + "required": [ + "object" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/GetWorkflowConfigResponse.json b/packages/spec/json-schema/api/GetWorkflowConfigResponse.json new file mode 100644 index 000000000..7b87c47f7 --- /dev/null +++ b/packages/spec/json-schema/api/GetWorkflowConfigResponse.json @@ -0,0 +1,712 @@ +{ + "$ref": "#/definitions/GetWorkflowConfigResponse", + "definitions": { + "GetWorkflowConfigResponse": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name" + }, + "workflows": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 2, + "pattern": "^[a-z][a-z0-9_]*$", + "description": "Unique workflow name (lowercase snake_case)" + }, + "objectName": { + "type": "string", + "description": "Target Object" + }, + "triggerType": { + "type": "string", + "enum": [ + "on_create", + "on_update", + "on_create_or_update", + "on_delete", + "schedule" + ], + "description": "When to evaluate" + }, + "criteria": { + "type": "string", + "description": "Formula condition. If TRUE, actions execute." + }, + "actions": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Action name" + }, + "type": { + "type": "string", + "const": "field_update" + }, + "field": { + "type": "string", + "description": "Field to update" + }, + "value": { + "description": "Value or Formula to set" + } + }, + "required": [ + "name", + "type", + "field" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Action name" + }, + "type": { + "type": "string", + "const": "email_alert" + }, + "template": { + "type": "string", + "description": "Email template ID/DevName" + }, + "recipients": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of recipient emails or user IDs" + } + }, + "required": [ + "name", + "type", + "template", + "recipients" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Action name" + }, + "type": { + "type": "string", + "const": "http_call" + }, + "url": { + "type": "string", + "description": "Target URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "DELETE", + "PATCH" + ], + "default": "POST", + "description": "HTTP Method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "HTTP Headers" + }, + "body": { + "type": "string", + "description": "Request body (JSON or text)" + } + }, + "required": [ + "name", + "type", + "url" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Action name" + }, + "type": { + "type": "string", + "const": "connector_action" + }, + "connectorId": { + "type": "string", + "description": "Target Connector ID (e.g. slack, twilio)" + }, + "actionId": { + "type": "string", + "description": "Target Action ID (e.g. send_message)" + }, + "input": { + "type": "object", + "additionalProperties": {}, + "description": "Input parameters matching the action schema" + } + }, + "required": [ + "name", + "type", + "connectorId", + "actionId", + "input" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Action name" + }, + "type": { + "type": "string", + "const": "task_creation" + }, + "taskObject": { + "type": "string", + "description": "Task object name (e.g., \"task\", \"project_task\")" + }, + "subject": { + "type": "string", + "description": "Task subject/title" + }, + "description": { + "type": "string", + "description": "Task description" + }, + "assignedTo": { + "type": "string", + "description": "User ID or field reference for assignee" + }, + "dueDate": { + "type": "string", + "description": "Due date (ISO string or formula)" + }, + "priority": { + "type": "string", + "description": "Task priority" + }, + "relatedTo": { + "type": "string", + "description": "Related record ID or field reference" + }, + "additionalFields": { + "type": "object", + "additionalProperties": {}, + "description": "Additional custom fields" + } + }, + "required": [ + "name", + "type", + "taskObject", + "subject" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Action name" + }, + "type": { + "type": "string", + "const": "push_notification" + }, + "title": { + "type": "string", + "description": "Notification title" + }, + "body": { + "type": "string", + "description": "Notification body text" + }, + "recipients": { + "type": "array", + "items": { + "type": "string" + }, + "description": "User IDs or device tokens" + }, + "data": { + "type": "object", + "additionalProperties": {}, + "description": "Additional data payload" + }, + "badge": { + "type": "number", + "description": "Badge count (iOS)" + }, + "sound": { + "type": "string", + "description": "Notification sound" + }, + "clickAction": { + "type": "string", + "description": "Action/URL when notification is clicked" + } + }, + "required": [ + "name", + "type", + "title", + "body", + "recipients" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Action name" + }, + "type": { + "type": "string", + "const": "custom_script" + }, + "language": { + "type": "string", + "enum": [ + "javascript", + "typescript", + "python" + ], + "default": "javascript", + "description": "Script language" + }, + "code": { + "type": "string", + "description": "Script code to execute" + }, + "timeout": { + "type": "number", + "default": 30000, + "description": "Execution timeout in milliseconds" + }, + "context": { + "type": "object", + "additionalProperties": {}, + "description": "Additional context variables" + } + }, + "required": [ + "name", + "type", + "code" + ], + "additionalProperties": false + } + ] + }, + "description": "Immediate actions" + }, + "timeTriggers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier" + }, + "timeLength": { + "type": "integer", + "description": "Duration amount (e.g. 1, 30)" + }, + "timeUnit": { + "type": "string", + "enum": [ + "minutes", + "hours", + "days" + ], + "description": "Unit of time" + }, + "offsetDirection": { + "type": "string", + "enum": [ + "before", + "after" + ], + "description": "Before or After the reference date" + }, + "offsetFrom": { + "type": "string", + "enum": [ + "trigger_date", + "date_field" + ], + "description": "Basis for calculation" + }, + "dateField": { + "type": "string", + "description": "Date field to calculate from (required if offsetFrom is date_field)" + }, + "actions": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Action name" + }, + "type": { + "type": "string", + "const": "field_update" + }, + "field": { + "type": "string", + "description": "Field to update" + }, + "value": { + "description": "Value or Formula to set" + } + }, + "required": [ + "name", + "type", + "field" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Action name" + }, + "type": { + "type": "string", + "const": "email_alert" + }, + "template": { + "type": "string", + "description": "Email template ID/DevName" + }, + "recipients": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of recipient emails or user IDs" + } + }, + "required": [ + "name", + "type", + "template", + "recipients" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Action name" + }, + "type": { + "type": "string", + "const": "http_call" + }, + "url": { + "type": "string", + "description": "Target URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "DELETE", + "PATCH" + ], + "default": "POST", + "description": "HTTP Method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "HTTP Headers" + }, + "body": { + "type": "string", + "description": "Request body (JSON or text)" + } + }, + "required": [ + "name", + "type", + "url" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Action name" + }, + "type": { + "type": "string", + "const": "connector_action" + }, + "connectorId": { + "type": "string", + "description": "Target Connector ID (e.g. slack, twilio)" + }, + "actionId": { + "type": "string", + "description": "Target Action ID (e.g. send_message)" + }, + "input": { + "type": "object", + "additionalProperties": {}, + "description": "Input parameters matching the action schema" + } + }, + "required": [ + "name", + "type", + "connectorId", + "actionId", + "input" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Action name" + }, + "type": { + "type": "string", + "const": "task_creation" + }, + "taskObject": { + "type": "string", + "description": "Task object name (e.g., \"task\", \"project_task\")" + }, + "subject": { + "type": "string", + "description": "Task subject/title" + }, + "description": { + "type": "string", + "description": "Task description" + }, + "assignedTo": { + "type": "string", + "description": "User ID or field reference for assignee" + }, + "dueDate": { + "type": "string", + "description": "Due date (ISO string or formula)" + }, + "priority": { + "type": "string", + "description": "Task priority" + }, + "relatedTo": { + "type": "string", + "description": "Related record ID or field reference" + }, + "additionalFields": { + "type": "object", + "additionalProperties": {}, + "description": "Additional custom fields" + } + }, + "required": [ + "name", + "type", + "taskObject", + "subject" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Action name" + }, + "type": { + "type": "string", + "const": "push_notification" + }, + "title": { + "type": "string", + "description": "Notification title" + }, + "body": { + "type": "string", + "description": "Notification body text" + }, + "recipients": { + "type": "array", + "items": { + "type": "string" + }, + "description": "User IDs or device tokens" + }, + "data": { + "type": "object", + "additionalProperties": {}, + "description": "Additional data payload" + }, + "badge": { + "type": "number", + "description": "Badge count (iOS)" + }, + "sound": { + "type": "string", + "description": "Notification sound" + }, + "clickAction": { + "type": "string", + "description": "Action/URL when notification is clicked" + } + }, + "required": [ + "name", + "type", + "title", + "body", + "recipients" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Action name" + }, + "type": { + "type": "string", + "const": "custom_script" + }, + "language": { + "type": "string", + "enum": [ + "javascript", + "typescript", + "python" + ], + "default": "javascript", + "description": "Script language" + }, + "code": { + "type": "string", + "description": "Script code to execute" + }, + "timeout": { + "type": "number", + "default": 30000, + "description": "Execution timeout in milliseconds" + }, + "context": { + "type": "object", + "additionalProperties": {}, + "description": "Additional context variables" + } + }, + "required": [ + "name", + "type", + "code" + ], + "additionalProperties": false + } + ] + }, + "description": "Actions to execute at the scheduled time" + } + }, + "required": [ + "timeLength", + "timeUnit", + "offsetDirection", + "offsetFrom", + "actions" + ], + "additionalProperties": false + }, + "description": "Scheduled actions relative to trigger or date field" + }, + "active": { + "type": "boolean", + "default": true, + "description": "Whether this workflow is active" + }, + "reevaluateOnChange": { + "type": "boolean", + "default": false, + "description": "Re-evaluate rule if field updates change the record validity" + } + }, + "required": [ + "name", + "objectName", + "triggerType" + ], + "additionalProperties": false + }, + "description": "Active workflow rules for this object" + } + }, + "required": [ + "object", + "workflows" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/GetWorkflowStateRequest.json b/packages/spec/json-schema/api/GetWorkflowStateRequest.json new file mode 100644 index 000000000..183df6b58 --- /dev/null +++ b/packages/spec/json-schema/api/GetWorkflowStateRequest.json @@ -0,0 +1,24 @@ +{ + "$ref": "#/definitions/GetWorkflowStateRequest", + "definitions": { + "GetWorkflowStateRequest": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name" + }, + "recordId": { + "type": "string", + "description": "Record ID to get workflow state for" + } + }, + "required": [ + "object", + "recordId" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/GetWorkflowStateResponse.json b/packages/spec/json-schema/api/GetWorkflowStateResponse.json new file mode 100644 index 000000000..268a2e3f3 --- /dev/null +++ b/packages/spec/json-schema/api/GetWorkflowStateResponse.json @@ -0,0 +1,113 @@ +{ + "$ref": "#/definitions/GetWorkflowStateResponse", + "definitions": { + "GetWorkflowStateResponse": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name" + }, + "recordId": { + "type": "string", + "description": "Record ID" + }, + "state": { + "type": "object", + "properties": { + "currentState": { + "type": "string", + "description": "Current workflow state name" + }, + "availableTransitions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Transition name" + }, + "targetState": { + "type": "string", + "description": "Target state after transition" + }, + "label": { + "type": "string", + "description": "Display label" + }, + "requiresApproval": { + "type": "boolean", + "default": false, + "description": "Whether transition requires approval" + } + }, + "required": [ + "name", + "targetState" + ], + "additionalProperties": false + }, + "description": "Available transitions from current state" + }, + "history": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fromState": { + "type": "string", + "description": "Previous state" + }, + "toState": { + "type": "string", + "description": "New state" + }, + "action": { + "type": "string", + "description": "Action that triggered the transition" + }, + "userId": { + "type": "string", + "description": "User who performed the action" + }, + "timestamp": { + "type": "string", + "format": "date-time", + "description": "When the transition occurred" + }, + "comment": { + "type": "string", + "description": "Optional comment" + } + }, + "required": [ + "fromState", + "toState", + "action", + "userId", + "timestamp" + ], + "additionalProperties": false + }, + "description": "State transition history" + } + }, + "required": [ + "currentState", + "availableTransitions" + ], + "additionalProperties": false, + "description": "Current workflow state and available transitions" + } + }, + "required": [ + "object", + "recordId", + "state" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/ListNotificationsRequest.json b/packages/spec/json-schema/api/ListNotificationsRequest.json new file mode 100644 index 000000000..c6887e868 --- /dev/null +++ b/packages/spec/json-schema/api/ListNotificationsRequest.json @@ -0,0 +1,29 @@ +{ + "$ref": "#/definitions/ListNotificationsRequest", + "definitions": { + "ListNotificationsRequest": { + "type": "object", + "properties": { + "read": { + "type": "boolean", + "description": "Filter by read status" + }, + "type": { + "type": "string", + "description": "Filter by notification type" + }, + "limit": { + "type": "number", + "default": 20, + "description": "Maximum number of notifications to return" + }, + "cursor": { + "type": "string", + "description": "Pagination cursor" + } + }, + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/ListNotificationsResponse.json b/packages/spec/json-schema/api/ListNotificationsResponse.json new file mode 100644 index 000000000..3e4c3db02 --- /dev/null +++ b/packages/spec/json-schema/api/ListNotificationsResponse.json @@ -0,0 +1,76 @@ +{ + "$ref": "#/definitions/ListNotificationsResponse", + "definitions": { + "ListNotificationsResponse": { + "type": "object", + "properties": { + "notifications": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Notification ID" + }, + "type": { + "type": "string", + "description": "Notification type" + }, + "title": { + "type": "string", + "description": "Notification title" + }, + "body": { + "type": "string", + "description": "Notification body text" + }, + "read": { + "type": "boolean", + "default": false, + "description": "Whether notification has been read" + }, + "data": { + "type": "object", + "additionalProperties": {}, + "description": "Additional notification data" + }, + "actionUrl": { + "type": "string", + "description": "URL to navigate to when clicked" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "When notification was created" + } + }, + "required": [ + "id", + "type", + "title", + "body", + "createdAt" + ], + "additionalProperties": false + }, + "description": "List of notifications" + }, + "unreadCount": { + "type": "number", + "description": "Total number of unread notifications" + }, + "cursor": { + "type": "string", + "description": "Next page cursor" + } + }, + "required": [ + "notifications", + "unreadCount" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/ListViewsRequest.json b/packages/spec/json-schema/api/ListViewsRequest.json new file mode 100644 index 000000000..d02d4952c --- /dev/null +++ b/packages/spec/json-schema/api/ListViewsRequest.json @@ -0,0 +1,27 @@ +{ + "$ref": "#/definitions/ListViewsRequest", + "definitions": { + "ListViewsRequest": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name (snake_case)" + }, + "type": { + "type": "string", + "enum": [ + "list", + "form" + ], + "description": "Filter by view type" + } + }, + "required": [ + "object" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/ListViewsResponse.json b/packages/spec/json-schema/api/ListViewsResponse.json new file mode 100644 index 000000000..fe9cbedfb --- /dev/null +++ b/packages/spec/json-schema/api/ListViewsResponse.json @@ -0,0 +1,1800 @@ +{ + "$ref": "#/definitions/ListViewsResponse", + "definitions": { + "ListViewsResponse": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name" + }, + "views": { + "type": "array", + "items": { + "type": "object", + "properties": { + "list": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 2, + "pattern": "^[a-z][a-z0-9_]*$", + "description": "Internal view name (lowercase snake_case)" + }, + "label": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "grid", + "kanban", + "gallery", + "calendar", + "timeline", + "gantt", + "map" + ], + "default": "grid" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "object" + }, + "object": { + "type": "string", + "description": "Target object name" + } + }, + "required": [ + "provider", + "object" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "api" + }, + "read": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for fetching data" + }, + "write": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for submitting data (for forms/editable tables)" + } + }, + "required": [ + "provider" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "value" + }, + "items": { + "type": "array", + "items": {}, + "description": "Static data array" + } + }, + "required": [ + "provider", + "items" + ], + "additionalProperties": false + } + ], + "description": "Data source configuration (defaults to \"object\" provider)" + }, + "columns": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "width": { + "type": "number", + "exclusiveMinimum": 0, + "description": "Column width in pixels" + }, + "align": { + "type": "string", + "enum": [ + "left", + "center", + "right" + ], + "description": "Text alignment" + }, + "hidden": { + "type": "boolean", + "description": "Hide column by default" + }, + "sortable": { + "type": "boolean", + "description": "Allow sorting by this column" + }, + "resizable": { + "type": "boolean", + "description": "Allow resizing this column" + }, + "wrap": { + "type": "boolean", + "description": "Allow text wrapping" + }, + "type": { + "type": "string", + "description": "Renderer type override (e.g., \"currency\", \"date\")" + }, + "link": { + "type": "boolean", + "description": "Functions as the primary navigation link (triggers View navigation)" + }, + "action": { + "type": "string", + "description": "Registered Action ID to execute when clicked" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + } + ], + "description": "Fields to display as columns" + }, + "filter": { + "type": "array", + "items": {}, + "description": "Filter criteria (JSON Rules)" + }, + "sort": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "field": { + "type": "string" + }, + "order": { + "type": "string", + "enum": [ + "asc", + "desc" + ] + } + }, + "required": [ + "field", + "order" + ], + "additionalProperties": false + } + } + ] + }, + "searchableFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields enabled for search" + }, + "filterableFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields enabled for end-user filtering in the top bar" + }, + "resizable": { + "type": "boolean", + "description": "Enable column resizing" + }, + "striped": { + "type": "boolean", + "description": "Striped row styling" + }, + "bordered": { + "type": "boolean", + "description": "Show borders" + }, + "selection": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "none", + "single", + "multiple" + ], + "default": "none", + "description": "Selection mode" + } + }, + "additionalProperties": false, + "description": "Row selection configuration" + }, + "navigation": { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "page", + "drawer", + "modal", + "split", + "popover", + "new_window", + "none" + ], + "default": "page" + }, + "view": { + "type": "string", + "description": "Name of the form view to use for details (e.g. \"summary_view\", \"edit_form\")" + }, + "preventNavigation": { + "type": "boolean", + "default": false, + "description": "Disable standard navigation entirely" + }, + "openNewTab": { + "type": "boolean", + "default": false, + "description": "Force open in new tab (applies to page mode)" + }, + "width": { + "type": [ + "string", + "number" + ], + "description": "Width of the drawer/modal (e.g. \"600px\", \"50%\")" + } + }, + "additionalProperties": false, + "description": "Configuration for item click navigation (page, drawer, modal, etc.)" + }, + "pagination": { + "type": "object", + "properties": { + "pageSize": { + "type": "integer", + "exclusiveMinimum": 0, + "default": 25, + "description": "Number of records per page" + }, + "pageSizeOptions": { + "type": "array", + "items": { + "type": "integer", + "exclusiveMinimum": 0 + }, + "description": "Available page size options" + } + }, + "additionalProperties": false, + "description": "Pagination configuration" + }, + "kanban": { + "type": "object", + "properties": { + "groupByField": { + "type": "string", + "description": "Field to group columns by (usually status/select)" + }, + "summarizeField": { + "type": "string", + "description": "Field to sum at top of column (e.g. amount)" + }, + "columns": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields to show on cards" + } + }, + "required": [ + "groupByField", + "columns" + ], + "additionalProperties": false + }, + "calendar": { + "type": "object", + "properties": { + "startDateField": { + "type": "string" + }, + "endDateField": { + "type": "string" + }, + "titleField": { + "type": "string" + }, + "colorField": { + "type": "string" + } + }, + "required": [ + "startDateField", + "titleField" + ], + "additionalProperties": false + }, + "gantt": { + "type": "object", + "properties": { + "startDateField": { + "type": "string" + }, + "endDateField": { + "type": "string" + }, + "titleField": { + "type": "string" + }, + "progressField": { + "type": "string" + }, + "dependenciesField": { + "type": "string" + } + }, + "required": [ + "startDateField", + "endDateField", + "titleField" + ], + "additionalProperties": false + }, + "rowActions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Actions available for individual row items" + }, + "bulkActions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Actions available when multiple rows are selected" + }, + "virtualScroll": { + "type": "boolean", + "description": "Enable virtual scrolling for large datasets" + }, + "conditionalFormatting": { + "type": "array", + "items": { + "type": "object", + "properties": { + "condition": { + "type": "string", + "description": "Condition expression to evaluate" + }, + "style": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "CSS styles to apply when condition is true" + } + }, + "required": [ + "condition", + "style" + ], + "additionalProperties": false + }, + "description": "Conditional formatting rules for list rows" + }, + "inlineEdit": { + "type": "boolean", + "description": "Allow inline editing of records directly in the list view" + }, + "exportOptions": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "csv", + "xlsx", + "pdf", + "json" + ] + }, + "description": "Available export format options" + }, + "emptyState": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "message": { + "type": "string" + }, + "icon": { + "type": "string" + } + }, + "additionalProperties": false, + "description": "Empty state configuration when no records found" + } + }, + "required": [ + "columns" + ], + "additionalProperties": false + }, + "form": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "simple", + "tabbed", + "wizard", + "split", + "drawer", + "modal" + ], + "default": "simple" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "object" + }, + "object": { + "type": "string", + "description": "Target object name" + } + }, + "required": [ + "provider", + "object" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "api" + }, + "read": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for fetching data" + }, + "write": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for submitting data (for forms/editable tables)" + } + }, + "required": [ + "provider" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "value" + }, + "items": { + "type": "array", + "items": {}, + "description": "Static data array" + } + }, + "required": [ + "provider", + "items" + ], + "additionalProperties": false + } + ], + "description": "Data source configuration (defaults to \"object\" provider)" + }, + "sections": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "collapsible": { + "type": "boolean", + "default": false + }, + "collapsed": { + "type": "boolean", + "default": false + }, + "columns": { + "type": "string", + "enum": [ + "1", + "2", + "3", + "4" + ], + "default": "2" + }, + "fields": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "placeholder": { + "type": "string", + "description": "Placeholder text" + }, + "helpText": { + "type": "string", + "description": "Help/hint text" + }, + "readonly": { + "type": "boolean", + "description": "Read-only override" + }, + "required": { + "type": "boolean", + "description": "Required override" + }, + "hidden": { + "type": "boolean", + "description": "Hidden override" + }, + "colSpan": { + "type": "integer", + "minimum": 1, + "maximum": 4, + "description": "Column span in grid layout (1-4)" + }, + "widget": { + "type": "string", + "description": "Custom widget/component name" + }, + "dependsOn": { + "type": "string", + "description": "Parent field name for cascading" + }, + "visibleOn": { + "type": "string", + "description": "Visibility condition expression" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "fields" + ], + "additionalProperties": false + } + }, + "groups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "collapsible": { + "type": "boolean", + "default": false + }, + "collapsed": { + "type": "boolean", + "default": false + }, + "columns": { + "type": "string", + "enum": [ + "1", + "2", + "3", + "4" + ], + "default": "2" + }, + "fields": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "placeholder": { + "type": "string", + "description": "Placeholder text" + }, + "helpText": { + "type": "string", + "description": "Help/hint text" + }, + "readonly": { + "type": "boolean", + "description": "Read-only override" + }, + "required": { + "type": "boolean", + "description": "Required override" + }, + "hidden": { + "type": "boolean", + "description": "Hidden override" + }, + "colSpan": { + "type": "integer", + "minimum": 1, + "maximum": 4, + "description": "Column span in grid layout (1-4)" + }, + "widget": { + "type": "string", + "description": "Custom widget/component name" + }, + "dependsOn": { + "type": "string", + "description": "Parent field name for cascading" + }, + "visibleOn": { + "type": "string", + "description": "Visibility condition expression" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "fields" + ], + "additionalProperties": false + } + } + }, + "additionalProperties": false + }, + "listViews": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 2, + "pattern": "^[a-z][a-z0-9_]*$", + "description": "Internal view name (lowercase snake_case)" + }, + "label": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "grid", + "kanban", + "gallery", + "calendar", + "timeline", + "gantt", + "map" + ], + "default": "grid" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "object" + }, + "object": { + "type": "string", + "description": "Target object name" + } + }, + "required": [ + "provider", + "object" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "api" + }, + "read": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for fetching data" + }, + "write": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for submitting data (for forms/editable tables)" + } + }, + "required": [ + "provider" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "value" + }, + "items": { + "type": "array", + "items": {}, + "description": "Static data array" + } + }, + "required": [ + "provider", + "items" + ], + "additionalProperties": false + } + ], + "description": "Data source configuration (defaults to \"object\" provider)" + }, + "columns": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "width": { + "type": "number", + "exclusiveMinimum": 0, + "description": "Column width in pixels" + }, + "align": { + "type": "string", + "enum": [ + "left", + "center", + "right" + ], + "description": "Text alignment" + }, + "hidden": { + "type": "boolean", + "description": "Hide column by default" + }, + "sortable": { + "type": "boolean", + "description": "Allow sorting by this column" + }, + "resizable": { + "type": "boolean", + "description": "Allow resizing this column" + }, + "wrap": { + "type": "boolean", + "description": "Allow text wrapping" + }, + "type": { + "type": "string", + "description": "Renderer type override (e.g., \"currency\", \"date\")" + }, + "link": { + "type": "boolean", + "description": "Functions as the primary navigation link (triggers View navigation)" + }, + "action": { + "type": "string", + "description": "Registered Action ID to execute when clicked" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + } + ], + "description": "Fields to display as columns" + }, + "filter": { + "type": "array", + "items": {}, + "description": "Filter criteria (JSON Rules)" + }, + "sort": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "field": { + "type": "string" + }, + "order": { + "type": "string", + "enum": [ + "asc", + "desc" + ] + } + }, + "required": [ + "field", + "order" + ], + "additionalProperties": false + } + } + ] + }, + "searchableFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields enabled for search" + }, + "filterableFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields enabled for end-user filtering in the top bar" + }, + "resizable": { + "type": "boolean", + "description": "Enable column resizing" + }, + "striped": { + "type": "boolean", + "description": "Striped row styling" + }, + "bordered": { + "type": "boolean", + "description": "Show borders" + }, + "selection": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "none", + "single", + "multiple" + ], + "default": "none", + "description": "Selection mode" + } + }, + "additionalProperties": false, + "description": "Row selection configuration" + }, + "navigation": { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "page", + "drawer", + "modal", + "split", + "popover", + "new_window", + "none" + ], + "default": "page" + }, + "view": { + "type": "string", + "description": "Name of the form view to use for details (e.g. \"summary_view\", \"edit_form\")" + }, + "preventNavigation": { + "type": "boolean", + "default": false, + "description": "Disable standard navigation entirely" + }, + "openNewTab": { + "type": "boolean", + "default": false, + "description": "Force open in new tab (applies to page mode)" + }, + "width": { + "type": [ + "string", + "number" + ], + "description": "Width of the drawer/modal (e.g. \"600px\", \"50%\")" + } + }, + "additionalProperties": false, + "description": "Configuration for item click navigation (page, drawer, modal, etc.)" + }, + "pagination": { + "type": "object", + "properties": { + "pageSize": { + "type": "integer", + "exclusiveMinimum": 0, + "default": 25, + "description": "Number of records per page" + }, + "pageSizeOptions": { + "type": "array", + "items": { + "type": "integer", + "exclusiveMinimum": 0 + }, + "description": "Available page size options" + } + }, + "additionalProperties": false, + "description": "Pagination configuration" + }, + "kanban": { + "type": "object", + "properties": { + "groupByField": { + "type": "string", + "description": "Field to group columns by (usually status/select)" + }, + "summarizeField": { + "type": "string", + "description": "Field to sum at top of column (e.g. amount)" + }, + "columns": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields to show on cards" + } + }, + "required": [ + "groupByField", + "columns" + ], + "additionalProperties": false + }, + "calendar": { + "type": "object", + "properties": { + "startDateField": { + "type": "string" + }, + "endDateField": { + "type": "string" + }, + "titleField": { + "type": "string" + }, + "colorField": { + "type": "string" + } + }, + "required": [ + "startDateField", + "titleField" + ], + "additionalProperties": false + }, + "gantt": { + "type": "object", + "properties": { + "startDateField": { + "type": "string" + }, + "endDateField": { + "type": "string" + }, + "titleField": { + "type": "string" + }, + "progressField": { + "type": "string" + }, + "dependenciesField": { + "type": "string" + } + }, + "required": [ + "startDateField", + "endDateField", + "titleField" + ], + "additionalProperties": false + }, + "rowActions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Actions available for individual row items" + }, + "bulkActions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Actions available when multiple rows are selected" + }, + "virtualScroll": { + "type": "boolean", + "description": "Enable virtual scrolling for large datasets" + }, + "conditionalFormatting": { + "type": "array", + "items": { + "type": "object", + "properties": { + "condition": { + "type": "string", + "description": "Condition expression to evaluate" + }, + "style": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "CSS styles to apply when condition is true" + } + }, + "required": [ + "condition", + "style" + ], + "additionalProperties": false + }, + "description": "Conditional formatting rules for list rows" + }, + "inlineEdit": { + "type": "boolean", + "description": "Allow inline editing of records directly in the list view" + }, + "exportOptions": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "csv", + "xlsx", + "pdf", + "json" + ] + }, + "description": "Available export format options" + }, + "emptyState": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "message": { + "type": "string" + }, + "icon": { + "type": "string" + } + }, + "additionalProperties": false, + "description": "Empty state configuration when no records found" + } + }, + "required": [ + "columns" + ], + "additionalProperties": false + }, + "description": "Additional named list views" + }, + "formViews": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "simple", + "tabbed", + "wizard", + "split", + "drawer", + "modal" + ], + "default": "simple" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "object" + }, + "object": { + "type": "string", + "description": "Target object name" + } + }, + "required": [ + "provider", + "object" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "api" + }, + "read": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for fetching data" + }, + "write": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for submitting data (for forms/editable tables)" + } + }, + "required": [ + "provider" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "value" + }, + "items": { + "type": "array", + "items": {}, + "description": "Static data array" + } + }, + "required": [ + "provider", + "items" + ], + "additionalProperties": false + } + ], + "description": "Data source configuration (defaults to \"object\" provider)" + }, + "sections": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "collapsible": { + "type": "boolean", + "default": false + }, + "collapsed": { + "type": "boolean", + "default": false + }, + "columns": { + "type": "string", + "enum": [ + "1", + "2", + "3", + "4" + ], + "default": "2" + }, + "fields": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "placeholder": { + "type": "string", + "description": "Placeholder text" + }, + "helpText": { + "type": "string", + "description": "Help/hint text" + }, + "readonly": { + "type": "boolean", + "description": "Read-only override" + }, + "required": { + "type": "boolean", + "description": "Required override" + }, + "hidden": { + "type": "boolean", + "description": "Hidden override" + }, + "colSpan": { + "type": "integer", + "minimum": 1, + "maximum": 4, + "description": "Column span in grid layout (1-4)" + }, + "widget": { + "type": "string", + "description": "Custom widget/component name" + }, + "dependsOn": { + "type": "string", + "description": "Parent field name for cascading" + }, + "visibleOn": { + "type": "string", + "description": "Visibility condition expression" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "fields" + ], + "additionalProperties": false + } + }, + "groups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "collapsible": { + "type": "boolean", + "default": false + }, + "collapsed": { + "type": "boolean", + "default": false + }, + "columns": { + "type": "string", + "enum": [ + "1", + "2", + "3", + "4" + ], + "default": "2" + }, + "fields": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "placeholder": { + "type": "string", + "description": "Placeholder text" + }, + "helpText": { + "type": "string", + "description": "Help/hint text" + }, + "readonly": { + "type": "boolean", + "description": "Read-only override" + }, + "required": { + "type": "boolean", + "description": "Required override" + }, + "hidden": { + "type": "boolean", + "description": "Hidden override" + }, + "colSpan": { + "type": "integer", + "minimum": 1, + "maximum": 4, + "description": "Column span in grid layout (1-4)" + }, + "widget": { + "type": "string", + "description": "Custom widget/component name" + }, + "dependsOn": { + "type": "string", + "description": "Parent field name for cascading" + }, + "visibleOn": { + "type": "string", + "description": "Visibility condition expression" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "fields" + ], + "additionalProperties": false + } + } + }, + "additionalProperties": false + }, + "description": "Additional named form views" + } + }, + "additionalProperties": false + }, + "description": "Array of view definitions" + } + }, + "required": [ + "object", + "views" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/MarkAllNotificationsReadRequest.json b/packages/spec/json-schema/api/MarkAllNotificationsReadRequest.json new file mode 100644 index 000000000..09d75a3bd --- /dev/null +++ b/packages/spec/json-schema/api/MarkAllNotificationsReadRequest.json @@ -0,0 +1,11 @@ +{ + "$ref": "#/definitions/MarkAllNotificationsReadRequest", + "definitions": { + "MarkAllNotificationsReadRequest": { + "type": "object", + "properties": {}, + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/MarkAllNotificationsReadResponse.json b/packages/spec/json-schema/api/MarkAllNotificationsReadResponse.json new file mode 100644 index 000000000..f813becd2 --- /dev/null +++ b/packages/spec/json-schema/api/MarkAllNotificationsReadResponse.json @@ -0,0 +1,24 @@ +{ + "$ref": "#/definitions/MarkAllNotificationsReadResponse", + "definitions": { + "MarkAllNotificationsReadResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "description": "Whether the operation succeeded" + }, + "readCount": { + "type": "number", + "description": "Number of notifications marked as read" + } + }, + "required": [ + "success", + "readCount" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/MarkNotificationsReadRequest.json b/packages/spec/json-schema/api/MarkNotificationsReadRequest.json new file mode 100644 index 000000000..36baac799 --- /dev/null +++ b/packages/spec/json-schema/api/MarkNotificationsReadRequest.json @@ -0,0 +1,22 @@ +{ + "$ref": "#/definitions/MarkNotificationsReadRequest", + "definitions": { + "MarkNotificationsReadRequest": { + "type": "object", + "properties": { + "ids": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Notification IDs to mark as read" + } + }, + "required": [ + "ids" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/MarkNotificationsReadResponse.json b/packages/spec/json-schema/api/MarkNotificationsReadResponse.json new file mode 100644 index 000000000..3a8b1fd65 --- /dev/null +++ b/packages/spec/json-schema/api/MarkNotificationsReadResponse.json @@ -0,0 +1,24 @@ +{ + "$ref": "#/definitions/MarkNotificationsReadResponse", + "definitions": { + "MarkNotificationsReadResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "description": "Whether the operation succeeded" + }, + "readCount": { + "type": "number", + "description": "Number of notifications marked as read" + } + }, + "required": [ + "success", + "readCount" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/Notification.json b/packages/spec/json-schema/api/Notification.json new file mode 100644 index 000000000..293796535 --- /dev/null +++ b/packages/spec/json-schema/api/Notification.json @@ -0,0 +1,54 @@ +{ + "$ref": "#/definitions/Notification", + "definitions": { + "Notification": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Notification ID" + }, + "type": { + "type": "string", + "description": "Notification type" + }, + "title": { + "type": "string", + "description": "Notification title" + }, + "body": { + "type": "string", + "description": "Notification body text" + }, + "read": { + "type": "boolean", + "default": false, + "description": "Whether notification has been read" + }, + "data": { + "type": "object", + "additionalProperties": {}, + "description": "Additional notification data" + }, + "actionUrl": { + "type": "string", + "description": "URL to navigate to when clicked" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "When notification was created" + } + }, + "required": [ + "id", + "type", + "title", + "body", + "createdAt" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/NotificationPreferences.json b/packages/spec/json-schema/api/NotificationPreferences.json new file mode 100644 index 000000000..e6961b8b8 --- /dev/null +++ b/packages/spec/json-schema/api/NotificationPreferences.json @@ -0,0 +1,60 @@ +{ + "$ref": "#/definitions/NotificationPreferences", + "definitions": { + "NotificationPreferences": { + "type": "object", + "properties": { + "email": { + "type": "boolean", + "default": true, + "description": "Receive email notifications" + }, + "push": { + "type": "boolean", + "default": true, + "description": "Receive push notifications" + }, + "inApp": { + "type": "boolean", + "default": true, + "description": "Receive in-app notifications" + }, + "digest": { + "type": "string", + "enum": [ + "none", + "daily", + "weekly" + ], + "default": "none", + "description": "Email digest frequency" + }, + "channels": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "default": true, + "description": "Whether this channel is enabled" + }, + "email": { + "type": "boolean", + "description": "Override email setting" + }, + "push": { + "type": "boolean", + "description": "Override push setting" + } + }, + "additionalProperties": false + }, + "description": "Per-channel notification preferences" + } + }, + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/RealtimeConnectRequest.json b/packages/spec/json-schema/api/RealtimeConnectRequest.json new file mode 100644 index 000000000..a63c1eeef --- /dev/null +++ b/packages/spec/json-schema/api/RealtimeConnectRequest.json @@ -0,0 +1,32 @@ +{ + "$ref": "#/definitions/RealtimeConnectRequest", + "definitions": { + "RealtimeConnectRequest": { + "type": "object", + "properties": { + "transport": { + "type": "string", + "enum": [ + "websocket", + "sse", + "polling" + ], + "description": "Preferred transport protocol" + }, + "channels": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Channels to subscribe to on connect" + }, + "token": { + "type": "string", + "description": "Authentication token" + } + }, + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/RealtimeConnectResponse.json b/packages/spec/json-schema/api/RealtimeConnectResponse.json new file mode 100644 index 000000000..a62cf0101 --- /dev/null +++ b/packages/spec/json-schema/api/RealtimeConnectResponse.json @@ -0,0 +1,33 @@ +{ + "$ref": "#/definitions/RealtimeConnectResponse", + "definitions": { + "RealtimeConnectResponse": { + "type": "object", + "properties": { + "connectionId": { + "type": "string", + "description": "Unique connection identifier" + }, + "transport": { + "type": "string", + "enum": [ + "websocket", + "sse", + "polling" + ], + "description": "Negotiated transport protocol" + }, + "url": { + "type": "string", + "description": "WebSocket/SSE endpoint URL" + } + }, + "required": [ + "connectionId", + "transport" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/RealtimeDisconnectRequest.json b/packages/spec/json-schema/api/RealtimeDisconnectRequest.json new file mode 100644 index 000000000..465df6fe0 --- /dev/null +++ b/packages/spec/json-schema/api/RealtimeDisconnectRequest.json @@ -0,0 +1,16 @@ +{ + "$ref": "#/definitions/RealtimeDisconnectRequest", + "definitions": { + "RealtimeDisconnectRequest": { + "type": "object", + "properties": { + "connectionId": { + "type": "string", + "description": "Connection ID to disconnect" + } + }, + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/RealtimeDisconnectResponse.json b/packages/spec/json-schema/api/RealtimeDisconnectResponse.json new file mode 100644 index 000000000..14767f476 --- /dev/null +++ b/packages/spec/json-schema/api/RealtimeDisconnectResponse.json @@ -0,0 +1,19 @@ +{ + "$ref": "#/definitions/RealtimeDisconnectResponse", + "definitions": { + "RealtimeDisconnectResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "description": "Whether disconnection succeeded" + } + }, + "required": [ + "success" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/RealtimeSubscribeRequest.json b/packages/spec/json-schema/api/RealtimeSubscribeRequest.json new file mode 100644 index 000000000..8e13fbe36 --- /dev/null +++ b/packages/spec/json-schema/api/RealtimeSubscribeRequest.json @@ -0,0 +1,31 @@ +{ + "$ref": "#/definitions/RealtimeSubscribeRequest", + "definitions": { + "RealtimeSubscribeRequest": { + "type": "object", + "properties": { + "channel": { + "type": "string", + "description": "Channel name to subscribe to" + }, + "events": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Specific event types to listen for" + }, + "filter": { + "type": "object", + "additionalProperties": {}, + "description": "Event filter criteria" + } + }, + "required": [ + "channel" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/RealtimeSubscribeResponse.json b/packages/spec/json-schema/api/RealtimeSubscribeResponse.json new file mode 100644 index 000000000..ce6465b02 --- /dev/null +++ b/packages/spec/json-schema/api/RealtimeSubscribeResponse.json @@ -0,0 +1,24 @@ +{ + "$ref": "#/definitions/RealtimeSubscribeResponse", + "definitions": { + "RealtimeSubscribeResponse": { + "type": "object", + "properties": { + "subscriptionId": { + "type": "string", + "description": "Unique subscription identifier" + }, + "channel": { + "type": "string", + "description": "Subscribed channel name" + } + }, + "required": [ + "subscriptionId", + "channel" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/RealtimeUnsubscribeRequest.json b/packages/spec/json-schema/api/RealtimeUnsubscribeRequest.json new file mode 100644 index 000000000..566e1f6f9 --- /dev/null +++ b/packages/spec/json-schema/api/RealtimeUnsubscribeRequest.json @@ -0,0 +1,19 @@ +{ + "$ref": "#/definitions/RealtimeUnsubscribeRequest", + "definitions": { + "RealtimeUnsubscribeRequest": { + "type": "object", + "properties": { + "subscriptionId": { + "type": "string", + "description": "Subscription ID to cancel" + } + }, + "required": [ + "subscriptionId" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/RealtimeUnsubscribeResponse.json b/packages/spec/json-schema/api/RealtimeUnsubscribeResponse.json new file mode 100644 index 000000000..a12d73ebf --- /dev/null +++ b/packages/spec/json-schema/api/RealtimeUnsubscribeResponse.json @@ -0,0 +1,19 @@ +{ + "$ref": "#/definitions/RealtimeUnsubscribeResponse", + "definitions": { + "RealtimeUnsubscribeResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "description": "Whether unsubscription succeeded" + } + }, + "required": [ + "success" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/RegisterDeviceRequest.json b/packages/spec/json-schema/api/RegisterDeviceRequest.json new file mode 100644 index 000000000..8aa4f32d0 --- /dev/null +++ b/packages/spec/json-schema/api/RegisterDeviceRequest.json @@ -0,0 +1,37 @@ +{ + "$ref": "#/definitions/RegisterDeviceRequest", + "definitions": { + "RegisterDeviceRequest": { + "type": "object", + "properties": { + "token": { + "type": "string", + "description": "Device push notification token" + }, + "platform": { + "type": "string", + "enum": [ + "ios", + "android", + "web" + ], + "description": "Device platform" + }, + "deviceId": { + "type": "string", + "description": "Unique device identifier" + }, + "name": { + "type": "string", + "description": "Device friendly name" + } + }, + "required": [ + "token", + "platform" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/RegisterDeviceResponse.json b/packages/spec/json-schema/api/RegisterDeviceResponse.json new file mode 100644 index 000000000..e7dc605e0 --- /dev/null +++ b/packages/spec/json-schema/api/RegisterDeviceResponse.json @@ -0,0 +1,24 @@ +{ + "$ref": "#/definitions/RegisterDeviceResponse", + "definitions": { + "RegisterDeviceResponse": { + "type": "object", + "properties": { + "deviceId": { + "type": "string", + "description": "Registered device ID" + }, + "success": { + "type": "boolean", + "description": "Whether registration succeeded" + } + }, + "required": [ + "deviceId", + "success" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/SetPresenceRequest.json b/packages/spec/json-schema/api/SetPresenceRequest.json new file mode 100644 index 000000000..a0b97cfc5 --- /dev/null +++ b/packages/spec/json-schema/api/SetPresenceRequest.json @@ -0,0 +1,56 @@ +{ + "$ref": "#/definitions/SetPresenceRequest", + "definitions": { + "SetPresenceRequest": { + "type": "object", + "properties": { + "channel": { + "type": "string", + "description": "Channel to set presence in" + }, + "state": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User identifier" + }, + "status": { + "type": "string", + "enum": [ + "online", + "away", + "busy", + "offline" + ], + "description": "Current presence status" + }, + "lastSeen": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 datetime of last activity" + }, + "metadata": { + "type": "object", + "additionalProperties": {}, + "description": "Custom presence data (e.g., current page, custom status)" + } + }, + "required": [ + "userId", + "status", + "lastSeen" + ], + "additionalProperties": false, + "description": "Presence state to set" + } + }, + "required": [ + "channel", + "state" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/SetPresenceResponse.json b/packages/spec/json-schema/api/SetPresenceResponse.json new file mode 100644 index 000000000..fab2c0c3d --- /dev/null +++ b/packages/spec/json-schema/api/SetPresenceResponse.json @@ -0,0 +1,19 @@ +{ + "$ref": "#/definitions/SetPresenceResponse", + "definitions": { + "SetPresenceResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "description": "Whether presence was set" + } + }, + "required": [ + "success" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/UnregisterDeviceRequest.json b/packages/spec/json-schema/api/UnregisterDeviceRequest.json new file mode 100644 index 000000000..3f2b02574 --- /dev/null +++ b/packages/spec/json-schema/api/UnregisterDeviceRequest.json @@ -0,0 +1,19 @@ +{ + "$ref": "#/definitions/UnregisterDeviceRequest", + "definitions": { + "UnregisterDeviceRequest": { + "type": "object", + "properties": { + "deviceId": { + "type": "string", + "description": "Device ID to unregister" + } + }, + "required": [ + "deviceId" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/UnregisterDeviceResponse.json b/packages/spec/json-schema/api/UnregisterDeviceResponse.json new file mode 100644 index 000000000..b1205b1f2 --- /dev/null +++ b/packages/spec/json-schema/api/UnregisterDeviceResponse.json @@ -0,0 +1,19 @@ +{ + "$ref": "#/definitions/UnregisterDeviceResponse", + "definitions": { + "UnregisterDeviceResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "description": "Whether unregistration succeeded" + } + }, + "required": [ + "success" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/UpdateNotificationPreferencesRequest.json b/packages/spec/json-schema/api/UpdateNotificationPreferencesRequest.json new file mode 100644 index 000000000..b115656cc --- /dev/null +++ b/packages/spec/json-schema/api/UpdateNotificationPreferencesRequest.json @@ -0,0 +1,70 @@ +{ + "$ref": "#/definitions/UpdateNotificationPreferencesRequest", + "definitions": { + "UpdateNotificationPreferencesRequest": { + "type": "object", + "properties": { + "preferences": { + "type": "object", + "properties": { + "email": { + "type": "boolean", + "default": true, + "description": "Receive email notifications" + }, + "push": { + "type": "boolean", + "default": true, + "description": "Receive push notifications" + }, + "inApp": { + "type": "boolean", + "default": true, + "description": "Receive in-app notifications" + }, + "digest": { + "type": "string", + "enum": [ + "none", + "daily", + "weekly" + ], + "default": "none", + "description": "Email digest frequency" + }, + "channels": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "default": true, + "description": "Whether this channel is enabled" + }, + "email": { + "type": "boolean", + "description": "Override email setting" + }, + "push": { + "type": "boolean", + "description": "Override push setting" + } + }, + "additionalProperties": false + }, + "description": "Per-channel notification preferences" + } + }, + "additionalProperties": false, + "description": "Preferences to update" + } + }, + "required": [ + "preferences" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/UpdateNotificationPreferencesResponse.json b/packages/spec/json-schema/api/UpdateNotificationPreferencesResponse.json new file mode 100644 index 000000000..6ffbc2244 --- /dev/null +++ b/packages/spec/json-schema/api/UpdateNotificationPreferencesResponse.json @@ -0,0 +1,70 @@ +{ + "$ref": "#/definitions/UpdateNotificationPreferencesResponse", + "definitions": { + "UpdateNotificationPreferencesResponse": { + "type": "object", + "properties": { + "preferences": { + "type": "object", + "properties": { + "email": { + "type": "boolean", + "default": true, + "description": "Receive email notifications" + }, + "push": { + "type": "boolean", + "default": true, + "description": "Receive push notifications" + }, + "inApp": { + "type": "boolean", + "default": true, + "description": "Receive in-app notifications" + }, + "digest": { + "type": "string", + "enum": [ + "none", + "daily", + "weekly" + ], + "default": "none", + "description": "Email digest frequency" + }, + "channels": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "default": true, + "description": "Whether this channel is enabled" + }, + "email": { + "type": "boolean", + "description": "Override email setting" + }, + "push": { + "type": "boolean", + "description": "Override push setting" + } + }, + "additionalProperties": false + }, + "description": "Per-channel notification preferences" + } + }, + "additionalProperties": false, + "description": "Updated notification preferences" + } + }, + "required": [ + "preferences" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/UpdateViewRequest.json b/packages/spec/json-schema/api/UpdateViewRequest.json new file mode 100644 index 000000000..a798e5007 --- /dev/null +++ b/packages/spec/json-schema/api/UpdateViewRequest.json @@ -0,0 +1,1802 @@ +{ + "$ref": "#/definitions/UpdateViewRequest", + "definitions": { + "UpdateViewRequest": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name (snake_case)" + }, + "viewId": { + "type": "string", + "description": "View identifier" + }, + "data": { + "type": "object", + "properties": { + "list": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 2, + "pattern": "^[a-z][a-z0-9_]*$", + "description": "Internal view name (lowercase snake_case)" + }, + "label": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "grid", + "kanban", + "gallery", + "calendar", + "timeline", + "gantt", + "map" + ], + "default": "grid" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "object" + }, + "object": { + "type": "string", + "description": "Target object name" + } + }, + "required": [ + "provider", + "object" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "api" + }, + "read": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for fetching data" + }, + "write": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for submitting data (for forms/editable tables)" + } + }, + "required": [ + "provider" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "value" + }, + "items": { + "type": "array", + "items": {}, + "description": "Static data array" + } + }, + "required": [ + "provider", + "items" + ], + "additionalProperties": false + } + ], + "description": "Data source configuration (defaults to \"object\" provider)" + }, + "columns": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "width": { + "type": "number", + "exclusiveMinimum": 0, + "description": "Column width in pixels" + }, + "align": { + "type": "string", + "enum": [ + "left", + "center", + "right" + ], + "description": "Text alignment" + }, + "hidden": { + "type": "boolean", + "description": "Hide column by default" + }, + "sortable": { + "type": "boolean", + "description": "Allow sorting by this column" + }, + "resizable": { + "type": "boolean", + "description": "Allow resizing this column" + }, + "wrap": { + "type": "boolean", + "description": "Allow text wrapping" + }, + "type": { + "type": "string", + "description": "Renderer type override (e.g., \"currency\", \"date\")" + }, + "link": { + "type": "boolean", + "description": "Functions as the primary navigation link (triggers View navigation)" + }, + "action": { + "type": "string", + "description": "Registered Action ID to execute when clicked" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + } + ], + "description": "Fields to display as columns" + }, + "filter": { + "type": "array", + "items": {}, + "description": "Filter criteria (JSON Rules)" + }, + "sort": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "field": { + "type": "string" + }, + "order": { + "type": "string", + "enum": [ + "asc", + "desc" + ] + } + }, + "required": [ + "field", + "order" + ], + "additionalProperties": false + } + } + ] + }, + "searchableFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields enabled for search" + }, + "filterableFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields enabled for end-user filtering in the top bar" + }, + "resizable": { + "type": "boolean", + "description": "Enable column resizing" + }, + "striped": { + "type": "boolean", + "description": "Striped row styling" + }, + "bordered": { + "type": "boolean", + "description": "Show borders" + }, + "selection": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "none", + "single", + "multiple" + ], + "default": "none", + "description": "Selection mode" + } + }, + "additionalProperties": false, + "description": "Row selection configuration" + }, + "navigation": { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "page", + "drawer", + "modal", + "split", + "popover", + "new_window", + "none" + ], + "default": "page" + }, + "view": { + "type": "string", + "description": "Name of the form view to use for details (e.g. \"summary_view\", \"edit_form\")" + }, + "preventNavigation": { + "type": "boolean", + "default": false, + "description": "Disable standard navigation entirely" + }, + "openNewTab": { + "type": "boolean", + "default": false, + "description": "Force open in new tab (applies to page mode)" + }, + "width": { + "type": [ + "string", + "number" + ], + "description": "Width of the drawer/modal (e.g. \"600px\", \"50%\")" + } + }, + "additionalProperties": false, + "description": "Configuration for item click navigation (page, drawer, modal, etc.)" + }, + "pagination": { + "type": "object", + "properties": { + "pageSize": { + "type": "integer", + "exclusiveMinimum": 0, + "default": 25, + "description": "Number of records per page" + }, + "pageSizeOptions": { + "type": "array", + "items": { + "type": "integer", + "exclusiveMinimum": 0 + }, + "description": "Available page size options" + } + }, + "additionalProperties": false, + "description": "Pagination configuration" + }, + "kanban": { + "type": "object", + "properties": { + "groupByField": { + "type": "string", + "description": "Field to group columns by (usually status/select)" + }, + "summarizeField": { + "type": "string", + "description": "Field to sum at top of column (e.g. amount)" + }, + "columns": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields to show on cards" + } + }, + "required": [ + "groupByField", + "columns" + ], + "additionalProperties": false + }, + "calendar": { + "type": "object", + "properties": { + "startDateField": { + "type": "string" + }, + "endDateField": { + "type": "string" + }, + "titleField": { + "type": "string" + }, + "colorField": { + "type": "string" + } + }, + "required": [ + "startDateField", + "titleField" + ], + "additionalProperties": false + }, + "gantt": { + "type": "object", + "properties": { + "startDateField": { + "type": "string" + }, + "endDateField": { + "type": "string" + }, + "titleField": { + "type": "string" + }, + "progressField": { + "type": "string" + }, + "dependenciesField": { + "type": "string" + } + }, + "required": [ + "startDateField", + "endDateField", + "titleField" + ], + "additionalProperties": false + }, + "rowActions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Actions available for individual row items" + }, + "bulkActions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Actions available when multiple rows are selected" + }, + "virtualScroll": { + "type": "boolean", + "description": "Enable virtual scrolling for large datasets" + }, + "conditionalFormatting": { + "type": "array", + "items": { + "type": "object", + "properties": { + "condition": { + "type": "string", + "description": "Condition expression to evaluate" + }, + "style": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "CSS styles to apply when condition is true" + } + }, + "required": [ + "condition", + "style" + ], + "additionalProperties": false + }, + "description": "Conditional formatting rules for list rows" + }, + "inlineEdit": { + "type": "boolean", + "description": "Allow inline editing of records directly in the list view" + }, + "exportOptions": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "csv", + "xlsx", + "pdf", + "json" + ] + }, + "description": "Available export format options" + }, + "emptyState": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "message": { + "type": "string" + }, + "icon": { + "type": "string" + } + }, + "additionalProperties": false, + "description": "Empty state configuration when no records found" + } + }, + "required": [ + "columns" + ], + "additionalProperties": false + }, + "form": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "simple", + "tabbed", + "wizard", + "split", + "drawer", + "modal" + ], + "default": "simple" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "object" + }, + "object": { + "type": "string", + "description": "Target object name" + } + }, + "required": [ + "provider", + "object" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "api" + }, + "read": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for fetching data" + }, + "write": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for submitting data (for forms/editable tables)" + } + }, + "required": [ + "provider" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "value" + }, + "items": { + "type": "array", + "items": {}, + "description": "Static data array" + } + }, + "required": [ + "provider", + "items" + ], + "additionalProperties": false + } + ], + "description": "Data source configuration (defaults to \"object\" provider)" + }, + "sections": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "collapsible": { + "type": "boolean", + "default": false + }, + "collapsed": { + "type": "boolean", + "default": false + }, + "columns": { + "type": "string", + "enum": [ + "1", + "2", + "3", + "4" + ], + "default": "2" + }, + "fields": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "placeholder": { + "type": "string", + "description": "Placeholder text" + }, + "helpText": { + "type": "string", + "description": "Help/hint text" + }, + "readonly": { + "type": "boolean", + "description": "Read-only override" + }, + "required": { + "type": "boolean", + "description": "Required override" + }, + "hidden": { + "type": "boolean", + "description": "Hidden override" + }, + "colSpan": { + "type": "integer", + "minimum": 1, + "maximum": 4, + "description": "Column span in grid layout (1-4)" + }, + "widget": { + "type": "string", + "description": "Custom widget/component name" + }, + "dependsOn": { + "type": "string", + "description": "Parent field name for cascading" + }, + "visibleOn": { + "type": "string", + "description": "Visibility condition expression" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "fields" + ], + "additionalProperties": false + } + }, + "groups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "collapsible": { + "type": "boolean", + "default": false + }, + "collapsed": { + "type": "boolean", + "default": false + }, + "columns": { + "type": "string", + "enum": [ + "1", + "2", + "3", + "4" + ], + "default": "2" + }, + "fields": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "placeholder": { + "type": "string", + "description": "Placeholder text" + }, + "helpText": { + "type": "string", + "description": "Help/hint text" + }, + "readonly": { + "type": "boolean", + "description": "Read-only override" + }, + "required": { + "type": "boolean", + "description": "Required override" + }, + "hidden": { + "type": "boolean", + "description": "Hidden override" + }, + "colSpan": { + "type": "integer", + "minimum": 1, + "maximum": 4, + "description": "Column span in grid layout (1-4)" + }, + "widget": { + "type": "string", + "description": "Custom widget/component name" + }, + "dependsOn": { + "type": "string", + "description": "Parent field name for cascading" + }, + "visibleOn": { + "type": "string", + "description": "Visibility condition expression" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "fields" + ], + "additionalProperties": false + } + } + }, + "additionalProperties": false + }, + "listViews": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 2, + "pattern": "^[a-z][a-z0-9_]*$", + "description": "Internal view name (lowercase snake_case)" + }, + "label": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "grid", + "kanban", + "gallery", + "calendar", + "timeline", + "gantt", + "map" + ], + "default": "grid" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "object" + }, + "object": { + "type": "string", + "description": "Target object name" + } + }, + "required": [ + "provider", + "object" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "api" + }, + "read": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for fetching data" + }, + "write": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for submitting data (for forms/editable tables)" + } + }, + "required": [ + "provider" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "value" + }, + "items": { + "type": "array", + "items": {}, + "description": "Static data array" + } + }, + "required": [ + "provider", + "items" + ], + "additionalProperties": false + } + ], + "description": "Data source configuration (defaults to \"object\" provider)" + }, + "columns": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "width": { + "type": "number", + "exclusiveMinimum": 0, + "description": "Column width in pixels" + }, + "align": { + "type": "string", + "enum": [ + "left", + "center", + "right" + ], + "description": "Text alignment" + }, + "hidden": { + "type": "boolean", + "description": "Hide column by default" + }, + "sortable": { + "type": "boolean", + "description": "Allow sorting by this column" + }, + "resizable": { + "type": "boolean", + "description": "Allow resizing this column" + }, + "wrap": { + "type": "boolean", + "description": "Allow text wrapping" + }, + "type": { + "type": "string", + "description": "Renderer type override (e.g., \"currency\", \"date\")" + }, + "link": { + "type": "boolean", + "description": "Functions as the primary navigation link (triggers View navigation)" + }, + "action": { + "type": "string", + "description": "Registered Action ID to execute when clicked" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + } + ], + "description": "Fields to display as columns" + }, + "filter": { + "type": "array", + "items": {}, + "description": "Filter criteria (JSON Rules)" + }, + "sort": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "field": { + "type": "string" + }, + "order": { + "type": "string", + "enum": [ + "asc", + "desc" + ] + } + }, + "required": [ + "field", + "order" + ], + "additionalProperties": false + } + } + ] + }, + "searchableFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields enabled for search" + }, + "filterableFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields enabled for end-user filtering in the top bar" + }, + "resizable": { + "type": "boolean", + "description": "Enable column resizing" + }, + "striped": { + "type": "boolean", + "description": "Striped row styling" + }, + "bordered": { + "type": "boolean", + "description": "Show borders" + }, + "selection": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "none", + "single", + "multiple" + ], + "default": "none", + "description": "Selection mode" + } + }, + "additionalProperties": false, + "description": "Row selection configuration" + }, + "navigation": { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "page", + "drawer", + "modal", + "split", + "popover", + "new_window", + "none" + ], + "default": "page" + }, + "view": { + "type": "string", + "description": "Name of the form view to use for details (e.g. \"summary_view\", \"edit_form\")" + }, + "preventNavigation": { + "type": "boolean", + "default": false, + "description": "Disable standard navigation entirely" + }, + "openNewTab": { + "type": "boolean", + "default": false, + "description": "Force open in new tab (applies to page mode)" + }, + "width": { + "type": [ + "string", + "number" + ], + "description": "Width of the drawer/modal (e.g. \"600px\", \"50%\")" + } + }, + "additionalProperties": false, + "description": "Configuration for item click navigation (page, drawer, modal, etc.)" + }, + "pagination": { + "type": "object", + "properties": { + "pageSize": { + "type": "integer", + "exclusiveMinimum": 0, + "default": 25, + "description": "Number of records per page" + }, + "pageSizeOptions": { + "type": "array", + "items": { + "type": "integer", + "exclusiveMinimum": 0 + }, + "description": "Available page size options" + } + }, + "additionalProperties": false, + "description": "Pagination configuration" + }, + "kanban": { + "type": "object", + "properties": { + "groupByField": { + "type": "string", + "description": "Field to group columns by (usually status/select)" + }, + "summarizeField": { + "type": "string", + "description": "Field to sum at top of column (e.g. amount)" + }, + "columns": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields to show on cards" + } + }, + "required": [ + "groupByField", + "columns" + ], + "additionalProperties": false + }, + "calendar": { + "type": "object", + "properties": { + "startDateField": { + "type": "string" + }, + "endDateField": { + "type": "string" + }, + "titleField": { + "type": "string" + }, + "colorField": { + "type": "string" + } + }, + "required": [ + "startDateField", + "titleField" + ], + "additionalProperties": false + }, + "gantt": { + "type": "object", + "properties": { + "startDateField": { + "type": "string" + }, + "endDateField": { + "type": "string" + }, + "titleField": { + "type": "string" + }, + "progressField": { + "type": "string" + }, + "dependenciesField": { + "type": "string" + } + }, + "required": [ + "startDateField", + "endDateField", + "titleField" + ], + "additionalProperties": false + }, + "rowActions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Actions available for individual row items" + }, + "bulkActions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Actions available when multiple rows are selected" + }, + "virtualScroll": { + "type": "boolean", + "description": "Enable virtual scrolling for large datasets" + }, + "conditionalFormatting": { + "type": "array", + "items": { + "type": "object", + "properties": { + "condition": { + "type": "string", + "description": "Condition expression to evaluate" + }, + "style": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "CSS styles to apply when condition is true" + } + }, + "required": [ + "condition", + "style" + ], + "additionalProperties": false + }, + "description": "Conditional formatting rules for list rows" + }, + "inlineEdit": { + "type": "boolean", + "description": "Allow inline editing of records directly in the list view" + }, + "exportOptions": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "csv", + "xlsx", + "pdf", + "json" + ] + }, + "description": "Available export format options" + }, + "emptyState": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "message": { + "type": "string" + }, + "icon": { + "type": "string" + } + }, + "additionalProperties": false, + "description": "Empty state configuration when no records found" + } + }, + "required": [ + "columns" + ], + "additionalProperties": false + }, + "description": "Additional named list views" + }, + "formViews": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "simple", + "tabbed", + "wizard", + "split", + "drawer", + "modal" + ], + "default": "simple" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "object" + }, + "object": { + "type": "string", + "description": "Target object name" + } + }, + "required": [ + "provider", + "object" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "api" + }, + "read": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for fetching data" + }, + "write": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for submitting data (for forms/editable tables)" + } + }, + "required": [ + "provider" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "value" + }, + "items": { + "type": "array", + "items": {}, + "description": "Static data array" + } + }, + "required": [ + "provider", + "items" + ], + "additionalProperties": false + } + ], + "description": "Data source configuration (defaults to \"object\" provider)" + }, + "sections": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "collapsible": { + "type": "boolean", + "default": false + }, + "collapsed": { + "type": "boolean", + "default": false + }, + "columns": { + "type": "string", + "enum": [ + "1", + "2", + "3", + "4" + ], + "default": "2" + }, + "fields": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "placeholder": { + "type": "string", + "description": "Placeholder text" + }, + "helpText": { + "type": "string", + "description": "Help/hint text" + }, + "readonly": { + "type": "boolean", + "description": "Read-only override" + }, + "required": { + "type": "boolean", + "description": "Required override" + }, + "hidden": { + "type": "boolean", + "description": "Hidden override" + }, + "colSpan": { + "type": "integer", + "minimum": 1, + "maximum": 4, + "description": "Column span in grid layout (1-4)" + }, + "widget": { + "type": "string", + "description": "Custom widget/component name" + }, + "dependsOn": { + "type": "string", + "description": "Parent field name for cascading" + }, + "visibleOn": { + "type": "string", + "description": "Visibility condition expression" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "fields" + ], + "additionalProperties": false + } + }, + "groups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "collapsible": { + "type": "boolean", + "default": false + }, + "collapsed": { + "type": "boolean", + "default": false + }, + "columns": { + "type": "string", + "enum": [ + "1", + "2", + "3", + "4" + ], + "default": "2" + }, + "fields": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "placeholder": { + "type": "string", + "description": "Placeholder text" + }, + "helpText": { + "type": "string", + "description": "Help/hint text" + }, + "readonly": { + "type": "boolean", + "description": "Read-only override" + }, + "required": { + "type": "boolean", + "description": "Required override" + }, + "hidden": { + "type": "boolean", + "description": "Hidden override" + }, + "colSpan": { + "type": "integer", + "minimum": 1, + "maximum": 4, + "description": "Column span in grid layout (1-4)" + }, + "widget": { + "type": "string", + "description": "Custom widget/component name" + }, + "dependsOn": { + "type": "string", + "description": "Parent field name for cascading" + }, + "visibleOn": { + "type": "string", + "description": "Visibility condition expression" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "fields" + ], + "additionalProperties": false + } + } + }, + "additionalProperties": false + }, + "description": "Additional named form views" + } + }, + "additionalProperties": false, + "description": "Partial view data to update" + } + }, + "required": [ + "object", + "viewId", + "data" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/UpdateViewResponse.json b/packages/spec/json-schema/api/UpdateViewResponse.json new file mode 100644 index 000000000..6019ea746 --- /dev/null +++ b/packages/spec/json-schema/api/UpdateViewResponse.json @@ -0,0 +1,1802 @@ +{ + "$ref": "#/definitions/UpdateViewResponse", + "definitions": { + "UpdateViewResponse": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name" + }, + "viewId": { + "type": "string", + "description": "Updated view identifier" + }, + "view": { + "type": "object", + "properties": { + "list": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 2, + "pattern": "^[a-z][a-z0-9_]*$", + "description": "Internal view name (lowercase snake_case)" + }, + "label": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "grid", + "kanban", + "gallery", + "calendar", + "timeline", + "gantt", + "map" + ], + "default": "grid" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "object" + }, + "object": { + "type": "string", + "description": "Target object name" + } + }, + "required": [ + "provider", + "object" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "api" + }, + "read": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for fetching data" + }, + "write": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for submitting data (for forms/editable tables)" + } + }, + "required": [ + "provider" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "value" + }, + "items": { + "type": "array", + "items": {}, + "description": "Static data array" + } + }, + "required": [ + "provider", + "items" + ], + "additionalProperties": false + } + ], + "description": "Data source configuration (defaults to \"object\" provider)" + }, + "columns": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "width": { + "type": "number", + "exclusiveMinimum": 0, + "description": "Column width in pixels" + }, + "align": { + "type": "string", + "enum": [ + "left", + "center", + "right" + ], + "description": "Text alignment" + }, + "hidden": { + "type": "boolean", + "description": "Hide column by default" + }, + "sortable": { + "type": "boolean", + "description": "Allow sorting by this column" + }, + "resizable": { + "type": "boolean", + "description": "Allow resizing this column" + }, + "wrap": { + "type": "boolean", + "description": "Allow text wrapping" + }, + "type": { + "type": "string", + "description": "Renderer type override (e.g., \"currency\", \"date\")" + }, + "link": { + "type": "boolean", + "description": "Functions as the primary navigation link (triggers View navigation)" + }, + "action": { + "type": "string", + "description": "Registered Action ID to execute when clicked" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + } + ], + "description": "Fields to display as columns" + }, + "filter": { + "type": "array", + "items": {}, + "description": "Filter criteria (JSON Rules)" + }, + "sort": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "field": { + "type": "string" + }, + "order": { + "type": "string", + "enum": [ + "asc", + "desc" + ] + } + }, + "required": [ + "field", + "order" + ], + "additionalProperties": false + } + } + ] + }, + "searchableFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields enabled for search" + }, + "filterableFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields enabled for end-user filtering in the top bar" + }, + "resizable": { + "type": "boolean", + "description": "Enable column resizing" + }, + "striped": { + "type": "boolean", + "description": "Striped row styling" + }, + "bordered": { + "type": "boolean", + "description": "Show borders" + }, + "selection": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "none", + "single", + "multiple" + ], + "default": "none", + "description": "Selection mode" + } + }, + "additionalProperties": false, + "description": "Row selection configuration" + }, + "navigation": { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "page", + "drawer", + "modal", + "split", + "popover", + "new_window", + "none" + ], + "default": "page" + }, + "view": { + "type": "string", + "description": "Name of the form view to use for details (e.g. \"summary_view\", \"edit_form\")" + }, + "preventNavigation": { + "type": "boolean", + "default": false, + "description": "Disable standard navigation entirely" + }, + "openNewTab": { + "type": "boolean", + "default": false, + "description": "Force open in new tab (applies to page mode)" + }, + "width": { + "type": [ + "string", + "number" + ], + "description": "Width of the drawer/modal (e.g. \"600px\", \"50%\")" + } + }, + "additionalProperties": false, + "description": "Configuration for item click navigation (page, drawer, modal, etc.)" + }, + "pagination": { + "type": "object", + "properties": { + "pageSize": { + "type": "integer", + "exclusiveMinimum": 0, + "default": 25, + "description": "Number of records per page" + }, + "pageSizeOptions": { + "type": "array", + "items": { + "type": "integer", + "exclusiveMinimum": 0 + }, + "description": "Available page size options" + } + }, + "additionalProperties": false, + "description": "Pagination configuration" + }, + "kanban": { + "type": "object", + "properties": { + "groupByField": { + "type": "string", + "description": "Field to group columns by (usually status/select)" + }, + "summarizeField": { + "type": "string", + "description": "Field to sum at top of column (e.g. amount)" + }, + "columns": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields to show on cards" + } + }, + "required": [ + "groupByField", + "columns" + ], + "additionalProperties": false + }, + "calendar": { + "type": "object", + "properties": { + "startDateField": { + "type": "string" + }, + "endDateField": { + "type": "string" + }, + "titleField": { + "type": "string" + }, + "colorField": { + "type": "string" + } + }, + "required": [ + "startDateField", + "titleField" + ], + "additionalProperties": false + }, + "gantt": { + "type": "object", + "properties": { + "startDateField": { + "type": "string" + }, + "endDateField": { + "type": "string" + }, + "titleField": { + "type": "string" + }, + "progressField": { + "type": "string" + }, + "dependenciesField": { + "type": "string" + } + }, + "required": [ + "startDateField", + "endDateField", + "titleField" + ], + "additionalProperties": false + }, + "rowActions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Actions available for individual row items" + }, + "bulkActions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Actions available when multiple rows are selected" + }, + "virtualScroll": { + "type": "boolean", + "description": "Enable virtual scrolling for large datasets" + }, + "conditionalFormatting": { + "type": "array", + "items": { + "type": "object", + "properties": { + "condition": { + "type": "string", + "description": "Condition expression to evaluate" + }, + "style": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "CSS styles to apply when condition is true" + } + }, + "required": [ + "condition", + "style" + ], + "additionalProperties": false + }, + "description": "Conditional formatting rules for list rows" + }, + "inlineEdit": { + "type": "boolean", + "description": "Allow inline editing of records directly in the list view" + }, + "exportOptions": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "csv", + "xlsx", + "pdf", + "json" + ] + }, + "description": "Available export format options" + }, + "emptyState": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "message": { + "type": "string" + }, + "icon": { + "type": "string" + } + }, + "additionalProperties": false, + "description": "Empty state configuration when no records found" + } + }, + "required": [ + "columns" + ], + "additionalProperties": false + }, + "form": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "simple", + "tabbed", + "wizard", + "split", + "drawer", + "modal" + ], + "default": "simple" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "object" + }, + "object": { + "type": "string", + "description": "Target object name" + } + }, + "required": [ + "provider", + "object" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "api" + }, + "read": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for fetching data" + }, + "write": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for submitting data (for forms/editable tables)" + } + }, + "required": [ + "provider" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "value" + }, + "items": { + "type": "array", + "items": {}, + "description": "Static data array" + } + }, + "required": [ + "provider", + "items" + ], + "additionalProperties": false + } + ], + "description": "Data source configuration (defaults to \"object\" provider)" + }, + "sections": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "collapsible": { + "type": "boolean", + "default": false + }, + "collapsed": { + "type": "boolean", + "default": false + }, + "columns": { + "type": "string", + "enum": [ + "1", + "2", + "3", + "4" + ], + "default": "2" + }, + "fields": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "placeholder": { + "type": "string", + "description": "Placeholder text" + }, + "helpText": { + "type": "string", + "description": "Help/hint text" + }, + "readonly": { + "type": "boolean", + "description": "Read-only override" + }, + "required": { + "type": "boolean", + "description": "Required override" + }, + "hidden": { + "type": "boolean", + "description": "Hidden override" + }, + "colSpan": { + "type": "integer", + "minimum": 1, + "maximum": 4, + "description": "Column span in grid layout (1-4)" + }, + "widget": { + "type": "string", + "description": "Custom widget/component name" + }, + "dependsOn": { + "type": "string", + "description": "Parent field name for cascading" + }, + "visibleOn": { + "type": "string", + "description": "Visibility condition expression" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "fields" + ], + "additionalProperties": false + } + }, + "groups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "collapsible": { + "type": "boolean", + "default": false + }, + "collapsed": { + "type": "boolean", + "default": false + }, + "columns": { + "type": "string", + "enum": [ + "1", + "2", + "3", + "4" + ], + "default": "2" + }, + "fields": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "placeholder": { + "type": "string", + "description": "Placeholder text" + }, + "helpText": { + "type": "string", + "description": "Help/hint text" + }, + "readonly": { + "type": "boolean", + "description": "Read-only override" + }, + "required": { + "type": "boolean", + "description": "Required override" + }, + "hidden": { + "type": "boolean", + "description": "Hidden override" + }, + "colSpan": { + "type": "integer", + "minimum": 1, + "maximum": 4, + "description": "Column span in grid layout (1-4)" + }, + "widget": { + "type": "string", + "description": "Custom widget/component name" + }, + "dependsOn": { + "type": "string", + "description": "Parent field name for cascading" + }, + "visibleOn": { + "type": "string", + "description": "Visibility condition expression" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "fields" + ], + "additionalProperties": false + } + } + }, + "additionalProperties": false + }, + "listViews": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 2, + "pattern": "^[a-z][a-z0-9_]*$", + "description": "Internal view name (lowercase snake_case)" + }, + "label": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "grid", + "kanban", + "gallery", + "calendar", + "timeline", + "gantt", + "map" + ], + "default": "grid" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "object" + }, + "object": { + "type": "string", + "description": "Target object name" + } + }, + "required": [ + "provider", + "object" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "api" + }, + "read": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for fetching data" + }, + "write": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for submitting data (for forms/editable tables)" + } + }, + "required": [ + "provider" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "value" + }, + "items": { + "type": "array", + "items": {}, + "description": "Static data array" + } + }, + "required": [ + "provider", + "items" + ], + "additionalProperties": false + } + ], + "description": "Data source configuration (defaults to \"object\" provider)" + }, + "columns": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "width": { + "type": "number", + "exclusiveMinimum": 0, + "description": "Column width in pixels" + }, + "align": { + "type": "string", + "enum": [ + "left", + "center", + "right" + ], + "description": "Text alignment" + }, + "hidden": { + "type": "boolean", + "description": "Hide column by default" + }, + "sortable": { + "type": "boolean", + "description": "Allow sorting by this column" + }, + "resizable": { + "type": "boolean", + "description": "Allow resizing this column" + }, + "wrap": { + "type": "boolean", + "description": "Allow text wrapping" + }, + "type": { + "type": "string", + "description": "Renderer type override (e.g., \"currency\", \"date\")" + }, + "link": { + "type": "boolean", + "description": "Functions as the primary navigation link (triggers View navigation)" + }, + "action": { + "type": "string", + "description": "Registered Action ID to execute when clicked" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + } + ], + "description": "Fields to display as columns" + }, + "filter": { + "type": "array", + "items": {}, + "description": "Filter criteria (JSON Rules)" + }, + "sort": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "field": { + "type": "string" + }, + "order": { + "type": "string", + "enum": [ + "asc", + "desc" + ] + } + }, + "required": [ + "field", + "order" + ], + "additionalProperties": false + } + } + ] + }, + "searchableFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields enabled for search" + }, + "filterableFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields enabled for end-user filtering in the top bar" + }, + "resizable": { + "type": "boolean", + "description": "Enable column resizing" + }, + "striped": { + "type": "boolean", + "description": "Striped row styling" + }, + "bordered": { + "type": "boolean", + "description": "Show borders" + }, + "selection": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "none", + "single", + "multiple" + ], + "default": "none", + "description": "Selection mode" + } + }, + "additionalProperties": false, + "description": "Row selection configuration" + }, + "navigation": { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "page", + "drawer", + "modal", + "split", + "popover", + "new_window", + "none" + ], + "default": "page" + }, + "view": { + "type": "string", + "description": "Name of the form view to use for details (e.g. \"summary_view\", \"edit_form\")" + }, + "preventNavigation": { + "type": "boolean", + "default": false, + "description": "Disable standard navigation entirely" + }, + "openNewTab": { + "type": "boolean", + "default": false, + "description": "Force open in new tab (applies to page mode)" + }, + "width": { + "type": [ + "string", + "number" + ], + "description": "Width of the drawer/modal (e.g. \"600px\", \"50%\")" + } + }, + "additionalProperties": false, + "description": "Configuration for item click navigation (page, drawer, modal, etc.)" + }, + "pagination": { + "type": "object", + "properties": { + "pageSize": { + "type": "integer", + "exclusiveMinimum": 0, + "default": 25, + "description": "Number of records per page" + }, + "pageSizeOptions": { + "type": "array", + "items": { + "type": "integer", + "exclusiveMinimum": 0 + }, + "description": "Available page size options" + } + }, + "additionalProperties": false, + "description": "Pagination configuration" + }, + "kanban": { + "type": "object", + "properties": { + "groupByField": { + "type": "string", + "description": "Field to group columns by (usually status/select)" + }, + "summarizeField": { + "type": "string", + "description": "Field to sum at top of column (e.g. amount)" + }, + "columns": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields to show on cards" + } + }, + "required": [ + "groupByField", + "columns" + ], + "additionalProperties": false + }, + "calendar": { + "type": "object", + "properties": { + "startDateField": { + "type": "string" + }, + "endDateField": { + "type": "string" + }, + "titleField": { + "type": "string" + }, + "colorField": { + "type": "string" + } + }, + "required": [ + "startDateField", + "titleField" + ], + "additionalProperties": false + }, + "gantt": { + "type": "object", + "properties": { + "startDateField": { + "type": "string" + }, + "endDateField": { + "type": "string" + }, + "titleField": { + "type": "string" + }, + "progressField": { + "type": "string" + }, + "dependenciesField": { + "type": "string" + } + }, + "required": [ + "startDateField", + "endDateField", + "titleField" + ], + "additionalProperties": false + }, + "rowActions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Actions available for individual row items" + }, + "bulkActions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Actions available when multiple rows are selected" + }, + "virtualScroll": { + "type": "boolean", + "description": "Enable virtual scrolling for large datasets" + }, + "conditionalFormatting": { + "type": "array", + "items": { + "type": "object", + "properties": { + "condition": { + "type": "string", + "description": "Condition expression to evaluate" + }, + "style": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "CSS styles to apply when condition is true" + } + }, + "required": [ + "condition", + "style" + ], + "additionalProperties": false + }, + "description": "Conditional formatting rules for list rows" + }, + "inlineEdit": { + "type": "boolean", + "description": "Allow inline editing of records directly in the list view" + }, + "exportOptions": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "csv", + "xlsx", + "pdf", + "json" + ] + }, + "description": "Available export format options" + }, + "emptyState": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "message": { + "type": "string" + }, + "icon": { + "type": "string" + } + }, + "additionalProperties": false, + "description": "Empty state configuration when no records found" + } + }, + "required": [ + "columns" + ], + "additionalProperties": false + }, + "description": "Additional named list views" + }, + "formViews": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "simple", + "tabbed", + "wizard", + "split", + "drawer", + "modal" + ], + "default": "simple" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "object" + }, + "object": { + "type": "string", + "description": "Target object name" + } + }, + "required": [ + "provider", + "object" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "api" + }, + "read": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for fetching data" + }, + "write": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "API endpoint URL" + }, + "method": { + "type": "string", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" + ], + "default": "GET", + "description": "HTTP method" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Custom HTTP headers" + }, + "params": { + "type": "object", + "additionalProperties": {}, + "description": "Query parameters" + }, + "body": { + "description": "Request body for POST/PUT/PATCH" + } + }, + "required": [ + "url" + ], + "additionalProperties": false, + "description": "Configuration for submitting data (for forms/editable tables)" + } + }, + "required": [ + "provider" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "const": "value" + }, + "items": { + "type": "array", + "items": {}, + "description": "Static data array" + } + }, + "required": [ + "provider", + "items" + ], + "additionalProperties": false + } + ], + "description": "Data source configuration (defaults to \"object\" provider)" + }, + "sections": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "collapsible": { + "type": "boolean", + "default": false + }, + "collapsed": { + "type": "boolean", + "default": false + }, + "columns": { + "type": "string", + "enum": [ + "1", + "2", + "3", + "4" + ], + "default": "2" + }, + "fields": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "placeholder": { + "type": "string", + "description": "Placeholder text" + }, + "helpText": { + "type": "string", + "description": "Help/hint text" + }, + "readonly": { + "type": "boolean", + "description": "Read-only override" + }, + "required": { + "type": "boolean", + "description": "Required override" + }, + "hidden": { + "type": "boolean", + "description": "Hidden override" + }, + "colSpan": { + "type": "integer", + "minimum": 1, + "maximum": 4, + "description": "Column span in grid layout (1-4)" + }, + "widget": { + "type": "string", + "description": "Custom widget/component name" + }, + "dependsOn": { + "type": "string", + "description": "Parent field name for cascading" + }, + "visibleOn": { + "type": "string", + "description": "Visibility condition expression" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "fields" + ], + "additionalProperties": false + } + }, + "groups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "collapsible": { + "type": "boolean", + "default": false + }, + "collapsed": { + "type": "boolean", + "default": false + }, + "columns": { + "type": "string", + "enum": [ + "1", + "2", + "3", + "4" + ], + "default": "2" + }, + "fields": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "field": { + "type": "string", + "description": "Field name (snake_case)" + }, + "label": { + "type": "string", + "description": "Display label override" + }, + "placeholder": { + "type": "string", + "description": "Placeholder text" + }, + "helpText": { + "type": "string", + "description": "Help/hint text" + }, + "readonly": { + "type": "boolean", + "description": "Read-only override" + }, + "required": { + "type": "boolean", + "description": "Required override" + }, + "hidden": { + "type": "boolean", + "description": "Hidden override" + }, + "colSpan": { + "type": "integer", + "minimum": 1, + "maximum": 4, + "description": "Column span in grid layout (1-4)" + }, + "widget": { + "type": "string", + "description": "Custom widget/component name" + }, + "dependsOn": { + "type": "string", + "description": "Parent field name for cascading" + }, + "visibleOn": { + "type": "string", + "description": "Visibility condition expression" + } + }, + "required": [ + "field" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "fields" + ], + "additionalProperties": false + } + } + }, + "additionalProperties": false + }, + "description": "Additional named form views" + } + }, + "additionalProperties": false, + "description": "Updated view definition" + } + }, + "required": [ + "object", + "viewId", + "view" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/WorkflowApproveRequest.json b/packages/spec/json-schema/api/WorkflowApproveRequest.json new file mode 100644 index 000000000..8fb38fa28 --- /dev/null +++ b/packages/spec/json-schema/api/WorkflowApproveRequest.json @@ -0,0 +1,33 @@ +{ + "$ref": "#/definitions/WorkflowApproveRequest", + "definitions": { + "WorkflowApproveRequest": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name" + }, + "recordId": { + "type": "string", + "description": "Record ID" + }, + "comment": { + "type": "string", + "description": "Approval comment" + }, + "data": { + "type": "object", + "additionalProperties": {}, + "description": "Additional data" + } + }, + "required": [ + "object", + "recordId" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/WorkflowApproveResponse.json b/packages/spec/json-schema/api/WorkflowApproveResponse.json new file mode 100644 index 000000000..be94c09dd --- /dev/null +++ b/packages/spec/json-schema/api/WorkflowApproveResponse.json @@ -0,0 +1,118 @@ +{ + "$ref": "#/definitions/WorkflowApproveResponse", + "definitions": { + "WorkflowApproveResponse": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name" + }, + "recordId": { + "type": "string", + "description": "Record ID" + }, + "success": { + "type": "boolean", + "description": "Whether the approval succeeded" + }, + "state": { + "type": "object", + "properties": { + "currentState": { + "type": "string", + "description": "Current workflow state name" + }, + "availableTransitions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Transition name" + }, + "targetState": { + "type": "string", + "description": "Target state after transition" + }, + "label": { + "type": "string", + "description": "Display label" + }, + "requiresApproval": { + "type": "boolean", + "default": false, + "description": "Whether transition requires approval" + } + }, + "required": [ + "name", + "targetState" + ], + "additionalProperties": false + }, + "description": "Available transitions from current state" + }, + "history": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fromState": { + "type": "string", + "description": "Previous state" + }, + "toState": { + "type": "string", + "description": "New state" + }, + "action": { + "type": "string", + "description": "Action that triggered the transition" + }, + "userId": { + "type": "string", + "description": "User who performed the action" + }, + "timestamp": { + "type": "string", + "format": "date-time", + "description": "When the transition occurred" + }, + "comment": { + "type": "string", + "description": "Optional comment" + } + }, + "required": [ + "fromState", + "toState", + "action", + "userId", + "timestamp" + ], + "additionalProperties": false + }, + "description": "State transition history" + } + }, + "required": [ + "currentState", + "availableTransitions" + ], + "additionalProperties": false, + "description": "New workflow state after approval" + } + }, + "required": [ + "object", + "recordId", + "success", + "state" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/WorkflowRejectRequest.json b/packages/spec/json-schema/api/WorkflowRejectRequest.json new file mode 100644 index 000000000..7b72c5f1e --- /dev/null +++ b/packages/spec/json-schema/api/WorkflowRejectRequest.json @@ -0,0 +1,33 @@ +{ + "$ref": "#/definitions/WorkflowRejectRequest", + "definitions": { + "WorkflowRejectRequest": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name" + }, + "recordId": { + "type": "string", + "description": "Record ID" + }, + "reason": { + "type": "string", + "description": "Rejection reason" + }, + "comment": { + "type": "string", + "description": "Additional comment" + } + }, + "required": [ + "object", + "recordId", + "reason" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/WorkflowRejectResponse.json b/packages/spec/json-schema/api/WorkflowRejectResponse.json new file mode 100644 index 000000000..d97da833c --- /dev/null +++ b/packages/spec/json-schema/api/WorkflowRejectResponse.json @@ -0,0 +1,118 @@ +{ + "$ref": "#/definitions/WorkflowRejectResponse", + "definitions": { + "WorkflowRejectResponse": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name" + }, + "recordId": { + "type": "string", + "description": "Record ID" + }, + "success": { + "type": "boolean", + "description": "Whether the rejection succeeded" + }, + "state": { + "type": "object", + "properties": { + "currentState": { + "type": "string", + "description": "Current workflow state name" + }, + "availableTransitions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Transition name" + }, + "targetState": { + "type": "string", + "description": "Target state after transition" + }, + "label": { + "type": "string", + "description": "Display label" + }, + "requiresApproval": { + "type": "boolean", + "default": false, + "description": "Whether transition requires approval" + } + }, + "required": [ + "name", + "targetState" + ], + "additionalProperties": false + }, + "description": "Available transitions from current state" + }, + "history": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fromState": { + "type": "string", + "description": "Previous state" + }, + "toState": { + "type": "string", + "description": "New state" + }, + "action": { + "type": "string", + "description": "Action that triggered the transition" + }, + "userId": { + "type": "string", + "description": "User who performed the action" + }, + "timestamp": { + "type": "string", + "format": "date-time", + "description": "When the transition occurred" + }, + "comment": { + "type": "string", + "description": "Optional comment" + } + }, + "required": [ + "fromState", + "toState", + "action", + "userId", + "timestamp" + ], + "additionalProperties": false + }, + "description": "State transition history" + } + }, + "required": [ + "currentState", + "availableTransitions" + ], + "additionalProperties": false, + "description": "New workflow state after rejection" + } + }, + "required": [ + "object", + "recordId", + "success", + "state" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/WorkflowState.json b/packages/spec/json-schema/api/WorkflowState.json new file mode 100644 index 000000000..299bdc684 --- /dev/null +++ b/packages/spec/json-schema/api/WorkflowState.json @@ -0,0 +1,93 @@ +{ + "$ref": "#/definitions/WorkflowState", + "definitions": { + "WorkflowState": { + "type": "object", + "properties": { + "currentState": { + "type": "string", + "description": "Current workflow state name" + }, + "availableTransitions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Transition name" + }, + "targetState": { + "type": "string", + "description": "Target state after transition" + }, + "label": { + "type": "string", + "description": "Display label" + }, + "requiresApproval": { + "type": "boolean", + "default": false, + "description": "Whether transition requires approval" + } + }, + "required": [ + "name", + "targetState" + ], + "additionalProperties": false + }, + "description": "Available transitions from current state" + }, + "history": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fromState": { + "type": "string", + "description": "Previous state" + }, + "toState": { + "type": "string", + "description": "New state" + }, + "action": { + "type": "string", + "description": "Action that triggered the transition" + }, + "userId": { + "type": "string", + "description": "User who performed the action" + }, + "timestamp": { + "type": "string", + "format": "date-time", + "description": "When the transition occurred" + }, + "comment": { + "type": "string", + "description": "Optional comment" + } + }, + "required": [ + "fromState", + "toState", + "action", + "userId", + "timestamp" + ], + "additionalProperties": false + }, + "description": "State transition history" + } + }, + "required": [ + "currentState", + "availableTransitions" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/WorkflowTransitionRequest.json b/packages/spec/json-schema/api/WorkflowTransitionRequest.json new file mode 100644 index 000000000..30a5a0a78 --- /dev/null +++ b/packages/spec/json-schema/api/WorkflowTransitionRequest.json @@ -0,0 +1,38 @@ +{ + "$ref": "#/definitions/WorkflowTransitionRequest", + "definitions": { + "WorkflowTransitionRequest": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name" + }, + "recordId": { + "type": "string", + "description": "Record ID" + }, + "transition": { + "type": "string", + "description": "Transition name to execute" + }, + "comment": { + "type": "string", + "description": "Optional comment for the transition" + }, + "data": { + "type": "object", + "additionalProperties": {}, + "description": "Additional data for the transition" + } + }, + "required": [ + "object", + "recordId", + "transition" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/api/WorkflowTransitionResponse.json b/packages/spec/json-schema/api/WorkflowTransitionResponse.json new file mode 100644 index 000000000..443064465 --- /dev/null +++ b/packages/spec/json-schema/api/WorkflowTransitionResponse.json @@ -0,0 +1,118 @@ +{ + "$ref": "#/definitions/WorkflowTransitionResponse", + "definitions": { + "WorkflowTransitionResponse": { + "type": "object", + "properties": { + "object": { + "type": "string", + "description": "Object name" + }, + "recordId": { + "type": "string", + "description": "Record ID" + }, + "success": { + "type": "boolean", + "description": "Whether the transition succeeded" + }, + "state": { + "type": "object", + "properties": { + "currentState": { + "type": "string", + "description": "Current workflow state name" + }, + "availableTransitions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Transition name" + }, + "targetState": { + "type": "string", + "description": "Target state after transition" + }, + "label": { + "type": "string", + "description": "Display label" + }, + "requiresApproval": { + "type": "boolean", + "default": false, + "description": "Whether transition requires approval" + } + }, + "required": [ + "name", + "targetState" + ], + "additionalProperties": false + }, + "description": "Available transitions from current state" + }, + "history": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fromState": { + "type": "string", + "description": "Previous state" + }, + "toState": { + "type": "string", + "description": "New state" + }, + "action": { + "type": "string", + "description": "Action that triggered the transition" + }, + "userId": { + "type": "string", + "description": "User who performed the action" + }, + "timestamp": { + "type": "string", + "format": "date-time", + "description": "When the transition occurred" + }, + "comment": { + "type": "string", + "description": "Optional comment" + } + }, + "required": [ + "fromState", + "toState", + "action", + "userId", + "timestamp" + ], + "additionalProperties": false + }, + "description": "State transition history" + } + }, + "required": [ + "currentState", + "availableTransitions" + ], + "additionalProperties": false, + "description": "New workflow state after transition" + } + }, + "required": [ + "object", + "recordId", + "success", + "state" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/packages/spec/json-schema/integration/Authentication.json b/packages/spec/json-schema/integration/Authentication.json deleted file mode 100644 index 97a19e9d9..000000000 --- a/packages/spec/json-schema/integration/Authentication.json +++ /dev/null @@ -1,146 +0,0 @@ -{ - "$ref": "#/definitions/Authentication", - "definitions": { - "Authentication": { - "anyOf": [ - { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "oauth2" - }, - "authorizationUrl": { - "type": "string", - "format": "uri", - "description": "OAuth2 authorization endpoint" - }, - "tokenUrl": { - "type": "string", - "format": "uri", - "description": "OAuth2 token endpoint" - }, - "clientId": { - "type": "string", - "description": "OAuth2 client ID" - }, - "clientSecret": { - "type": "string", - "description": "OAuth2 client secret (typically from ENV)" - }, - "scopes": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Requested OAuth2 scopes" - }, - "redirectUri": { - "type": "string", - "format": "uri", - "description": "OAuth2 redirect URI" - }, - "refreshToken": { - "type": "string", - "description": "Refresh token for token renewal" - }, - "tokenExpiry": { - "type": "number", - "description": "Token expiry timestamp" - } - }, - "required": [ - "type", - "authorizationUrl", - "tokenUrl", - "clientId", - "clientSecret" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "api-key" - }, - "key": { - "type": "string", - "description": "API key value" - }, - "headerName": { - "type": "string", - "default": "X-API-Key", - "description": "HTTP header name for API key" - }, - "paramName": { - "type": "string", - "description": "Query parameter name (alternative to header)" - } - }, - "required": [ - "type", - "key" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "basic" - }, - "username": { - "type": "string", - "description": "Username" - }, - "password": { - "type": "string", - "description": "Password" - } - }, - "required": [ - "type", - "username", - "password" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "bearer" - }, - "token": { - "type": "string", - "description": "Bearer token" - } - }, - "required": [ - "type", - "token" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "none" - } - }, - "required": [ - "type" - ], - "additionalProperties": false - } - ] - } - }, - "$schema": "http://json-schema.org/draft-07/schema#" -} \ No newline at end of file diff --git a/packages/spec/json-schema/integration/FieldTransform.json b/packages/spec/json-schema/integration/FieldTransform.json deleted file mode 100644 index 6d8ce629f..000000000 --- a/packages/spec/json-schema/integration/FieldTransform.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$ref": "#/definitions/FieldTransform", - "definitions": { - "FieldTransform": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "uppercase", - "lowercase", - "trim", - "date_format", - "number_format", - "custom" - ], - "description": "Transformation type" - }, - "params": { - "type": "object", - "additionalProperties": {}, - "description": "Transformation parameters" - }, - "function": { - "type": "string", - "description": "Custom JavaScript function for transformation" - } - }, - "required": [ - "type" - ], - "additionalProperties": false - } - }, - "$schema": "http://json-schema.org/draft-07/schema#" -} \ No newline at end of file diff --git a/packages/spec/json-schema/qa/TestAction.json b/packages/spec/json-schema/qa/TestAction.json index 05681b817..25a750054 100644 --- a/packages/spec/json-schema/qa/TestAction.json +++ b/packages/spec/json-schema/qa/TestAction.json @@ -15,7 +15,8 @@ "api_call", "run_script", "wait" - ] + ], + "description": "The action type to execute" }, "target": { "type": "string", @@ -28,14 +29,15 @@ }, "user": { "type": "string", - "description": "Run as specific user/role" + "description": "Run as specific user/role for impersonation testing" } }, "required": [ "type", "target" ], - "additionalProperties": false + "additionalProperties": false, + "description": "A single test action to execute against the system" } }, "$schema": "http://json-schema.org/draft-07/schema#" diff --git a/packages/spec/json-schema/qa/TestActionType.json b/packages/spec/json-schema/qa/TestActionType.json index 2a98d3599..cc9fb5979 100644 --- a/packages/spec/json-schema/qa/TestActionType.json +++ b/packages/spec/json-schema/qa/TestActionType.json @@ -12,7 +12,8 @@ "api_call", "run_script", "wait" - ] + ], + "description": "Type of test action to perform" } }, "$schema": "http://json-schema.org/draft-07/schema#" diff --git a/packages/spec/json-schema/qa/TestAssertion.json b/packages/spec/json-schema/qa/TestAssertion.json index 231d933e6..6ceedf201 100644 --- a/packages/spec/json-schema/qa/TestAssertion.json +++ b/packages/spec/json-schema/qa/TestAssertion.json @@ -22,15 +22,19 @@ "lt", "lte", "error" - ] + ], + "description": "Comparison operator to use" }, - "expectedValue": {} + "expectedValue": { + "description": "Expected value to compare against" + } }, "required": [ "field", "operator" ], - "additionalProperties": false + "additionalProperties": false, + "description": "A test assertion that validates the result of a test action" } }, "$schema": "http://json-schema.org/draft-07/schema#" diff --git a/packages/spec/json-schema/qa/TestAssertionType.json b/packages/spec/json-schema/qa/TestAssertionType.json index c1aa30681..0829d70c6 100644 --- a/packages/spec/json-schema/qa/TestAssertionType.json +++ b/packages/spec/json-schema/qa/TestAssertionType.json @@ -15,7 +15,8 @@ "lt", "lte", "error" - ] + ], + "description": "Comparison operator for test assertions" } }, "$schema": "http://json-schema.org/draft-07/schema#" diff --git a/packages/spec/json-schema/qa/TestScenario.json b/packages/spec/json-schema/qa/TestScenario.json index c67030925..2a9a215b2 100644 --- a/packages/spec/json-schema/qa/TestScenario.json +++ b/packages/spec/json-schema/qa/TestScenario.json @@ -5,19 +5,23 @@ "type": "object", "properties": { "id": { - "type": "string" + "type": "string", + "description": "Unique scenario identifier" }, "name": { - "type": "string" + "type": "string", + "description": "Scenario name for test reports" }, "description": { - "type": "string" + "type": "string", + "description": "Detailed description of the test scenario" }, "tags": { "type": "array", "items": { "type": "string" - } + }, + "description": "Tags for filtering and categorization (e.g. \"critical\", \"regression\", \"crm\")" }, "setup": { "type": "array", @@ -25,10 +29,12 @@ "type": "object", "properties": { "name": { - "type": "string" + "type": "string", + "description": "Step name for identification in test reports" }, "description": { - "type": "string" + "type": "string", + "description": "Human-readable description of what this step tests" }, "action": { "type": "object", @@ -44,7 +50,8 @@ "api_call", "run_script", "wait" - ] + ], + "description": "The action type to execute" }, "target": { "type": "string", @@ -57,14 +64,15 @@ }, "user": { "type": "string", - "description": "Run as specific user/role" + "description": "Run as specific user/role for impersonation testing" } }, "required": [ "type", "target" ], - "additionalProperties": false + "additionalProperties": false, + "description": "The action to execute in this step" }, "assertions": { "type": "array", @@ -89,16 +97,21 @@ "lt", "lte", "error" - ] + ], + "description": "Comparison operator to use" }, - "expectedValue": {} + "expectedValue": { + "description": "Expected value to compare against" + } }, "required": [ "field", "operator" ], - "additionalProperties": false - } + "additionalProperties": false, + "description": "A test assertion that validates the result of a test action" + }, + "description": "Assertions to validate after the action completes" }, "capture": { "type": "object", @@ -112,9 +125,10 @@ "name", "action" ], - "additionalProperties": false + "additionalProperties": false, + "description": "A single step in a test scenario, consisting of an action and optional assertions" }, - "description": "Steps to run before main test" + "description": "Steps to run before main test (preconditions)" }, "steps": { "type": "array", @@ -122,10 +136,12 @@ "type": "object", "properties": { "name": { - "type": "string" + "type": "string", + "description": "Step name for identification in test reports" }, "description": { - "type": "string" + "type": "string", + "description": "Human-readable description of what this step tests" }, "action": { "type": "object", @@ -141,7 +157,8 @@ "api_call", "run_script", "wait" - ] + ], + "description": "The action type to execute" }, "target": { "type": "string", @@ -154,14 +171,15 @@ }, "user": { "type": "string", - "description": "Run as specific user/role" + "description": "Run as specific user/role for impersonation testing" } }, "required": [ "type", "target" ], - "additionalProperties": false + "additionalProperties": false, + "description": "The action to execute in this step" }, "assertions": { "type": "array", @@ -186,16 +204,21 @@ "lt", "lte", "error" - ] + ], + "description": "Comparison operator to use" }, - "expectedValue": {} + "expectedValue": { + "description": "Expected value to compare against" + } }, "required": [ "field", "operator" ], - "additionalProperties": false - } + "additionalProperties": false, + "description": "A test assertion that validates the result of a test action" + }, + "description": "Assertions to validate after the action completes" }, "capture": { "type": "object", @@ -209,9 +232,10 @@ "name", "action" ], - "additionalProperties": false + "additionalProperties": false, + "description": "A single step in a test scenario, consisting of an action and optional assertions" }, - "description": "Main test sequence" + "description": "Main test sequence to execute" }, "teardown": { "type": "array", @@ -219,10 +243,12 @@ "type": "object", "properties": { "name": { - "type": "string" + "type": "string", + "description": "Step name for identification in test reports" }, "description": { - "type": "string" + "type": "string", + "description": "Human-readable description of what this step tests" }, "action": { "type": "object", @@ -238,7 +264,8 @@ "api_call", "run_script", "wait" - ] + ], + "description": "The action type to execute" }, "target": { "type": "string", @@ -251,14 +278,15 @@ }, "user": { "type": "string", - "description": "Run as specific user/role" + "description": "Run as specific user/role for impersonation testing" } }, "required": [ "type", "target" ], - "additionalProperties": false + "additionalProperties": false, + "description": "The action to execute in this step" }, "assertions": { "type": "array", @@ -283,16 +311,21 @@ "lt", "lte", "error" - ] + ], + "description": "Comparison operator to use" }, - "expectedValue": {} + "expectedValue": { + "description": "Expected value to compare against" + } }, "required": [ "field", "operator" ], - "additionalProperties": false - } + "additionalProperties": false, + "description": "A test assertion that validates the result of a test action" + }, + "description": "Assertions to validate after the action completes" }, "capture": { "type": "object", @@ -306,9 +339,10 @@ "name", "action" ], - "additionalProperties": false + "additionalProperties": false, + "description": "A single step in a test scenario, consisting of an action and optional assertions" }, - "description": "Steps to cleanup" + "description": "Steps to cleanup after test execution" }, "requires": { "type": "object", @@ -317,16 +351,19 @@ "type": "array", "items": { "type": "string" - } + }, + "description": "Required environment variables or parameters" }, "plugins": { "type": "array", "items": { "type": "string" - } + }, + "description": "Required plugins that must be loaded" } }, - "additionalProperties": false + "additionalProperties": false, + "description": "Environment requirements for this scenario" } }, "required": [ @@ -334,7 +371,8 @@ "name", "steps" ], - "additionalProperties": false + "additionalProperties": false, + "description": "A complete test scenario with setup, execution steps, and teardown" } }, "$schema": "http://json-schema.org/draft-07/schema#" diff --git a/packages/spec/json-schema/qa/TestStep.json b/packages/spec/json-schema/qa/TestStep.json index 8b3be1d41..06dd35219 100644 --- a/packages/spec/json-schema/qa/TestStep.json +++ b/packages/spec/json-schema/qa/TestStep.json @@ -5,10 +5,12 @@ "type": "object", "properties": { "name": { - "type": "string" + "type": "string", + "description": "Step name for identification in test reports" }, "description": { - "type": "string" + "type": "string", + "description": "Human-readable description of what this step tests" }, "action": { "type": "object", @@ -24,7 +26,8 @@ "api_call", "run_script", "wait" - ] + ], + "description": "The action type to execute" }, "target": { "type": "string", @@ -37,14 +40,15 @@ }, "user": { "type": "string", - "description": "Run as specific user/role" + "description": "Run as specific user/role for impersonation testing" } }, "required": [ "type", "target" ], - "additionalProperties": false + "additionalProperties": false, + "description": "The action to execute in this step" }, "assertions": { "type": "array", @@ -69,16 +73,21 @@ "lt", "lte", "error" - ] + ], + "description": "Comparison operator to use" }, - "expectedValue": {} + "expectedValue": { + "description": "Expected value to compare against" + } }, "required": [ "field", "operator" ], - "additionalProperties": false - } + "additionalProperties": false, + "description": "A test assertion that validates the result of a test action" + }, + "description": "Assertions to validate after the action completes" }, "capture": { "type": "object", @@ -92,7 +101,8 @@ "name", "action" ], - "additionalProperties": false + "additionalProperties": false, + "description": "A single step in a test scenario, consisting of an action and optional assertions" } }, "$schema": "http://json-schema.org/draft-07/schema#" diff --git a/packages/spec/json-schema/qa/TestSuite.json b/packages/spec/json-schema/qa/TestSuite.json index e9816b386..de002bd4b 100644 --- a/packages/spec/json-schema/qa/TestSuite.json +++ b/packages/spec/json-schema/qa/TestSuite.json @@ -5,7 +5,8 @@ "type": "object", "properties": { "name": { - "type": "string" + "type": "string", + "description": "Test suite name" }, "scenarios": { "type": "array", @@ -13,19 +14,23 @@ "type": "object", "properties": { "id": { - "type": "string" + "type": "string", + "description": "Unique scenario identifier" }, "name": { - "type": "string" + "type": "string", + "description": "Scenario name for test reports" }, "description": { - "type": "string" + "type": "string", + "description": "Detailed description of the test scenario" }, "tags": { "type": "array", "items": { "type": "string" - } + }, + "description": "Tags for filtering and categorization (e.g. \"critical\", \"regression\", \"crm\")" }, "setup": { "type": "array", @@ -33,10 +38,12 @@ "type": "object", "properties": { "name": { - "type": "string" + "type": "string", + "description": "Step name for identification in test reports" }, "description": { - "type": "string" + "type": "string", + "description": "Human-readable description of what this step tests" }, "action": { "type": "object", @@ -52,7 +59,8 @@ "api_call", "run_script", "wait" - ] + ], + "description": "The action type to execute" }, "target": { "type": "string", @@ -65,14 +73,15 @@ }, "user": { "type": "string", - "description": "Run as specific user/role" + "description": "Run as specific user/role for impersonation testing" } }, "required": [ "type", "target" ], - "additionalProperties": false + "additionalProperties": false, + "description": "The action to execute in this step" }, "assertions": { "type": "array", @@ -97,16 +106,21 @@ "lt", "lte", "error" - ] + ], + "description": "Comparison operator to use" }, - "expectedValue": {} + "expectedValue": { + "description": "Expected value to compare against" + } }, "required": [ "field", "operator" ], - "additionalProperties": false - } + "additionalProperties": false, + "description": "A test assertion that validates the result of a test action" + }, + "description": "Assertions to validate after the action completes" }, "capture": { "type": "object", @@ -120,9 +134,10 @@ "name", "action" ], - "additionalProperties": false + "additionalProperties": false, + "description": "A single step in a test scenario, consisting of an action and optional assertions" }, - "description": "Steps to run before main test" + "description": "Steps to run before main test (preconditions)" }, "steps": { "type": "array", @@ -130,10 +145,12 @@ "type": "object", "properties": { "name": { - "type": "string" + "type": "string", + "description": "Step name for identification in test reports" }, "description": { - "type": "string" + "type": "string", + "description": "Human-readable description of what this step tests" }, "action": { "type": "object", @@ -149,7 +166,8 @@ "api_call", "run_script", "wait" - ] + ], + "description": "The action type to execute" }, "target": { "type": "string", @@ -162,14 +180,15 @@ }, "user": { "type": "string", - "description": "Run as specific user/role" + "description": "Run as specific user/role for impersonation testing" } }, "required": [ "type", "target" ], - "additionalProperties": false + "additionalProperties": false, + "description": "The action to execute in this step" }, "assertions": { "type": "array", @@ -194,16 +213,21 @@ "lt", "lte", "error" - ] + ], + "description": "Comparison operator to use" }, - "expectedValue": {} + "expectedValue": { + "description": "Expected value to compare against" + } }, "required": [ "field", "operator" ], - "additionalProperties": false - } + "additionalProperties": false, + "description": "A test assertion that validates the result of a test action" + }, + "description": "Assertions to validate after the action completes" }, "capture": { "type": "object", @@ -217,9 +241,10 @@ "name", "action" ], - "additionalProperties": false + "additionalProperties": false, + "description": "A single step in a test scenario, consisting of an action and optional assertions" }, - "description": "Main test sequence" + "description": "Main test sequence to execute" }, "teardown": { "type": "array", @@ -227,10 +252,12 @@ "type": "object", "properties": { "name": { - "type": "string" + "type": "string", + "description": "Step name for identification in test reports" }, "description": { - "type": "string" + "type": "string", + "description": "Human-readable description of what this step tests" }, "action": { "type": "object", @@ -246,7 +273,8 @@ "api_call", "run_script", "wait" - ] + ], + "description": "The action type to execute" }, "target": { "type": "string", @@ -259,14 +287,15 @@ }, "user": { "type": "string", - "description": "Run as specific user/role" + "description": "Run as specific user/role for impersonation testing" } }, "required": [ "type", "target" ], - "additionalProperties": false + "additionalProperties": false, + "description": "The action to execute in this step" }, "assertions": { "type": "array", @@ -291,16 +320,21 @@ "lt", "lte", "error" - ] + ], + "description": "Comparison operator to use" }, - "expectedValue": {} + "expectedValue": { + "description": "Expected value to compare against" + } }, "required": [ "field", "operator" ], - "additionalProperties": false - } + "additionalProperties": false, + "description": "A test assertion that validates the result of a test action" + }, + "description": "Assertions to validate after the action completes" }, "capture": { "type": "object", @@ -314,9 +348,10 @@ "name", "action" ], - "additionalProperties": false + "additionalProperties": false, + "description": "A single step in a test scenario, consisting of an action and optional assertions" }, - "description": "Steps to cleanup" + "description": "Steps to cleanup after test execution" }, "requires": { "type": "object", @@ -325,16 +360,19 @@ "type": "array", "items": { "type": "string" - } + }, + "description": "Required environment variables or parameters" }, "plugins": { "type": "array", "items": { "type": "string" - } + }, + "description": "Required plugins that must be loaded" } }, - "additionalProperties": false + "additionalProperties": false, + "description": "Environment requirements for this scenario" } }, "required": [ @@ -342,15 +380,18 @@ "name", "steps" ], - "additionalProperties": false - } + "additionalProperties": false, + "description": "A complete test scenario with setup, execution steps, and teardown" + }, + "description": "List of test scenarios in this suite" } }, "required": [ "name", "scenarios" ], - "additionalProperties": false + "additionalProperties": false, + "description": "A collection of test scenarios grouped into a test suite" } }, "$schema": "http://json-schema.org/draft-07/schema#" diff --git a/packages/spec/src/api/protocol.zod.ts b/packages/spec/src/api/protocol.zod.ts index e0be161c1..3e1607221 100644 --- a/packages/spec/src/api/protocol.zod.ts +++ b/packages/spec/src/api/protocol.zod.ts @@ -17,6 +17,10 @@ import { InstallPluginRequest, InstallPluginResponse } from './hub.zod'; +import { RealtimePresenceSchema, TransportProtocol } from './realtime.zod'; +import { ObjectPermissionSchema, FieldPermissionSchema } from '../security/permission.zod'; +import { WorkflowRuleSchema } from '../automation/workflow.zod'; +import { TranslationDataSchema } from '../system/translation.zod'; import { ListPackagesRequestSchema, ListPackagesResponseSchema, @@ -425,6 +429,438 @@ export { DisablePackageResponseSchema, }; +// ========================================== +// View Management Operations +// ========================================== + +export const ListViewsRequestSchema = z.object({ + object: z.string().describe('Object name (snake_case)'), + type: z.enum(['list', 'form']).optional().describe('Filter by view type'), +}); + +export const ListViewsResponseSchema = z.object({ + object: z.string().describe('Object name'), + views: z.array(ViewSchema).describe('Array of view definitions'), +}); + +export const GetViewRequestSchema = z.object({ + object: z.string().describe('Object name (snake_case)'), + viewId: z.string().describe('View identifier'), +}); + +export const GetViewResponseSchema = z.object({ + object: z.string().describe('Object name'), + view: ViewSchema.describe('View definition'), +}); + +export const CreateViewRequestSchema = z.object({ + object: z.string().describe('Object name (snake_case)'), + data: ViewSchema.describe('View definition to create'), +}); + +export const CreateViewResponseSchema = z.object({ + object: z.string().describe('Object name'), + viewId: z.string().describe('Created view identifier'), + view: ViewSchema.describe('Created view definition'), +}); + +export const UpdateViewRequestSchema = z.object({ + object: z.string().describe('Object name (snake_case)'), + viewId: z.string().describe('View identifier'), + data: ViewSchema.partial().describe('Partial view data to update'), +}); + +export const UpdateViewResponseSchema = z.object({ + object: z.string().describe('Object name'), + viewId: z.string().describe('Updated view identifier'), + view: ViewSchema.describe('Updated view definition'), +}); + +export const DeleteViewRequestSchema = z.object({ + object: z.string().describe('Object name (snake_case)'), + viewId: z.string().describe('View identifier to delete'), +}); + +export const DeleteViewResponseSchema = z.object({ + object: z.string().describe('Object name'), + viewId: z.string().describe('Deleted view identifier'), + success: z.boolean().describe('Whether deletion succeeded'), +}); + +// ========================================== +// Permission Operations +// ========================================== + +export const CheckPermissionRequestSchema = z.object({ + object: z.string().describe('Object name to check permissions for'), + action: z.enum(['create', 'read', 'edit', 'delete', 'transfer', 'restore', 'purge']).describe('Action to check'), + recordId: z.string().optional().describe('Specific record ID (for record-level checks)'), + field: z.string().optional().describe('Specific field name (for field-level checks)'), +}); + +export const CheckPermissionResponseSchema = z.object({ + allowed: z.boolean().describe('Whether the action is permitted'), + reason: z.string().optional().describe('Reason if denied'), +}); + +export const GetObjectPermissionsRequestSchema = z.object({ + object: z.string().describe('Object name to get permissions for'), +}); + +export const GetObjectPermissionsResponseSchema = z.object({ + object: z.string().describe('Object name'), + permissions: ObjectPermissionSchema.describe('Object-level permissions'), + fieldPermissions: z.record(z.string(), FieldPermissionSchema).optional().describe('Field-level permissions keyed by field name'), +}); + +export const GetEffectivePermissionsRequestSchema = z.object({}); + +export const GetEffectivePermissionsResponseSchema = z.object({ + objects: z.record(z.string(), ObjectPermissionSchema).describe('Effective object permissions keyed by object name'), + systemPermissions: z.array(z.string()).describe('Effective system-level permissions'), +}); + +// ========================================== +// Workflow Operations +// ========================================== + +export const GetWorkflowConfigRequestSchema = z.object({ + object: z.string().describe('Object name to get workflow config for'), +}); + +export const GetWorkflowConfigResponseSchema = z.object({ + object: z.string().describe('Object name'), + workflows: z.array(WorkflowRuleSchema).describe('Active workflow rules for this object'), +}); + +export const WorkflowStateSchema = z.object({ + currentState: z.string().describe('Current workflow state name'), + availableTransitions: z.array(z.object({ + name: z.string().describe('Transition name'), + targetState: z.string().describe('Target state after transition'), + label: z.string().optional().describe('Display label'), + requiresApproval: z.boolean().default(false).describe('Whether transition requires approval'), + })).describe('Available transitions from current state'), + history: z.array(z.object({ + fromState: z.string().describe('Previous state'), + toState: z.string().describe('New state'), + action: z.string().describe('Action that triggered the transition'), + userId: z.string().describe('User who performed the action'), + timestamp: z.string().datetime().describe('When the transition occurred'), + comment: z.string().optional().describe('Optional comment'), + })).optional().describe('State transition history'), +}); + +export const GetWorkflowStateRequestSchema = z.object({ + object: z.string().describe('Object name'), + recordId: z.string().describe('Record ID to get workflow state for'), +}); + +export const GetWorkflowStateResponseSchema = z.object({ + object: z.string().describe('Object name'), + recordId: z.string().describe('Record ID'), + state: WorkflowStateSchema.describe('Current workflow state and available transitions'), +}); + +export const WorkflowTransitionRequestSchema = z.object({ + object: z.string().describe('Object name'), + recordId: z.string().describe('Record ID'), + transition: z.string().describe('Transition name to execute'), + comment: z.string().optional().describe('Optional comment for the transition'), + data: z.record(z.string(), z.unknown()).optional().describe('Additional data for the transition'), +}); + +export const WorkflowTransitionResponseSchema = z.object({ + object: z.string().describe('Object name'), + recordId: z.string().describe('Record ID'), + success: z.boolean().describe('Whether the transition succeeded'), + state: WorkflowStateSchema.describe('New workflow state after transition'), +}); + +export const WorkflowApproveRequestSchema = z.object({ + object: z.string().describe('Object name'), + recordId: z.string().describe('Record ID'), + comment: z.string().optional().describe('Approval comment'), + data: z.record(z.string(), z.unknown()).optional().describe('Additional data'), +}); + +export const WorkflowApproveResponseSchema = z.object({ + object: z.string().describe('Object name'), + recordId: z.string().describe('Record ID'), + success: z.boolean().describe('Whether the approval succeeded'), + state: WorkflowStateSchema.describe('New workflow state after approval'), +}); + +export const WorkflowRejectRequestSchema = z.object({ + object: z.string().describe('Object name'), + recordId: z.string().describe('Record ID'), + reason: z.string().describe('Rejection reason'), + comment: z.string().optional().describe('Additional comment'), +}); + +export const WorkflowRejectResponseSchema = z.object({ + object: z.string().describe('Object name'), + recordId: z.string().describe('Record ID'), + success: z.boolean().describe('Whether the rejection succeeded'), + state: WorkflowStateSchema.describe('New workflow state after rejection'), +}); + +// ========================================== +// Realtime Operations +// ========================================== + +export const RealtimeConnectRequestSchema = z.object({ + transport: TransportProtocol.optional().describe('Preferred transport protocol'), + channels: z.array(z.string()).optional().describe('Channels to subscribe to on connect'), + token: z.string().optional().describe('Authentication token'), +}); + +export const RealtimeConnectResponseSchema = z.object({ + connectionId: z.string().describe('Unique connection identifier'), + transport: TransportProtocol.describe('Negotiated transport protocol'), + url: z.string().optional().describe('WebSocket/SSE endpoint URL'), +}); + +export const RealtimeDisconnectRequestSchema = z.object({ + connectionId: z.string().optional().describe('Connection ID to disconnect'), +}); + +export const RealtimeDisconnectResponseSchema = z.object({ + success: z.boolean().describe('Whether disconnection succeeded'), +}); + +export const RealtimeSubscribeRequestSchema = z.object({ + channel: z.string().describe('Channel name to subscribe to'), + events: z.array(z.string()).optional().describe('Specific event types to listen for'), + filter: z.record(z.string(), z.unknown()).optional().describe('Event filter criteria'), +}); + +export const RealtimeSubscribeResponseSchema = z.object({ + subscriptionId: z.string().describe('Unique subscription identifier'), + channel: z.string().describe('Subscribed channel name'), +}); + +export const RealtimeUnsubscribeRequestSchema = z.object({ + subscriptionId: z.string().describe('Subscription ID to cancel'), +}); + +export const RealtimeUnsubscribeResponseSchema = z.object({ + success: z.boolean().describe('Whether unsubscription succeeded'), +}); + +export const SetPresenceRequestSchema = z.object({ + channel: z.string().describe('Channel to set presence in'), + state: RealtimePresenceSchema.describe('Presence state to set'), +}); + +export const SetPresenceResponseSchema = z.object({ + success: z.boolean().describe('Whether presence was set'), +}); + +export const GetPresenceRequestSchema = z.object({ + channel: z.string().describe('Channel to get presence for'), +}); + +export const GetPresenceResponseSchema = z.object({ + channel: z.string().describe('Channel name'), + members: z.array(RealtimePresenceSchema).describe('Active members and their presence state'), +}); + +// ========================================== +// Notification Operations +// ========================================== + +export const RegisterDeviceRequestSchema = z.object({ + token: z.string().describe('Device push notification token'), + platform: z.enum(['ios', 'android', 'web']).describe('Device platform'), + deviceId: z.string().optional().describe('Unique device identifier'), + name: z.string().optional().describe('Device friendly name'), +}); + +export const RegisterDeviceResponseSchema = z.object({ + deviceId: z.string().describe('Registered device ID'), + success: z.boolean().describe('Whether registration succeeded'), +}); + +export const UnregisterDeviceRequestSchema = z.object({ + deviceId: z.string().describe('Device ID to unregister'), +}); + +export const UnregisterDeviceResponseSchema = z.object({ + success: z.boolean().describe('Whether unregistration succeeded'), +}); + +export const NotificationPreferencesSchema = z.object({ + email: z.boolean().default(true).describe('Receive email notifications'), + push: z.boolean().default(true).describe('Receive push notifications'), + inApp: z.boolean().default(true).describe('Receive in-app notifications'), + digest: z.enum(['none', 'daily', 'weekly']).default('none').describe('Email digest frequency'), + channels: z.record(z.string(), z.object({ + enabled: z.boolean().default(true).describe('Whether this channel is enabled'), + email: z.boolean().optional().describe('Override email setting'), + push: z.boolean().optional().describe('Override push setting'), + })).optional().describe('Per-channel notification preferences'), +}); + +export const GetNotificationPreferencesRequestSchema = z.object({}); + +export const GetNotificationPreferencesResponseSchema = z.object({ + preferences: NotificationPreferencesSchema.describe('Current notification preferences'), +}); + +export const UpdateNotificationPreferencesRequestSchema = z.object({ + preferences: NotificationPreferencesSchema.partial().describe('Preferences to update'), +}); + +export const UpdateNotificationPreferencesResponseSchema = z.object({ + preferences: NotificationPreferencesSchema.describe('Updated notification preferences'), +}); + +export const NotificationSchema = z.object({ + id: z.string().describe('Notification ID'), + type: z.string().describe('Notification type'), + title: z.string().describe('Notification title'), + body: z.string().describe('Notification body text'), + read: z.boolean().default(false).describe('Whether notification has been read'), + data: z.record(z.string(), z.unknown()).optional().describe('Additional notification data'), + actionUrl: z.string().optional().describe('URL to navigate to when clicked'), + createdAt: z.string().datetime().describe('When notification was created'), +}); + +export const ListNotificationsRequestSchema = z.object({ + read: z.boolean().optional().describe('Filter by read status'), + type: z.string().optional().describe('Filter by notification type'), + limit: z.number().default(20).describe('Maximum number of notifications to return'), + cursor: z.string().optional().describe('Pagination cursor'), +}); + +export const ListNotificationsResponseSchema = z.object({ + notifications: z.array(NotificationSchema).describe('List of notifications'), + unreadCount: z.number().describe('Total number of unread notifications'), + cursor: z.string().optional().describe('Next page cursor'), +}); + +export const MarkNotificationsReadRequestSchema = z.object({ + ids: z.array(z.string()).describe('Notification IDs to mark as read'), +}); + +export const MarkNotificationsReadResponseSchema = z.object({ + success: z.boolean().describe('Whether the operation succeeded'), + readCount: z.number().describe('Number of notifications marked as read'), +}); + +export const MarkAllNotificationsReadRequestSchema = z.object({}); + +export const MarkAllNotificationsReadResponseSchema = z.object({ + success: z.boolean().describe('Whether the operation succeeded'), + readCount: z.number().describe('Number of notifications marked as read'), +}); + +// ========================================== +// AI Operations +// ========================================== + +export const AiNlqRequestSchema = z.object({ + query: z.string().describe('Natural language query string'), + object: z.string().optional().describe('Target object context'), + conversationId: z.string().optional().describe('Conversation ID for multi-turn queries'), +}); + +export const AiNlqResponseSchema = z.object({ + query: z.unknown().describe('Generated structured query (AST)'), + explanation: z.string().optional().describe('Human-readable explanation of the query'), + confidence: z.number().min(0).max(1).optional().describe('Confidence score (0-1)'), + suggestions: z.array(z.string()).optional().describe('Suggested follow-up queries'), +}); + +export const AiChatRequestSchema = z.object({ + message: z.string().describe('User message'), + conversationId: z.string().optional().describe('Conversation ID for context'), + context: z.record(z.string(), z.unknown()).optional().describe('Additional context data'), +}); + +export const AiChatResponseSchema = z.object({ + message: z.string().describe('Assistant response message'), + conversationId: z.string().describe('Conversation ID'), + actions: z.array(z.object({ + type: z.string().describe('Action type'), + label: z.string().describe('Action display label'), + data: z.record(z.string(), z.unknown()).optional().describe('Action data'), + })).optional().describe('Suggested actions'), +}); + +export const AiSuggestRequestSchema = z.object({ + object: z.string().describe('Object name for context'), + field: z.string().optional().describe('Field to suggest values for'), + recordId: z.string().optional().describe('Record ID for context'), + partial: z.string().optional().describe('Partial input for completion'), +}); + +export const AiSuggestResponseSchema = z.object({ + suggestions: z.array(z.object({ + value: z.unknown().describe('Suggested value'), + label: z.string().describe('Display label'), + confidence: z.number().min(0).max(1).optional().describe('Confidence score (0-1)'), + reason: z.string().optional().describe('Reason for this suggestion'), + })).describe('Suggested values'), +}); + +export const AiInsightsRequestSchema = z.object({ + object: z.string().describe('Object name to analyze'), + recordId: z.string().optional().describe('Specific record to analyze'), + type: z.enum(['summary', 'trends', 'anomalies', 'recommendations']).optional().describe('Type of insight'), +}); + +export const AiInsightsResponseSchema = z.object({ + insights: z.array(z.object({ + type: z.string().describe('Insight type'), + title: z.string().describe('Insight title'), + description: z.string().describe('Detailed description'), + confidence: z.number().min(0).max(1).optional().describe('Confidence score (0-1)'), + data: z.record(z.string(), z.unknown()).optional().describe('Supporting data'), + })).describe('Generated insights'), +}); + +// ========================================== +// i18n Operations +// ========================================== + +export const GetLocalesRequestSchema = z.object({}); + +export const GetLocalesResponseSchema = z.object({ + locales: z.array(z.object({ + code: z.string().describe('BCP-47 locale code (e.g., en-US, zh-CN)'), + label: z.string().describe('Display name of the locale'), + isDefault: z.boolean().default(false).describe('Whether this is the default locale'), + })).describe('Available locales'), +}); + +export const GetTranslationsRequestSchema = z.object({ + locale: z.string().describe('BCP-47 locale code'), + namespace: z.string().optional().describe('Translation namespace (e.g., objects, apps, messages)'), + keys: z.array(z.string()).optional().describe('Specific translation keys to fetch'), +}); + +export const GetTranslationsResponseSchema = z.object({ + locale: z.string().describe('Locale code'), + translations: TranslationDataSchema.describe('Translation data'), +}); + +export const GetFieldLabelsRequestSchema = z.object({ + object: z.string().describe('Object name'), + locale: z.string().describe('BCP-47 locale code'), +}); + +export const GetFieldLabelsResponseSchema = z.object({ + object: z.string().describe('Object name'), + locale: z.string().describe('Locale code'), + labels: z.record(z.string(), z.object({ + label: z.string().describe('Translated field label'), + help: z.string().optional().describe('Translated help text'), + options: z.record(z.string(), z.string()).optional().describe('Translated option labels'), + })).describe('Field labels keyed by field name'), +}); + // ========================================== // Protocol Interface Schema // ========================================== @@ -531,6 +967,86 @@ export const ObjectStackProtocolSchema = z.object({ deleteManyData: z.function() .describe('Delete multiple records'), + + // View Management Operations + listViews: z.function() + .describe('List views for an object'), + getView: z.function() + .describe('Get a specific view'), + createView: z.function() + .describe('Create a new view'), + updateView: z.function() + .describe('Update an existing view'), + deleteView: z.function() + .describe('Delete a view'), + + // Permission Operations + checkPermission: z.function() + .describe('Check if an action is permitted'), + getObjectPermissions: z.function() + .describe('Get permissions for an object'), + getEffectivePermissions: z.function() + .describe('Get effective permissions for current user'), + + // Workflow Operations + getWorkflowConfig: z.function() + .describe('Get workflow configuration for an object'), + getWorkflowState: z.function() + .describe('Get workflow state for a record'), + workflowTransition: z.function() + .describe('Execute a workflow state transition'), + workflowApprove: z.function() + .describe('Approve a workflow step'), + workflowReject: z.function() + .describe('Reject a workflow step'), + + // Realtime Operations + realtimeConnect: z.function() + .describe('Establish realtime connection'), + realtimeDisconnect: z.function() + .describe('Close realtime connection'), + realtimeSubscribe: z.function() + .describe('Subscribe to a realtime channel'), + realtimeUnsubscribe: z.function() + .describe('Unsubscribe from a realtime channel'), + setPresence: z.function() + .describe('Set user presence state'), + getPresence: z.function() + .describe('Get channel presence information'), + + // Notification Operations + registerDevice: z.function() + .describe('Register a device for push notifications'), + unregisterDevice: z.function() + .describe('Unregister a device'), + getNotificationPreferences: z.function() + .describe('Get notification preferences'), + updateNotificationPreferences: z.function() + .describe('Update notification preferences'), + listNotifications: z.function() + .describe('List notifications'), + markNotificationsRead: z.function() + .describe('Mark specific notifications as read'), + markAllNotificationsRead: z.function() + .describe('Mark all notifications as read'), + + // AI Operations + aiNlq: z.function() + .describe('Natural language query'), + aiChat: z.function() + .describe('AI chat interaction'), + aiSuggest: z.function() + .describe('Get AI-powered suggestions'), + aiInsights: z.function() + .describe('Get AI-generated insights'), + + // i18n Operations + getLocales: z.function() + .describe('Get available locales'), + getTranslations: z.function() + .describe('Get translations for a locale'), + getFieldLabels: z.function() + .describe('Get translated field labels for an object'), }); /** @@ -580,6 +1096,91 @@ export type UpdateManyDataResponse = z.infer; export type DeleteManyDataResponse = z.infer; +// View Management Types +export type ListViewsRequest = z.input; +export type ListViewsResponse = z.infer; +export type GetViewRequest = z.input; +export type GetViewResponse = z.infer; +export type CreateViewRequest = z.input; +export type CreateViewResponse = z.infer; +export type UpdateViewRequest = z.input; +export type UpdateViewResponse = z.infer; +export type DeleteViewRequest = z.input; +export type DeleteViewResponse = z.infer; + +// Permission Types +export type CheckPermissionRequest = z.input; +export type CheckPermissionResponse = z.infer; +export type GetObjectPermissionsRequest = z.input; +export type GetObjectPermissionsResponse = z.infer; +export type GetEffectivePermissionsRequest = z.input; +export type GetEffectivePermissionsResponse = z.infer; + +// Workflow Types +export type GetWorkflowConfigRequest = z.input; +export type GetWorkflowConfigResponse = z.infer; +export type WorkflowState = z.infer; +export type GetWorkflowStateRequest = z.input; +export type GetWorkflowStateResponse = z.infer; +export type WorkflowTransitionRequest = z.input; +export type WorkflowTransitionResponse = z.infer; +export type WorkflowApproveRequest = z.input; +export type WorkflowApproveResponse = z.infer; +export type WorkflowRejectRequest = z.input; +export type WorkflowRejectResponse = z.infer; + +// Realtime Types +export type RealtimeConnectRequest = z.input; +export type RealtimeConnectResponse = z.infer; +export type RealtimeDisconnectRequest = z.input; +export type RealtimeDisconnectResponse = z.infer; +export type RealtimeSubscribeRequest = z.input; +export type RealtimeSubscribeResponse = z.infer; +export type RealtimeUnsubscribeRequest = z.input; +export type RealtimeUnsubscribeResponse = z.infer; +export type SetPresenceRequest = z.input; +export type SetPresenceResponse = z.infer; +export type GetPresenceRequest = z.input; +export type GetPresenceResponse = z.infer; + +// Notification Types +export type RegisterDeviceRequest = z.input; +export type RegisterDeviceResponse = z.infer; +export type UnregisterDeviceRequest = z.input; +export type UnregisterDeviceResponse = z.infer; +export type NotificationPreferences = z.infer; +export type NotificationPreferencesInput = z.input; +export type GetNotificationPreferencesRequest = z.input; +export type GetNotificationPreferencesResponse = z.infer; +export type UpdateNotificationPreferencesRequest = z.input; +export type UpdateNotificationPreferencesResponse = z.infer; +export type Notification = z.infer; +export type NotificationInput = z.input; +export type ListNotificationsRequest = z.input; +export type ListNotificationsResponse = z.infer; +export type MarkNotificationsReadRequest = z.input; +export type MarkNotificationsReadResponse = z.infer; +export type MarkAllNotificationsReadRequest = z.input; +export type MarkAllNotificationsReadResponse = z.infer; + +// AI Types +export type AiNlqRequest = z.input; +export type AiNlqResponse = z.infer; +export type AiChatRequest = z.input; +export type AiChatResponse = z.infer; +export type AiSuggestRequest = z.input; +export type AiSuggestResponse = z.infer; +export type AiInsightsRequest = z.input; +export type AiInsightsResponse = z.infer; + +// i18n Types +export type GetLocalesRequest = z.input; +export type GetLocalesResponse = z.infer; +export type GetTranslationsRequest = z.input; +export type GetTranslationsResponse = z.infer; +export type GetFieldLabelsRequest = z.input; +export type GetFieldLabelsResponse = z.infer; + // Package Management Types (re-exported from kernel for convenience) export type { ListPackagesRequest, @@ -641,4 +1242,51 @@ export interface IObjectStackProtocolLegacy { createManyData(request: CreateManyDataRequest): Promise; updateManyData(request: UpdateManyDataRequest): Promise; deleteManyData(request: DeleteManyDataRequest): Promise; + + // View Management + listViews(request: ListViewsRequest): Promise; + getView(request: GetViewRequest): Promise; + createView(request: CreateViewRequest): Promise; + updateView(request: UpdateViewRequest): Promise; + deleteView(request: DeleteViewRequest): Promise; + + // Permissions + checkPermission(request: CheckPermissionRequest): Promise; + getObjectPermissions(request: GetObjectPermissionsRequest): Promise; + getEffectivePermissions(request: GetEffectivePermissionsRequest): Promise; + + // Workflows + getWorkflowConfig(request: GetWorkflowConfigRequest): Promise; + getWorkflowState(request: GetWorkflowStateRequest): Promise; + workflowTransition(request: WorkflowTransitionRequest): Promise; + workflowApprove(request: WorkflowApproveRequest): Promise; + workflowReject(request: WorkflowRejectRequest): Promise; + + // Realtime + realtimeConnect(request: RealtimeConnectRequest): Promise; + realtimeDisconnect(request: RealtimeDisconnectRequest): Promise; + realtimeSubscribe(request: RealtimeSubscribeRequest): Promise; + realtimeUnsubscribe(request: RealtimeUnsubscribeRequest): Promise; + setPresence(request: SetPresenceRequest): Promise; + getPresence(request: GetPresenceRequest): Promise; + + // Notifications + registerDevice(request: RegisterDeviceRequest): Promise; + unregisterDevice(request: UnregisterDeviceRequest): Promise; + getNotificationPreferences(request: GetNotificationPreferencesRequest): Promise; + updateNotificationPreferences(request: UpdateNotificationPreferencesRequest): Promise; + listNotifications(request: ListNotificationsRequest): Promise; + markNotificationsRead(request: MarkNotificationsReadRequest): Promise; + markAllNotificationsRead(request: MarkAllNotificationsReadRequest): Promise; + + // AI + aiNlq(request: AiNlqRequest): Promise; + aiChat(request: AiChatRequest): Promise; + aiSuggest(request: AiSuggestRequest): Promise; + aiInsights(request: AiInsightsRequest): Promise; + + // i18n + getLocales(request: GetLocalesRequest): Promise; + getTranslations(request: GetTranslationsRequest): Promise; + getFieldLabels(request: GetFieldLabelsRequest): Promise; } From 7bf879de0a54fcc9a07af2ea5b95d2b958b8baac Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Feb 2026 07:44:41 +0000 Subject: [PATCH 3/3] Add tests for new API protocol operations (Views, Permissions, Workflows, Realtime, Notifications, AI, i18n) Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com> --- packages/spec/src/api/protocol.test.ts | 205 ++++++++++++++++++++++++- 1 file changed, 204 insertions(+), 1 deletion(-) diff --git a/packages/spec/src/api/protocol.test.ts b/packages/spec/src/api/protocol.test.ts index d532ab144..f1130976f 100644 --- a/packages/spec/src/api/protocol.test.ts +++ b/packages/spec/src/api/protocol.test.ts @@ -12,7 +12,59 @@ import { BatchDataRequestSchema, CreateManyDataResponseSchema, UpdateManyDataRequestSchema, - DeleteManyDataRequestSchema + DeleteManyDataRequestSchema, + // Views + ListViewsRequestSchema, + ListViewsResponseSchema, + GetViewRequestSchema, + CreateViewRequestSchema, + UpdateViewRequestSchema, + DeleteViewRequestSchema, + DeleteViewResponseSchema, + // Permissions + CheckPermissionRequestSchema, + CheckPermissionResponseSchema, + GetObjectPermissionsRequestSchema, + GetObjectPermissionsResponseSchema, + GetEffectivePermissionsResponseSchema, + // Workflows + GetWorkflowConfigRequestSchema, + WorkflowStateSchema, + GetWorkflowStateRequestSchema, + WorkflowTransitionRequestSchema, + WorkflowTransitionResponseSchema, + WorkflowApproveRequestSchema, + WorkflowRejectRequestSchema, + // Realtime + RealtimeConnectRequestSchema, + RealtimeConnectResponseSchema, + RealtimeSubscribeRequestSchema, + RealtimeSubscribeResponseSchema, + SetPresenceRequestSchema, + GetPresenceResponseSchema, + // Notifications + RegisterDeviceRequestSchema, + RegisterDeviceResponseSchema, + NotificationPreferencesSchema, + NotificationSchema, + ListNotificationsRequestSchema, + ListNotificationsResponseSchema, + MarkNotificationsReadRequestSchema, + // AI + AiNlqRequestSchema, + AiNlqResponseSchema, + AiChatRequestSchema, + AiChatResponseSchema, + AiSuggestRequestSchema, + AiSuggestResponseSchema, + AiInsightsRequestSchema, + AiInsightsResponseSchema, + // i18n + GetLocalesResponseSchema, + GetTranslationsRequestSchema, + GetTranslationsResponseSchema, + GetFieldLabelsRequestSchema, + GetFieldLabelsResponseSchema, } from './protocol.zod'; describe('ObjectStack Protocol', () => { @@ -115,4 +167,155 @@ describe('ObjectStack Protocol', () => { expect(DeleteManyDataRequestSchema.safeParse(deleteManyReq).success).toBe(true); }); + it('validates Views operations', () => { + expect(ListViewsRequestSchema.safeParse({ object: 'project', type: 'list' }).success).toBe(true); + expect(ListViewsResponseSchema.safeParse({ + object: 'project', + views: [{ list: { columns: [] } }], + }).success).toBe(true); + expect(GetViewRequestSchema.safeParse({ object: 'project', viewId: 'v1' }).success).toBe(true); + expect(CreateViewRequestSchema.safeParse({ + object: 'project', + data: { list: { columns: [] } }, + }).success).toBe(true); + expect(UpdateViewRequestSchema.safeParse({ + object: 'project', + viewId: 'v1', + data: { list: { columns: [] } }, + }).success).toBe(true); + expect(DeleteViewRequestSchema.safeParse({ object: 'project', viewId: 'v1' }).success).toBe(true); + expect(DeleteViewResponseSchema.safeParse({ object: 'project', viewId: 'v1', success: true }).success).toBe(true); + }); + + it('validates Permissions operations', () => { + expect(CheckPermissionRequestSchema.safeParse({ + object: 'account', + action: 'edit', + recordId: 'a1', + }).success).toBe(true); + expect(CheckPermissionResponseSchema.safeParse({ allowed: false, reason: 'Insufficient privileges' }).success).toBe(true); + expect(GetObjectPermissionsRequestSchema.safeParse({ object: 'account' }).success).toBe(true); + expect(GetObjectPermissionsResponseSchema.safeParse({ + object: 'account', + permissions: { allowCreate: true, allowRead: true, allowEdit: false, allowDelete: false }, + fieldPermissions: { email: { readable: true, editable: false } }, + }).success).toBe(true); + expect(GetEffectivePermissionsResponseSchema.safeParse({ + objects: { account: { allowRead: true } }, + systemPermissions: ['manage_users', 'view_reports'], + }).success).toBe(true); + }); + + it('validates Workflow operations', () => { + expect(GetWorkflowConfigRequestSchema.safeParse({ object: 'lead' }).success).toBe(true); + const state = { + currentState: 'open', + availableTransitions: [ + { name: 'approve', targetState: 'approved', label: 'Approve', requiresApproval: true }, + ], + history: [{ + fromState: 'draft', toState: 'open', action: 'submit', + userId: 'u1', timestamp: '2024-01-15T10:00:00Z', + }], + }; + expect(WorkflowStateSchema.safeParse(state).success).toBe(true); + expect(GetWorkflowStateRequestSchema.safeParse({ object: 'lead', recordId: 'l1' }).success).toBe(true); + expect(WorkflowTransitionRequestSchema.safeParse({ + object: 'lead', recordId: 'l1', transition: 'approve', comment: 'Looks good', + }).success).toBe(true); + expect(WorkflowTransitionResponseSchema.safeParse({ + object: 'lead', recordId: 'l1', success: true, state, + }).success).toBe(true); + expect(WorkflowApproveRequestSchema.safeParse({ + object: 'lead', recordId: 'l1', comment: 'Approved', + }).success).toBe(true); + expect(WorkflowRejectRequestSchema.safeParse({ + object: 'lead', recordId: 'l1', reason: 'Missing info', + }).success).toBe(true); + }); + + it('validates Realtime operations', () => { + expect(RealtimeConnectRequestSchema.safeParse({ + transport: 'websocket', channels: ['project.updates'], token: 'tok_abc', + }).success).toBe(true); + expect(RealtimeConnectResponseSchema.safeParse({ + connectionId: 'conn_1', transport: 'websocket', url: 'wss://rt.example.com', + }).success).toBe(true); + expect(RealtimeSubscribeRequestSchema.safeParse({ + channel: 'project.updates', events: ['record.created', 'record.updated'], + }).success).toBe(true); + expect(RealtimeSubscribeResponseSchema.safeParse({ + subscriptionId: 'sub_1', channel: 'project.updates', + }).success).toBe(true); + expect(SetPresenceRequestSchema.safeParse({ + channel: 'project.updates', + state: { userId: 'u1', status: 'online', lastSeen: '2024-01-15T10:00:00Z' }, + }).success).toBe(true); + expect(GetPresenceResponseSchema.safeParse({ + channel: 'project.updates', + members: [{ userId: 'u1', status: 'online', lastSeen: '2024-01-15T10:00:00Z' }], + }).success).toBe(true); + }); + + it('validates Notification operations', () => { + expect(RegisterDeviceRequestSchema.safeParse({ + token: 'fcm_token_xyz', platform: 'android', deviceId: 'dev_1', name: 'Pixel 8', + }).success).toBe(true); + expect(RegisterDeviceResponseSchema.safeParse({ deviceId: 'dev_1', success: true }).success).toBe(true); + expect(NotificationPreferencesSchema.safeParse({ + email: true, push: true, inApp: true, digest: 'daily', + channels: { alerts: { enabled: true, push: false } }, + }).success).toBe(true); + expect(NotificationSchema.safeParse({ + id: 'n1', type: 'task_assigned', title: 'New Task', body: 'You were assigned a task', + read: false, actionUrl: '/tasks/t1', createdAt: '2024-01-15T10:00:00Z', + }).success).toBe(true); + expect(ListNotificationsRequestSchema.safeParse({ read: false, limit: 10 }).success).toBe(true); + expect(ListNotificationsResponseSchema.safeParse({ + notifications: [{ id: 'n1', type: 'info', title: 'Hi', body: 'Hello', read: false, createdAt: '2024-01-15T10:00:00Z' }], + unreadCount: 1, + }).success).toBe(true); + expect(MarkNotificationsReadRequestSchema.safeParse({ ids: ['n1', 'n2'] }).success).toBe(true); + }); + + it('validates AI operations', () => { + expect(AiNlqRequestSchema.safeParse({ query: 'show me all open tasks', object: 'task' }).success).toBe(true); + expect(AiNlqResponseSchema.safeParse({ + query: { object: 'task', where: { status: 'open' } }, + explanation: 'Find all tasks with open status', confidence: 0.92, + }).success).toBe(true); + expect(AiChatRequestSchema.safeParse({ message: 'How many tasks are overdue?', conversationId: 'c1' }).success).toBe(true); + expect(AiChatResponseSchema.safeParse({ + message: 'There are 5 overdue tasks.', conversationId: 'c1', + actions: [{ type: 'navigate', label: 'View overdue tasks' }], + }).success).toBe(true); + expect(AiSuggestRequestSchema.safeParse({ object: 'task', field: 'priority', partial: 'hi' }).success).toBe(true); + expect(AiSuggestResponseSchema.safeParse({ + suggestions: [{ value: 'high', label: 'High', confidence: 0.95, reason: 'Matches partial input' }], + }).success).toBe(true); + expect(AiInsightsRequestSchema.safeParse({ object: 'task', type: 'trends' }).success).toBe(true); + expect(AiInsightsResponseSchema.safeParse({ + insights: [{ type: 'trends', title: 'Task Completion Rate', description: 'Completion rate increased by 15% this month', confidence: 0.88 }], + }).success).toBe(true); + }); + + it('validates i18n operations', () => { + expect(GetLocalesResponseSchema.safeParse({ + locales: [ + { code: 'en-US', label: 'English (US)', isDefault: true }, + { code: 'es-ES', label: 'Spanish (Spain)' }, + ], + }).success).toBe(true); + expect(GetTranslationsRequestSchema.safeParse({ locale: 'en-US', namespace: 'objects' }).success).toBe(true); + expect(GetTranslationsResponseSchema.safeParse({ + locale: 'en-US', + translations: { objects: { task: { label: 'Task', pluralLabel: 'Tasks' } }, messages: { save: 'Save' } }, + }).success).toBe(true); + expect(GetFieldLabelsRequestSchema.safeParse({ object: 'task', locale: 'en-US' }).success).toBe(true); + expect(GetFieldLabelsResponseSchema.safeParse({ + object: 'task', locale: 'en-US', + labels: { status: { label: 'Status', help: 'Current task status', options: { open: 'Open', closed: 'Closed' } } }, + }).success).toBe(true); + }); + });