Skip to content

Extensions

Extension mechanism for optional capabilities


Extensions add optional capabilities to Mesh without modifying the core protocol. They enable experimentation and domain-specific features while maintaining interoperability.


  1. Explicit — Extensions MUST be declared in the request
  2. Contained — Extension data MUST be within the extension object
  3. Additive — Extensions MUST only add, not modify core behavior
  4. Negotiated — Both client and server MUST support the extension

Extensions are declared in the extensions array as objects:

{
"protocol": { "name": "mesh", "version": "0.1.0" },
"id": "req_123",
"call": {
"function": "reports.generate",
"version": "1",
"arguments": { "type": "quarterly" }
},
"extensions": [
{
"urn": "urn:mesh:ext:async",
"options": {
"preferred": true,
"callback_url": "https://my-service.example.com/webhooks"
}
}
]
}
FieldTypeRequiredDescription
urnstringYesExtension identifier URN
optionsobjectNoExtension-specific request options

Responses mirror the request structure:

{
"protocol": { "name": "mesh", "version": "0.1.0" },
"id": "req_123",
"result": { "queued": true },
"meta": {
"duration": { "value": 45, "unit": "millisecond" }
},
"extensions": [
{
"urn": "urn:mesh:ext:async",
"data": {
"operation_id": "op_xyz789",
"status": "processing",
"poll": {
"function": "mesh.operation.status",
"version": "1",
"arguments": { "operation_id": "op_xyz789" }
}
}
}
]
}
FieldTypeRequiredDescription
urnstringYesExtension identifier URN (echoed from request)
dataobjectNoExtension-specific response data

Each extension is identified by a URN:

urn:mesh:ext:async
urn:mesh:ext:example:audit

Rules:

  • MUST be a valid URN
  • SHOULD resolve to documentation
  • SHOULD use HTTPS

When a server supports all declared extensions:

  1. Process extension-specific options
  2. Return response with same extensions (by URN)
  3. Include extension-specific response data

When a server does not support a declared extension:

{
"protocol": { "name": "mesh", "version": "0.1.0" },
"id": "req_123",
"result": null,
"errors": [{
"code": "EXTENSION_NOT_SUPPORTED",
"message": "Extension not supported: urn:mesh:ext:example:unknown",
"retryable": false,
"details": {
"unsupported": ["urn:mesh:ext:example:unknown"],
"supported": ["urn:mesh:ext:async"]
}
}]
}

Servers MUST ignore extension objects with unrecognized URIs if the request does not require them.


An extension specification MUST define:

  1. URN — Unique identifier
  2. Options — Request options the extension accepts
  3. Data — Response data the extension returns
  4. Behavior — Processing rules
  5. Examples — Usage examples
# Audit Extension
**URN:** urn:mesh:ext:audit
## Options (Request)
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `actor.user_id` | string | Yes | User performing the action |
| `actor.ip_address` | string | No | Client IP address |
| `actor.reason` | string | No | Reason for action |
## Data (Response)
| Field | Type | Description |
|-------|------|-------------|
| `log_id` | string | Audit log entry identifier |
| `logged_at` | string | ISO 8601 timestamp |
## Behavior
When the audit extension is included:
1. Server MUST log the action with actor details
2. Server MUST return `log_id` referencing the log entry
3. Log entries MUST be immutable once created

ExtensionURNDescription
Asyncurn:mesh:ext:asyncLong-running operations with polling/callbacks
Batchurn:mesh:ext:batchMultiple operations in a single request
Cachingurn:mesh:ext:cachingETags, cache hints, conditional requests
Deadlineurn:mesh:ext:deadlineRequest timeouts to prevent cascading failures
Deprecationurn:mesh:ext:deprecationWarnings for deprecated functions/versions
Dry Runurn:mesh:ext:dry-runValidate operations without executing
Idempotencyurn:mesh:ext:idempotencyRequest deduplication for safe retries
Priorityurn:mesh:ext:priorityRequest priority hints for queue management
Quotaurn:mesh:ext:quotaUsage quotas and limits information
Tracingurn:mesh:ext:tracingDistributed tracing for observability

Clients MAY discover supported extensions:

// Request
{
"protocol": { "name": "mesh", "version": "0.1.0" },
"id": "req_discover",
"call": {
"function": "mesh.capabilities",
"version": "1",
"arguments": {}
}
}
// Response
{
"protocol": { "name": "mesh", "version": "0.1.0" },
"id": "req_discover",
"result": {
"protocol_versions": ["0.1.0"],
"extensions": [
{
"urn": "urn:mesh:ext:async",
"documentation": "urn:mesh:ext:async"
}
]
}
}

See System Functions for details.


{
"protocol": { "name": "mesh", "version": "0.1.0" },
"id": "req_ext",
"call": {
"function": "users.delete",
"version": "1",
"arguments": { "user_id": 42 }
},
"context": {
"trace_id": "tr_abc",
"span_id": "sp_123"
},
"extensions": [
{
"urn": "urn:mesh:ext:audit",
"options": {
"actor": {
"user_id": "admin_1",
"ip_address": "192.168.1.1",
"reason": "GDPR deletion request"
}
}
}
]
}
{
"protocol": { "name": "mesh", "version": "0.1.0" },
"id": "req_ext",
"result": {
"deleted": true
},
"meta": {
"duration": { "value": 45, "unit": "millisecond" }
},
"extensions": [
{
"urn": "urn:mesh:ext:audit",
"data": {
"log_id": "audit_log_789",
"logged_at": "2024-03-15T14:30:00Z"
}
}
]
}
{
"protocol": { "name": "mesh", "version": "0.1.0" },
"id": "req_multi",
"call": {
"function": "reports.generate",
"version": "1",
"arguments": { "type": "quarterly" }
},
"extensions": [
{
"urn": "urn:mesh:ext:audit",
"options": {
"actor": { "user_id": "admin_1" }
}
},
{
"urn": "urn:mesh:ext:async",
"options": {
"preferred": true
}
}
]
}
{
"protocol": { "name": "mesh", "version": "0.1.0" },
"id": "req_multi",
"result": null,
"meta": {
"duration": { "value": 12, "unit": "millisecond" }
},
"extensions": [
{
"urn": "urn:mesh:ext:audit",
"data": {
"log_id": "audit_log_790"
}
},
{
"urn": "urn:mesh:ext:async",
"data": {
"operation_id": "op_abc123",
"status": "processing",
"poll": {
"function": "mesh.operation.status",
"version": "1",
"arguments": { "operation_id": "op_abc123" }
},
"retry_after": { "value": 5, "unit": "second" }
}
}
]
}