Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ jobs:
uses: actions/checkout@v7
with:
repository: mdbase-dev/mdbase-connect
ref: 8e960317f0886f8c504023dad873cf8cec82fd99
ref: c4fd2f801b12686e1fd1bd25de4a72cf9e14bc5c
path: .sources/mdbase-connect

- name: Check out Rust implementation
uses: actions/checkout@v7
with:
repository: callumalpass/mdbase-rs
ref: fafea262cffbce1205563a580e4d5850e7e942b2
ref: e9297f465f779d0bf6bb3a361abf16eaf80a6944
path: .sources/mdbase-rs

- name: Check out TypeScript implementation
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@ jobs:
uses: actions/checkout@v7
with:
repository: mdbase-dev/mdbase-connect
ref: 8e960317f0886f8c504023dad873cf8cec82fd99
ref: c4fd2f801b12686e1fd1bd25de4a72cf9e14bc5c
path: .sources/mdbase-connect

- name: Check out Rust implementation
uses: actions/checkout@v7
with:
repository: callumalpass/mdbase-rs
ref: fafea262cffbce1205563a580e4d5850e7e942b2
ref: e9297f465f779d0bf6bb3a361abf16eaf80a6944
path: .sources/mdbase-rs

- name: Check out TypeScript implementation
Expand Down
142 changes: 140 additions & 2 deletions public/connect/schemas/connect-protocol.v1.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,19 @@
"oneOf": [
{ "$ref": "#/$defs/relayOperationRequest" },
{ "$ref": "#/$defs/relayOperationResponse" },
{ "$ref": "#/$defs/relayPolicySnapshot" }
{ "$ref": "#/$defs/relayPolicySnapshot" },
{ "$ref": "#/$defs/authorizationOfferRequest" },
{ "$ref": "#/$defs/authorizationOfferResponse" },
{ "$ref": "#/$defs/authorizationActivationRequest" },
{ "$ref": "#/$defs/authorizationActivationResponse" }
],
"$defs": {
"uuid": {
"type": "string",
"pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
},
"operation": {
"enum": ["describe", "changes", "read", "query", "list_views", "execute_view", "read_view_source", "create_view_source", "update_view_source", "delete_view_source", "validate", "create", "update", "delete", "rename", "read_type", "create_type", "update_type", "list_timers", "put_timer", "cancel_timer", "reconcile_timers"]
"enum": ["describe", "changes", "read", "query", "list_views", "execute_view", "read_view_source", "create_view_source", "update_view_source", "delete_view_source", "validate", "create", "update", "delete", "rename", "read_type", "create_type", "update_type", "list_timers", "put_timer", "cancel_timer", "reconcile_timers", "sync"]
},
"contractRequirement": {
"type": "object",
Expand Down Expand Up @@ -145,6 +149,140 @@
"encryption": { "$ref": "#/$defs/grantEncryption" }
}
},
"authorizationCollectionOffer": {
"type": "object",
"additionalProperties": false,
"required": ["collection_id", "display_name", "spec_version", "contracts"],
"properties": {
"collection_id": { "$ref": "#/$defs/uuid" },
"display_name": { "type": "string", "minLength": 1, "maxLength": 200 },
"spec_version": { "type": "string", "minLength": 1, "maxLength": 30 },
"contracts": {
"type": "array",
"maxItems": 100,
"items": { "$ref": "#/$defs/contractRequirement" }
}
}
},
"applicationRequirements": {
"type": "object",
"additionalProperties": false,
"required": ["contracts"],
"properties": {
"contracts": {
"type": "array",
"maxItems": 20,
"items": { "$ref": "#/$defs/contractRequirement" }
},
"access": { "enum": ["contract", "full_collection"] }
}
},
"typeProvision": {
"type": "object",
"additionalProperties": false,
"required": ["name", "document", "provides"],
"properties": {
"name": { "type": "string", "minLength": 1, "maxLength": 100 },
"path": { "type": "string", "minLength": 1, "maxLength": 500 },
"document": { "type": "string", "minLength": 1, "maxLength": 262144 },
"provides": {
"type": "array",
"maxItems": 20,
"items": { "$ref": "#/$defs/contractRequirement" }
}
}
},
"applicationProvisions": {
"type": "object",
"additionalProperties": false,
"required": ["types"],
"properties": {
"types": {
"type": "array",
"maxItems": 100,
"items": { "$ref": "#/$defs/typeProvision" }
}
}
},
"authorizationOfferRequest": {
"type": "object",
"additionalProperties": false,
"required": ["type", "protocol_version", "request_id", "authorization_id"],
"properties": {
"type": { "const": "authorization_offer_request" },
"protocol_version": { "const": 1 },
"request_id": { "$ref": "#/$defs/uuid" },
"authorization_id": { "$ref": "#/$defs/uuid" }
}
},
"authorizationOfferResponse": {
"type": "object",
"additionalProperties": false,
"required": ["type", "protocol_version", "request_id", "paused", "collections"],
"properties": {
"type": { "const": "authorization_offer_response" },
"protocol_version": { "const": 1 },
"request_id": { "$ref": "#/$defs/uuid" },
"paused": { "type": "boolean" },
"collections": {
"type": "array",
"maxItems": 1000,
"items": { "$ref": "#/$defs/authorizationCollectionOffer" }
}
}
},
"authorizationActivationRequest": {
"type": "object",
"additionalProperties": false,
"required": ["type", "protocol_version", "request_id", "authorization_id", "collection_id", "requirements", "provisions", "grant"],
"properties": {
"type": { "const": "authorization_activation_request" },
"protocol_version": { "const": 1 },
"request_id": { "$ref": "#/$defs/uuid" },
"authorization_id": { "$ref": "#/$defs/uuid" },
"collection_id": { "$ref": "#/$defs/uuid" },
"requirements": { "$ref": "#/$defs/applicationRequirements" },
"provisions": { "$ref": "#/$defs/applicationProvisions" },
"grant": { "$ref": "#/$defs/grantPolicy" }
}
},
"authorizationActivationResponse": {
"type": "object",
"additionalProperties": false,
"required": ["type", "protocol_version", "request_id", "ok", "contracts"],
"properties": {
"type": { "const": "authorization_activation_response" },
"protocol_version": { "const": 1 },
"request_id": { "$ref": "#/$defs/uuid" },
"ok": { "type": "boolean" },
"contracts": {
"type": "array",
"maxItems": 100,
"items": { "$ref": "#/$defs/contractRequirement" }
},
"error": {
"type": "object",
"additionalProperties": false,
"required": ["code", "message"],
"properties": {
"code": { "type": "string", "minLength": 1 },
"message": { "type": "string", "minLength": 1 },
"details": true
}
}
},
"allOf": [
{
"if": { "properties": { "ok": { "const": true } }, "required": ["ok"] },
"then": {
"not": { "properties": { "error": true }, "required": ["error"] }
},
"else": {
"required": ["error"]
}
}
]
},
"notificationCriterion": {
"type": "object",
"additionalProperties": false,
Expand Down
4 changes: 2 additions & 2 deletions src/components/DocsLayout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const docGroups = [
{ href: "/sdk/contracts/", label: "Contracts and adapters", key: "contracts" },
{ href: "/sdk/authorization/", label: "Authorization", key: "authorization" },
{ href: "/sdk/operations/", label: "Records and operations", key: "operations" },
{ href: "/sdk/routing/", label: "Local and hosted routes", key: "routing" },
{ href: "/sdk/routing/", label: "Authority routes", key: "routing" },
{ href: "/sdk/testing/", label: "Testing", key: "testing" },
{ href: "/sdk/notifications/", label: "Notifications and timers", key: "notifications" },
{ href: "/sdk/offline-sync/", label: "Offline sync", key: "offline-sync" }
Expand Down Expand Up @@ -66,7 +66,7 @@ const docGroups = [
</details>
<div class="docs-nav__meta">
<span>@mdbase/connect</span>
<strong>0.1.0-beta.1</strong>
<strong>0.1.0-beta.7</strong>
</div>
</aside>
<article class="docs-article">
Expand Down
2 changes: 1 addition & 1 deletion src/data/conformance.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"generated_at": "2026-07-26",
"generated_at": "2026-07-27",
"spec_version": "0.3.0",
"implementations": [
{
Expand Down
63 changes: 61 additions & 2 deletions src/pages/connect/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ const steps = [
<h2>Local and hosted collections</h2>
<p>
Applications use the same SDK and operation envelopes. Routing changes
according to where the authoritative collection lives.
according to which connector or provider currently holds the collection's
authority.
</p>
<table class="trust-table">
<thead>
Expand Down Expand Up @@ -116,6 +117,64 @@ const steps = [
</div>
</section>

<section class="content-section" id="one-authority">
<h2>Why one movable authority?</h2>
<p>
Authority is a coordination role, not the only copy of a collection.
Writable mirrors can keep ordinary Markdown on several devices, accept
changes while offline, and synchronize them later. One authority orders
the final accepted changes, enforces collection-wide rules, and gives
every mirror the same history to converge on.
</p>
<p>
Removing that role would not remove coordination. It would require every
peer—including filesystem editors that only know how to rewrite a
Markdown file—to preserve causal history and agree continuously about
concurrent edits, renames, deletes, schema changes, revocation, and
garbage collection.
</p>
<table class="trust-table">
<thead>
<tr>
<th>Concern</th>
<th>Equal peers would require</th>
<th>One movable authority provides</th>
</tr>
</thead>
<tbody>
<tr>
<td>Ordinary Markdown tools</td>
<td>CRDT or event metadata preserved by every writer</td>
<td>Open files remain the editable local format</td>
</tr>
<tr>
<td>Concurrent changes</td>
<td>A deterministic merge for every body and frontmatter value</td>
<td>Revision checks, durable mutation receipts, and explicit conflicts</td>
</tr>
<tr>
<td>Renames, deletes, and configuration</td>
<td>Distributed agreement over paths, tombstones, schemas, and constraints</td>
<td>One canonical order for collection-wide decisions</td>
</tr>
<tr>
<td>Offline devices</td>
<td>Split-brain reconciliation and peer-membership machinery</td>
<td>Queued local work that safely converges when the mirror reconnects</td>
</tr>
</tbody>
</table>
<div class="callout">
<strong>The role can move without changing the collection.</strong>
<p>
Authority transfer preserves the collection and record identities,
advances an authority epoch, and retires the previous authority. When
the previous authority was a local folder, that folder can continue as
a mirror. A stale authority cannot accept writes after cutover.
</p>
</div>
</section>

<section class="content-section">
<h2>The authorization sequence</h2>
<div class="steps">
Expand Down Expand Up @@ -203,7 +262,7 @@ const steps = [
</div>
<div>
<dt>Authority</dt>
<dd>The local connector or hosted provider that controls the main copy and makes the final authorization decision.</dd>
<dd>The movable coordination role that orders accepted changes, enforces collection rules, and makes the final authorization decision.</dd>
</div>
<div>
<dt>Control plane</dt>
Expand Down
4 changes: 2 additions & 2 deletions src/pages/sdk/api/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ const error = `try {
</tbody>
</table>

<h2 id="connection">Connection, routing, and hosted sync</h2>
<h2 id="connection">Connection, routing, and sync</h2>
<table class="api-table">
<thead>
<tr><th>Method</th><th>Purpose</th></tr>
Expand All @@ -280,7 +280,7 @@ const error = `try {
<tr><td><code>checkDirectAccess()</code></td><td>Read same-computer availability silently</td></tr>
<tr><td><code>requestDirectAccess()</code></td><td>Prompt from a user gesture where required</td></tr>
<tr><td><code>disableDirectAccess()</code></td><td>Persist a relay-only preference for this app</td></tr>
<tr><td><code>hostedSync()</code></td><td>Return a refresh-aware sync transport for a hosted grant, or null</td></tr>
<tr><td><code>sync()</code></td><td>Return one credential-hiding sync transport for a remote, direct, or relayed authority, or null</td></tr>
<tr><td><code>pendingMutation()</code></td><td>Inspect an interrupted encrypted mutation</td></tr>
<tr><td><code>resumePendingMutation()</code></td><td>Recover its exact durable connector receipt</td></tr>
</tbody>
Expand Down
8 changes: 4 additions & 4 deletions src/pages/sdk/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export async function listOpenTasks(client: MdbaseCollectionClient<Task>) {
</tr>
<tr>
<td><code>MdbaseConnection</code></td>
<td>One collection's operations, renewal, routing, notifications, and hosted sync</td>
<td>One collection's operations, renewal, routing, notifications, and provider-neutral sync</td>
<td>Browser APIs or adapters supplied by a native shell</td>
</tr>
<tr>
Expand All @@ -97,7 +97,7 @@ export async function listOpenTasks(client: MdbaseCollectionClient<Task>) {
</tr>
<tr>
<td><code>OfflineReplica</code></td>
<td>Offline-first applications backed by a hosted collection</td>
<td>Offline-first applications backed by any sync-capable authority</td>
<td><code>@mdbase/connect-sync</code></td>
</tr>
</tbody>
Expand Down Expand Up @@ -143,7 +143,7 @@ export async function listOpenTasks(client: MdbaseCollectionClient<Task>) {
<tbody>
<tr>
<td><code>@mdbase/connect</code></td>
<td>Authorization, routes, operations, notifications, and hosted sync handoff</td>
<td>Authorization, routes, operations, notifications, and authority-neutral sync handoff</td>
</tr>
<tr>
<td><code>@mdbase/connect-dev</code></td>
Expand All @@ -155,7 +155,7 @@ export async function listOpenTasks(client: MdbaseCollectionClient<Task>) {
</tr>
<tr>
<td><code>@mdbase/connect-sync</code></td>
<td>Hosted replication state machine, IndexedDB replica, conflicts, and offline mutations</td>
<td>Authority-neutral replication state machine, IndexedDB replica, conflicts, and offline mutations</td>
</tr>
<tr>
<td><code>@mdbase/connect-webhooks</code></td>
Expand Down
Loading