diff --git a/public/connect/schemas/catalog.json b/public/connect/schemas/catalog.json index f5a1c9d..3da4280 100644 --- a/public/connect/schemas/catalog.json +++ b/public/connect/schemas/catalog.json @@ -3,6 +3,7 @@ "schemas": { "app_manifest": "./mdbase-app.schema.json", "data_contract": "./data-contract.schema.json", + "event_action_interop": "./interop/v0.1/profile.schema.json", "connect_protocol": "./connect-protocol.v1.schema.json", "encrypted_relay": "./encrypted-relay.v1.schema.json", "notification_webhook": "./notification-webhook.v1.schema.json", diff --git a/public/connect/schemas/connect-protocol.v1.schema.json b/public/connect/schemas/connect-protocol.v1.schema.json index 2adc64c..13fec59 100644 --- a/public/connect/schemas/connect-protocol.v1.schema.json +++ b/public/connect/schemas/connect-protocol.v1.schema.json @@ -429,8 +429,9 @@ "collectionContract": { "type": "object", "additionalProperties": false, - "required": ["id", "version", "digest", "schema", "implementations"], + "required": ["contract_type", "id", "version", "digest", "schema", "implementations"], "properties": { + "contract_type": { "const": "record" }, "id": { "type": "string", "minLength": 1 }, "version": { "$ref": "#/$defs/semanticVersion" }, "digest": { "$ref": "#/$defs/digest" }, diff --git a/public/connect/schemas/data-contract.schema.json b/public/connect/schemas/data-contract.schema.json index f8da60b..d20a200 100644 --- a/public/connect/schemas/data-contract.schema.json +++ b/public/connect/schemas/data-contract.schema.json @@ -1,21 +1,107 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://mdbase.dev/schemas/v0.3/data-contract.schema.json", - "title": "mdbase v0.3 data contract frontmatter", + "title": "mdbase v0.3 contract frontmatter", "type": "object", - "required": ["kind", "id", "version", "schema"], + "required": ["kind", "contract_type", "id", "version"], "properties": { - "kind": { "const": "mdbase.contract" }, - "id": { "$ref": "#/$defs/contractId" }, - "version": { "$ref": "#/$defs/semanticVersion" }, - "name": { "type": "string", "minLength": 1 }, - "description": { "type": "string" }, - "schema": { "$ref": "#/$defs/schemaWrapper" }, - "binding_schema": { "$ref": "#/$defs/schemaWrapper" } + "kind": { + "const": "mdbase.contract" + }, + "contract_type": { + "enum": ["record", "event", "action"] + }, + "id": { + "$ref": "#/$defs/contractId" + }, + "version": { + "$ref": "#/$defs/semanticVersion" + }, + "name": { + "type": "string", + "minLength": 1 + }, + "description": { + "type": "string" + }, + "record_schema": { + "$ref": "#/$defs/schemaWrapper" + }, + "binding_schema": { + "$ref": "#/$defs/schemaWrapper" + }, + "data_schema": { + "$ref": "#/$defs/schemaWrapper" + }, + "source_schema": { + "$ref": "#/$defs/schemaWrapper" + }, + "input_schema": { + "$ref": "#/$defs/schemaWrapper" + }, + "output_schema": { + "$ref": "#/$defs/schemaWrapper" + }, + "error_schema": { + "$ref": "#/$defs/schemaWrapper" + }, + "provider_schema": { + "$ref": "#/$defs/schemaWrapper" + }, + "behavior": { + "$ref": "#/$defs/actionBehavior" + } }, "patternProperties": { "^x-[A-Za-z][A-Za-z0-9._:-]{0,127}$": true }, + "oneOf": [ + { + "properties": { + "contract_type": { "const": "record" }, + "record_schema": true, + "binding_schema": true, + "data_schema": false, + "source_schema": false, + "input_schema": false, + "output_schema": false, + "error_schema": false, + "provider_schema": false, + "behavior": false + }, + "required": ["record_schema"] + }, + { + "properties": { + "contract_type": { "const": "event" }, + "record_schema": false, + "binding_schema": false, + "data_schema": true, + "source_schema": true, + "input_schema": false, + "output_schema": false, + "error_schema": false, + "provider_schema": false, + "behavior": false + }, + "required": ["data_schema"] + }, + { + "properties": { + "contract_type": { "const": "action" }, + "record_schema": false, + "binding_schema": false, + "data_schema": false, + "source_schema": false, + "input_schema": true, + "output_schema": true, + "error_schema": true, + "provider_schema": true, + "behavior": true + }, + "required": ["input_schema"] + } + ], "additionalProperties": false, "$defs": { "contractId": { @@ -32,9 +118,16 @@ "type": "object", "required": ["dialect"], "properties": { - "dialect": { "const": "json-schema-2020-12" }, - "value": { "type": "object" }, - "ref": { "type": "string", "minLength": 1 } + "dialect": { + "const": "json-schema-2020-12" + }, + "value": { + "type": "object" + }, + "ref": { + "type": "string", + "minLength": 1 + } }, "oneOf": [ { @@ -53,6 +146,18 @@ } ], "additionalProperties": false + }, + "actionBehavior": { + "type": "object", + "properties": { + "idempotency": { + "enum": ["none", "optional", "required"] + }, + "cancellation": { + "enum": ["none", "cooperative"] + } + }, + "additionalProperties": false } } } diff --git a/public/connect/schemas/interop/v0.1/action-cancellation.schema.json b/public/connect/schemas/interop/v0.1/action-cancellation.schema.json new file mode 100644 index 0000000..d195904 --- /dev/null +++ b/public/connect/schemas/interop/v0.1/action-cancellation.schema.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://mdbase.dev/schemas/interop/v0.1/action-cancellation.schema.json", + "title": "mdbase action cancellation request", + "$ref": "profile.schema.json#/$defs/actionCancellation" +} diff --git a/public/connect/schemas/interop/v0.1/action-invocation.schema.json b/public/connect/schemas/interop/v0.1/action-invocation.schema.json new file mode 100644 index 0000000..748c3b5 --- /dev/null +++ b/public/connect/schemas/interop/v0.1/action-invocation.schema.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://mdbase.dev/schemas/interop/v0.1/action-invocation.schema.json", + "title": "mdbase admitted action invocation", + "$ref": "profile.schema.json#/$defs/actionInvocation" +} diff --git a/public/connect/schemas/interop/v0.1/action-outcome.schema.json b/public/connect/schemas/interop/v0.1/action-outcome.schema.json new file mode 100644 index 0000000..6c8248d --- /dev/null +++ b/public/connect/schemas/interop/v0.1/action-outcome.schema.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://mdbase.dev/schemas/interop/v0.1/action-outcome.schema.json", + "title": "mdbase action outcome", + "$ref": "profile.schema.json#/$defs/actionOutcome" +} diff --git a/public/connect/schemas/interop/v0.1/action-provider-declaration.schema.json b/public/connect/schemas/interop/v0.1/action-provider-declaration.schema.json new file mode 100644 index 0000000..19beaf5 --- /dev/null +++ b/public/connect/schemas/interop/v0.1/action-provider-declaration.schema.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://mdbase.dev/schemas/interop/v0.1/action-provider-declaration.schema.json", + "title": "mdbase action-provider declaration", + "$ref": "profile.schema.json#/$defs/actionProviderDeclaration" +} diff --git a/public/connect/schemas/interop/v0.1/action-request.schema.json b/public/connect/schemas/interop/v0.1/action-request.schema.json new file mode 100644 index 0000000..28a95e9 --- /dev/null +++ b/public/connect/schemas/interop/v0.1/action-request.schema.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://mdbase.dev/schemas/interop/v0.1/action-request.schema.json", + "title": "mdbase action request", + "$ref": "profile.schema.json#/$defs/actionRequest" +} diff --git a/public/connect/schemas/interop/v0.1/conformance-claim.schema.json b/public/connect/schemas/interop/v0.1/conformance-claim.schema.json new file mode 100644 index 0000000..7625af1 --- /dev/null +++ b/public/connect/schemas/interop/v0.1/conformance-claim.schema.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://mdbase.dev/schemas/interop/v0.1/conformance-claim.schema.json", + "title": "mdbase interoperability conformance claim", + "$ref": "profile.schema.json#/$defs/conformanceClaim" +} diff --git a/public/connect/schemas/interop/v0.1/event-source-declaration.schema.json b/public/connect/schemas/interop/v0.1/event-source-declaration.schema.json new file mode 100644 index 0000000..4f11f93 --- /dev/null +++ b/public/connect/schemas/interop/v0.1/event-source-declaration.schema.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://mdbase.dev/schemas/interop/v0.1/event-source-declaration.schema.json", + "title": "mdbase event-source declaration", + "$ref": "profile.schema.json#/$defs/eventSourceDeclaration" +} diff --git a/public/connect/schemas/interop/v0.1/event.schema.json b/public/connect/schemas/interop/v0.1/event.schema.json new file mode 100644 index 0000000..e66cd0e --- /dev/null +++ b/public/connect/schemas/interop/v0.1/event.schema.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://mdbase.dev/schemas/interop/v0.1/event.schema.json", + "title": "mdbase CloudEvents event envelope", + "$ref": "profile.schema.json#/$defs/event" +} diff --git a/public/connect/schemas/interop/v0.1/profile.schema.json b/public/connect/schemas/interop/v0.1/profile.schema.json new file mode 100644 index 0000000..4ba0146 --- /dev/null +++ b/public/connect/schemas/interop/v0.1/profile.schema.json @@ -0,0 +1,456 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://mdbase.dev/schemas/interop/v0.1/profile.schema.json", + "title": "mdbase event and action interoperability profile 0.1", + "oneOf": [ + { "$ref": "#/$defs/event" }, + { "$ref": "#/$defs/actionRequest" }, + { "$ref": "#/$defs/actionInvocation" }, + { "$ref": "#/$defs/actionOutcome" }, + { "$ref": "#/$defs/actionCancellation" }, + { "$ref": "#/$defs/eventSourceDeclaration" }, + { "$ref": "#/$defs/actionProviderDeclaration" }, + { "$ref": "#/$defs/conformanceClaim" } + ], + "$defs": { + "contractId": { + "type": "string", + "minLength": 3, + "maxLength": 128, + "pattern": "^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)+$" + }, + "semanticVersion": { + "type": "string", + "pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(?:-[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$" + }, + "semanticVersionRequirement": { + "type": "string", + "minLength": 1, + "maxLength": 128 + }, + "digest": { + "type": "string", + "pattern": "^sha256:[0-9a-f]{64}$" + }, + "portableId": { + "type": "string", + "minLength": 1, + "maxLength": 256, + "pattern": "^[A-Za-z0-9][A-Za-z0-9._:@/-]*$" + }, + "exactContract": { + "type": "object", + "required": ["id", "version", "digest"], + "properties": { + "id": { "$ref": "#/$defs/contractId" }, + "version": { "$ref": "#/$defs/semanticVersion" }, + "digest": { "$ref": "#/$defs/digest" } + }, + "additionalProperties": false + }, + "contractRequirement": { + "type": "object", + "required": ["id", "version"], + "properties": { + "id": { "$ref": "#/$defs/contractId" }, + "version": { "$ref": "#/$defs/semanticVersionRequirement" }, + "digest": { "$ref": "#/$defs/digest" } + }, + "additionalProperties": false + }, + "implementationIdentity": { + "type": "object", + "required": ["application", "implementation", "version"], + "properties": { + "application": { "$ref": "#/$defs/portableId" }, + "implementation": { "$ref": "#/$defs/portableId" }, + "version": { "$ref": "#/$defs/semanticVersion" }, + "instance_id": { "$ref": "#/$defs/portableId" } + }, + "additionalProperties": false + }, + "transportCapabilities": { + "type": "object", + "required": ["delivery", "ordering", "cancellation", "deadlines"], + "properties": { + "delivery": { + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "enum": ["ephemeral", "at_least_once", "durable_cursor", "offline_queue"] + } + }, + "ordering": { + "type": "array", + "uniqueItems": true, + "items": { + "enum": ["none", "source", "subject"] + } + }, + "cancellation": { "type": "boolean" }, + "deadlines": { "type": "boolean" }, + "provider_discovery": { "type": "boolean" }, + "max_payload_bytes": { "type": "integer", "minimum": 1 }, + "outcome_retention_seconds": { "type": "integer", "minimum": 0 }, + "request_deduplication": { "type": "boolean" }, + "cross_process_identity": { "type": "boolean" } + }, + "additionalProperties": false + }, + "extensionValue": { + "oneOf": [ + { "type": "null" }, + { "type": "boolean" }, + { "type": "integer" }, + { "type": "number" }, + { "type": "string" } + ] + }, + "event": { + "title": "mdbase CloudEvents event envelope", + "type": "object", + "required": [ + "specversion", + "id", + "source", + "type", + "time", + "datacontenttype", + "dataschema", + "data", + "mdbaseprofile", + "mdbasecontractversion", + "mdbasecontractdigest", + "mdbaseapplication", + "mdbaseimplementation", + "mdbaseimplementationversion" + ], + "properties": { + "specversion": { "const": "1.0" }, + "id": { "$ref": "#/$defs/portableId" }, + "source": { "type": "string", "format": "uri-reference", "minLength": 1 }, + "type": { "$ref": "#/$defs/contractId" }, + "time": { "type": "string", "format": "date-time" }, + "subject": { "type": "string", "format": "uri-reference", "minLength": 1 }, + "datacontenttype": { "const": "application/json" }, + "dataschema": { "type": "string", "format": "uri", "minLength": 1 }, + "data": true, + "mdbaseprofile": { "const": "0.1" }, + "mdbasecontractversion": { "$ref": "#/$defs/semanticVersion" }, + "mdbasecontractdigest": { "$ref": "#/$defs/digest" }, + "mdbaseapplication": { "$ref": "#/$defs/portableId" }, + "mdbaseimplementation": { "$ref": "#/$defs/portableId" }, + "mdbaseimplementationversion": { "$ref": "#/$defs/semanticVersion" }, + "mdbaseinstanceid": { "$ref": "#/$defs/portableId" }, + "correlationid": { "$ref": "#/$defs/portableId" }, + "causationid": { "$ref": "#/$defs/portableId" } + }, + "propertyNames": { "pattern": "^[a-z0-9]+$" }, + "additionalProperties": { "$ref": "#/$defs/extensionValue" } + }, + "actionRequest": { + "title": "mdbase action request", + "type": "object", + "required": [ + "kind", + "profile_version", + "request_id", + "contract", + "caller", + "created_at", + "input" + ], + "properties": { + "kind": { "const": "mdbase.action.request" }, + "profile_version": { "const": "0.1" }, + "request_id": { "$ref": "#/$defs/portableId" }, + "contract": { "$ref": "#/$defs/contractRequirement" }, + "caller": { "$ref": "#/$defs/implementationIdentity" }, + "created_at": { "type": "string", "format": "date-time" }, + "correlation_id": { "$ref": "#/$defs/portableId" }, + "causation_id": { "$ref": "#/$defs/portableId" }, + "subject": { "type": "string", "format": "uri-reference", "minLength": 1 }, + "idempotency_key": { "type": "string", "minLength": 1, "maxLength": 512 }, + "deadline": { "type": "string", "format": "date-time" }, + "requested_provider": { + "type": "object", + "properties": { + "application": { "$ref": "#/$defs/portableId" }, + "implementation": { "$ref": "#/$defs/portableId" }, + "instance_id": { "$ref": "#/$defs/portableId" } + }, + "minProperties": 1, + "additionalProperties": false + }, + "authorization_context": { + "type": "string", + "format": "uri-reference", + "minLength": 1 + }, + "input": true + }, + "additionalProperties": false + }, + "actionInvocation": { + "title": "mdbase admitted action invocation", + "type": "object", + "required": [ + "kind", + "profile_version", + "invocation_id", + "attempt_id", + "request_id", + "contract", + "caller", + "provider", + "provider_declaration_digest", + "handler_id", + "admitted_at", + "input" + ], + "properties": { + "kind": { "const": "mdbase.action.invocation" }, + "profile_version": { "const": "0.1" }, + "invocation_id": { "$ref": "#/$defs/portableId" }, + "attempt_id": { "$ref": "#/$defs/portableId" }, + "request_id": { "$ref": "#/$defs/portableId" }, + "contract": { "$ref": "#/$defs/exactContract" }, + "caller": { "$ref": "#/$defs/implementationIdentity" }, + "provider": { "$ref": "#/$defs/implementationIdentity" }, + "provider_declaration_digest": { "$ref": "#/$defs/digest" }, + "handler_id": { "$ref": "#/$defs/portableId" }, + "admitted_at": { "type": "string", "format": "date-time" }, + "correlation_id": { "$ref": "#/$defs/portableId" }, + "causation_id": { "$ref": "#/$defs/portableId" }, + "subject": { "type": "string", "format": "uri-reference", "minLength": 1 }, + "idempotency_key": { "type": "string", "minLength": 1, "maxLength": 512 }, + "deadline": { "type": "string", "format": "date-time" }, + "authorization_context": { + "type": "string", + "format": "uri-reference", + "minLength": 1 + }, + "input": true + }, + "additionalProperties": false + }, + "portableError": { + "type": "object", + "required": ["code", "message"], + "properties": { + "code": { + "enum": [ + "unknown_contract", + "unsupported_contract_version", + "contract_digest_conflict", + "invalid_event_data", + "invalid_action_input", + "invalid_action_output", + "no_provider", + "ambiguous_provider", + "requested_provider_unavailable", + "unauthorized", + "capability_denied", + "request_rejected", + "deadline_exceeded", + "cancellation_unsupported", + "cancelled", + "handler_failure", + "outcome_indeterminate", + "transport_unavailable", + "unsupported_transport_capability" + ] + }, + "message": { "type": "string", "minLength": 1 }, + "details": true, + "retryable": { "type": "boolean" } + }, + "additionalProperties": false + }, + "actionOutcome": { + "title": "mdbase action outcome", + "type": "object", + "required": [ + "kind", + "profile_version", + "outcome_id", + "request_id", + "invocation_id", + "attempt_id", + "contract", + "provider", + "provider_declaration_digest", + "status", + "completed_at" + ], + "properties": { + "kind": { "const": "mdbase.action.outcome" }, + "profile_version": { "const": "0.1" }, + "outcome_id": { "$ref": "#/$defs/portableId" }, + "request_id": { "$ref": "#/$defs/portableId" }, + "invocation_id": { "$ref": "#/$defs/portableId" }, + "attempt_id": { "$ref": "#/$defs/portableId" }, + "contract": { "$ref": "#/$defs/exactContract" }, + "provider": { "$ref": "#/$defs/implementationIdentity" }, + "provider_declaration_digest": { "$ref": "#/$defs/digest" }, + "status": { + "enum": ["succeeded", "rejected", "failed", "cancelled", "outcome_indeterminate"] + }, + "completed_at": { "type": "string", "format": "date-time" }, + "output": true, + "error": { "$ref": "#/$defs/portableError" } + }, + "allOf": [ + { + "if": { + "properties": { "status": { "const": "succeeded" } }, + "required": ["status"] + }, + "then": { + "required": ["output"], + "not": { "required": ["error"] } + }, + "else": { + "required": ["error"], + "not": { "required": ["output"] } + } + } + ], + "additionalProperties": false + }, + "actionCancellation": { + "title": "mdbase action cancellation request", + "type": "object", + "required": ["kind", "profile_version", "cancellation_id", "request_id", "caller", "requested_at"], + "properties": { + "kind": { "const": "mdbase.action.cancel" }, + "profile_version": { "const": "0.1" }, + "cancellation_id": { "$ref": "#/$defs/portableId" }, + "request_id": { "$ref": "#/$defs/portableId" }, + "caller": { "$ref": "#/$defs/implementationIdentity" }, + "requested_at": { "type": "string", "format": "date-time" }, + "reason": { "type": "string", "maxLength": 1024 } + }, + "additionalProperties": false + }, + "eventSourceDeclaration": { + "title": "mdbase event-source declaration", + "type": "object", + "required": [ + "kind", + "profile_version", + "declaration_id", + "declaration_digest", + "source", + "contracts" + ], + "properties": { + "kind": { "const": "mdbase.event-source" }, + "profile_version": { "const": "0.1" }, + "declaration_id": { "$ref": "#/$defs/portableId" }, + "declaration_digest": { "$ref": "#/$defs/digest" }, + "source": { "$ref": "#/$defs/implementationIdentity" }, + "contracts": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "required": ["requirement", "resolved"], + "properties": { + "requirement": { "$ref": "#/$defs/contractRequirement" }, + "resolved": { "$ref": "#/$defs/exactContract" }, + "binding": true, + "ordering": { + "type": "array", + "uniqueItems": true, + "items": { "enum": ["none", "source", "subject"] } + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + }, + "actionProviderDeclaration": { + "title": "mdbase action-provider declaration", + "type": "object", + "required": [ + "kind", + "profile_version", + "declaration_id", + "declaration_digest", + "provider", + "handlers" + ], + "properties": { + "kind": { "const": "mdbase.action-provider" }, + "profile_version": { "const": "0.1" }, + "declaration_id": { "$ref": "#/$defs/portableId" }, + "declaration_digest": { "$ref": "#/$defs/digest" }, + "provider": { "$ref": "#/$defs/implementationIdentity" }, + "handlers": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "required": ["handler_id", "requirement", "resolved"], + "properties": { + "handler_id": { "$ref": "#/$defs/portableId" }, + "requirement": { "$ref": "#/$defs/contractRequirement" }, + "resolved": { "$ref": "#/$defs/exactContract" }, + "binding": true, + "idempotency": { + "type": "object", + "required": ["mode"], + "properties": { + "mode": { "enum": ["none", "request"] }, + "retention_seconds": { "type": "integer", "minimum": 1 } + }, + "additionalProperties": false + }, + "cancellation": { "enum": ["none", "cooperative"] }, + "max_concurrency": { "type": "integer", "minimum": 1 } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + }, + "conformanceClaim": { + "title": "mdbase interoperability conformance claim", + "type": "object", + "required": ["kind", "profile_version", "implementation", "roles", "transport"], + "properties": { + "kind": { "const": "mdbase.interop.conformance" }, + "profile_version": { "const": "0.1" }, + "implementation": { "$ref": "#/$defs/implementationIdentity" }, + "roles": { + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "enum": ["event_source", "event_consumer", "action_caller", "action_provider", "bridge"] + } + }, + "transport": { "$ref": "#/$defs/transportCapabilities" }, + "evidence": { + "type": "array", + "items": { + "type": "object", + "required": ["scenario", "result"], + "properties": { + "scenario": { "type": "string", "minLength": 1 }, + "result": { "const": "pass" }, + "uri": { "type": "string", "format": "uri-reference" } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + } +} diff --git a/public/connect/schemas/sync.v1.schema.json b/public/connect/schemas/sync.v1.schema.json index 436b121..a845a45 100644 --- a/public/connect/schemas/sync.v1.schema.json +++ b/public/connect/schemas/sync.v1.schema.json @@ -36,8 +36,9 @@ "contract": { "type": "object", "additionalProperties": false, - "required": ["id", "version", "digest", "schema", "implementations"], + "required": ["contract_type", "id", "version", "digest", "schema", "implementations"], "properties": { + "contract_type": { "const": "record" }, "id": { "type": "string", "minLength": 1 }, "version": { "$ref": "#/$defs/semanticVersion" }, "digest": { "$ref": "#/$defs/digest" }, diff --git a/public/interop/schemas/v0.1/README.md b/public/interop/schemas/v0.1/README.md new file mode 100644 index 0000000..0626941 --- /dev/null +++ b/public/interop/schemas/v0.1/README.md @@ -0,0 +1,9 @@ +# Interoperability profile schemas + +These schemas define mdbase event/action interoperability profile `0.1`. +`profile.schema.json` contains the shared definitions and complete envelope +union. The smaller files are stable entry points for one envelope or +declaration. + +Implementations preload the profile schema before compiling an entry-point +schema. They never fetch schema references from the network. diff --git a/public/interop/schemas/v0.1/action-cancellation.schema.json b/public/interop/schemas/v0.1/action-cancellation.schema.json new file mode 100644 index 0000000..d195904 --- /dev/null +++ b/public/interop/schemas/v0.1/action-cancellation.schema.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://mdbase.dev/schemas/interop/v0.1/action-cancellation.schema.json", + "title": "mdbase action cancellation request", + "$ref": "profile.schema.json#/$defs/actionCancellation" +} diff --git a/public/interop/schemas/v0.1/action-invocation.schema.json b/public/interop/schemas/v0.1/action-invocation.schema.json new file mode 100644 index 0000000..748c3b5 --- /dev/null +++ b/public/interop/schemas/v0.1/action-invocation.schema.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://mdbase.dev/schemas/interop/v0.1/action-invocation.schema.json", + "title": "mdbase admitted action invocation", + "$ref": "profile.schema.json#/$defs/actionInvocation" +} diff --git a/public/interop/schemas/v0.1/action-outcome.schema.json b/public/interop/schemas/v0.1/action-outcome.schema.json new file mode 100644 index 0000000..6c8248d --- /dev/null +++ b/public/interop/schemas/v0.1/action-outcome.schema.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://mdbase.dev/schemas/interop/v0.1/action-outcome.schema.json", + "title": "mdbase action outcome", + "$ref": "profile.schema.json#/$defs/actionOutcome" +} diff --git a/public/interop/schemas/v0.1/action-provider-declaration.schema.json b/public/interop/schemas/v0.1/action-provider-declaration.schema.json new file mode 100644 index 0000000..19beaf5 --- /dev/null +++ b/public/interop/schemas/v0.1/action-provider-declaration.schema.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://mdbase.dev/schemas/interop/v0.1/action-provider-declaration.schema.json", + "title": "mdbase action-provider declaration", + "$ref": "profile.schema.json#/$defs/actionProviderDeclaration" +} diff --git a/public/interop/schemas/v0.1/action-request.schema.json b/public/interop/schemas/v0.1/action-request.schema.json new file mode 100644 index 0000000..28a95e9 --- /dev/null +++ b/public/interop/schemas/v0.1/action-request.schema.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://mdbase.dev/schemas/interop/v0.1/action-request.schema.json", + "title": "mdbase action request", + "$ref": "profile.schema.json#/$defs/actionRequest" +} diff --git a/public/interop/schemas/v0.1/conformance-claim.schema.json b/public/interop/schemas/v0.1/conformance-claim.schema.json new file mode 100644 index 0000000..7625af1 --- /dev/null +++ b/public/interop/schemas/v0.1/conformance-claim.schema.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://mdbase.dev/schemas/interop/v0.1/conformance-claim.schema.json", + "title": "mdbase interoperability conformance claim", + "$ref": "profile.schema.json#/$defs/conformanceClaim" +} diff --git a/public/interop/schemas/v0.1/event-source-declaration.schema.json b/public/interop/schemas/v0.1/event-source-declaration.schema.json new file mode 100644 index 0000000..4f11f93 --- /dev/null +++ b/public/interop/schemas/v0.1/event-source-declaration.schema.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://mdbase.dev/schemas/interop/v0.1/event-source-declaration.schema.json", + "title": "mdbase event-source declaration", + "$ref": "profile.schema.json#/$defs/eventSourceDeclaration" +} diff --git a/public/interop/schemas/v0.1/event.schema.json b/public/interop/schemas/v0.1/event.schema.json new file mode 100644 index 0000000..e66cd0e --- /dev/null +++ b/public/interop/schemas/v0.1/event.schema.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://mdbase.dev/schemas/interop/v0.1/event.schema.json", + "title": "mdbase CloudEvents event envelope", + "$ref": "profile.schema.json#/$defs/event" +} diff --git a/public/interop/schemas/v0.1/profile.schema.json b/public/interop/schemas/v0.1/profile.schema.json new file mode 100644 index 0000000..4ba0146 --- /dev/null +++ b/public/interop/schemas/v0.1/profile.schema.json @@ -0,0 +1,456 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://mdbase.dev/schemas/interop/v0.1/profile.schema.json", + "title": "mdbase event and action interoperability profile 0.1", + "oneOf": [ + { "$ref": "#/$defs/event" }, + { "$ref": "#/$defs/actionRequest" }, + { "$ref": "#/$defs/actionInvocation" }, + { "$ref": "#/$defs/actionOutcome" }, + { "$ref": "#/$defs/actionCancellation" }, + { "$ref": "#/$defs/eventSourceDeclaration" }, + { "$ref": "#/$defs/actionProviderDeclaration" }, + { "$ref": "#/$defs/conformanceClaim" } + ], + "$defs": { + "contractId": { + "type": "string", + "minLength": 3, + "maxLength": 128, + "pattern": "^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)+$" + }, + "semanticVersion": { + "type": "string", + "pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(?:-[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$" + }, + "semanticVersionRequirement": { + "type": "string", + "minLength": 1, + "maxLength": 128 + }, + "digest": { + "type": "string", + "pattern": "^sha256:[0-9a-f]{64}$" + }, + "portableId": { + "type": "string", + "minLength": 1, + "maxLength": 256, + "pattern": "^[A-Za-z0-9][A-Za-z0-9._:@/-]*$" + }, + "exactContract": { + "type": "object", + "required": ["id", "version", "digest"], + "properties": { + "id": { "$ref": "#/$defs/contractId" }, + "version": { "$ref": "#/$defs/semanticVersion" }, + "digest": { "$ref": "#/$defs/digest" } + }, + "additionalProperties": false + }, + "contractRequirement": { + "type": "object", + "required": ["id", "version"], + "properties": { + "id": { "$ref": "#/$defs/contractId" }, + "version": { "$ref": "#/$defs/semanticVersionRequirement" }, + "digest": { "$ref": "#/$defs/digest" } + }, + "additionalProperties": false + }, + "implementationIdentity": { + "type": "object", + "required": ["application", "implementation", "version"], + "properties": { + "application": { "$ref": "#/$defs/portableId" }, + "implementation": { "$ref": "#/$defs/portableId" }, + "version": { "$ref": "#/$defs/semanticVersion" }, + "instance_id": { "$ref": "#/$defs/portableId" } + }, + "additionalProperties": false + }, + "transportCapabilities": { + "type": "object", + "required": ["delivery", "ordering", "cancellation", "deadlines"], + "properties": { + "delivery": { + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "enum": ["ephemeral", "at_least_once", "durable_cursor", "offline_queue"] + } + }, + "ordering": { + "type": "array", + "uniqueItems": true, + "items": { + "enum": ["none", "source", "subject"] + } + }, + "cancellation": { "type": "boolean" }, + "deadlines": { "type": "boolean" }, + "provider_discovery": { "type": "boolean" }, + "max_payload_bytes": { "type": "integer", "minimum": 1 }, + "outcome_retention_seconds": { "type": "integer", "minimum": 0 }, + "request_deduplication": { "type": "boolean" }, + "cross_process_identity": { "type": "boolean" } + }, + "additionalProperties": false + }, + "extensionValue": { + "oneOf": [ + { "type": "null" }, + { "type": "boolean" }, + { "type": "integer" }, + { "type": "number" }, + { "type": "string" } + ] + }, + "event": { + "title": "mdbase CloudEvents event envelope", + "type": "object", + "required": [ + "specversion", + "id", + "source", + "type", + "time", + "datacontenttype", + "dataschema", + "data", + "mdbaseprofile", + "mdbasecontractversion", + "mdbasecontractdigest", + "mdbaseapplication", + "mdbaseimplementation", + "mdbaseimplementationversion" + ], + "properties": { + "specversion": { "const": "1.0" }, + "id": { "$ref": "#/$defs/portableId" }, + "source": { "type": "string", "format": "uri-reference", "minLength": 1 }, + "type": { "$ref": "#/$defs/contractId" }, + "time": { "type": "string", "format": "date-time" }, + "subject": { "type": "string", "format": "uri-reference", "minLength": 1 }, + "datacontenttype": { "const": "application/json" }, + "dataschema": { "type": "string", "format": "uri", "minLength": 1 }, + "data": true, + "mdbaseprofile": { "const": "0.1" }, + "mdbasecontractversion": { "$ref": "#/$defs/semanticVersion" }, + "mdbasecontractdigest": { "$ref": "#/$defs/digest" }, + "mdbaseapplication": { "$ref": "#/$defs/portableId" }, + "mdbaseimplementation": { "$ref": "#/$defs/portableId" }, + "mdbaseimplementationversion": { "$ref": "#/$defs/semanticVersion" }, + "mdbaseinstanceid": { "$ref": "#/$defs/portableId" }, + "correlationid": { "$ref": "#/$defs/portableId" }, + "causationid": { "$ref": "#/$defs/portableId" } + }, + "propertyNames": { "pattern": "^[a-z0-9]+$" }, + "additionalProperties": { "$ref": "#/$defs/extensionValue" } + }, + "actionRequest": { + "title": "mdbase action request", + "type": "object", + "required": [ + "kind", + "profile_version", + "request_id", + "contract", + "caller", + "created_at", + "input" + ], + "properties": { + "kind": { "const": "mdbase.action.request" }, + "profile_version": { "const": "0.1" }, + "request_id": { "$ref": "#/$defs/portableId" }, + "contract": { "$ref": "#/$defs/contractRequirement" }, + "caller": { "$ref": "#/$defs/implementationIdentity" }, + "created_at": { "type": "string", "format": "date-time" }, + "correlation_id": { "$ref": "#/$defs/portableId" }, + "causation_id": { "$ref": "#/$defs/portableId" }, + "subject": { "type": "string", "format": "uri-reference", "minLength": 1 }, + "idempotency_key": { "type": "string", "minLength": 1, "maxLength": 512 }, + "deadline": { "type": "string", "format": "date-time" }, + "requested_provider": { + "type": "object", + "properties": { + "application": { "$ref": "#/$defs/portableId" }, + "implementation": { "$ref": "#/$defs/portableId" }, + "instance_id": { "$ref": "#/$defs/portableId" } + }, + "minProperties": 1, + "additionalProperties": false + }, + "authorization_context": { + "type": "string", + "format": "uri-reference", + "minLength": 1 + }, + "input": true + }, + "additionalProperties": false + }, + "actionInvocation": { + "title": "mdbase admitted action invocation", + "type": "object", + "required": [ + "kind", + "profile_version", + "invocation_id", + "attempt_id", + "request_id", + "contract", + "caller", + "provider", + "provider_declaration_digest", + "handler_id", + "admitted_at", + "input" + ], + "properties": { + "kind": { "const": "mdbase.action.invocation" }, + "profile_version": { "const": "0.1" }, + "invocation_id": { "$ref": "#/$defs/portableId" }, + "attempt_id": { "$ref": "#/$defs/portableId" }, + "request_id": { "$ref": "#/$defs/portableId" }, + "contract": { "$ref": "#/$defs/exactContract" }, + "caller": { "$ref": "#/$defs/implementationIdentity" }, + "provider": { "$ref": "#/$defs/implementationIdentity" }, + "provider_declaration_digest": { "$ref": "#/$defs/digest" }, + "handler_id": { "$ref": "#/$defs/portableId" }, + "admitted_at": { "type": "string", "format": "date-time" }, + "correlation_id": { "$ref": "#/$defs/portableId" }, + "causation_id": { "$ref": "#/$defs/portableId" }, + "subject": { "type": "string", "format": "uri-reference", "minLength": 1 }, + "idempotency_key": { "type": "string", "minLength": 1, "maxLength": 512 }, + "deadline": { "type": "string", "format": "date-time" }, + "authorization_context": { + "type": "string", + "format": "uri-reference", + "minLength": 1 + }, + "input": true + }, + "additionalProperties": false + }, + "portableError": { + "type": "object", + "required": ["code", "message"], + "properties": { + "code": { + "enum": [ + "unknown_contract", + "unsupported_contract_version", + "contract_digest_conflict", + "invalid_event_data", + "invalid_action_input", + "invalid_action_output", + "no_provider", + "ambiguous_provider", + "requested_provider_unavailable", + "unauthorized", + "capability_denied", + "request_rejected", + "deadline_exceeded", + "cancellation_unsupported", + "cancelled", + "handler_failure", + "outcome_indeterminate", + "transport_unavailable", + "unsupported_transport_capability" + ] + }, + "message": { "type": "string", "minLength": 1 }, + "details": true, + "retryable": { "type": "boolean" } + }, + "additionalProperties": false + }, + "actionOutcome": { + "title": "mdbase action outcome", + "type": "object", + "required": [ + "kind", + "profile_version", + "outcome_id", + "request_id", + "invocation_id", + "attempt_id", + "contract", + "provider", + "provider_declaration_digest", + "status", + "completed_at" + ], + "properties": { + "kind": { "const": "mdbase.action.outcome" }, + "profile_version": { "const": "0.1" }, + "outcome_id": { "$ref": "#/$defs/portableId" }, + "request_id": { "$ref": "#/$defs/portableId" }, + "invocation_id": { "$ref": "#/$defs/portableId" }, + "attempt_id": { "$ref": "#/$defs/portableId" }, + "contract": { "$ref": "#/$defs/exactContract" }, + "provider": { "$ref": "#/$defs/implementationIdentity" }, + "provider_declaration_digest": { "$ref": "#/$defs/digest" }, + "status": { + "enum": ["succeeded", "rejected", "failed", "cancelled", "outcome_indeterminate"] + }, + "completed_at": { "type": "string", "format": "date-time" }, + "output": true, + "error": { "$ref": "#/$defs/portableError" } + }, + "allOf": [ + { + "if": { + "properties": { "status": { "const": "succeeded" } }, + "required": ["status"] + }, + "then": { + "required": ["output"], + "not": { "required": ["error"] } + }, + "else": { + "required": ["error"], + "not": { "required": ["output"] } + } + } + ], + "additionalProperties": false + }, + "actionCancellation": { + "title": "mdbase action cancellation request", + "type": "object", + "required": ["kind", "profile_version", "cancellation_id", "request_id", "caller", "requested_at"], + "properties": { + "kind": { "const": "mdbase.action.cancel" }, + "profile_version": { "const": "0.1" }, + "cancellation_id": { "$ref": "#/$defs/portableId" }, + "request_id": { "$ref": "#/$defs/portableId" }, + "caller": { "$ref": "#/$defs/implementationIdentity" }, + "requested_at": { "type": "string", "format": "date-time" }, + "reason": { "type": "string", "maxLength": 1024 } + }, + "additionalProperties": false + }, + "eventSourceDeclaration": { + "title": "mdbase event-source declaration", + "type": "object", + "required": [ + "kind", + "profile_version", + "declaration_id", + "declaration_digest", + "source", + "contracts" + ], + "properties": { + "kind": { "const": "mdbase.event-source" }, + "profile_version": { "const": "0.1" }, + "declaration_id": { "$ref": "#/$defs/portableId" }, + "declaration_digest": { "$ref": "#/$defs/digest" }, + "source": { "$ref": "#/$defs/implementationIdentity" }, + "contracts": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "required": ["requirement", "resolved"], + "properties": { + "requirement": { "$ref": "#/$defs/contractRequirement" }, + "resolved": { "$ref": "#/$defs/exactContract" }, + "binding": true, + "ordering": { + "type": "array", + "uniqueItems": true, + "items": { "enum": ["none", "source", "subject"] } + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + }, + "actionProviderDeclaration": { + "title": "mdbase action-provider declaration", + "type": "object", + "required": [ + "kind", + "profile_version", + "declaration_id", + "declaration_digest", + "provider", + "handlers" + ], + "properties": { + "kind": { "const": "mdbase.action-provider" }, + "profile_version": { "const": "0.1" }, + "declaration_id": { "$ref": "#/$defs/portableId" }, + "declaration_digest": { "$ref": "#/$defs/digest" }, + "provider": { "$ref": "#/$defs/implementationIdentity" }, + "handlers": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "required": ["handler_id", "requirement", "resolved"], + "properties": { + "handler_id": { "$ref": "#/$defs/portableId" }, + "requirement": { "$ref": "#/$defs/contractRequirement" }, + "resolved": { "$ref": "#/$defs/exactContract" }, + "binding": true, + "idempotency": { + "type": "object", + "required": ["mode"], + "properties": { + "mode": { "enum": ["none", "request"] }, + "retention_seconds": { "type": "integer", "minimum": 1 } + }, + "additionalProperties": false + }, + "cancellation": { "enum": ["none", "cooperative"] }, + "max_concurrency": { "type": "integer", "minimum": 1 } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + }, + "conformanceClaim": { + "title": "mdbase interoperability conformance claim", + "type": "object", + "required": ["kind", "profile_version", "implementation", "roles", "transport"], + "properties": { + "kind": { "const": "mdbase.interop.conformance" }, + "profile_version": { "const": "0.1" }, + "implementation": { "$ref": "#/$defs/implementationIdentity" }, + "roles": { + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "enum": ["event_source", "event_consumer", "action_caller", "action_provider", "bridge"] + } + }, + "transport": { "$ref": "#/$defs/transportCapabilities" }, + "evidence": { + "type": "array", + "items": { + "type": "object", + "required": ["scenario", "result"], + "properties": { + "scenario": { "type": "string", "minLength": 1 }, + "result": { "const": "pass" }, + "uri": { "type": "string", "format": "uri-reference" } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + } +} diff --git a/scripts/sync-sources.mjs b/scripts/sync-sources.mjs index ccc88f5..bbbedcf 100644 --- a/scripts/sync-sources.mjs +++ b/scripts/sync-sources.mjs @@ -22,6 +22,12 @@ mkdirSync(schemaDestination, { recursive: true }); cpSync(schemaSource, schemaDestination, { recursive: true, force: true }); copyAlias("mdbase-app.schema.json", "mdbase-app.v1.json"); +const interopSchemaSource = join(specDir, "schemas", "interop", "v0.1"); +const interopSchemaDestination = join(root, "public", "interop", "schemas", "v0.1"); +required(interopSchemaSource, "mdbase interoperability schemas"); +mkdirSync(interopSchemaDestination, { recursive: true }); +cpSync(interopSchemaSource, interopSchemaDestination, { recursive: true, force: true }); + const introductionSource = join(connectDir, "docs", "mdbase-configurations-v2.html"); required(introductionSource, "Connect introduction prototype"); const introduction = readFileSync(introductionSource, "utf8"); @@ -65,34 +71,47 @@ cpSync( const manifest = yaml(join(specDir, "tests", "v0.3", "manifest.yaml")); const claims = [ - yaml(join(rustDir, "conformance", "v0.3.0-rc.1.yml")), - yaml(join(typescriptDir, "conformance", "v0.3.0-rc.2.yml")) + yaml(join(rustDir, "conformance", "v0.4.0-rc.2.yml")), + yaml(join(typescriptDir, "conformance", "v0.3.0-rc.3.yml")) ]; +const interopClaim = yaml( + join(specDir, "packages", "interop", "conformance", "v0.1.yml") +); const conformance = { generated_at: new Date().toISOString().slice(0, 10), spec_version: manifest.spec_version, - implementations: claims.map((claim) => { - const verifiedAt = claim.evidence - .map((entry) => entry.verified_at) - .filter(Boolean) - .sort() - .at(-1); - const isRust = claim.implementation.id === "mdbase-rs"; - return { - name: claim.implementation.id === "mdbase-ts" ? "mdbase" : claim.implementation.id, - language: claim.implementation.language, - version: claim.implementation.version, - repository: claim.implementation.url, - evidence_date: verifiedAt ? String(verifiedAt).slice(0, 10) : null, - profiles: claim.profiles ?? [], - optional_features: claim.optional_features ?? [], - workflow_execution: claim.limits?.runtime_execution === true, - note: isRust - ? "The current Rust claim records runtime_execution: false. workflow/0.1 will follow shared fixture evidence." - : "The claim uses the machine-readable v0.3 atomic profiles." - }; - }), + implementations: [ + ...claims.map((claim) => { + const verifiedAt = claim.evidence + .map((entry) => entry.verified_at) + .filter(Boolean) + .sort() + .at(-1); + return { + name: claim.implementation.id === "mdbase-ts" ? "mdbase" : claim.implementation.id, + language: claim.implementation.language, + version: claim.implementation.version, + repository: claim.implementation.url, + evidence_date: verifiedAt ? String(verifiedAt).slice(0, 10) : null, + profiles: claim.profiles ?? [], + optional_features: claim.optional_features ?? [], + workflow_execution: claim.limits?.runtime_execution === true, + note: "The claim uses the machine-readable v0.3 atomic profiles." + }; + }), + { + name: interopClaim.implementation.application, + language: "TypeScript", + version: interopClaim.implementation.version, + repository: "https://github.com/mdbase-dev/mdbase-spec", + evidence_date: null, + profiles: ["event_action_interop/0.1"], + optional_features: [], + workflow_execution: false, + note: `Reference ${interopClaim.transport.delivery.join(", ")} bridge; roles: ${interopClaim.roles.join(", ")}.` + } + ], coverage: { coverage_complete: manifest.claim_profiles .filter((profile) => profile.status === "coverage_complete") @@ -109,9 +128,10 @@ writeFileSync( ); console.log(`Copied Connect schemas from ${schemaSource}`); +console.log(`Copied interoperability schemas from ${interopSchemaSource}`); console.log(`Copied the homepage design and murmuration from ${introductionSource}`); console.log(`Copied shared theme values from ${connectThemeSource}`); -console.log(`Generated conformance data from ${claims.length} implementation claims`); +console.log(`Generated conformance data from ${claims.length + 1} implementation claims`); function yaml(path) { required(path, "YAML source"); diff --git a/site-sources.json b/site-sources.json index fdc65bf..d305dc8 100644 --- a/site-sources.json +++ b/site-sources.json @@ -1,11 +1,11 @@ { "specification": { "repository": "mdbase-dev/mdbase-spec", - "ref": "8180449530b5db54cde88383c3b96798596cc4b4" + "ref": "88f4d64ff2d54df23631db9d03a95eba566b4eee" }, "connect": { "repository": "mdbase-dev/mdbase-connect", - "ref": "129d136cf082317d3ea07d25b18759b9e494526d" + "ref": "81199416aa67de140778b3d81d8f6bdbdac6fba6" }, "contracts": { "repository": "mdbase-dev/mdbase-contracts", @@ -15,12 +15,12 @@ { "id": "rust", "repository": "callumalpass/mdbase-rs", - "ref": "a94c364f71cd126723baaf6d027649f0144dd182" + "ref": "323766220950371a3856d84eeb05e51ab106fd72" }, { "id": "typescript", "repository": "callumalpass/mdbase", - "ref": "b7504f9292eca1202eed6f20eea025cd917bf748" + "ref": "a45632ab51f97f55dab05ad55d4fe91bdb118183" } ] } diff --git a/src/components/SiteFooter.astro b/src/components/SiteFooter.astro index 5c9970d..8181050 100644 --- a/src/components/SiteFooter.astro +++ b/src/components/SiteFooter.astro @@ -8,6 +8,7 @@ Start here Connect SDK docs + Interoperability Runtime Contracts Implementations diff --git a/src/components/SiteHeader.astro b/src/components/SiteHeader.astro index 094eb9e..8c28c98 100644 --- a/src/components/SiteHeader.astro +++ b/src/components/SiteHeader.astro @@ -2,7 +2,7 @@ import BrandMark from "./BrandMark.astro"; interface Props { - current?: "home" | "connect" | "sdk" | "runtime" | "implementations" | "spec"; + current?: "home" | "connect" | "sdk" | "interop" | "runtime" | "implementations" | "spec"; showSceneCount?: boolean; } @@ -11,6 +11,7 @@ const links = [ { href: "/", label: "Learn", key: "home" }, { href: "/connect/", label: "Connect", key: "connect" }, { href: "/sdk/quickstart/", label: "Build", key: "sdk" }, + { href: "/interop/", label: "Interop", key: "interop" }, { href: "/implementations/", label: "Implement", key: "implementations" }, { href: "/spec/", label: "Spec", key: "spec" } ] as const; diff --git a/src/data/conformance.json b/src/data/conformance.json index 6ca643b..ede3b94 100644 --- a/src/data/conformance.json +++ b/src/data/conformance.json @@ -5,9 +5,9 @@ { "name": "mdbase-rs", "language": "Rust", - "version": "0.3.0-rc.1", + "version": "0.4.0-rc.2", "repository": "https://github.com/callumalpass/mdbase-rs", - "evidence_date": "2026-07-22", + "evidence_date": "2026-07-28", "profiles": [ "core_read", "collection_semantics", @@ -17,19 +17,16 @@ "links", "core_write", "lifecycle", - "runtime_contracts/0.1", "watch" ], - "optional_features": [ - "runtime_contract_materialization" - ], + "optional_features": [], "workflow_execution": false, - "note": "The current Rust claim records runtime_execution: false. workflow/0.1 will follow shared fixture evidence." + "note": "The claim uses the machine-readable v0.3 atomic profiles." }, { "name": "mdbase", "language": "TypeScript", - "version": "0.3.0-rc.2", + "version": "0.3.0-rc.3", "repository": "https://github.com/callumalpass/mdbase", "evidence_date": "2026-07-28", "profiles": [ @@ -40,14 +37,26 @@ "cel_query", "links", "core_write", - "lifecycle", - "runtime_contracts/0.1" + "lifecycle" ], "optional_features": [ "view_records" ], "workflow_execution": false, "note": "The claim uses the machine-readable v0.3 atomic profiles." + }, + { + "name": "mdbase-interop", + "language": "TypeScript", + "version": "0.1.0-rc.2", + "repository": "https://github.com/mdbase-dev/mdbase-spec", + "evidence_date": null, + "profiles": [ + "event_action_interop/0.1" + ], + "optional_features": [], + "workflow_execution": false, + "note": "Reference ephemeral bridge; roles: event_source, event_consumer, action_caller, action_provider, bridge." } ], "coverage": { @@ -62,6 +71,7 @@ "links", "core_write", "lifecycle", + "event_action_interop/0.1", "runtime_contracts/0.1", "workflow/0.1", "watch" diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index cfed5d6..2c632c8 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -12,7 +12,7 @@ import ThemeControlScript from "../components/ThemeControlScript.astro"; interface Props { title: string; description: string; - current?: "home" | "connect" | "sdk" | "runtime" | "implementations" | "spec"; + current?: "home" | "connect" | "sdk" | "interop" | "runtime" | "implementations" | "spec"; noIndex?: boolean; } diff --git a/src/pages/index.astro b/src/pages/index.astro index f44fbe1..b1b4983 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -218,9 +218,10 @@ easier to understand.

- Runtime contracts and workflow execution are - optional layers for declared events, actions, timers, and durable - automation. + Event and action interoperability lets + independent applications cooperate through shared contracts.{" "} + Durable runtime execution is an optional layer + for persisted workflows, timers, retries, and recovery.

@@ -310,6 +311,11 @@ easier to understand. Compare profiles, open the shared fixtures, and publish exact evidence. + + Connect applications + Publish CloudEvents and invoke schema-validated actions through a local or durable bridge. + + diff --git a/src/pages/interop/index.astro b/src/pages/interop/index.astro new file mode 100644 index 0000000..22c7541 --- /dev/null +++ b/src/pages/interop/index.astro @@ -0,0 +1,160 @@ +--- +import BaseLayout from "../../layouts/BaseLayout.astro"; +import CodeBlock from "../../components/CodeBlock.astro"; + +const eventSource = `const tasknotes = bridge.connect({ + application: "tasknotes", + implementation: "tasknotes.obsidian", + version: "5.0.0" +}); + +await tasknotes.registerEventSource({ + declaration_id: "tasknotes.events", + contracts: [{ contract: taskCompletedContract }] +}); + +await tasknotes.publishEvent({ + contract: { id: "tasknotes.task.completed", version: "1.0.0" }, + subject: "Tasks/Ship%20contracts.md", + correlation_id: "workflow-42", + data: { + task_id: "task-42", + task_path: "Tasks/Ship contracts.md", + title: "Ship contracts", + status: "done", + completed_at: "2026-07-28T10:15:00Z" + } +});`; + +const actionCaller = `const outcome = await workflows.invokeAction({ + request_id: "workflow:run-42:add-card", + contract: { id: "canvas.card.create", version: "^1.0.0" }, + requested_provider: { application: "canvas-bases" }, + correlation_id: "workflow-42", + causation_id: "evt-42", + idempotency_key: "run-42:add-card", + input: { + canvas_path: "TaskNotes/Canvases/Completed tasks.canvas", + card: { kind: "file", file: "Tasks/Ship contracts.md" } + } +}); + +if (outcome.status !== "succeeded") { + throw new Error(\`\${outcome.error.message} [\${outcome.error.code}]\`); +}`; +--- + + +
+
+
+

Interoperability profile 0.1

+

Shared contracts. Independent applications.

+
+
+

+ Applications can publish events and invoke actions without adopting + one universal runtime. JSON Schema proves compatibility; a separate + bridge grant supplies authority. +

+ +
+
+
+ +
+

The mental model

+
+
+
+

Contracts define meaning

+

+ Every record, event, and action is an ordinary first-class{" "} + mdbase.contract. Its discriminated shape names the + relevant JSON Schemas: record_schema,{" "} + data_schema, or action input and outcome schemas. +

+
+
+
+
+

Applications declare one role at a time

+

+ An application may be an event source, event consumer, action + caller, or action provider. A type file uses implements{" "} + only for record contracts; application declarations provide event + sources and action handlers. +

+
+
+
+
+

The bridge validates and routes

+

+ Events multicast to every authorized compatible consumer. Actions + resolve to exactly one authorized provider before any side effect. + Multiple eligible providers produce ambiguous_provider{" "} + until the caller or policy selects one. +

+
+
+
+
+ +
+

Events are CloudEvents 1.0

+

+ The profile uses CloudEvents structured JSON and adds exact contract + version, digest, application, and implementation attributes. The event + ID survives redelivery. Correlation and causation are explicit. Event + data always validates against the exact contract artifact. +

+ +
+ +
+

Actions produce evidence, not a delivery fiction

+

+ A logical request is admitted as an exact invocation with a selected + provider and concrete attempt. Its terminal outcome is{" "} + succeeded, rejected, failed,{" "} + cancelled, or outcome_indeterminate. Accepting a + message for delivery is never reported as successful execution. +

+ +
+ +
+

What stays outside the profile

+ + + + + + + + + + + + + + + + + + +
In the profileOwned elsewhere
Contract identity, exact digests, envelopes, validation, resolutionWorkflow languages, scheduling, retries, and application behavior
Correlation, causation, cancellation, duplicate and indeterminate semanticsPersistence, journals, leases, recovery, and offline queues
Identity and authorization context carried to a bridgeThe user grant or transport-specific policy engine
+
+
diff --git a/src/pages/runtime/index.astro b/src/pages/runtime/index.astro index c9871b3..5dc3bd0 100644 --- a/src/pages/runtime/index.astro +++ b/src/pages/runtime/index.astro @@ -4,23 +4,23 @@ import BaseLayout from "../../layouts/BaseLayout.astro";

Runtime profile 0.1

-

Runtime contracts and workflow execution.

+

Durable execution builds on interoperability.

- mdbase separates passive collection semantics from declared provider - contracts and durable workflow execution. Hosts declare support for - each layer independently. + The event/action profile defines portable messages and provider + resolution. The runtime adds journals, scheduling, retries, and + recovery without inventing a second contract system.

@@ -42,11 +42,11 @@ import BaseLayout from "../../layouts/BaseLayout.astro";
-

Runtime Contracts 0.1

+

Event/action interoperability 0.1

- Portable event and action declarations, provider registration, - compatibility checks, and preflight. The TypeScript package - implements this browser-safe provider-host layer. + CloudEvents envelopes, exact contract evidence, role declarations, + boundary validation, and one-provider action resolution. The + browser-safe reference bridge implements this layer.

@@ -65,10 +65,10 @@ import BaseLayout from "../../layouts/BaseLayout.astro";

Connect embedding

- Connect compiles exact application grants into runtime behavior, + Connect compiles exact application grants into transport behavior, supplies local or hosted collection authorities, and routes - notification signals. The runtime profile defines the contracts - that Connect hosts. + notification signals. It can bind the same portable envelopes + durably without becoming mandatory for local applications.

@@ -78,8 +78,8 @@ import BaseLayout from "../../layouts/BaseLayout.astro";

Conformance profiles

- Conformance uses atomic profiles. Provider hosts claim{" "} - runtime_contracts/0.1. Workflow engines add{" "} + Conformance uses atomic profiles. Interoperability bridges claim{" "} + event_action_interop/0.1. Durable workflow engines add{" "} workflow/0.1 after publishing shared fixture evidence.

@@ -91,10 +91,15 @@ import BaseLayout from "../../layouts/BaseLayout.astro"; + + + + + - - + + diff --git a/src/pages/sdk/connect-quickstart/index.astro b/src/pages/sdk/connect-quickstart/index.astro index 4be4db0..7d220c1 100644 --- a/src/pages/sdk/connect-quickstart/index.astro +++ b/src/pages/sdk/connect-quickstart/index.astro @@ -43,7 +43,7 @@ const manifest = `{ "resources": [ { "source": "contracts/workout.record.md", - "document": "---\\nkind: mdbase.contract\\nid: workout.record\\nversion: 1.0.0\\nschema:\\n dialect: json-schema-2020-12\\n value:\\n $schema: https://json-schema.org/draft/2020-12/schema\\n type: object\\n additionalProperties: false\\n properties:\\n title: { type: string }\\n completed: { type: boolean, default: false }\\n required: [title]\\n---\\n" + "document": "---\\nkind: mdbase.contract\\ncontract_type: record\\nid: workout.record\\nversion: 1.0.0\\nrecord_schema:\\n dialect: json-schema-2020-12\\n value:\\n $schema: https://json-schema.org/draft/2020-12/schema\\n type: object\\n additionalProperties: false\\n properties:\\n title: { type: string }\\n completed: { type: boolean, default: false }\\n required: [title]\\n---\\n" }, { "source": "types/workout.md", diff --git a/src/pages/sdk/contracts/index.astro b/src/pages/sdk/contracts/index.astro index a4919f9..a2b6a92 100644 --- a/src/pages/sdk/contracts/index.astro +++ b/src/pages/sdk/contracts/index.astro @@ -52,22 +52,25 @@ export class WorklogCollection { ]} >

- A type describes how one collection stores records. A data contract is a - versioned JSON Schema for a stable, portable record view. A type opts into a - contract through{" "}implements, where it maps contract field names - to its own frontmatter fields. + Every mdbase.contract has a stable ID, semantic version, exact + digest, and JSON Schema. Its contract_type says what it + describes: a portable record view, an emitted{" "} + event, or an invocable action.

- This is intentionally many-to-many. Several types can implement one - contract, so reads union all of them. One type can implement contracts used - by several applications, so those applications can share the same records - without sharing implementation-specific conventions. + Only record contracts are implemented by type files. A type opts in through{" "} + implements and maps contract field names to its own + frontmatter fields. This is intentionally many-to-many: reads union every + approved implementing type, and several applications can consume the same + portable record view. Event sources and action providers declare executable + implementations through the interoperability bridge, + not through a type file.

Read the approved collection description

- describe() returns each exact string version, contract schema, + describe() returns each exact record-contract version, schema, digest, and complete{" "}implementations list. Each implementation includes its concrete type, field mapping, binding metadata, and digest. Use this data after authorization; do not look for semantic meaning in{" "} diff --git a/src/pages/sdk/manifest/index.astro b/src/pages/sdk/manifest/index.astro index 0d40a4e..ed5d947 100644 --- a/src/pages/sdk/manifest/index.astro +++ b/src/pages/sdk/manifest/index.astro @@ -44,7 +44,7 @@ const contractManifest = `{ "resources": [ { "source": "contracts/example.work-item.md", - "document": "---\\nkind: mdbase.contract\\nid: example.work-item\\nversion: 1.0.0\\nschema:\\n dialect: json-schema-2020-12\\n value:\\n $schema: https://json-schema.org/draft/2020-12/schema\\n type: object\\n additionalProperties: false\\n properties:\\n title: { type: string }\\n required: [title]\\n---\\n" + "document": "---\\nkind: mdbase.contract\\ncontract_type: record\\nid: example.work-item\\nversion: 1.0.0\\nrecord_schema:\\n dialect: json-schema-2020-12\\n value:\\n $schema: https://json-schema.org/draft/2020-12/schema\\n type: object\\n additionalProperties: false\\n properties:\\n title: { type: string }\\n required: [title]\\n---\\n" }, { "source": "types/work-item.md",

event_action_interop/0.1CloudEvents, declarations, validation, authorization boundaries, multicast, and action resolutionWorkflow syntax, scheduling, retries, persistence, or recovery
runtime_contracts/0.1Declaration validation, registry behavior, compatibility, dispatch, preflightWatching, timers, durable execution, or recoveryLegacy runtime-host behavior during migration to the interoperability substrateThe portable event/action profile and durable execution evidence
workflow/0.1