1343 lines
35 KiB
Markdown
1343 lines
35 KiB
Markdown
|
|
# AdapterInterfaceSpecification.md
|
|||
|
|
|
|||
|
|
## 1. Document Status
|
|||
|
|
|
|||
|
|
**Document:** AdapterInterfaceSpecification.md
|
|||
|
|
**Project:** coordination-engine
|
|||
|
|
**Version:** 1.0
|
|||
|
|
**Status:** Release Candidate
|
|||
|
|
**Scope:** Contract between coordination-engine and external adapters
|
|||
|
|
**Primary Reference Adapter:** email-connect
|
|||
|
|
|
|||
|
|
## 2. Purpose
|
|||
|
|
|
|||
|
|
This document defines the adapter interface contract between `coordination-engine` and external adapter components such as `email-connect`, `rss-connect`, `sms-connect`, `push-connect`, `xmpp-connect`, `portal-connect`, `payment-connect`, `signature-connect`, `document-connect`, `identity-connect`, and future adapters.
|
|||
|
|
|
|||
|
|
The adapter interface allows `coordination-engine` to remain protocol-neutral while integrating with concrete technologies, providers, systems, and communication channels.
|
|||
|
|
|
|||
|
|
Adapters translate between external systems and the internal coordination model by:
|
|||
|
|
|
|||
|
|
1. Declaring capabilities.
|
|||
|
|
2. Accepting action requests.
|
|||
|
|
3. Returning action results.
|
|||
|
|
4. Emitting normalized evidence events.
|
|||
|
|
5. Exposing health and operational state.
|
|||
|
|
6. Preserving correlation between coordination cases and external provider events.
|
|||
|
|
|
|||
|
|
The goal of this specification is to ensure that adapters are independently useful components while still being compatible with `coordination-engine`.
|
|||
|
|
|
|||
|
|
## 3. Core Design Principle
|
|||
|
|
|
|||
|
|
Adapters are not merely transport drivers.
|
|||
|
|
|
|||
|
|
An adapter is a capability component that can perform actions and produce evidence.
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
Adapter = Capability Descriptor + Action Provider + Signal Provider
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
The coordination engine remains responsible for:
|
|||
|
|
|
|||
|
|
* coordination case lifecycle
|
|||
|
|
* result evaluation
|
|||
|
|
* participant state derivation
|
|||
|
|
* policy decisions
|
|||
|
|
* follow-up decisions
|
|||
|
|
* uncertainty handling
|
|||
|
|
* case-level success/failure/expiry/escalation
|
|||
|
|
|
|||
|
|
The adapter remains responsible for:
|
|||
|
|
|
|||
|
|
* provider-specific integration
|
|||
|
|
* protocol-specific action execution
|
|||
|
|
* native event ingestion
|
|||
|
|
* native-to-normalized event mapping
|
|||
|
|
* adapter-level diagnostics
|
|||
|
|
* provider-level correlation
|
|||
|
|
* adapter health reporting
|
|||
|
|
|
|||
|
|
## 4. Boundary Between coordination-engine and Adapters
|
|||
|
|
|
|||
|
|
### 4.1 coordination-engine Owns
|
|||
|
|
|
|||
|
|
`coordination-engine` owns:
|
|||
|
|
|
|||
|
|
* `CoordinationCase`
|
|||
|
|
* `Participant`
|
|||
|
|
* `IntendedResult`
|
|||
|
|
* case-level state
|
|||
|
|
* participant-level state
|
|||
|
|
* result predicates
|
|||
|
|
* policy evaluation
|
|||
|
|
* next-action selection
|
|||
|
|
* evidence ledger
|
|||
|
|
* adapter selection
|
|||
|
|
* scenario-specific orchestration
|
|||
|
|
* closure, failure, expiry, escalation, and manual override
|
|||
|
|
|
|||
|
|
### 4.2 Adapters Own
|
|||
|
|
|
|||
|
|
Adapters own:
|
|||
|
|
|
|||
|
|
* provider communication
|
|||
|
|
* protocol-specific execution
|
|||
|
|
* provider credentials and configuration
|
|||
|
|
* native event ingestion
|
|||
|
|
* provider-native identifiers
|
|||
|
|
* native status interpretation
|
|||
|
|
* native-to-normalized event mapping
|
|||
|
|
* adapter-specific retries where appropriate
|
|||
|
|
* adapter-specific diagnostics
|
|||
|
|
* adapter health
|
|||
|
|
|
|||
|
|
### 4.3 Shared Contract
|
|||
|
|
|
|||
|
|
The shared contract consists of:
|
|||
|
|
|
|||
|
|
* `AdapterDescriptor`
|
|||
|
|
* `AdapterCapability`
|
|||
|
|
* `AdapterActionRequest`
|
|||
|
|
* `AdapterActionResult`
|
|||
|
|
* `AdapterEvent`
|
|||
|
|
* `EvidenceEvent`
|
|||
|
|
* `AdapterHealth`
|
|||
|
|
* `CorrelationContext`
|
|||
|
|
* `EvidenceGrade`
|
|||
|
|
* `ErrorDescriptor`
|
|||
|
|
|
|||
|
|
## 5. Adapter Types
|
|||
|
|
|
|||
|
|
An adapter may belong to one or more adapter types.
|
|||
|
|
|
|||
|
|
Recommended canonical adapter types:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
notification
|
|||
|
|
communication
|
|||
|
|
access
|
|||
|
|
delivery
|
|||
|
|
interaction
|
|||
|
|
identity
|
|||
|
|
authority
|
|||
|
|
payment
|
|||
|
|
signature
|
|||
|
|
document
|
|||
|
|
archive
|
|||
|
|
crm
|
|||
|
|
erp
|
|||
|
|
webhook
|
|||
|
|
feed
|
|||
|
|
system
|
|||
|
|
manual
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Examples:
|
|||
|
|
|
|||
|
|
| Adapter repo | Likely adapter types |
|
|||
|
|
| ------------------- | ---------------------------------------- |
|
|||
|
|
| `email-connect` | notification, communication, interaction |
|
|||
|
|
| `rss-connect` | notification, feed, communication |
|
|||
|
|
| `sms-connect` | notification, communication |
|
|||
|
|
| `push-connect` | notification, interaction |
|
|||
|
|
| `portal-connect` | access, delivery, interaction, identity |
|
|||
|
|
| `payment-connect` | payment, interaction, delivery |
|
|||
|
|
| `signature-connect` | signature, identity, authority, delivery |
|
|||
|
|
| `document-connect` | document, payload, archive, delivery |
|
|||
|
|
| `identity-connect` | identity, authority |
|
|||
|
|
| `webhook-connect` | system, delivery, interaction |
|
|||
|
|
|
|||
|
|
Adapter type is descriptive, not exclusive.
|
|||
|
|
|
|||
|
|
An adapter may expose capabilities from multiple types if that reflects its real function.
|
|||
|
|
|
|||
|
|
## 6. Normative Language
|
|||
|
|
|
|||
|
|
The following terms are used in this specification:
|
|||
|
|
|
|||
|
|
* **MUST** means required for contract compliance.
|
|||
|
|
* **SHOULD** means recommended unless a documented reason exists.
|
|||
|
|
* **MAY** means optional.
|
|||
|
|
* **MUST NOT** means prohibited for contract compliance.
|
|||
|
|
|
|||
|
|
## 7. Core Interface Objects
|
|||
|
|
|
|||
|
|
## 7.1 AdapterDescriptor
|
|||
|
|
|
|||
|
|
An `AdapterDescriptor` declares the identity, version, capabilities, event support, evidence profile, and operational characteristics of an adapter.
|
|||
|
|
|
|||
|
|
Adapters MUST expose a descriptor.
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
AdapterDescriptor:
|
|||
|
|
adapter_id: string
|
|||
|
|
adapter_name: string
|
|||
|
|
adapter_version: string
|
|||
|
|
adapter_contract_version: string
|
|||
|
|
adapter_types:
|
|||
|
|
- string
|
|||
|
|
provider_family: string?
|
|||
|
|
provider_name: string?
|
|||
|
|
deployment_mode: embedded | sidecar | external | unknown
|
|||
|
|
supported_actions:
|
|||
|
|
- AdapterActionCapability
|
|||
|
|
emitted_event_types:
|
|||
|
|
- string
|
|||
|
|
supported_channels:
|
|||
|
|
- string
|
|||
|
|
supported_endpoint_types:
|
|||
|
|
- string
|
|||
|
|
evidence_profile: AdapterEvidenceProfile
|
|||
|
|
identity_profile: AdapterIdentityProfile
|
|||
|
|
latency_profile: AdapterLatencyProfile?
|
|||
|
|
cost_profile: AdapterCostProfile?
|
|||
|
|
reliability_profile: AdapterReliabilityProfile?
|
|||
|
|
configuration_schema_ref: string?
|
|||
|
|
health_endpoint_ref: string?
|
|||
|
|
documentation_ref: string?
|
|||
|
|
limitations:
|
|||
|
|
- string
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Required Fields
|
|||
|
|
|
|||
|
|
The following fields are REQUIRED:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
adapter_id
|
|||
|
|
adapter_name
|
|||
|
|
adapter_version
|
|||
|
|
adapter_contract_version
|
|||
|
|
adapter_types
|
|||
|
|
supported_actions
|
|||
|
|
emitted_event_types
|
|||
|
|
supported_channels
|
|||
|
|
supported_endpoint_types
|
|||
|
|
evidence_profile
|
|||
|
|
identity_profile
|
|||
|
|
limitations
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Example: email-connect
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
adapter_id: email-connect.default
|
|||
|
|
adapter_name: email-connect
|
|||
|
|
adapter_version: 1.0.0
|
|||
|
|
adapter_contract_version: 1.0
|
|||
|
|
adapter_types:
|
|||
|
|
- notification
|
|||
|
|
- communication
|
|||
|
|
- interaction
|
|||
|
|
provider_family: email
|
|||
|
|
provider_name: configurable
|
|||
|
|
deployment_mode: external
|
|||
|
|
supported_channels:
|
|||
|
|
- email
|
|||
|
|
supported_endpoint_types:
|
|||
|
|
- email_address
|
|||
|
|
supported_actions:
|
|||
|
|
- action_type: notification.send
|
|||
|
|
mode: async
|
|||
|
|
idempotency_required: true
|
|||
|
|
- action_type: notification.send_reminder
|
|||
|
|
mode: async
|
|||
|
|
idempotency_required: true
|
|||
|
|
- action_type: recipient.suppress
|
|||
|
|
mode: sync
|
|||
|
|
idempotency_required: true
|
|||
|
|
- action_type: recipient.unsuppress
|
|||
|
|
mode: sync
|
|||
|
|
idempotency_required: true
|
|||
|
|
emitted_event_types:
|
|||
|
|
- notification.attempt.accepted_by_provider
|
|||
|
|
- notification.attempt.rejected_by_provider
|
|||
|
|
- notification.endpoint.accepted
|
|||
|
|
- notification.endpoint.deferred
|
|||
|
|
- notification.endpoint.rejected_permanent
|
|||
|
|
- notification.channel.complaint_received
|
|||
|
|
- interaction.proxy_or_privacy_interaction
|
|||
|
|
- interaction.scanner_or_bot_interaction
|
|||
|
|
- interaction.unverified_actor_interaction
|
|||
|
|
- interaction.reply_received
|
|||
|
|
evidence_profile:
|
|||
|
|
strongest_evidence_level: weak_to_medium
|
|||
|
|
can_prove_human_awareness: false
|
|||
|
|
can_prove_payload_delivery: false
|
|||
|
|
can_prove_identity: false
|
|||
|
|
identity_profile:
|
|||
|
|
identity_strength: none
|
|||
|
|
authority_strength: none
|
|||
|
|
limitations:
|
|||
|
|
- Recipient mail server acceptance does not prove inbox delivery.
|
|||
|
|
- Open tracking is ambiguous and may be caused by privacy proxies.
|
|||
|
|
- Click tracking may be caused by security scanners.
|
|||
|
|
- Email events alone usually cannot prove intended-recipient awareness.
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 7.2 AdapterActionCapability
|
|||
|
|
|
|||
|
|
An `AdapterActionCapability` declares one action an adapter can perform.
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
AdapterActionCapability:
|
|||
|
|
action_type: string
|
|||
|
|
description: string?
|
|||
|
|
mode: sync | async | scheduled
|
|||
|
|
idempotency_required: boolean
|
|||
|
|
required_fields:
|
|||
|
|
- string
|
|||
|
|
optional_fields:
|
|||
|
|
- string
|
|||
|
|
supported_channels:
|
|||
|
|
- string
|
|||
|
|
supported_endpoint_types:
|
|||
|
|
- string
|
|||
|
|
expected_initial_events:
|
|||
|
|
- string
|
|||
|
|
possible_later_events:
|
|||
|
|
- string
|
|||
|
|
known_failure_modes:
|
|||
|
|
- string
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Action Type Naming
|
|||
|
|
|
|||
|
|
Action types SHOULD use dotted semantic names.
|
|||
|
|
|
|||
|
|
Recommended families:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
notification.*
|
|||
|
|
access.*
|
|||
|
|
delivery.*
|
|||
|
|
interaction.*
|
|||
|
|
identity.*
|
|||
|
|
authority.*
|
|||
|
|
payment.*
|
|||
|
|
signature.*
|
|||
|
|
document.*
|
|||
|
|
archive.*
|
|||
|
|
feed.*
|
|||
|
|
webhook.*
|
|||
|
|
recipient.*
|
|||
|
|
system.*
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Examples:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
notification.send
|
|||
|
|
notification.send_reminder
|
|||
|
|
access.grant
|
|||
|
|
access.revoke
|
|||
|
|
delivery.publish_payload
|
|||
|
|
delivery.request_submission
|
|||
|
|
payment.create_request
|
|||
|
|
payment.cancel_request
|
|||
|
|
signature.create_envelope
|
|||
|
|
signature.cancel_envelope
|
|||
|
|
feed.publish_item
|
|||
|
|
recipient.suppress
|
|||
|
|
recipient.unsuppress
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 7.3 AdapterActionRequest
|
|||
|
|
|
|||
|
|
An `AdapterActionRequest` is a command from `coordination-engine` to an adapter.
|
|||
|
|
|
|||
|
|
Adapters MUST accept action requests in this conceptual shape, even if transport-specific serialization differs.
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
AdapterActionRequest:
|
|||
|
|
request_id: string
|
|||
|
|
action_type: string
|
|||
|
|
coordination_case_id: string
|
|||
|
|
participant_id: string?
|
|||
|
|
payload_ref: ResourceRef?
|
|||
|
|
action_surface_ref: ResourceRef?
|
|||
|
|
channel: string?
|
|||
|
|
target_endpoint: EndpointRef?
|
|||
|
|
actor_context: ActorContext?
|
|||
|
|
content: ActionContent?
|
|||
|
|
template_ref: string?
|
|||
|
|
variables: object?
|
|||
|
|
tracking_context: TrackingContext
|
|||
|
|
policy_context: PolicyContext?
|
|||
|
|
security_context: SecurityContext?
|
|||
|
|
idempotency_key: string
|
|||
|
|
requested_at: timestamp
|
|||
|
|
expires_at: timestamp?
|
|||
|
|
metadata: object?
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Required Fields
|
|||
|
|
|
|||
|
|
The following fields are REQUIRED:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
request_id
|
|||
|
|
action_type
|
|||
|
|
coordination_case_id
|
|||
|
|
tracking_context
|
|||
|
|
idempotency_key
|
|||
|
|
requested_at
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Fields such as `participant_id`, `payload_ref`, `target_endpoint`, or `action_surface_ref` may be optional for system-level or broadcast actions, but adapters MAY require them for specific action types.
|
|||
|
|
|
|||
|
|
### Idempotency
|
|||
|
|
|
|||
|
|
`idempotency_key` MUST be provided for all externally visible actions.
|
|||
|
|
|
|||
|
|
Adapters MUST treat repeated action requests with the same `idempotency_key` as duplicates of the same logical request.
|
|||
|
|
|
|||
|
|
Adapters SHOULD return the original or current action result for duplicate requests.
|
|||
|
|
|
|||
|
|
### Correlation
|
|||
|
|
|
|||
|
|
`tracking_context` MUST contain enough information to correlate later adapter events back to the coordination case.
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
TrackingContext:
|
|||
|
|
correlation_id: string
|
|||
|
|
coordination_case_id: string
|
|||
|
|
participant_id: string?
|
|||
|
|
notification_id: string?
|
|||
|
|
delivery_id: string?
|
|||
|
|
interaction_id: string?
|
|||
|
|
payload_id: string?
|
|||
|
|
action_surface_id: string?
|
|||
|
|
external_context:
|
|||
|
|
- key: string
|
|||
|
|
value: string
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### EndpointRef
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
EndpointRef:
|
|||
|
|
endpoint_id: string?
|
|||
|
|
endpoint_type: string
|
|||
|
|
value: string?
|
|||
|
|
display_name: string?
|
|||
|
|
verified: boolean?
|
|||
|
|
metadata: object?
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Examples of `endpoint_type`:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
email_address
|
|||
|
|
phone_number
|
|||
|
|
push_token
|
|||
|
|
xmpp_jid
|
|||
|
|
rss_feed
|
|||
|
|
webhook_url
|
|||
|
|
portal_account
|
|||
|
|
payment_account
|
|||
|
|
signature_recipient
|
|||
|
|
api_client
|
|||
|
|
physical_address
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### ActionContent
|
|||
|
|
|
|||
|
|
`ActionContent` represents content or content references.
|
|||
|
|
|
|||
|
|
Adapters SHOULD prefer references over large inline content where possible.
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
ActionContent:
|
|||
|
|
content_ref: string?
|
|||
|
|
subject: string?
|
|||
|
|
body_text: string?
|
|||
|
|
body_html: string?
|
|||
|
|
payload_refs:
|
|||
|
|
- ResourceRef
|
|||
|
|
action_links:
|
|||
|
|
- ActionLink
|
|||
|
|
attachments:
|
|||
|
|
- ResourceRef
|
|||
|
|
inline_data: object?
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### ResourceRef
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
ResourceRef:
|
|||
|
|
ref_type: string
|
|||
|
|
ref_id: string
|
|||
|
|
uri: string?
|
|||
|
|
version: string?
|
|||
|
|
integrity_hash: string?
|
|||
|
|
metadata: object?
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### ActionLink
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
ActionLink:
|
|||
|
|
link_id: string
|
|||
|
|
purpose: string
|
|||
|
|
url: string
|
|||
|
|
expires_at: timestamp?
|
|||
|
|
tokenized: boolean?
|
|||
|
|
requires_authentication: boolean?
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 7.4 AdapterActionResult
|
|||
|
|
|
|||
|
|
An `AdapterActionResult` is the adapter’s response to an action request.
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
AdapterActionResult:
|
|||
|
|
request_id: string
|
|||
|
|
adapter_id: string
|
|||
|
|
accepted: boolean
|
|||
|
|
action_state: AdapterActionState
|
|||
|
|
adapter_operation_id: string?
|
|||
|
|
provider_operation_id: string?
|
|||
|
|
initial_events:
|
|||
|
|
- EvidenceEvent
|
|||
|
|
raw_response_ref: string?
|
|||
|
|
error: ErrorDescriptor?
|
|||
|
|
received_at: timestamp
|
|||
|
|
completed_at: timestamp?
|
|||
|
|
metadata: object?
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### AdapterActionState
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
accepted
|
|||
|
|
rejected
|
|||
|
|
queued
|
|||
|
|
scheduled
|
|||
|
|
in_progress
|
|||
|
|
completed
|
|||
|
|
failed
|
|||
|
|
cancelled
|
|||
|
|
duplicate
|
|||
|
|
unknown
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Important Rule
|
|||
|
|
|
|||
|
|
An accepted action result is not proof that the intended result was achieved.
|
|||
|
|
|
|||
|
|
Example:
|
|||
|
|
|
|||
|
|
For email, `accepted: true` means the email adapter accepted the send request. It does not prove that the recipient received, saw, understood, or acted on the notification.
|
|||
|
|
|
|||
|
|
## 7.5 AdapterEvent
|
|||
|
|
|
|||
|
|
An `AdapterEvent` is an incoming event from an adapter before or during evidence normalization.
|
|||
|
|
|
|||
|
|
Adapters MAY expose native-like adapter events, but MUST provide a mapping to `EvidenceEvent`.
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
AdapterEvent:
|
|||
|
|
event_id: string
|
|||
|
|
adapter_id: string
|
|||
|
|
adapter_event_type: string
|
|||
|
|
native_event_type: string?
|
|||
|
|
occurred_at: timestamp
|
|||
|
|
received_at: timestamp
|
|||
|
|
correlation: CorrelationContext
|
|||
|
|
participant_id: string?
|
|||
|
|
payload_ref: ResourceRef?
|
|||
|
|
action_surface_ref: ResourceRef?
|
|||
|
|
endpoint_ref: EndpointRef?
|
|||
|
|
actor_context: ActorContext?
|
|||
|
|
provider_refs:
|
|||
|
|
- ProviderRef
|
|||
|
|
raw_event_ref: string?
|
|||
|
|
normalization_status: normalized | ignored | failed | pending
|
|||
|
|
normalized_events:
|
|||
|
|
- EvidenceEvent
|
|||
|
|
metadata: object?
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 7.6 EvidenceEvent
|
|||
|
|
|
|||
|
|
An `EvidenceEvent` is the normalized event format consumed by the `evidence-ledger`.
|
|||
|
|
|
|||
|
|
Adapters MUST produce or enable production of `EvidenceEvent` records.
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
EvidenceEvent:
|
|||
|
|
evidence_event_id: string
|
|||
|
|
event_type: string
|
|||
|
|
event_family: string
|
|||
|
|
occurred_at: timestamp
|
|||
|
|
observed_at: timestamp
|
|||
|
|
source_adapter_id: string?
|
|||
|
|
source_adapter_event_id: string?
|
|||
|
|
coordination_case_id: string
|
|||
|
|
participant_id: string?
|
|||
|
|
payload_ref: ResourceRef?
|
|||
|
|
action_surface_ref: ResourceRef?
|
|||
|
|
endpoint_ref: EndpointRef?
|
|||
|
|
actor_context: ActorContext?
|
|||
|
|
provider_refs:
|
|||
|
|
- ProviderRef
|
|||
|
|
normalized_meaning: string
|
|||
|
|
evidence_grade: EvidenceGrade
|
|||
|
|
confidence: ConfidenceGrade
|
|||
|
|
raw_event_ref: string?
|
|||
|
|
correlation: CorrelationContext
|
|||
|
|
metadata: object?
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Required Fields
|
|||
|
|
|
|||
|
|
The following fields are REQUIRED:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
evidence_event_id
|
|||
|
|
event_type
|
|||
|
|
event_family
|
|||
|
|
occurred_at
|
|||
|
|
observed_at
|
|||
|
|
coordination_case_id
|
|||
|
|
normalized_meaning
|
|||
|
|
evidence_grade
|
|||
|
|
confidence
|
|||
|
|
correlation
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 8. Canonical Event Families
|
|||
|
|
|
|||
|
|
The following event families are canonical for adapter-generated evidence.
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
notification
|
|||
|
|
access
|
|||
|
|
delivery
|
|||
|
|
interaction
|
|||
|
|
identity
|
|||
|
|
authority
|
|||
|
|
payload
|
|||
|
|
payment
|
|||
|
|
signature
|
|||
|
|
feed
|
|||
|
|
webhook
|
|||
|
|
system
|
|||
|
|
manual
|
|||
|
|
result
|
|||
|
|
policy
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Adapters SHOULD map native events into these families.
|
|||
|
|
|
|||
|
|
## 9. Canonical Event Types
|
|||
|
|
|
|||
|
|
This version defines a starter vocabulary. It is not exhaustive.
|
|||
|
|
|
|||
|
|
## 9.1 Notification Events
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
notification.attempt.created
|
|||
|
|
notification.attempt.accepted_by_adapter
|
|||
|
|
notification.attempt.rejected_by_adapter
|
|||
|
|
notification.attempt.accepted_by_provider
|
|||
|
|
notification.attempt.rejected_by_provider
|
|||
|
|
notification.attempt.queued
|
|||
|
|
notification.attempt.scheduled
|
|||
|
|
notification.attempt.delayed
|
|||
|
|
notification.attempt.cancelled
|
|||
|
|
notification.endpoint.accepted
|
|||
|
|
notification.endpoint.deferred
|
|||
|
|
notification.endpoint.rejected_temporary
|
|||
|
|
notification.endpoint.rejected_permanent
|
|||
|
|
notification.endpoint.unreachable
|
|||
|
|
notification.endpoint.unknown
|
|||
|
|
notification.channel.complaint_received
|
|||
|
|
notification.channel.unsubscribe_received
|
|||
|
|
notification.channel.suppression_added
|
|||
|
|
notification.channel.suppression_removed
|
|||
|
|
notification.channel.reputation_warning
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 9.2 Access Events
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
access.grant.created
|
|||
|
|
access.grant.issued
|
|||
|
|
access.grant.used
|
|||
|
|
access.grant.denied
|
|||
|
|
access.grant.expired
|
|||
|
|
access.grant.revoked
|
|||
|
|
access.grant.delegated
|
|||
|
|
access.grant.suspicious_use_detected
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 9.3 Delivery Events
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
delivery.payload.available
|
|||
|
|
delivery.payload.presented
|
|||
|
|
delivery.payload.viewed
|
|||
|
|
delivery.payload.retrieved
|
|||
|
|
delivery.payload.downloaded
|
|||
|
|
delivery.payload.submitted
|
|||
|
|
delivery.payload.received
|
|||
|
|
delivery.payload.validated
|
|||
|
|
delivery.payload.validation_failed
|
|||
|
|
delivery.payload.accepted
|
|||
|
|
delivery.payload.rejected
|
|||
|
|
delivery.payload.archived
|
|||
|
|
delivery.payload.failed
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 9.4 Interaction Events
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
interaction.surface.opened
|
|||
|
|
interaction.notification.opened
|
|||
|
|
interaction.link.clicked
|
|||
|
|
interaction.proxy_or_privacy_interaction
|
|||
|
|
interaction.scanner_or_bot_interaction
|
|||
|
|
interaction.unverified_actor_interaction
|
|||
|
|
interaction.authenticated_actor_interaction
|
|||
|
|
interaction.authorized_actor_interaction
|
|||
|
|
interaction.reply_received
|
|||
|
|
interaction.out_of_office_received
|
|||
|
|
interaction.acknowledgement_recorded
|
|||
|
|
interaction.decline_recorded
|
|||
|
|
interaction.dispute_opened
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 9.5 Identity Events
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
identity.actor_unknown
|
|||
|
|
identity.actor_suspected
|
|||
|
|
identity.actor_authenticated
|
|||
|
|
identity.actor_mfa_verified
|
|||
|
|
identity.actor_verified_by_provider
|
|||
|
|
identity.actor_mismatch_detected
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 9.6 Authority Events
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
authority.unknown
|
|||
|
|
authority.self_asserted
|
|||
|
|
authority.delegate_authorized
|
|||
|
|
authority.organizational_representative_verified
|
|||
|
|
authority.signer_authorized
|
|||
|
|
authority.payment_authorized
|
|||
|
|
authority.authorization_failed
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 9.7 Payment Events
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
payment.request.created
|
|||
|
|
payment.request.presented
|
|||
|
|
payment.started
|
|||
|
|
payment.failed
|
|||
|
|
payment.cancelled
|
|||
|
|
payment.succeeded
|
|||
|
|
payment.settled
|
|||
|
|
payment.partially_settled
|
|||
|
|
payment.refunded
|
|||
|
|
payment.disputed
|
|||
|
|
payment.promise_to_pay_recorded
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 9.8 Signature Events
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
signature.envelope.created
|
|||
|
|
signature.envelope.sent
|
|||
|
|
signature.document.viewed
|
|||
|
|
signature.signing.started
|
|||
|
|
signature.signing.completed
|
|||
|
|
signature.signing.declined
|
|||
|
|
signature.signing.expired
|
|||
|
|
signature.signing.cancelled
|
|||
|
|
signature.document.finalized
|
|||
|
|
signature.document.archived
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 9.9 Feed/Webhook/System Events
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
feed.item.published
|
|||
|
|
feed.item.updated
|
|||
|
|
feed.item.removed
|
|||
|
|
feed.item.fetched
|
|||
|
|
webhook.request.sent
|
|||
|
|
webhook.response.accepted
|
|||
|
|
webhook.response.rejected
|
|||
|
|
webhook.delivery.failed
|
|||
|
|
system.adapter.health_changed
|
|||
|
|
system.provider.degraded
|
|||
|
|
system.provider.unavailable
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 10. EvidenceGrade
|
|||
|
|
|
|||
|
|
An `EvidenceGrade` describes what an event can reasonably support.
|
|||
|
|
|
|||
|
|
Adapters MUST assign an evidence grade to normalized evidence events.
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
EvidenceGrade:
|
|||
|
|
strength: none | weak | medium | strong | conclusive | negative | ambiguous
|
|||
|
|
actor_certainty: none | low | medium | high
|
|||
|
|
authority_certainty: none | low | medium | high
|
|||
|
|
payload_certainty: none | low | medium | high
|
|||
|
|
interaction_certainty: none | low | medium | high
|
|||
|
|
timing_certainty: none | low | medium | high
|
|||
|
|
channel_certainty: none | low | medium | high
|
|||
|
|
non_repudiation_strength: none | low | medium | high
|
|||
|
|
notes:
|
|||
|
|
- string
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Examples
|
|||
|
|
|
|||
|
|
#### Email MX Acceptance
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
strength: weak
|
|||
|
|
actor_certainty: none
|
|||
|
|
authority_certainty: none
|
|||
|
|
payload_certainty: low
|
|||
|
|
interaction_certainty: none
|
|||
|
|
timing_certainty: medium
|
|||
|
|
channel_certainty: medium
|
|||
|
|
non_repudiation_strength: none
|
|||
|
|
notes:
|
|||
|
|
- Recipient mail server acceptance does not prove inbox placement or human awareness.
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### Scanner-Like Email Click
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
strength: ambiguous
|
|||
|
|
actor_certainty: low
|
|||
|
|
authority_certainty: none
|
|||
|
|
payload_certainty: low
|
|||
|
|
interaction_certainty: low
|
|||
|
|
timing_certainty: medium
|
|||
|
|
channel_certainty: medium
|
|||
|
|
non_repudiation_strength: none
|
|||
|
|
notes:
|
|||
|
|
- Click appears automated and should not be treated as recipient engagement.
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### Authenticated Portal Download
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
strength: strong
|
|||
|
|
actor_certainty: high
|
|||
|
|
authority_certainty: medium
|
|||
|
|
payload_certainty: high
|
|||
|
|
interaction_certainty: high
|
|||
|
|
timing_certainty: high
|
|||
|
|
channel_certainty: high
|
|||
|
|
non_repudiation_strength: medium
|
|||
|
|
notes:
|
|||
|
|
- Authenticated participant retrieved the payload.
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### Qualified Signature
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
strength: conclusive
|
|||
|
|
actor_certainty: high
|
|||
|
|
authority_certainty: high
|
|||
|
|
payload_certainty: high
|
|||
|
|
interaction_certainty: high
|
|||
|
|
timing_certainty: high
|
|||
|
|
channel_certainty: high
|
|||
|
|
non_repudiation_strength: high
|
|||
|
|
notes:
|
|||
|
|
- Signature provider reports completed signing with verified signer identity and document integrity.
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 11. ConfidenceGrade
|
|||
|
|
|
|||
|
|
`ConfidenceGrade` expresses how confident the adapter is in the normalized interpretation.
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
ConfidenceGrade:
|
|||
|
|
level: low | medium | high
|
|||
|
|
basis:
|
|||
|
|
- string
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Example:
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
level: medium
|
|||
|
|
basis:
|
|||
|
|
- Provider event type is known.
|
|||
|
|
- Native event contains provider message ID.
|
|||
|
|
- Event was correlated to known action request.
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 12. ActorContext
|
|||
|
|
|
|||
|
|
`ActorContext` describes the actor associated with an event, if known.
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
ActorContext:
|
|||
|
|
actor_ref: string?
|
|||
|
|
actor_type: human | organization | system | agent | bot | unknown
|
|||
|
|
identity_strength: none | low | medium | high
|
|||
|
|
authority_strength: none | low | medium | high
|
|||
|
|
authenticated: boolean?
|
|||
|
|
delegated: boolean?
|
|||
|
|
provider_identity_ref: string?
|
|||
|
|
metadata: object?
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Adapters SHOULD avoid overclaiming identity.
|
|||
|
|
|
|||
|
|
For example, `email-connect` SHOULD NOT mark a click as `authenticated` unless it is backed by a trusted identity or portal event.
|
|||
|
|
|
|||
|
|
## 13. CorrelationContext
|
|||
|
|
|
|||
|
|
Correlation is mandatory for useful adapter integration.
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
CorrelationContext:
|
|||
|
|
correlation_id: string
|
|||
|
|
request_id: string?
|
|||
|
|
coordination_case_id: string
|
|||
|
|
participant_id: string?
|
|||
|
|
notification_id: string?
|
|||
|
|
delivery_id: string?
|
|||
|
|
interaction_id: string?
|
|||
|
|
payload_id: string?
|
|||
|
|
action_surface_id: string?
|
|||
|
|
adapter_operation_id: string?
|
|||
|
|
provider_operation_id: string?
|
|||
|
|
provider_message_id: string?
|
|||
|
|
external_refs:
|
|||
|
|
- ProviderRef
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Adapters MUST preserve correlation identifiers where technically possible.
|
|||
|
|
|
|||
|
|
Adapters SHOULD include correlation identifiers in outbound provider metadata, message headers, webhook metadata, URLs, tokens, or provider custom arguments when supported.
|
|||
|
|
|
|||
|
|
## 14. ProviderRef
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
ProviderRef:
|
|||
|
|
provider_name: string
|
|||
|
|
ref_type: string
|
|||
|
|
ref_value: string
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Examples:
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
provider_name: sendgrid
|
|||
|
|
ref_type: message_id
|
|||
|
|
ref_value: abc123
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
provider_name: stripe
|
|||
|
|
ref_type: payment_intent_id
|
|||
|
|
ref_value: pi_123
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 15. ErrorDescriptor
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
ErrorDescriptor:
|
|||
|
|
code: string
|
|||
|
|
message: string
|
|||
|
|
retryable: boolean
|
|||
|
|
category: validation | authentication | authorization | configuration | provider | network | rate_limit | timeout | conflict | unknown
|
|||
|
|
native_error_code: string?
|
|||
|
|
native_error_message: string?
|
|||
|
|
details: object?
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Adapters MUST return an `ErrorDescriptor` when an action request is rejected or fails before acceptance.
|
|||
|
|
|
|||
|
|
## 16. Adapter Health
|
|||
|
|
|
|||
|
|
Adapters MUST expose health state.
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
AdapterHealth:
|
|||
|
|
adapter_id: string
|
|||
|
|
status: healthy | degraded | unavailable | misconfigured | unknown
|
|||
|
|
checked_at: timestamp
|
|||
|
|
provider_connectivity: healthy | degraded | unavailable | unknown
|
|||
|
|
configuration_validity: valid | invalid | partial | unknown
|
|||
|
|
credential_status: valid | expired | missing | insufficient | unknown
|
|||
|
|
last_action_success_at: timestamp?
|
|||
|
|
last_event_received_at: timestamp?
|
|||
|
|
known_degradations:
|
|||
|
|
- string
|
|||
|
|
metrics:
|
|||
|
|
actions_accepted_last_24h: integer?
|
|||
|
|
actions_failed_last_24h: integer?
|
|||
|
|
events_received_last_24h: integer?
|
|||
|
|
average_action_latency_ms: integer?
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 17. Transport Patterns
|
|||
|
|
|
|||
|
|
This specification does not mandate one technical transport.
|
|||
|
|
|
|||
|
|
Adapters MAY integrate through:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
REST API
|
|||
|
|
event bus
|
|||
|
|
message queue
|
|||
|
|
webhook
|
|||
|
|
gRPC
|
|||
|
|
embedded library
|
|||
|
|
CLI
|
|||
|
|
file drop
|
|||
|
|
polling
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
However, any transport MUST preserve the semantic contract defined here.
|
|||
|
|
|
|||
|
|
## 18. Adapter Integration Modes
|
|||
|
|
|
|||
|
|
## 18.1 Embedded Mode
|
|||
|
|
|
|||
|
|
Adapter code runs in the same process as `coordination-engine`.
|
|||
|
|
|
|||
|
|
Suitable for:
|
|||
|
|
|
|||
|
|
* local development
|
|||
|
|
* test adapters
|
|||
|
|
* simulated adapters
|
|||
|
|
* simple deployments
|
|||
|
|
|
|||
|
|
## 18.2 Sidecar Mode
|
|||
|
|
|
|||
|
|
Adapter runs next to the engine but is deployed separately.
|
|||
|
|
|
|||
|
|
Suitable for:
|
|||
|
|
|
|||
|
|
* credential isolation
|
|||
|
|
* provider-specific webhook handling
|
|||
|
|
* protocol-specific runtime dependencies
|
|||
|
|
|
|||
|
|
## 18.3 External Service Mode
|
|||
|
|
|
|||
|
|
Adapter is an independently deployed service.
|
|||
|
|
|
|||
|
|
Suitable for:
|
|||
|
|
|
|||
|
|
* reusable `*-connect` components
|
|||
|
|
* multi-tenant installations
|
|||
|
|
* independent scaling
|
|||
|
|
* provider abstraction
|
|||
|
|
* operational separation
|
|||
|
|
|
|||
|
|
Preferred direction for production adapters:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
*-connect repositories SHOULD implement external service mode first,
|
|||
|
|
while optionally also offering embedded or sidecar modes.
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 19. Adapter Lifecycle
|
|||
|
|
|
|||
|
|
Adapters SHOULD support the following lifecycle:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
registered
|
|||
|
|
configured
|
|||
|
|
healthy
|
|||
|
|
degraded
|
|||
|
|
disabled
|
|||
|
|
retired
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 19.1 Registration
|
|||
|
|
|
|||
|
|
During registration, the adapter provides its `AdapterDescriptor`.
|
|||
|
|
|
|||
|
|
### 19.2 Configuration
|
|||
|
|
|
|||
|
|
Configuration may include credentials, provider selection, endpoint settings, webhook secrets, templates, routing policies, or tenant-specific settings.
|
|||
|
|
|
|||
|
|
### 19.3 Health Monitoring
|
|||
|
|
|
|||
|
|
The engine or platform periodically checks `AdapterHealth`.
|
|||
|
|
|
|||
|
|
### 19.4 Action Dispatch
|
|||
|
|
|
|||
|
|
The engine dispatches `AdapterActionRequest` objects to the adapter.
|
|||
|
|
|
|||
|
|
### 19.5 Event Ingestion
|
|||
|
|
|
|||
|
|
The adapter emits `AdapterEvent` or `EvidenceEvent` objects.
|
|||
|
|
|
|||
|
|
### 19.6 Degradation Handling
|
|||
|
|
|
|||
|
|
If an adapter is degraded, the policy engine may switch channel, delay actions, retry later, or escalate.
|
|||
|
|
|
|||
|
|
## 20. Event Ordering, Idempotency, and Late Events
|
|||
|
|
|
|||
|
|
### 20.1 Event Ordering
|
|||
|
|
|
|||
|
|
Adapters MUST NOT assume events arrive in causal order.
|
|||
|
|
|
|||
|
|
The engine MUST be able to process late events.
|
|||
|
|
|
|||
|
|
Adapters SHOULD include accurate `occurred_at` and `observed_at` timestamps.
|
|||
|
|
|
|||
|
|
### 20.2 Duplicate Events
|
|||
|
|
|
|||
|
|
Adapters SHOULD provide stable event identifiers where possible.
|
|||
|
|
|
|||
|
|
The engine MUST deduplicate events using:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
evidence_event_id
|
|||
|
|
adapter_event_id
|
|||
|
|
provider event id
|
|||
|
|
correlation context
|
|||
|
|
event type
|
|||
|
|
timestamp
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 20.3 Late Events
|
|||
|
|
|
|||
|
|
Late events MUST still be accepted and recorded if they are relevant.
|
|||
|
|
|
|||
|
|
A late hard bounce may change or annotate a previously unresolved participant state.
|
|||
|
|
|
|||
|
|
A late payment settlement may close an otherwise escalated participant state.
|
|||
|
|
|
|||
|
|
### 20.4 Idempotent Actions
|
|||
|
|
|
|||
|
|
All externally visible actions MUST include `idempotency_key`.
|
|||
|
|
|
|||
|
|
Adapters MUST avoid duplicate external side effects for repeated action requests with the same key.
|
|||
|
|
|
|||
|
|
## 21. Security Requirements
|
|||
|
|
|
|||
|
|
Adapters MUST:
|
|||
|
|
|
|||
|
|
* protect provider credentials
|
|||
|
|
* verify incoming provider webhooks where possible
|
|||
|
|
* validate action request authenticity
|
|||
|
|
* avoid leaking sensitive payloads in logs
|
|||
|
|
* support least-privilege configuration
|
|||
|
|
* preserve correlation without exposing unnecessary personal data
|
|||
|
|
* avoid storing raw sensitive data unless explicitly configured
|
|||
|
|
|
|||
|
|
Adapters SHOULD:
|
|||
|
|
|
|||
|
|
* support tenant separation
|
|||
|
|
* support secret rotation
|
|||
|
|
* support signed callbacks or event signatures
|
|||
|
|
* support audit logging of action execution
|
|||
|
|
|
|||
|
|
## 22. Privacy Requirements
|
|||
|
|
|
|||
|
|
Adapters SHOULD minimize personal data.
|
|||
|
|
|
|||
|
|
Adapters SHOULD support:
|
|||
|
|
|
|||
|
|
* endpoint references instead of full endpoint values where possible
|
|||
|
|
* redaction of raw provider events
|
|||
|
|
* retention limits for raw event data
|
|||
|
|
* configurable storage of message content
|
|||
|
|
* metadata-only mode
|
|||
|
|
* data deletion or anonymization workflows where applicable
|
|||
|
|
|
|||
|
|
The adapter interface MUST allow references to external payloads rather than requiring payload content to be copied into the adapter.
|
|||
|
|
|
|||
|
|
## 23. Standalone Adapter Requirements
|
|||
|
|
|
|||
|
|
Adapters are encouraged to be useful outside `coordination-engine`.
|
|||
|
|
|
|||
|
|
A standalone adapter MAY provide:
|
|||
|
|
|
|||
|
|
* provider abstraction
|
|||
|
|
* operational dashboard
|
|||
|
|
* message timeline API
|
|||
|
|
* diagnostic API
|
|||
|
|
* native event archive
|
|||
|
|
* normalized event stream
|
|||
|
|
* suppression management
|
|||
|
|
* provider health checks
|
|||
|
|
* local policy hints
|
|||
|
|
|
|||
|
|
However, standalone features MUST NOT contradict the coordination-engine contract.
|
|||
|
|
|
|||
|
|
For example, `email-connect` may provide a message-level status called `delivered_to_mx`, but it MUST NOT expose that as business-level proof of recipient awareness.
|
|||
|
|
|
|||
|
|
## 24. email-connect Reference Mapping
|
|||
|
|
|
|||
|
|
The following mapping defines expected behavior for the first reference adapter.
|
|||
|
|
|
|||
|
|
| Email-native event | Normalized event | Evidence interpretation |
|
|||
|
|
| --------------------------------- | --------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
|
|||
|
|
| Message accepted by email adapter | `notification.attempt.accepted_by_adapter` | Weak evidence that adapter accepted request |
|
|||
|
|
| Provider accepted message | `notification.attempt.accepted_by_provider` | Weak evidence that sending began |
|
|||
|
|
| Provider rejected message | `notification.attempt.rejected_by_provider` | Strong failure for this attempt |
|
|||
|
|
| Recipient MX accepted message | `notification.endpoint.accepted` | Weak technical evidence, not awareness |
|
|||
|
|
| Temporary deferral | `notification.endpoint.deferred` | Pending/uncertain |
|
|||
|
|
| Soft bounce | `notification.endpoint.rejected_temporary` | Pending or retryable failure |
|
|||
|
|
| Hard bounce | `notification.endpoint.rejected_permanent` | Strong endpoint failure |
|
|||
|
|
| Spam complaint | `notification.channel.complaint_received` | Strong negative channel evidence |
|
|||
|
|
| Unsubscribe/suppression | `notification.channel.unsubscribe_received` or `notification.channel.suppression_added` | Channel not viable or constrained |
|
|||
|
|
| Open via privacy proxy | `interaction.proxy_or_privacy_interaction` | Ambiguous/weak |
|
|||
|
|
| Human-like open | `interaction.notification.opened` | Weak-to-medium, not sufficient for high-assurance cases |
|
|||
|
|
| Scanner-like click | `interaction.scanner_or_bot_interaction` | Ambiguous, should not count as recipient action |
|
|||
|
|
| Unverified click | `interaction.unverified_actor_interaction` | Weak-to-medium, identity uncertain |
|
|||
|
|
| Reply received | `interaction.reply_received` | Medium-to-strong awareness evidence, identity may still need validation |
|
|||
|
|
| Out-of-office reply | `interaction.out_of_office_received` | Evidence mailbox exists, not completion |
|
|||
|
|
|
|||
|
|
## 25. RSS Reference Mapping
|
|||
|
|
|
|||
|
|
`rss-connect` should demonstrate pull-based notification semantics.
|
|||
|
|
|
|||
|
|
| RSS-native event | Normalized event | Evidence interpretation |
|
|||
|
|
| ---------------------- | ------------------------------------------ | ---------------------------------------- |
|
|||
|
|
| Feed item published | `feed.item.published` | Payload/notice made available |
|
|||
|
|
| Feed item updated | `feed.item.updated` | Published item changed |
|
|||
|
|
| Feed fetched | `feed.item.fetched` | Weak evidence of reader/system retrieval |
|
|||
|
|
| Link clicked from feed | `interaction.unverified_actor_interaction` | Weak-to-medium, identity uncertain |
|
|||
|
|
| Feed item removed | `feed.item.removed` | Publication revoked or expired |
|
|||
|
|
|
|||
|
|
RSS publication alone should usually not count as participant awareness unless scenario policy explicitly accepts publication as sufficient.
|
|||
|
|
|
|||
|
|
## 26. Portal Reference Mapping
|
|||
|
|
|
|||
|
|
`portal-connect` is expected to provide stronger access and interaction evidence.
|
|||
|
|
|
|||
|
|
| Portal-native event | Normalized event | Evidence interpretation |
|
|||
|
|
| ------------------------- | --------------------------------------------- | ----------------------------------- |
|
|||
|
|
| Access grant issued | `access.grant.issued` | Access path created |
|
|||
|
|
| Login successful | `identity.actor_authenticated` | Stronger actor evidence |
|
|||
|
|
| Payload page opened | `interaction.authenticated_actor_interaction` | Actor reached action surface |
|
|||
|
|
| Document viewed | `delivery.payload.viewed` | Strong payload interaction evidence |
|
|||
|
|
| Document downloaded | `delivery.payload.downloaded` | Strong payload retrieval evidence |
|
|||
|
|
| Acknowledgement submitted | `interaction.acknowledgement_recorded` | Strong result-relevant evidence |
|
|||
|
|
| Access denied | `access.grant.denied` | Failed or blocked access attempt |
|
|||
|
|
| Access expired | `access.grant.expired` | Access no longer usable |
|
|||
|
|
|
|||
|
|
## 27. Compatibility Requirements for Adapter Repositories
|
|||
|
|
|
|||
|
|
Every `*-connect` repository SHOULD contain:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
INTENT.md
|
|||
|
|
docs/AdapterImplementation.md
|
|||
|
|
docs/EventMapping.md
|
|||
|
|
docs/ProviderModel.md
|
|||
|
|
docs/EvidenceClassification.md
|
|||
|
|
schemas/
|
|||
|
|
src/
|
|||
|
|
tests/
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Every adapter repository MUST document:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
Implemented adapter contract version
|
|||
|
|
Supported actions
|
|||
|
|
Emitted normalized events
|
|||
|
|
Native event mappings
|
|||
|
|
Evidence grading rules
|
|||
|
|
Known limitations
|
|||
|
|
Provider-specific assumptions
|
|||
|
|
Security model
|
|||
|
|
Privacy model
|
|||
|
|
Standalone usage
|
|||
|
|
coordination-engine integration mode
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 28. Versioning
|
|||
|
|
|
|||
|
|
### 28.1 Contract Version
|
|||
|
|
|
|||
|
|
Adapters MUST declare `adapter_contract_version`.
|
|||
|
|
|
|||
|
|
This document defines:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
adapter_contract_version: 1.0
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 28.2 Backward Compatibility
|
|||
|
|
|
|||
|
|
Minor extensions MAY add:
|
|||
|
|
|
|||
|
|
* optional fields
|
|||
|
|
* new event types
|
|||
|
|
* new action types
|
|||
|
|
* new adapter types
|
|||
|
|
* new evidence metadata
|
|||
|
|
|
|||
|
|
Breaking changes include:
|
|||
|
|
|
|||
|
|
* removing required fields
|
|||
|
|
* changing meaning of existing fields
|
|||
|
|
* changing event semantics
|
|||
|
|
* changing idempotency requirements
|
|||
|
|
* changing evidence grade semantics
|
|||
|
|
|
|||
|
|
Breaking changes require a new major version.
|
|||
|
|
|
|||
|
|
## 29. Minimal Compliance Checklist
|
|||
|
|
|
|||
|
|
An adapter is minimally compliant with AdapterInterfaceSpecification 1.0 if it:
|
|||
|
|
|
|||
|
|
1. Exposes an `AdapterDescriptor`.
|
|||
|
|
2. Declares supported actions.
|
|||
|
|
3. Declares emitted event types.
|
|||
|
|
4. Accepts `AdapterActionRequest` objects for supported actions.
|
|||
|
|
5. Returns `AdapterActionResult` objects.
|
|||
|
|
6. Supports idempotency keys.
|
|||
|
|
7. Emits or maps to `EvidenceEvent` objects.
|
|||
|
|
8. Provides `EvidenceGrade` and `ConfidenceGrade`.
|
|||
|
|
9. Preserves `CorrelationContext`.
|
|||
|
|
10. Exposes `AdapterHealth`.
|
|||
|
|
11. Documents known limitations.
|
|||
|
|
12. Does not overclaim result success.
|
|||
|
|
13. Clearly separates provider-native events from normalized evidence.
|
|||
|
|
|
|||
|
|
## 30. Non-Goals
|
|||
|
|
|
|||
|
|
This adapter specification does not define:
|
|||
|
|
|
|||
|
|
* the internal storage model of adapters
|
|||
|
|
* the provider-specific API shape
|
|||
|
|
* the transport protocol used between engine and adapter
|
|||
|
|
* legal validity of evidence
|
|||
|
|
* UI requirements
|
|||
|
|
* billing models
|
|||
|
|
* tenant management model
|
|||
|
|
* full workflow semantics
|
|||
|
|
* complete event vocabulary for every possible domain
|
|||
|
|
|
|||
|
|
Those concerns may be defined in separate documents or scenario-specific specifications.
|
|||
|
|
|
|||
|
|
## 31. Strategic Summary
|
|||
|
|
|
|||
|
|
The adapter interface allows `coordination-engine` to remain a generalized coordination runtime while integrating with many concrete systems.
|
|||
|
|
|
|||
|
|
Adapters perform actions and emit evidence. They translate external provider realities into a normalized coordination vocabulary without deciding overall business success.
|
|||
|
|
|
|||
|
|
The central rule is:
|
|||
|
|
|
|||
|
|
> Adapters report what happened and what it may mean. coordination-engine decides what that means for the coordination case.
|
|||
|
|
|
|||
|
|
This distinction is essential for reliable, extensible, evidence-driven digital coordination.
|
|||
|
|
|