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. 03 + + Connect applications + Publish CloudEvents and invoke schema-validated actions through a local or durable bridge. + 04 + 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
++ Applications can publish events and invoke actions without adopting + one universal runtime. JSON Schema proves compatibility; a separate + bridge grant supplies authority. +
+ +
+ 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.
+
+ 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.
+
+ 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.
+
+ 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. +
+
+ 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.
+
| In the profile | Owned elsewhere |
|---|---|
| Contract identity, exact digests, envelopes, validation, resolution | +Workflow languages, scheduling, retries, and application behavior | +
| Correlation, causation, cancellation, duplicate and indeterminate semantics | +Persistence, journals, leases, recovery, and offline queues | +
| Identity and authorization context carried to a bridge | +The user grant or transport-specific policy engine | +
Runtime profile 0.1
-- 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.
- 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.
- 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.
- 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.
event_action_interop/0.1 |
+ CloudEvents, declarations, validation, authorization boundaries, multicast, and action resolution | +Workflow syntax, scheduling, retries, persistence, or recovery | +||
runtime_contracts/0.1 |
- Declaration validation, registry behavior, compatibility, dispatch, preflight | -Watching, timers, durable execution, or recovery | +Legacy runtime-host behavior during migration to the interoperability substrate | +The portable event/action profile and durable execution evidence |
workflow/0.1 |
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 {
]}
>