From ce7ead23a9ee14f34bf9fe3e42523d6814ba5987 Mon Sep 17 00:00:00 2001
From: callumalpass
Date: Tue, 28 Jul 2026 15:09:49 +1000
Subject: [PATCH] Document first-class data contracts
---
public/connect/schemas/catalog.json | 2 +-
.../schemas/connect-protocol.v1.schema.json | 112 +++++++++++++++---
.../connect/schemas/data-contract.schema.json | 58 +++++++++
public/connect/schemas/mdbase-app.schema.json | 73 ++++++++++--
public/connect/schemas/mdbase-app.v1.json | 73 ++++++++++--
public/connect/schemas/sync.v1.schema.json | 39 +++++-
site-sources.json | 8 +-
src/data/conformance.json | 2 +-
src/pages/sdk/connect-quickstart/index.astro | 72 ++++++++---
src/pages/sdk/contracts/index.astro | 57 ++++++---
src/pages/sdk/manifest/index.astro | 54 +++++++--
11 files changed, 459 insertions(+), 91 deletions(-)
create mode 100644 public/connect/schemas/data-contract.schema.json
diff --git a/public/connect/schemas/catalog.json b/public/connect/schemas/catalog.json
index bec7280..f5a1c9d 100644
--- a/public/connect/schemas/catalog.json
+++ b/public/connect/schemas/catalog.json
@@ -2,7 +2,7 @@
"manifest_version": 1,
"schemas": {
"app_manifest": "./mdbase-app.schema.json",
- "contract_extension": "./contract-extension.v1.schema.json",
+ "data_contract": "./data-contract.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 14f9fdb..2adc64c 100644
--- a/public/connect/schemas/connect-protocol.v1.schema.json
+++ b/public/connect/schemas/connect-protocol.v1.schema.json
@@ -26,9 +26,26 @@
"required": ["id", "version"],
"properties": {
"id": { "type": "string", "minLength": 1, "maxLength": 100, "pattern": "^[a-z0-9]+(?:[._-][a-z0-9]+)*$" },
+ "version": { "$ref": "#/$defs/semanticVersion" }
+ }
+ },
+ "runtimeContractRequirement": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["id", "version"],
+ "properties": {
+ "id": { "type": "string", "minLength": 1, "maxLength": 100 },
"version": { "type": "integer", "minimum": 1 }
}
},
+ "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-]+)*)?$"
+ },
+ "digest": {
+ "type": "string",
+ "pattern": "^sha256:[0-9a-f]{64}$"
+ },
"grantScope": {
"type": "object",
"additionalProperties": false,
@@ -38,7 +55,7 @@
"contracts": {
"type": "array",
"maxItems": 20,
- "items": { "$ref": "#/$defs/contractRequirement" }
+ "items": { "$ref": "#/$defs/collectionContract" }
}
}
},
@@ -160,7 +177,7 @@
"contracts": {
"type": "array",
"maxItems": 100,
- "items": { "$ref": "#/$defs/contractRequirement" }
+ "items": { "$ref": "#/$defs/collectionContract" }
}
}
},
@@ -177,14 +194,18 @@
"access": { "enum": ["contract", "full_collection"] }
}
},
- "typeProvision": {
+ "typePackProvision": {
"type": "object",
"additionalProperties": false,
- "required": ["name", "document", "provides"],
+ "required": ["manifest", "resources", "provides"],
"properties": {
- "name": { "type": "string", "minLength": 1, "maxLength": 100 },
- "path": { "type": "string", "minLength": 1, "maxLength": 500 },
- "document": { "type": "string", "minLength": 1, "maxLength": 262144 },
+ "manifest": { "$ref": "#/$defs/typePackManifest" },
+ "resources": {
+ "type": "array",
+ "minItems": 1,
+ "maxItems": 100,
+ "items": { "$ref": "#/$defs/typePackSourceResource" }
+ },
"provides": {
"type": "array",
"maxItems": 20,
@@ -192,15 +213,53 @@
}
}
},
+ "typePackManifest": {
+ "type": "object",
+ "required": ["kind", "id", "version", "resources"],
+ "properties": {
+ "kind": { "const": "mdbase.type-pack" },
+ "id": { "type": "string", "minLength": 3 },
+ "version": { "$ref": "#/$defs/semanticVersion" },
+ "name": { "type": "string", "minLength": 1 },
+ "description": { "type": "string" },
+ "resources": {
+ "type": "array",
+ "minItems": 1,
+ "items": { "$ref": "#/$defs/typePackManifestResource" }
+ }
+ },
+ "patternProperties": { "^x-[A-Za-z][A-Za-z0-9._:-]{0,127}$": true },
+ "additionalProperties": false
+ },
+ "typePackManifestResource": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["kind", "source", "target", "digest"],
+ "properties": {
+ "kind": { "enum": ["contract", "type", "schema"] },
+ "source": { "type": "string", "minLength": 1, "maxLength": 500 },
+ "target": { "type": "string", "minLength": 1, "maxLength": 500 },
+ "digest": { "$ref": "#/$defs/digest" }
+ }
+ },
+ "typePackSourceResource": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["source", "document"],
+ "properties": {
+ "source": { "type": "string", "minLength": 1, "maxLength": 500 },
+ "document": { "type": "string", "maxLength": 262144 }
+ }
+ },
"applicationProvisions": {
"type": "object",
"additionalProperties": false,
- "required": ["types"],
+ "required": ["type_packs"],
"properties": {
- "types": {
+ "type_packs": {
"type": "array",
"maxItems": 100,
- "items": { "$ref": "#/$defs/typeProvision" }
+ "items": { "$ref": "#/$defs/typePackProvision" }
}
}
},
@@ -258,7 +317,7 @@
"contracts": {
"type": "array",
"maxItems": 100,
- "items": { "$ref": "#/$defs/contractRequirement" }
+ "items": { "$ref": "#/$defs/collectionContract" }
},
"error": {
"type": "object",
@@ -289,7 +348,7 @@
"required": ["id", "event", "presentation"],
"properties": {
"id": { "type": "string", "minLength": 1, "maxLength": 100, "pattern": "^[a-z0-9]+(?:[._-][a-z0-9]+)*$" },
- "event": { "$ref": "#/$defs/contractRequirement" },
+ "event": { "$ref": "#/$defs/runtimeContractRequirement" },
"if": {
"type": "object",
"additionalProperties": false,
@@ -370,13 +429,34 @@
"collectionContract": {
"type": "object",
"additionalProperties": false,
- "required": ["id", "version", "type_name", "extension", "configuration"],
+ "required": ["id", "version", "digest", "schema", "implementations"],
"properties": {
"id": { "type": "string", "minLength": 1 },
- "version": { "type": "integer", "minimum": 1 },
+ "version": { "$ref": "#/$defs/semanticVersion" },
+ "digest": { "$ref": "#/$defs/digest" },
+ "schema": { "type": "object" },
+ "binding_schema": { "type": "object" },
+ "implementations": {
+ "type": "array",
+ "minItems": 1,
+ "items": { "$ref": "#/$defs/collectionContractImplementation" }
+ }
+ }
+ },
+ "collectionContractImplementation": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["type_name", "type_version", "digest", "fields"],
+ "properties": {
"type_name": { "type": "string", "minLength": 1 },
- "extension": { "type": "string", "pattern": "^x-[a-z0-9]+(?:[._-][a-z0-9]+)*$" },
- "configuration": { "type": "object" }
+ "type_version": { "type": "integer", "minimum": 1 },
+ "type_path": { "type": "string", "minLength": 1 },
+ "digest": { "$ref": "#/$defs/digest" },
+ "fields": {
+ "type": "object",
+ "additionalProperties": { "type": "string", "minLength": 1 }
+ },
+ "binding": { "type": "object" }
}
},
"changesPage": {
diff --git a/public/connect/schemas/data-contract.schema.json b/public/connect/schemas/data-contract.schema.json
new file mode 100644
index 0000000..f8da60b
--- /dev/null
+++ b/public/connect/schemas/data-contract.schema.json
@@ -0,0 +1,58 @@
+{
+ "$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",
+ "type": "object",
+ "required": ["kind", "id", "version", "schema"],
+ "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" }
+ },
+ "patternProperties": {
+ "^x-[A-Za-z][A-Za-z0-9._:-]{0,127}$": true
+ },
+ "additionalProperties": false,
+ "$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-]+)*)?$"
+ },
+ "schemaWrapper": {
+ "type": "object",
+ "required": ["dialect"],
+ "properties": {
+ "dialect": { "const": "json-schema-2020-12" },
+ "value": { "type": "object" },
+ "ref": { "type": "string", "minLength": 1 }
+ },
+ "oneOf": [
+ {
+ "required": ["value"],
+ "properties": {
+ "value": true,
+ "ref": false
+ }
+ },
+ {
+ "required": ["ref"],
+ "properties": {
+ "ref": true,
+ "value": false
+ }
+ }
+ ],
+ "additionalProperties": false
+ }
+ }
+}
diff --git a/public/connect/schemas/mdbase-app.schema.json b/public/connect/schemas/mdbase-app.schema.json
index ae7df73..696b272 100644
--- a/public/connect/schemas/mdbase-app.schema.json
+++ b/public/connect/schemas/mdbase-app.schema.json
@@ -37,12 +37,12 @@
"provisions": {
"type": "object",
"additionalProperties": false,
- "required": ["types"],
+ "required": ["type_packs"],
"properties": {
- "types": {
+ "type_packs": {
"type": "array",
"maxItems": 20,
- "items": { "$ref": "#/$defs/typeProvision" }
+ "items": { "$ref": "#/$defs/typePackProvision" }
}
}
},
@@ -91,6 +91,18 @@
"pattern": "^[0-9]+(ms|s|m|h|d)$"
},
"contract": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["id", "version"],
+ "properties": {
+ "id": { "$ref": "#/$defs/identifier" },
+ "version": {
+ "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-]+)*)?$"
+ }
+ }
+ },
+ "runtimeContract": {
"type": "object",
"additionalProperties": false,
"required": ["id", "version"],
@@ -120,14 +132,18 @@
}
}
},
- "typeProvision": {
+ "typePackProvision": {
"type": "object",
"additionalProperties": false,
- "required": ["name", "document", "provides"],
+ "required": ["manifest", "resources", "provides"],
"properties": {
- "name": { "type": "string", "minLength": 1, "maxLength": 100 },
- "path": { "type": "string", "minLength": 1, "maxLength": 240 },
- "document": { "type": "string", "minLength": 1, "maxLength": 131072 },
+ "manifest": { "$ref": "#/$defs/typePackManifest" },
+ "resources": {
+ "type": "array",
+ "minItems": 1,
+ "maxItems": 100,
+ "items": { "$ref": "#/$defs/typePackSourceResource" }
+ },
"provides": {
"type": "array",
"maxItems": 20,
@@ -136,13 +152,52 @@
}
}
},
+ "typePackManifest": {
+ "type": "object",
+ "required": ["kind", "id", "version", "resources"],
+ "properties": {
+ "kind": { "const": "mdbase.type-pack" },
+ "id": { "$ref": "#/$defs/identifier" },
+ "version": { "$ref": "#/$defs/contract/properties/version" },
+ "name": { "type": "string", "minLength": 1, "maxLength": 100 },
+ "description": { "type": "string", "maxLength": 500 },
+ "resources": {
+ "type": "array",
+ "minItems": 1,
+ "maxItems": 100,
+ "items": { "$ref": "#/$defs/typePackManifestResource" }
+ }
+ },
+ "patternProperties": { "^x-[A-Za-z][A-Za-z0-9._:-]{0,127}$": true },
+ "additionalProperties": false
+ },
+ "typePackManifestResource": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["kind", "source", "target", "digest"],
+ "properties": {
+ "kind": { "enum": ["contract", "type", "schema"] },
+ "source": { "type": "string", "minLength": 1, "maxLength": 240 },
+ "target": { "type": "string", "minLength": 1, "maxLength": 240 },
+ "digest": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" }
+ }
+ },
+ "typePackSourceResource": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["source", "document"],
+ "properties": {
+ "source": { "type": "string", "minLength": 1, "maxLength": 240 },
+ "document": { "type": "string", "maxLength": 262144 }
+ }
+ },
"notificationCriterion": {
"type": "object",
"additionalProperties": false,
"required": ["id", "event", "presentation"],
"properties": {
"id": { "$ref": "#/$defs/identifier" },
- "event": { "$ref": "#/$defs/contract" },
+ "event": { "$ref": "#/$defs/runtimeContract" },
"if": {
"type": "object",
"additionalProperties": false,
diff --git a/public/connect/schemas/mdbase-app.v1.json b/public/connect/schemas/mdbase-app.v1.json
index ae7df73..696b272 100644
--- a/public/connect/schemas/mdbase-app.v1.json
+++ b/public/connect/schemas/mdbase-app.v1.json
@@ -37,12 +37,12 @@
"provisions": {
"type": "object",
"additionalProperties": false,
- "required": ["types"],
+ "required": ["type_packs"],
"properties": {
- "types": {
+ "type_packs": {
"type": "array",
"maxItems": 20,
- "items": { "$ref": "#/$defs/typeProvision" }
+ "items": { "$ref": "#/$defs/typePackProvision" }
}
}
},
@@ -91,6 +91,18 @@
"pattern": "^[0-9]+(ms|s|m|h|d)$"
},
"contract": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["id", "version"],
+ "properties": {
+ "id": { "$ref": "#/$defs/identifier" },
+ "version": {
+ "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-]+)*)?$"
+ }
+ }
+ },
+ "runtimeContract": {
"type": "object",
"additionalProperties": false,
"required": ["id", "version"],
@@ -120,14 +132,18 @@
}
}
},
- "typeProvision": {
+ "typePackProvision": {
"type": "object",
"additionalProperties": false,
- "required": ["name", "document", "provides"],
+ "required": ["manifest", "resources", "provides"],
"properties": {
- "name": { "type": "string", "minLength": 1, "maxLength": 100 },
- "path": { "type": "string", "minLength": 1, "maxLength": 240 },
- "document": { "type": "string", "minLength": 1, "maxLength": 131072 },
+ "manifest": { "$ref": "#/$defs/typePackManifest" },
+ "resources": {
+ "type": "array",
+ "minItems": 1,
+ "maxItems": 100,
+ "items": { "$ref": "#/$defs/typePackSourceResource" }
+ },
"provides": {
"type": "array",
"maxItems": 20,
@@ -136,13 +152,52 @@
}
}
},
+ "typePackManifest": {
+ "type": "object",
+ "required": ["kind", "id", "version", "resources"],
+ "properties": {
+ "kind": { "const": "mdbase.type-pack" },
+ "id": { "$ref": "#/$defs/identifier" },
+ "version": { "$ref": "#/$defs/contract/properties/version" },
+ "name": { "type": "string", "minLength": 1, "maxLength": 100 },
+ "description": { "type": "string", "maxLength": 500 },
+ "resources": {
+ "type": "array",
+ "minItems": 1,
+ "maxItems": 100,
+ "items": { "$ref": "#/$defs/typePackManifestResource" }
+ }
+ },
+ "patternProperties": { "^x-[A-Za-z][A-Za-z0-9._:-]{0,127}$": true },
+ "additionalProperties": false
+ },
+ "typePackManifestResource": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["kind", "source", "target", "digest"],
+ "properties": {
+ "kind": { "enum": ["contract", "type", "schema"] },
+ "source": { "type": "string", "minLength": 1, "maxLength": 240 },
+ "target": { "type": "string", "minLength": 1, "maxLength": 240 },
+ "digest": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" }
+ }
+ },
+ "typePackSourceResource": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["source", "document"],
+ "properties": {
+ "source": { "type": "string", "minLength": 1, "maxLength": 240 },
+ "document": { "type": "string", "maxLength": 262144 }
+ }
+ },
"notificationCriterion": {
"type": "object",
"additionalProperties": false,
"required": ["id", "event", "presentation"],
"properties": {
"id": { "$ref": "#/$defs/identifier" },
- "event": { "$ref": "#/$defs/contract" },
+ "event": { "$ref": "#/$defs/runtimeContract" },
"if": {
"type": "object",
"additionalProperties": false,
diff --git a/public/connect/schemas/sync.v1.schema.json b/public/connect/schemas/sync.v1.schema.json
index d1bf928..436b121 100644
--- a/public/connect/schemas/sync.v1.schema.json
+++ b/public/connect/schemas/sync.v1.schema.json
@@ -11,6 +11,14 @@
],
"$defs": {
"uuid": { "type": "string", "format": "uuid" },
+ "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-]+)*)?$"
+ },
+ "digest": {
+ "type": "string",
+ "pattern": "^sha256:[0-9a-f]{64}$"
+ },
"collectionType": {
"type": "object",
"additionalProperties": false,
@@ -28,13 +36,34 @@
"contract": {
"type": "object",
"additionalProperties": false,
- "required": ["id", "version", "type_name", "extension", "configuration"],
+ "required": ["id", "version", "digest", "schema", "implementations"],
"properties": {
"id": { "type": "string", "minLength": 1 },
- "version": { "type": "integer", "minimum": 1 },
+ "version": { "$ref": "#/$defs/semanticVersion" },
+ "digest": { "$ref": "#/$defs/digest" },
+ "schema": { "type": "object" },
+ "binding_schema": { "type": "object" },
+ "implementations": {
+ "type": "array",
+ "minItems": 1,
+ "items": { "$ref": "#/$defs/contractImplementation" }
+ }
+ }
+ },
+ "contractImplementation": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["type_name", "type_version", "digest", "fields"],
+ "properties": {
"type_name": { "type": "string", "minLength": 1 },
- "extension": { "type": "string", "pattern": "^x-" },
- "configuration": { "type": "object" }
+ "type_version": { "type": "integer", "minimum": 1 },
+ "type_path": { "type": "string", "minLength": 1 },
+ "digest": { "$ref": "#/$defs/digest" },
+ "fields": {
+ "type": "object",
+ "additionalProperties": { "type": "string", "minLength": 1 }
+ },
+ "binding": { "type": "object" }
}
},
"resources": {
@@ -55,7 +84,7 @@
"required": ["path", "kind", "revision", "document"],
"properties": {
"path": { "type": "string", "minLength": 1 },
- "kind": { "enum": ["configuration", "type"] },
+ "kind": { "enum": ["configuration", "type", "contract", "schema", "view"] },
"revision": { "type": "string", "minLength": 1 },
"document": { "type": "string" }
}
diff --git a/site-sources.json b/site-sources.json
index 77da7f2..c47afde 100644
--- a/site-sources.json
+++ b/site-sources.json
@@ -1,20 +1,20 @@
{
"specification": {
"repository": "mdbase-dev/mdbase-spec",
- "ref": "2c5e1bbc8736d71b95fcaea1b593dc2eeaec739b"
+ "ref": "f0f6b5ab497f201a21723e137997b5d5d02358be"
},
"connect": {
"repository": "mdbase-dev/mdbase-connect",
- "ref": "8e960317f0886f8c504023dad873cf8cec82fd99"
+ "ref": "fc94dffefb2408a756d7610f26730cac2b22a843"
},
"implementations": [
{
"repository": "callumalpass/mdbase-rs",
- "ref": "fafea262cffbce1205563a580e4d5850e7e942b2"
+ "ref": "99d27a245523a6f6feea950a036bd796b89f99b4"
},
{
"repository": "callumalpass/mdbase",
- "ref": "4f419e0f4454682d42e067749db1fd16d72d1eb9"
+ "ref": "893c7aee289794a353a71546a8c87e9902d684ce"
}
]
}
diff --git a/src/data/conformance.json b/src/data/conformance.json
index bbbb1f6..3da243d 100644
--- a/src/data/conformance.json
+++ b/src/data/conformance.json
@@ -1,5 +1,5 @@
{
- "generated_at": "2026-07-27",
+ "generated_at": "2026-07-28",
"spec_version": "0.3.0",
"implementations": [
{
diff --git a/src/pages/sdk/connect-quickstart/index.astro b/src/pages/sdk/connect-quickstart/index.astro
index e7e7733..4be4db0 100644
--- a/src/pages/sdk/connect-quickstart/index.astro
+++ b/src/pages/sdk/connect-quickstart/index.astro
@@ -12,16 +12,43 @@ const manifest = `{
],
"requirements": {
"contracts": [
- { "id": "workout.record", "version": 1 }
+ { "id": "workout.record", "version": "1.0.0" }
]
},
"provisions": {
- "types": [
+ "type_packs": [
{
- "name": "Workout",
- "document": "---\\nkind: mdbase.type\\nname: workout\\nversion: 1\\nschema:\\n dialect: json-schema-2020-12\\n value:\\n type: object\\n required: [type, title]\\n additionalProperties: true\\n properties:\\n type: { const: workout }\\n title: { type: string }\\n completed: { type: boolean }\\nx-workout:\\n contract: workout.record\\n version: 1\\n field_roles:\\n title: title\\n---\\n",
"provides": [
- { "id": "workout.record", "version": 1 }
+ { "id": "workout.record", "version": "1.0.0" }
+ ],
+ "manifest": {
+ "kind": "mdbase.type-pack",
+ "id": "example.workouts",
+ "version": "1.0.0",
+ "resources": [
+ {
+ "kind": "contract",
+ "source": "contracts/workout.record.md",
+ "target": "_contracts/workout.record.md",
+ "digest": "sha256:e0c2f77dd7158ca7e6b52b13da8c306f0a7e1b97582a1024f00ec0cf7fe5f259"
+ },
+ {
+ "kind": "type",
+ "source": "types/workout.md",
+ "target": "_types/workout.md",
+ "digest": "sha256:ff35309cd4598182d2021f698ee85cad4d320d965cd5f7c1bd608ee2eb16505b"
+ }
+ ]
+ },
+ "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"
+ },
+ {
+ "source": "types/workout.md",
+ "document": "---\\nkind: mdbase.type\\nname: workout\\nversion: 1\\nschema:\\n dialect: json-schema-2020-12\\n value:\\n type: object\\n additionalProperties: true\\n properties:\\n title: { type: string }\\n completed: { type: boolean }\\n required: [title]\\nimplements:\\n - contract: workout.record\\n version: 1.0.0\\n fields:\\n title: title\\n completed: completed\\n---\\n"
+ }
]
}
]
@@ -48,7 +75,6 @@ const client = `import {
} from "@mdbase/connect";
export interface Workout extends JsonObject {
- type: "workout";
title: string;
completed?: boolean;
}
@@ -114,17 +140,26 @@ const collection = collectionLocation.activeConnection();
if (!collection) throw new Error("Choose a collection.");
const page = unwrapOperation(await collection.query({
- types: ["workout"],
- where: "completed != true",
- order_by: [{ field: "title", direction: "asc" }],
+ contract: {
+ id: "workout.record",
+ version: "1.0.0"
+ },
limit: 50
}));
-const first = page.results[0];
+const first = page.results
+ .filter((row) => row.completed !== true)
+ .sort((left, right) =>
+ left.title.localeCompare(right.title)
+ )[0];
if (first) {
unwrapOperation(await collection.update({
path: first.path,
patch: { completed: true },
+ contract: {
+ id: "workout.record",
+ version: "1.0.0"
+ },
if_revision: first.revision
}));
}`;
@@ -164,9 +199,9 @@ if (first) {
a Connect SDK source build or beta artifact.
- The example manifest carries a complete workout type. Connect can install
- that type during approval when the chosen collection does not yet provide
- {" "}workout.record@1.
+ The example manifest carries a complete transactional contract/type pack.
+ Connect can install it during approval when the chosen collection does not
+ yet provide workout.record 1.0.0.
1. Add a bundled application manifest
@@ -178,9 +213,9 @@ if (first) {
- The contract requirement limits compatible collections. The provision
- makes a collection safely provisionable during approval and does not give
- the application general type-management access.
+ The contract requirement limits compatible collections. The type pack makes
+ a collection safely provisionable during approval and does not give the
+ application general type-management access.
2. Add the SDK and validator
@@ -231,6 +266,11 @@ if (first) {
{" "}if_revision prevents one application from silently
overwriting a newer change.
+
+ Contract-scoped queries expose normalized mapped fields only. They union
+ every approved implementation and deliberately leave filtering and sorting
+ those normalized values to the application.
+
What success looks like
diff --git a/src/pages/sdk/contracts/index.astro b/src/pages/sdk/contracts/index.astro
index 9061639..a4919f9 100644
--- a/src/pages/sdk/contracts/index.astro
+++ b/src/pages/sdk/contracts/index.astro
@@ -7,15 +7,19 @@ const generic = `const description = await connection.describe();
const workItemContract = description.contracts.find(
(contract) =>
contract.id === "example.work-item" &&
- contract.version === 1
+ contract.version === "1.0.0"
);
if (!workItemContract) {
- throw new Error("The approved collection lacks example.work-item@1");
+ throw new Error("The approved collection lacks example.work-item 1.0.0");
}
-const workItemType = workItemContract.type_name;
-const fieldRoles = workItemContract.configuration.field_roles;`;
+for (const implementation of workItemContract.implementations) {
+ console.log(
+ implementation.type_name,
+ implementation.fields
+ );
+}`;
const domainFunction = `import type { MdbaseCollectionClient } from "@mdbase/connect";
@@ -27,7 +31,10 @@ export class WorklogCollection {
list() {
return this.client.queryAll({
- types: [this.contract.typeName]
+ contract: {
+ id: "example.work-item",
+ version: "1.0.0"
+ }
});
}
}`;
@@ -45,19 +52,26 @@ export class WorklogCollection {
]}
>
- A type describes record shape. A domain contract identifies portable
- behavior and maps semantic roles onto that type. Two collections can provide
- the same contract while using different frontmatter property names or path
- conventions.
+ 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.
+
+
+ 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.
Read the approved collection description
- describe() returns portable type definitions, complete contract
- descriptors, collection settings, JSON Schemas, and supported operations.
- Use this data after authorization. The manifest requirement guarantees that
- Connect only offers a ready or safely provisionable collection.
+ describe() returns each exact string version, contract 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{" "}
+ x-* extensions.
Keep your adapter on the transport-neutral client
@@ -68,6 +82,12 @@ export class WorklogCollection {
Connect, createSandbox(), offline transports, and conforming
providers.
+
+ A contract query returns normalized contract fields and unions every
+ approved implementation. If a record exposes several approved views, pass
+ the exact{" "}{"{ id, version, type }"} selector. Creates also need
+ an exact provider when more than one implementation is available.
+
Keep domain behavior with its application
@@ -80,10 +100,11 @@ export class WorklogCollection {
Contract scope and full collection access
- Contract-scoped grants confine record paths and operations to types that
- provide the required contracts. They cannot administer collection-wide
- type definitions. Request full_collection only for genuine
- collection-level behavior such as arbitrary saved views, schema editors, or
- general-purpose collection tools.
+ Contract-scoped grants expose only normalized mapped fields. Markdown
+ bodies, unmapped frontmatter, unrelated types, and collection-wide features
+ stay private. Filtering and sorting normalized fields happens in the
+ application. Request{" "}full_collection only for genuine
+ whole-record or collection-level behavior such as body-aware task tools,
+ arbitrary saved views, schema editors, or general-purpose collection tools.
diff --git a/src/pages/sdk/manifest/index.astro b/src/pages/sdk/manifest/index.astro
index e16118d..0d40a4e 100644
--- a/src/pages/sdk/manifest/index.astro
+++ b/src/pages/sdk/manifest/index.astro
@@ -12,16 +12,44 @@ const contractManifest = `{
],
"requirements": {
"contracts": [
- { "id": "example.work-item", "version": 1 }
+ { "id": "example.work-item", "version": "1.0.0" }
]
},
"provisions": {
- "types": [
+ "type_packs": [
{
- "name": "Work item",
- "document": "---\\nkind: mdbase.type\\nname: work-item\\nversion: 1\\nschema:\\n dialect: json-schema-2020-12\\n value:\\n type: object\\nx-worklog:\\n contract: example.work-item\\n version: 1\\n---\\n",
"provides": [
- { "id": "example.work-item", "version": 1 }
+ { "id": "example.work-item", "version": "1.0.0" }
+ ],
+ "manifest": {
+ "kind": "mdbase.type-pack",
+ "id": "example.work-items",
+ "version": "1.0.0",
+ "name": "Work items",
+ "resources": [
+ {
+ "kind": "contract",
+ "source": "contracts/example.work-item.md",
+ "target": "_contracts/example.work-item.md",
+ "digest": "sha256:9cd7f8e4b23ba20aaeaec3f7e209c6ba8de3fa5cd224204f2baef4e14dd69936"
+ },
+ {
+ "kind": "type",
+ "source": "types/work-item.md",
+ "target": "_types/work-item.md",
+ "digest": "sha256:2be7d8a5cd316fe2e4d31fa49b1d09f2d26a584846392b3ef21ff0219893230b"
+ }
+ ]
+ },
+ "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"
+ },
+ {
+ "source": "types/work-item.md",
+ "document": "---\\nkind: mdbase.type\\nname: work-item\\nversion: 1\\nschema:\\n dialect: json-schema-2020-12\\n value:\\n type: object\\n additionalProperties: true\\n properties:\\n title: { type: string }\\n required: [title]\\nimplements:\\n - contract: example.work-item\\n version: 1.0.0\\n fields:\\n title: title\\n---\\n"
+ }
]
}
]
@@ -143,7 +171,7 @@ const portableManifest = `{
contracts |
- Exact domain contract IDs and major versions the app understands |
+ Exact contract IDs and semantic versions the app understands |
access: "contract" |
@@ -169,17 +197,19 @@ const portableManifest = `{
Provision a missing contract safely
- A manifest may carry complete portable type documents. During approval, the
- authority installs only the missing definitions, reopens the collection,
- and verifies the declared contract before it creates the grant.
+ A manifest may carry a complete transactional type pack. During approval,
+ the authority validates every declared digest, preflights the contract,
+ types, and referenced schemas together, and writes all resources or none.
+ It then reopens the collection and pins the exact contract and
+ implementation digests before creating the grant.
General type administration requires a separate{" "}
create_type grant.
- A provision may only claim contracts listed in{" "}
- requirements.contracts. Auxiliary types installed with the
- same approved set use an empty provides array.
+ A pack may only claim contracts listed in{" "}
+ requirements.contracts. A target with different bytes is a
+ conflict, not an implicit overwrite. Repeating the same pack is idempotent.
Native application callbacks