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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
uses: actions/checkout@v7
with:
repository: mdbase-dev/mdbase-connect
ref: fec3e222cebb8f1711d3e6eb111ab8f225680006
ref: e6b8c7d552c74ad6c4163733ae3337302c97e434
path: .sources/mdbase-connect

- name: Check out Rust implementation
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
uses: actions/checkout@v7
with:
repository: mdbase-dev/mdbase-connect
ref: fec3e222cebb8f1711d3e6eb111ab8f225680006
ref: e6b8c7d552c74ad6c4163733ae3337302c97e434
path: .sources/mdbase-connect

- name: Check out Rust implementation
Expand Down
9 changes: 8 additions & 1 deletion public/connect/schemas/connect-protocol.v1.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,15 @@
"operations": { "type": "array", "uniqueItems": true, "items": { "$ref": "#/$defs/operation" } },
"scope": { "$ref": "#/$defs/grantScope" },
"application_name": { "type": "string", "minLength": 1 },
"application_distribution": { "enum": ["web", "portable"] },
"application_homepage": { "type": "string" },
"application_origin": { "type": "string", "format": "uri" },
"application_project_url": { "type": "string", "format": "uri" },
"application_origin": {
"anyOf": [
{ "const": "null" },
{ "type": "string", "format": "uri" }
]
},
"application_icon": { "type": "string" },
"collection_name": { "type": "string", "minLength": 1 },
"notification_criteria": {
Expand Down
26 changes: 25 additions & 1 deletion public/connect/schemas/mdbase-app.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@
"title": "mdbase connect bundled application manifest v1",
"type": "object",
"additionalProperties": false,
"required": ["manifest_version", "id", "name", "homepage", "redirect_uris"],
"required": ["manifest_version", "id", "name"],
"properties": {
"manifest_version": { "const": 1 },
"distribution": {
"enum": ["web", "portable"],
"description": "Portable declarations use device authorization and do not claim a browser origin."
},
"id": {
"type": "string",
"minLength": 5,
Expand All @@ -16,6 +20,7 @@
},
"name": { "type": "string", "minLength": 1, "maxLength": 100 },
"homepage": { "type": "string", "format": "uri", "pattern": "^https://" },
"project_url": { "type": "string", "format": "uri", "pattern": "^https://" },
"icon": { "type": "string", "format": "uri", "pattern": "^https://" },
"redirect_uris": {
"type": "array",
Expand Down Expand Up @@ -55,6 +60,25 @@
}
}
},
"oneOf": [
{
"required": ["homepage", "redirect_uris"],
"properties": {
"distribution": { "const": "web" },
"homepage": true,
"redirect_uris": true,
"project_url": false
}
},
{
"required": ["distribution"],
"properties": {
"distribution": { "const": "portable" },
"homepage": false,
"redirect_uris": false
}
}
],
"$defs": {
"identifier": {
"type": "string",
Expand Down
26 changes: 25 additions & 1 deletion public/connect/schemas/mdbase-app.v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@
"title": "mdbase connect bundled application manifest v1",
"type": "object",
"additionalProperties": false,
"required": ["manifest_version", "id", "name", "homepage", "redirect_uris"],
"required": ["manifest_version", "id", "name"],
"properties": {
"manifest_version": { "const": 1 },
"distribution": {
"enum": ["web", "portable"],
"description": "Portable declarations use device authorization and do not claim a browser origin."
},
"id": {
"type": "string",
"minLength": 5,
Expand All @@ -16,6 +20,7 @@
},
"name": { "type": "string", "minLength": 1, "maxLength": 100 },
"homepage": { "type": "string", "format": "uri", "pattern": "^https://" },
"project_url": { "type": "string", "format": "uri", "pattern": "^https://" },
"icon": { "type": "string", "format": "uri", "pattern": "^https://" },
"redirect_uris": {
"type": "array",
Expand Down Expand Up @@ -55,6 +60,25 @@
}
}
},
"oneOf": [
{
"required": ["homepage", "redirect_uris"],
"properties": {
"distribution": { "const": "web" },
"homepage": true,
"redirect_uris": true,
"project_url": false
}
},
{
"required": ["distribution"],
"properties": {
"distribution": { "const": "portable" },
"homepage": false,
"redirect_uris": false
}
}
],
"$defs": {
"identifier": {
"type": "string",
Expand Down
2 changes: 1 addition & 1 deletion site-sources.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
},
"connect": {
"repository": "mdbase-dev/mdbase-connect",
"ref": "fec3e222cebb8f1711d3e6eb111ab8f225680006"
"ref": "e6b8c7d552c74ad6c4163733ae3337302c97e434"
},
"implementations": [
{
Expand Down
1 change: 1 addition & 0 deletions src/components/DocsLayout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const { title, description, active, headings = [] } = Astro.props;
const docs = [
{ href: "/sdk/", label: "Overview", key: "overview" },
{ href: "/sdk/quickstart/", label: "Quickstart", key: "quickstart" },
{ href: "/sdk/portable-apps/", label: "Portable HTML apps", key: "portable-apps" },
{ href: "/sdk/manifest/", label: "Application manifest", key: "manifest" },
{ href: "/sdk/contracts/", label: "Contracts and adapters", key: "contracts" },
{ href: "/sdk/authorization/", label: "Authorization", key: "authorization" },
Expand Down
10 changes: 6 additions & 4 deletions src/pages/connect/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import BaseLayout from "../../layouts/BaseLayout.astro";
const steps = [
{
title: "The application declares what it understands",
copy: "Its bundled manifest names callback URLs, required domain contracts, collection kind, and any type definitions that can be installed safely."
copy: "Its bundled v1 manifest declares web callbacks or portable distribution, required domain contracts, collection kind, and any type definitions that can be installed safely."
},
{
title: "Connect checks collection compatibility",
Expand Down Expand Up @@ -40,6 +40,7 @@ const steps = [
</p>
<div class="button-row">
<a class="button button--primary" href="/sdk/quickstart/">SDK quickstart</a>
<a class="button" href="/sdk/portable-apps/">Portable HTML apps</a>
<a class="button" href="https://github.com/mdbase-dev/mdbase-connect">View source</a>
</div>
</div>
Expand Down Expand Up @@ -151,9 +152,10 @@ const steps = [
<p>
The private-beta stack includes local and hosted authorities, encrypted
relay operations, grant narrowing and revocation, sync, notifications,
and the browser SDK. Public registration, a production restore drill,
signed desktop releases, and abuse-response operations are still required
before public registration.
the browser SDK, and key-bound authorization for downloaded HTML files.
The npm packages have not yet received their first public release. Public
registration, a production restore drill, signed desktop releases, and
abuse-response operations are still required before public registration.
</p>
<div class="button-row" style="margin-top: 2rem">
<a class="button button--primary" href="/sdk/">Read the SDK documentation</a>
Expand Down
35 changes: 27 additions & 8 deletions src/pages/sdk/api/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const error = `try {
active="api"
headings={[
{ href: "#constructor", label: "Constructor" },
{ href: "#environment", label: "Environment" },
{ href: "#authorization", label: "Authorization methods" },
{ href: "#operations", label: "Operation methods" },
{ href: "#notifications", label: "Notifications and timers" },
Expand Down Expand Up @@ -62,13 +63,13 @@ const error = `try {
</tr>
<tr>
<td><code>redirectUri</code></td>
<td>Current page where supported</td>
<td>Exact callback listed in the manifest</td>
<td>Current page for web; unused for portable files</td>
<td>Exact callback listed in a web or native manifest</td>
</tr>
<tr>
<td><code>storage</code></td>
<td><code>localStorage</code></td>
<td>Authorization persistence boundary</td>
<td><code>localStorage</code> for web; memory for opaque portable files</td>
<td>Authorization credential boundary</td>
</tr>
<tr>
<td><code>relayEncryption</code></td>
Expand All @@ -77,7 +78,7 @@ const error = `try {
</tr>
<tr>
<td><code>keyStore</code></td>
<td>IndexedDB non-extractable key store</td>
<td>IndexedDB for web; memory for opaque portable files</td>
<td>Override encrypted grant key persistence</td>
</tr>
<tr>
Expand All @@ -98,6 +99,15 @@ const error = `try {
</tbody>
</table>

<h2 id="environment">Runtime environment</h2>
<p>
<code>environment()</code> returns the effective
{" "}<code>distribution</code>, <code>applicationOrigin</code>, and
{" "}<code>credentialStorage</code>. Portable files report origin
{" "}<code>null</code> and default to <code>memory</code>. A caller-supplied
storage or key adapter reports <code>custom</code>.
</p>

<h2 id="authorization">Registration and authorization</h2>
<table class="api-table">
<thead>
Expand All @@ -115,13 +125,13 @@ const error = `try {
</tr>
<tr>
<td><code>authorize(options?)</code></td>
<td>Does not return</td>
<td>Start PKCE; options include operations, collectionId hint, and returnTo</td>
<td><code>Promise&lt;MdbaseAuthorizationResult&gt;</code></td>
<td>Navigate for web/native, or resolve after short-code approval for portable files</td>
</tr>
<tr>
<td><code>completeAuthorization(callbackUrl?)</code></td>
<td><code>MdbaseAuthorizationResult</code></td>
<td>Return the bound connection and app-local returnTo value</td>
<td>Complete a web or native callback and return its bound connection</td>
</tr>
<tr>
<td><code>connections()</code></td>
Expand All @@ -145,6 +155,15 @@ const error = `try {
</tr>
</tbody>
</table>
<h3>Portable authorization options</h3>
<p>
<code>authorize()</code> accepts <code>onDeviceCode</code> to report
{" "}<code>userCode</code>, <code>verificationUri</code>,
{" "}<code>verificationUriComplete</code>, <code>expiresAt</code>, and
{" "}<code>intervalSeconds</code>. Supply <code>openVerification</code> to own
the approval window, or an <code>AbortSignal</code> to cancel polling and
discard the unapproved key.
</p>

<h2 id="operations">Collection operations</h2>
<p>
Expand Down
31 changes: 31 additions & 0 deletions src/pages/sdk/authorization/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,24 @@ const recover = `try {
}
throw error;
}`;

const portableAuthorize = `const controller = new AbortController();

const { connection } = await connect.authorize({
operations: ["describe", "read", "query"],
onDeviceCode: ({ userCode, verificationUriComplete }) => {
renderApprovalCode(userCode, verificationUriComplete);
},
signal: controller.signal
});`;
---

<DocsLayout
title="Authorization"
description="Request operation grants at the point of use and handle narrowing, pause, or revocation."
active="authorization"
headings={[
{ href: "#flows", label: "Authorization flows" },
{ href: "#operations", label: "Operation grants" },
{ href: "#step-up", label: "Step-up authorization" },
{ href: "#connection", label: "Connection state" },
Expand All @@ -69,6 +80,26 @@ const recover = `try {
through a <code>MdbaseConnection</code> bound to one collection ID.
</p>

<h2 id="flows">Use the flow selected by the manifest</h2>
<p>
Web and native-shell manifests use an authorization-code redirect with
PKCE. <code>authorize()</code> navigates away, and the callback route calls
{" "}<code>completeAuthorization()</code>.
</p>
<p>
A <code>distribution: "portable"</code> manifest uses short-code device
authorization with PKCE and a P-256 application key.
<code>authorize()</code> opens the approval page, polls at the server
interval, and resolves with the collection-bound connection after approval.
</p>
<CodeBlock code={portableAuthorize} language="ts" label="portable-authorization.ts" />
<p>
The abort signal stops polling and discards the unapproved in-memory key.
Use <code>openVerification</code> when a shell owns the approval window.
See the <a href="/sdk/portable-apps/">portable HTML application guide</a>
for the complete downloaded-file boundary.
</p>

<h2 id="operations">Choose operations by feature</h2>
<table class="api-table">
<thead>
Expand Down
Loading