generated from coulomb/repo-seed
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.
|
||
|