generated from coulomb/repo-seed
1992 lines
48 KiB
Markdown
1992 lines
48 KiB
Markdown
# AdapterInterfaceSpecification.md
|
||
|
||
## 1. Document Status
|
||
|
||
**Document:** AdapterInterfaceSpecification.md
|
||
**Project:** coordination-engine
|
||
**Version:** 1.1
|
||
**Status:** Updated Draft
|
||
**Scope:** Contract between coordination-engine and external adapters
|
||
**Primary Reference Adapters:** email-connect, sms-connect, rss-connect, xmpp-connect, hybridmail-connect
|
||
|
||
## 2. Version 1.1 Change Summary
|
||
|
||
Version 1.1 extends the original adapter interface based on concrete adapter design work for:
|
||
|
||
* Email
|
||
* SMS
|
||
* RSS / Atom / WebSub
|
||
* XMPP
|
||
* Hybrid Mail
|
||
|
||
The main changes are:
|
||
|
||
1. Added `AdapterCapabilityProfile`.
|
||
2. Added `EvidenceCeiling`.
|
||
3. Added `NativeStatusMapping` / `NativeEventSemantics`.
|
||
4. Added universal weakest-safe-mapping rule.
|
||
5. Added `AdapterEvidenceAssessment`.
|
||
6. Added `EndpointQuality`.
|
||
7. Added `LateEventPolicy`.
|
||
8. Added `EventObservation`.
|
||
9. Added `FeatureDependency`.
|
||
10. Added `AssuranceCapability`.
|
||
11. Added adapter conformance levels.
|
||
12. Added golden test requirements.
|
||
13. Strengthened semantic underclaiming requirements.
|
||
14. Clarified that adapters provide evidence, not coordination-result truth.
|
||
|
||
## 3. Purpose
|
||
|
||
This document defines the adapter interface contract between `coordination-engine` and external adapter components such as:
|
||
|
||
* `email-connect`
|
||
* `sms-connect`
|
||
* `rss-connect`
|
||
* `xmpp-connect`
|
||
* `hybridmail-connect`
|
||
* `push-connect`
|
||
* `portal-connect`
|
||
* `payment-connect`
|
||
* `signature-connect`
|
||
* `document-connect`
|
||
* `identity-connect`
|
||
* 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. Declaring evidence ceilings.
|
||
3. Accepting action requests.
|
||
4. Returning action results.
|
||
5. Preserving native events.
|
||
6. Mapping native events conservatively.
|
||
7. Emitting normalized evidence events.
|
||
8. Providing advisory evidence assessments.
|
||
9. Exposing endpoint quality and adapter health.
|
||
10. 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`.
|
||
|
||
## 4. Core Design Principle
|
||
|
||
Adapters are not merely transport drivers.
|
||
|
||
An adapter is a capability component that can perform actions, observe signals, preserve native events, classify evidence, and expose its own limitations.
|
||
|
||
```text
|
||
Adapter =
|
||
Capability Descriptor
|
||
+ Action Provider
|
||
+ Signal Provider
|
||
+ Evidence Normalizer
|
||
+ Evidence Ceiling Declaration
|
||
+ Health / Diagnostics 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
|
||
* final interpretation of adapter evidence
|
||
|
||
The adapter remains responsible for:
|
||
|
||
* provider-specific integration
|
||
* protocol-specific action execution
|
||
* native event ingestion
|
||
* native event preservation
|
||
* native-to-normalized event mapping
|
||
* adapter-level evidence assessment
|
||
* adapter-specific diagnostics
|
||
* provider-level correlation
|
||
* adapter health reporting
|
||
* explicit limitation reporting
|
||
|
||
## 5. Semantic Underclaiming Rule
|
||
|
||
Adapters MUST underclaim rather than overclaim.
|
||
|
||
If a native event or provider status is ambiguous, the adapter MUST map it to the weakest semantically safe normalized event and preserve the raw native event or status in metadata.
|
||
|
||
Examples:
|
||
|
||
```text
|
||
Email provider "delivered"
|
||
→ notification.endpoint.accepted
|
||
→ not recipient awareness
|
||
|
||
SMS provider "delivered"
|
||
→ notification.endpoint.accepted with delivery-receipt metadata
|
||
→ not human read confirmation
|
||
|
||
RSS item "published"
|
||
→ feed.item.published
|
||
→ not participant awareness
|
||
|
||
XMPP stream acknowledgement
|
||
→ notification.attempt.accepted_by_provider
|
||
→ not client delivery
|
||
|
||
Hybrid mail "sent"
|
||
→ delivery.payload.submitted or delivery.postal.handed_over only if semantics prove handover
|
||
→ not delivery confirmation
|
||
```
|
||
|
||
The central rule is:
|
||
|
||
> Adapters report what happened and what it may mean. coordination-engine decides what it means for the coordination case.
|
||
|
||
## 6. Boundary Between coordination-engine and Adapters
|
||
|
||
### 6.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
|
||
|
||
### 6.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
|
||
* adapter-native evidence assessment
|
||
|
||
### 6.3 Shared Contract
|
||
|
||
The shared contract consists of:
|
||
|
||
* `AdapterDescriptor`
|
||
* `AdapterCapabilityProfile`
|
||
* `AdapterActionCapability`
|
||
* `AdapterActionRequest`
|
||
* `AdapterActionResult`
|
||
* `AdapterEvent`
|
||
* `EvidenceEvent`
|
||
* `AdapterEvidenceAssessment`
|
||
* `EvidenceGrade`
|
||
* `EvidenceCeiling`
|
||
* `NativeStatusMapping`
|
||
* `NativeEventSemantics`
|
||
* `EndpointQuality`
|
||
* `AdapterHealth`
|
||
* `CorrelationContext`
|
||
* `ErrorDescriptor`
|
||
* `LateEventPolicy`
|
||
* `FeatureDependency`
|
||
* `AssuranceCapability`
|
||
* `AdapterGoldenTest`
|
||
|
||
## 7. Adapter Types
|
||
|
||
An adapter may belong to one or more adapter types.
|
||
|
||
Recommended canonical adapter types:
|
||
|
||
```text
|
||
notification
|
||
communication
|
||
publication
|
||
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 |
|
||
| `sms-connect` | notification, communication, interaction |
|
||
| `rss-connect` | publication, feed, notification |
|
||
| `xmpp-connect` | notification, communication, interaction, feed |
|
||
| `hybridmail-connect` | delivery, communication, document, archive |
|
||
| `portal-connect` | access, delivery, interaction, identity |
|
||
| `payment-connect` | payment, interaction, delivery |
|
||
| `signature-connect` | signature, identity, authority, delivery |
|
||
| `identity-connect` | identity, authority |
|
||
| `webhook-connect` | system, delivery, interaction |
|
||
|
||
Adapter type is descriptive, not exclusive.
|
||
|
||
## 8. 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.
|
||
|
||
## 9. Core Interface Objects
|
||
|
||
## 9.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
|
||
capability_profile: AdapterCapabilityProfile
|
||
supported_actions:
|
||
- AdapterActionCapability
|
||
emitted_event_types:
|
||
- string
|
||
supported_channels:
|
||
- string
|
||
supported_endpoint_types:
|
||
- string
|
||
evidence_profile: AdapterEvidenceProfile
|
||
evidence_ceiling: EvidenceCeiling
|
||
assurance_capability: AssuranceCapability
|
||
identity_profile: AdapterIdentityProfile
|
||
late_event_policy: LateEventPolicy
|
||
feature_dependencies:
|
||
- FeatureDependency
|
||
latency_profile: AdapterLatencyProfile?
|
||
cost_profile: AdapterCostProfile?
|
||
reliability_profile: AdapterReliabilityProfile?
|
||
configuration_schema_ref: string?
|
||
native_status_mapping_ref: string?
|
||
golden_tests_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
|
||
capability_profile
|
||
supported_actions
|
||
emitted_event_types
|
||
supported_channels
|
||
supported_endpoint_types
|
||
evidence_profile
|
||
evidence_ceiling
|
||
assurance_capability
|
||
identity_profile
|
||
late_event_policy
|
||
limitations
|
||
```
|
||
|
||
## 9.2 AdapterCapabilityProfile
|
||
|
||
An `AdapterCapabilityProfile` declares what the adapter can do, observe, and never prove.
|
||
|
||
```yaml
|
||
AdapterCapabilityProfile:
|
||
can_notify: boolean
|
||
can_publish: boolean
|
||
can_deliver_payload: boolean
|
||
can_collect_payload: boolean
|
||
can_grant_access: boolean
|
||
can_revoke_access: boolean
|
||
can_observe_interaction: boolean
|
||
can_observe_identity: boolean
|
||
can_observe_authority: boolean
|
||
can_emit_delivery_receipts: boolean
|
||
can_emit_display_or_read_receipts: boolean
|
||
can_emit_return_or_failure_events: boolean
|
||
can_emit_late_events: boolean
|
||
can_cancel_after_dispatch: boolean
|
||
supports_webhooks: boolean
|
||
supports_polling: boolean
|
||
supports_idempotency: native | adapter_managed | none | unknown
|
||
supports_endpoint_quality: boolean
|
||
supports_native_status_mapping: boolean
|
||
supports_golden_tests: boolean
|
||
limitations:
|
||
- string
|
||
```
|
||
|
||
### Example: email-connect
|
||
|
||
```yaml
|
||
AdapterCapabilityProfile:
|
||
can_notify: true
|
||
can_publish: false
|
||
can_deliver_payload: false
|
||
can_collect_payload: false
|
||
can_grant_access: false
|
||
can_revoke_access: false
|
||
can_observe_interaction: true
|
||
can_observe_identity: false
|
||
can_observe_authority: false
|
||
can_emit_delivery_receipts: false
|
||
can_emit_display_or_read_receipts: false
|
||
can_emit_return_or_failure_events: true
|
||
can_emit_late_events: true
|
||
can_cancel_after_dispatch: false
|
||
supports_webhooks: true
|
||
supports_polling: false
|
||
supports_idempotency: adapter_managed
|
||
supports_endpoint_quality: true
|
||
supports_native_status_mapping: true
|
||
supports_golden_tests: true
|
||
limitations:
|
||
- Recipient mail server acceptance does not prove inbox placement.
|
||
- Open and click tracking are ambiguous.
|
||
```
|
||
|
||
### Example: hybridmail-connect
|
||
|
||
```yaml
|
||
AdapterCapabilityProfile:
|
||
can_notify: false
|
||
can_publish: false
|
||
can_deliver_payload: true
|
||
can_collect_payload: false
|
||
can_grant_access: false
|
||
can_revoke_access: false
|
||
can_observe_interaction: false
|
||
can_observe_identity: false
|
||
can_observe_authority: false
|
||
can_emit_delivery_receipts: true
|
||
can_emit_display_or_read_receipts: false
|
||
can_emit_return_or_failure_events: true
|
||
can_emit_late_events: true
|
||
can_cancel_after_dispatch: false
|
||
supports_webhooks: true
|
||
supports_polling: true
|
||
supports_idempotency: adapter_managed
|
||
supports_endpoint_quality: true
|
||
supports_native_status_mapping: true
|
||
supports_golden_tests: true
|
||
limitations:
|
||
- Postal handover does not prove recipient reading.
|
||
- Ordinary letters often do not provide final delivery confirmation.
|
||
```
|
||
|
||
## 9.3 EvidenceCeiling
|
||
|
||
An `EvidenceCeiling` declares the strongest evidence the adapter can provide under its configured capabilities.
|
||
|
||
```yaml
|
||
EvidenceCeiling:
|
||
max_positive_event: string
|
||
max_positive_strength: none | weak | medium | strong | conclusive | unknown
|
||
can_prove_human_awareness: boolean | partially
|
||
can_prove_payload_access: boolean | partially
|
||
can_prove_payload_delivery: boolean | partially
|
||
can_prove_identity: boolean | partially
|
||
can_prove_authority: boolean | partially
|
||
can_prove_non_repudiation: boolean | partially
|
||
conditions:
|
||
- string
|
||
limitations:
|
||
- string
|
||
```
|
||
|
||
### Examples
|
||
|
||
```yaml
|
||
email:
|
||
max_positive_event: interaction.unverified_actor_interaction
|
||
max_positive_strength: medium
|
||
can_prove_human_awareness: false
|
||
can_prove_payload_access: false
|
||
can_prove_payload_delivery: false
|
||
can_prove_identity: false
|
||
can_prove_authority: false
|
||
can_prove_non_repudiation: false
|
||
limitations:
|
||
- Email tracking cannot reliably prove intended-recipient awareness.
|
||
```
|
||
|
||
```yaml
|
||
sms:
|
||
max_positive_event: notification.endpoint.accepted
|
||
max_positive_strength: strong
|
||
can_prove_human_awareness: false
|
||
can_prove_payload_access: false
|
||
can_prove_payload_delivery: false
|
||
can_prove_identity: false
|
||
can_prove_authority: false
|
||
can_prove_non_repudiation: false
|
||
conditions:
|
||
- Strongest evidence depends on carrier delivery receipts.
|
||
```
|
||
|
||
```yaml
|
||
xmpp_with_display_markers:
|
||
max_positive_event: interaction.notification.opened
|
||
max_positive_strength: strong
|
||
can_prove_human_awareness: partially
|
||
can_prove_payload_access: false
|
||
can_prove_payload_delivery: false
|
||
can_prove_identity: partially
|
||
can_prove_authority: false
|
||
can_prove_non_repudiation: false
|
||
conditions:
|
||
- Requires client support for displayed markers.
|
||
```
|
||
|
||
```yaml
|
||
hybridmail_registered:
|
||
max_positive_event: delivery.postal.delivery_confirmed
|
||
max_positive_strength: strong
|
||
can_prove_human_awareness: false
|
||
can_prove_payload_access: partially
|
||
can_prove_payload_delivery: partially
|
||
can_prove_identity: false
|
||
can_prove_authority: false
|
||
can_prove_non_repudiation: partially
|
||
conditions:
|
||
- Requires registered or delivery-confirmation postal product.
|
||
```
|
||
|
||
## 9.4 AssuranceCapability
|
||
|
||
`AssuranceCapability` allows coordination-engine to compare adapter capabilities against scenario assurance requirements.
|
||
|
||
```yaml
|
||
AssuranceCapability:
|
||
awareness_assurance: none | weak | medium | strong | conclusive | conditional | unknown
|
||
delivery_assurance: none | weak | medium | strong | conclusive | conditional | unknown
|
||
identity_assurance: none | weak | medium | strong | conclusive | conditional | unknown
|
||
authority_assurance: none | weak | medium | strong | conclusive | conditional | unknown
|
||
non_repudiation_assurance: none | weak | medium | strong | conclusive | conditional | unknown
|
||
conditions:
|
||
- string
|
||
limitations:
|
||
- string
|
||
```
|
||
|
||
Example:
|
||
|
||
```yaml
|
||
email:
|
||
awareness_assurance: weak
|
||
delivery_assurance: none
|
||
identity_assurance: none
|
||
authority_assurance: none
|
||
non_repudiation_assurance: none
|
||
```
|
||
|
||
```yaml
|
||
portal:
|
||
awareness_assurance: strong
|
||
delivery_assurance: strong
|
||
identity_assurance: strong
|
||
authority_assurance: conditional
|
||
non_repudiation_assurance: medium
|
||
```
|
||
|
||
## 9.5 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
|
||
preconditions:
|
||
- string
|
||
postconditions:
|
||
- string
|
||
capability_dependencies:
|
||
- string
|
||
unsupported_when:
|
||
- 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.*
|
||
publication.*
|
||
access.*
|
||
delivery.*
|
||
interaction.*
|
||
identity.*
|
||
authority.*
|
||
payment.*
|
||
signature.*
|
||
document.*
|
||
archive.*
|
||
feed.*
|
||
webhook.*
|
||
recipient.*
|
||
system.*
|
||
```
|
||
|
||
Examples:
|
||
|
||
```text
|
||
notification.send
|
||
notification.send_reminder
|
||
publication.publish
|
||
access.grant
|
||
access.revoke
|
||
delivery.submit_payload
|
||
delivery.submit_letter
|
||
delivery.request_submission
|
||
payment.create_request
|
||
payment.cancel_request
|
||
signature.create_envelope
|
||
signature.cancel_envelope
|
||
feed.publish_item
|
||
recipient.suppress
|
||
recipient.unsuppress
|
||
```
|
||
|
||
## 9.6 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: ActionSurfaceRef?
|
||
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, broadcast, or publication actions, but adapters MAY require them for specific action types.
|
||
|
||
## 9.7 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.
|
||
|
||
For irreversible or expensive side-effect actions, such as hybrid-mail physical dispatch or payment creation, adapters MUST implement strict duplicate prevention.
|
||
|
||
If the same idempotency key is used with conflicting request content, the adapter MUST return an idempotency conflict.
|
||
|
||
```yaml
|
||
IdempotencyConflict:
|
||
idempotency_key: string
|
||
original_request_ref: string
|
||
conflicting_request_ref: string
|
||
conflict_fields:
|
||
- string
|
||
```
|
||
|
||
## 9.8 TrackingContext
|
||
|
||
`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
|
||
```
|
||
|
||
Adapters MUST preserve correlation identifiers where technically possible.
|
||
|
||
Adapters SHOULD include correlation identifiers in outbound provider metadata, message headers, webhook metadata, URLs, tokens, provider custom arguments, or provider-specific reference fields when supported.
|
||
|
||
## 9.9 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
|
||
atom_feed
|
||
webhook_url
|
||
portal_account
|
||
payment_account
|
||
signature_recipient
|
||
api_client
|
||
postal_address
|
||
physical_address
|
||
muc_room_jid
|
||
pubsub_node
|
||
```
|
||
|
||
## 9.10 EndpointQuality
|
||
|
||
Adapters SHOULD expose endpoint quality where meaningful.
|
||
|
||
```yaml
|
||
EndpointQuality:
|
||
endpoint_ref: EndpointRef
|
||
endpoint_type: string
|
||
validity: valid | invalid | suspected_invalid | unknown
|
||
reachability: reachable | unreachable | degraded | unknown
|
||
verification_state: unverified | syntax_validated | provider_verified | recently_successful | failed | unknown
|
||
suppression_state: active | suppressed | blocked | opted_out | unknown
|
||
last_success_at: timestamp?
|
||
last_failure_at: timestamp?
|
||
quality_signals:
|
||
- string
|
||
confidence: low | medium | high
|
||
adapter_specific:
|
||
email: object?
|
||
sms: object?
|
||
rss: object?
|
||
xmpp: object?
|
||
hybridmail: object?
|
||
other: object?
|
||
```
|
||
|
||
Examples of adapter-specific quality signals:
|
||
|
||
```text
|
||
email: mx_exists, hard_bounce_history, catch_all_suspected
|
||
sms: e164_valid, number_type, carrier, opt_out_state
|
||
rss: feed_valid, last_fetch_observed, cache_status
|
||
xmpp: presence_state, roster_state, resource_known
|
||
hybridmail: address_valid, address_position_valid, return_history
|
||
```
|
||
|
||
## 9.11 ActionSurfaceRef
|
||
|
||
Adapters often point participants toward action surfaces rather than completing results themselves.
|
||
|
||
```yaml
|
||
ActionSurfaceRef:
|
||
action_surface_id: string
|
||
action_surface_type: portal | payment_page | signature_flow | upload_form | api_endpoint | physical_letter | chat_command | feed_item | other
|
||
uri: string?
|
||
requires_authentication: boolean?
|
||
expected_interactions:
|
||
- string
|
||
metadata: object?
|
||
```
|
||
|
||
Adapters SHOULD include `action_surface_ref` when the action contains a link, command, form, payment flow, signature flow, or physical action prompt.
|
||
|
||
## 9.12 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?
|
||
```
|
||
|
||
## 9.13 ResourceRef
|
||
|
||
```yaml
|
||
ResourceRef:
|
||
ref_type: string
|
||
ref_id: string
|
||
uri: string?
|
||
version: string?
|
||
integrity_hash: string?
|
||
metadata: object?
|
||
```
|
||
|
||
## 9.14 ActionLink
|
||
|
||
```yaml
|
||
ActionLink:
|
||
link_id: string
|
||
purpose: string
|
||
url: string
|
||
expires_at: timestamp?
|
||
tokenized: boolean?
|
||
requires_authentication: boolean?
|
||
```
|
||
|
||
## 9.15 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
|
||
idempotency_conflict
|
||
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.
|
||
|
||
For hybrid mail, `accepted: true` means the adapter accepted the request. It does not prove that the letter was validated, printed, handed over, delivered, or read.
|
||
|
||
## 9.16 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?
|
||
native_status: string?
|
||
occurred_at: timestamp?
|
||
received_at: timestamp
|
||
observation: EventObservation
|
||
correlation: CorrelationContext
|
||
participant_id: string?
|
||
payload_ref: ResourceRef?
|
||
action_surface_ref: ActionSurfaceRef?
|
||
endpoint_ref: EndpointRef?
|
||
actor_context: ActorContext?
|
||
provider_refs:
|
||
- ProviderRef
|
||
raw_event_ref: string?
|
||
normalization_status: normalized | ignored | failed | pending
|
||
normalized_events:
|
||
- EvidenceEvent
|
||
metadata: object?
|
||
```
|
||
|
||
## 9.17 EventObservation
|
||
|
||
`EventObservation` distinguishes the event source from the event meaning.
|
||
|
||
```yaml
|
||
EventObservation:
|
||
source_type: adapter | provider_api | provider_webhook | endpoint | carrier | recipient_client | postal_carrier | feed_server | action_surface | manual | system | unknown
|
||
observed_at: timestamp
|
||
occurred_at: timestamp?
|
||
source_confidence: low | medium | high
|
||
observer_ref: string?
|
||
transport_ref: string?
|
||
notes:
|
||
- string
|
||
```
|
||
|
||
This is useful because provider events may be delayed, forwarded, batched, inferred, or partially observed.
|
||
|
||
## 9.18 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: ActionSurfaceRef?
|
||
endpoint_ref: EndpointRef?
|
||
actor_context: ActorContext?
|
||
observation: EventObservation?
|
||
provider_refs:
|
||
- ProviderRef
|
||
normalized_meaning: string
|
||
evidence_grade: EvidenceGrade
|
||
confidence: ConfidenceGrade
|
||
raw_event_ref: string?
|
||
correlation: CorrelationContext
|
||
native_status_mapping_ref: string?
|
||
metadata: object?
|
||
```
|
||
|
||
### Required Fields
|
||
|
||
The following fields are REQUIRED:
|
||
|
||
```text
|
||
evidence_event_id
|
||
event_type
|
||
event_family
|
||
observed_at
|
||
coordination_case_id
|
||
normalized_meaning
|
||
evidence_grade
|
||
confidence
|
||
correlation
|
||
```
|
||
|
||
`occurred_at` SHOULD be included when the source provides it.
|
||
|
||
## 10. Canonical Event Families
|
||
|
||
The following event families are canonical for adapter-generated evidence.
|
||
|
||
```text
|
||
notification
|
||
publication
|
||
access
|
||
delivery
|
||
interaction
|
||
identity
|
||
authority
|
||
payload
|
||
payment
|
||
signature
|
||
feed
|
||
webhook
|
||
system
|
||
manual
|
||
result
|
||
policy
|
||
```
|
||
|
||
Adapters SHOULD map native events into these families.
|
||
|
||
## 11. Canonical Event Types
|
||
|
||
This version defines a starter vocabulary. It is not exhaustive.
|
||
|
||
## 11.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
|
||
```
|
||
|
||
## 11.2 Publication and Feed Events
|
||
|
||
```text
|
||
publication.item.published
|
||
publication.item.updated
|
||
publication.item.removed
|
||
feed.item.published
|
||
feed.item.updated
|
||
feed.item.removed
|
||
feed.item.expired
|
||
feed.item.fetched
|
||
feed.feed.fetched
|
||
feed.feed.validated
|
||
feed.feed.validation_failed
|
||
feed.hub.notified
|
||
feed.hub.notification_failed
|
||
```
|
||
|
||
## 11.3 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
|
||
```
|
||
|
||
## 11.4 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
|
||
delivery.production.started
|
||
delivery.production.completed
|
||
delivery.production.failed
|
||
delivery.postal.handed_over
|
||
delivery.postal.in_transit
|
||
delivery.postal.delivery_confirmed
|
||
delivery.postal.undeliverable
|
||
delivery.postal.return_received
|
||
delivery.postal.forwarded
|
||
delivery.postal.address_corrected
|
||
delivery.postal.status_unknown
|
||
delivery.postal.expired_without_final_status
|
||
```
|
||
|
||
The event `delivery.postal.delivered` SHOULD be avoided because it is ambiguous. Use `delivery.postal.delivery_confirmed` where actual confirmation semantics exist.
|
||
|
||
## 11.5 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
|
||
```
|
||
|
||
## 11.6 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
|
||
```
|
||
|
||
## 11.7 Authority Events
|
||
|
||
```text
|
||
authority.unknown
|
||
authority.self_asserted
|
||
authority.delegate_authorized
|
||
authority.organizational_representative_verified
|
||
authority.signer_authorized
|
||
authority.payment_authorized
|
||
authority.authorization_failed
|
||
```
|
||
|
||
## 11.8 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
|
||
```
|
||
|
||
## 11.9 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
|
||
```
|
||
|
||
## 11.10 Webhook/System Events
|
||
|
||
```text
|
||
webhook.request.sent
|
||
webhook.response.accepted
|
||
webhook.response.rejected
|
||
webhook.delivery.failed
|
||
system.adapter.health_changed
|
||
system.provider.degraded
|
||
system.provider.unavailable
|
||
```
|
||
|
||
## 12. Acceptance-Level Metadata
|
||
|
||
Some generic event names, especially `notification.endpoint.accepted`, may represent different strengths depending on protocol.
|
||
|
||
Adapters SHOULD include acceptance-level metadata.
|
||
|
||
```yaml
|
||
AcceptanceSemantics:
|
||
acceptance_level: provider | relay | carrier | server | endpoint | client | device | mailbox | physical_handover | unknown
|
||
finality: preliminary | intermediate | final | unknown
|
||
does_not_mean:
|
||
- string
|
||
```
|
||
|
||
Examples:
|
||
|
||
```yaml
|
||
email_mx_accepted:
|
||
acceptance_level: server
|
||
finality: intermediate
|
||
does_not_mean:
|
||
- inbox placement
|
||
- human awareness
|
||
```
|
||
|
||
```yaml
|
||
sms_delivered:
|
||
acceptance_level: device
|
||
finality: final
|
||
does_not_mean:
|
||
- human read
|
||
- intended-recipient identity
|
||
```
|
||
|
||
```yaml
|
||
xmpp_delivery_receipt:
|
||
acceptance_level: client
|
||
finality: intermediate
|
||
does_not_mean:
|
||
- displayed
|
||
- understood
|
||
```
|
||
|
||
```yaml
|
||
hybridmail_postal_handover:
|
||
acceptance_level: physical_handover
|
||
finality: intermediate
|
||
does_not_mean:
|
||
- final delivery confirmation
|
||
- human reading
|
||
```
|
||
|
||
## 13. 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
|
||
```
|
||
|
||
## 14. 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.
|
||
```
|
||
|
||
## 15. NativeStatusMapping
|
||
|
||
Adapters MUST define native-to-normalized mappings for provider statuses or native events where applicable.
|
||
|
||
```yaml
|
||
NativeStatusMapping:
|
||
native_status: string
|
||
native_event_type: string?
|
||
native_status_scope: provider | endpoint | transport | interaction | delivery | production | postal | payment | signature | publication | feed | system | unknown
|
||
normalized_event: string
|
||
normalized_state: string?
|
||
evidence_grade: EvidenceGrade
|
||
confidence: low | medium | high
|
||
terminal: boolean
|
||
retryable: boolean?
|
||
ambiguous: boolean
|
||
product_or_feature_dependent: boolean
|
||
required_features:
|
||
- string
|
||
warning: string?
|
||
examples:
|
||
- string
|
||
```
|
||
|
||
## 16. NativeEventSemantics
|
||
|
||
Adapters SHOULD document native event semantics for agent-friendly implementation.
|
||
|
||
```yaml
|
||
NativeEventSemantics:
|
||
native_event_type: string
|
||
source_system: string
|
||
plain_meaning: string
|
||
does_not_mean:
|
||
- string
|
||
normalized_mapping: string
|
||
evidence_grade: EvidenceGrade
|
||
examples:
|
||
- string
|
||
```
|
||
|
||
Example:
|
||
|
||
```yaml
|
||
native_event_type: delivered
|
||
source_system: email_provider
|
||
plain_meaning: Recipient mail server accepted the message.
|
||
does_not_mean:
|
||
- Message reached inbox.
|
||
- Human recipient saw the message.
|
||
- Payload was accessed.
|
||
normalized_mapping: notification.endpoint.accepted
|
||
```
|
||
|
||
## 17. AdapterEvidenceAssessment
|
||
|
||
Adapters SHOULD provide a native evidence assessment for standalone use and diagnostics.
|
||
|
||
```yaml
|
||
AdapterEvidenceAssessment:
|
||
subject_ref: string
|
||
coordination_case_id: string?
|
||
participant_id: string?
|
||
adapter_id: string
|
||
category: success | fail | undef
|
||
subclass: string
|
||
confidence: low | medium | high
|
||
strongest_signal: string?
|
||
evidence_summary:
|
||
- string
|
||
recommended_coordination_interpretation: string?
|
||
limitations:
|
||
- string
|
||
```
|
||
|
||
Adapter assessment is advisory.
|
||
|
||
`coordination-engine` remains authoritative for participant and case state.
|
||
|
||
Examples:
|
||
|
||
```text
|
||
email:
|
||
category: undef
|
||
subclass: endpoint_accepted_only
|
||
|
||
sms:
|
||
category: success
|
||
subclass: delivered
|
||
|
||
hybridmail:
|
||
category: success
|
||
subclass: handed_to_postal_service
|
||
```
|
||
|
||
These adapter-native classifications do not automatically become coordination-case success.
|
||
|
||
## 18. 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 backed by trusted identity or portal evidence.
|
||
* `sms-connect` SHOULD NOT assume phone possession equals intended participant identity.
|
||
* `rss-connect` SHOULD NOT assume feed fetch equals participant identity.
|
||
* `xmpp-connect` MAY provide medium/high identity evidence if JID mapping and authentication are reliable.
|
||
* `hybridmail-connect` SHOULD NOT infer recipient identity merely from postal dispatch.
|
||
|
||
## 19. 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.
|
||
|
||
## 20. 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
|
||
```
|
||
|
||
```yaml
|
||
provider_name: pingen
|
||
ref_type: letter_id
|
||
ref_value: letter_123
|
||
```
|
||
|
||
## 21. FeatureDependency
|
||
|
||
`FeatureDependency` describes provider-, route-, product-, or configuration-specific requirements.
|
||
|
||
```yaml
|
||
FeatureDependency:
|
||
feature_name: string
|
||
dependency_type: provider | product | route | country | endpoint | recipient_client | configuration | policy | account | unknown
|
||
required_for_events:
|
||
- string
|
||
fallback_behavior: string
|
||
limitation: string
|
||
```
|
||
|
||
Examples:
|
||
|
||
```yaml
|
||
feature_name: email_click_tracking
|
||
dependency_type: configuration
|
||
required_for_events:
|
||
- interaction.link.clicked
|
||
fallback_behavior: no click events emitted
|
||
limitation: Link clicks cannot be observed without tracking links.
|
||
```
|
||
|
||
```yaml
|
||
feature_name: xmpp_displayed_markers
|
||
dependency_type: recipient_client
|
||
required_for_events:
|
||
- interaction.notification.opened
|
||
fallback_behavior: delivery receipts only
|
||
limitation: Displayed markers depend on client support.
|
||
```
|
||
|
||
```yaml
|
||
feature_name: hybridmail_delivery_confirmation
|
||
dependency_type: product
|
||
required_for_events:
|
||
- delivery.postal.delivery_confirmed
|
||
fallback_behavior: postal handover is maximum positive evidence
|
||
limitation: Ordinary letters do not provide delivery confirmation.
|
||
```
|
||
|
||
## 22. LateEventPolicy
|
||
|
||
Adapters frequently produce late events.
|
||
|
||
Examples:
|
||
|
||
| Adapter | Late event example |
|
||
| ----------- | ------------------------ |
|
||
| Email | async bounce |
|
||
| SMS | late delivery receipt |
|
||
| RSS | delayed feed fetch log |
|
||
| XMPP | delayed delivery receipt |
|
||
| Hybrid mail | return mail weeks later |
|
||
|
||
Adapters MUST declare their late-event policy.
|
||
|
||
```yaml
|
||
LateEventPolicy:
|
||
accepts_late_events: boolean
|
||
late_events_can_revise_assessment: boolean
|
||
late_events_can_reopen_case: boolean
|
||
default_late_event_window: string?
|
||
expected_late_event_types:
|
||
- string
|
||
notes:
|
||
- string
|
||
```
|
||
|
||
Normative rule:
|
||
|
||
```text
|
||
Adapters MUST emit late events if they are relevant.
|
||
coordination-engine decides whether to revise, annotate, reopen, or ignore case state.
|
||
```
|
||
|
||
## 23. ErrorDescriptor
|
||
|
||
```yaml
|
||
ErrorDescriptor:
|
||
code: string
|
||
message: string
|
||
retryable: boolean
|
||
category: validation | authentication | authorization | configuration | provider | network | rate_limit | timeout | conflict | idempotency_conflict | unsupported_capability | 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.
|
||
|
||
## 24. AdapterHealth
|
||
|
||
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
|
||
webhook_status: healthy | degraded | unavailable | not_supported | unknown
|
||
polling_status: healthy | degraded | unavailable | not_supported | 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?
|
||
```
|
||
|
||
## 25. 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.
|
||
|
||
## 26. Adapter Integration Modes
|
||
|
||
## 26.1 Embedded Mode
|
||
|
||
Adapter code runs in the same process as `coordination-engine`.
|
||
|
||
Suitable for:
|
||
|
||
* local development
|
||
* test adapters
|
||
* simulated adapters
|
||
* simple deployments
|
||
|
||
## 26.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
|
||
|
||
## 26.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.
|
||
```
|
||
|
||
## 27. Adapter Lifecycle
|
||
|
||
Adapters SHOULD support the following lifecycle:
|
||
|
||
```text
|
||
registered
|
||
configured
|
||
healthy
|
||
degraded
|
||
disabled
|
||
retired
|
||
```
|
||
|
||
### 27.1 Registration
|
||
|
||
During registration, the adapter provides its `AdapterDescriptor`.
|
||
|
||
### 27.2 Configuration
|
||
|
||
Configuration may include credentials, provider selection, endpoint settings, webhook secrets, templates, routing policies, tenant-specific settings, product settings, or feature flags.
|
||
|
||
### 27.3 Health Monitoring
|
||
|
||
The engine or platform periodically checks `AdapterHealth`.
|
||
|
||
### 27.4 Action Dispatch
|
||
|
||
The engine dispatches `AdapterActionRequest` objects to the adapter.
|
||
|
||
### 27.5 Event Ingestion
|
||
|
||
The adapter emits `AdapterEvent` or `EvidenceEvent` objects.
|
||
|
||
### 27.6 Degradation Handling
|
||
|
||
If an adapter is degraded, the policy engine may switch channel, delay actions, retry later, or escalate.
|
||
|
||
## 28. Event Ordering, Idempotency, and Late Events
|
||
|
||
### 28.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.
|
||
|
||
### 28.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
|
||
```
|
||
|
||
### 28.3 Late Events
|
||
|
||
Late events MUST still be accepted and recorded if they are relevant.
|
||
|
||
Examples:
|
||
|
||
```text
|
||
Email: late hard bounce
|
||
SMS: late delivery receipt
|
||
RSS: delayed fetch log
|
||
XMPP: delayed receipt after offline delivery
|
||
Hybrid mail: return mail event after postal handover
|
||
```
|
||
|
||
### 28.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.
|
||
|
||
## 29. Adapter Conformance Levels
|
||
|
||
Adapters MAY implement different maturity levels.
|
||
|
||
```text
|
||
Level 0: Descriptor only / simulated
|
||
Level 1: Action execution + basic evidence events
|
||
Level 2: Native status mapping + health + idempotency
|
||
Level 3: Evidence grading + endpoint quality + late events
|
||
Level 4: Full provider flavor / product semantics / golden tests
|
||
```
|
||
|
||
### Level 0
|
||
|
||
The adapter exposes a descriptor and may simulate actions/events.
|
||
|
||
### Level 1
|
||
|
||
The adapter can execute at least one supported action and emit basic normalized evidence events.
|
||
|
||
### Level 2
|
||
|
||
The adapter supports health, idempotency, native status mapping, and error handling.
|
||
|
||
### Level 3
|
||
|
||
The adapter supports evidence grading, endpoint quality, late events, and advisory assessments.
|
||
|
||
### Level 4
|
||
|
||
The adapter includes provider/product semantics, capability profiles, native status mapping registry, golden tests, and conformance documentation.
|
||
|
||
Production adapters SHOULD target Level 3 or higher.
|
||
|
||
Provider-flavor-heavy adapters, such as `hybridmail-connect`, SHOULD target Level 4.
|
||
|
||
## 30. Golden Test Requirements
|
||
|
||
Every adapter SHOULD define golden test scenarios.
|
||
|
||
```yaml
|
||
AdapterGoldenTest:
|
||
test_id: string
|
||
scenario: string
|
||
adapter_id: string
|
||
native_events:
|
||
- object
|
||
expected_evidence_events:
|
||
- EvidenceEvent
|
||
expected_assessment: AdapterEvidenceAssessment
|
||
must_not_emit:
|
||
- string
|
||
notes:
|
||
- string
|
||
```
|
||
|
||
Recommended test categories:
|
||
|
||
```text
|
||
duplicate action request
|
||
idempotency conflict
|
||
provider acceptance
|
||
provider rejection
|
||
ambiguous native event
|
||
late event
|
||
out-of-order event
|
||
unsupported capability
|
||
endpoint failure
|
||
strongest supported positive event
|
||
status overclaim prevention
|
||
raw event preservation
|
||
```
|
||
|
||
Example:
|
||
|
||
```yaml
|
||
test_id: hybridmail_ordinary_handover_not_delivery_confirmation
|
||
scenario: Ordinary letter handed over to postal service.
|
||
expected_evidence_events:
|
||
- event_type: delivery.postal.handed_over
|
||
must_not_emit:
|
||
- delivery.postal.delivery_confirmed
|
||
```
|
||
|
||
Example:
|
||
|
||
```yaml
|
||
test_id: email_provider_delivered_not_awareness
|
||
scenario: Email provider reports delivered.
|
||
expected_evidence_events:
|
||
- event_type: notification.endpoint.accepted
|
||
must_not_emit:
|
||
- interaction.notification.opened
|
||
- delivery.payload.downloaded
|
||
```
|
||
|
||
## 31. 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
|
||
* distinguish test/sandbox from production where relevant
|
||
|
||
Adapters SHOULD:
|
||
|
||
* support tenant separation
|
||
* support secret rotation
|
||
* support signed callbacks or event signatures
|
||
* support audit logging of action execution
|
||
|
||
## 32. 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.
|
||
|
||
## 33. Standalone Adapter Requirements
|
||
|
||
Adapters are encouraged to be useful outside `coordination-engine`.
|
||
|
||
A standalone adapter MAY provide:
|
||
|
||
* provider abstraction
|
||
* operational dashboard
|
||
* message or delivery timeline API
|
||
* diagnostic API
|
||
* native event archive
|
||
* normalized event stream
|
||
* suppression management
|
||
* provider health checks
|
||
* local policy hints
|
||
* endpoint quality diagnostics
|
||
* adapter-native evidence assessment
|
||
|
||
However, standalone features MUST NOT contradict the coordination-engine contract.
|
||
|
||
For example:
|
||
|
||
* `email-connect` may expose `delivered_to_mx`, but MUST NOT expose it as business-level awareness.
|
||
* `sms-connect` may expose `delivered_to_device`, but MUST NOT expose it as human-read proof.
|
||
* `rss-connect` may expose `published`, but MUST NOT expose it as participant awareness.
|
||
* `xmpp-connect` may expose `displayed`, but MUST NOT expose it as comprehension.
|
||
* `hybridmail-connect` may expose `handed_to_postal_service`, but MUST NOT expose it as final delivery confirmation.
|
||
|
||
## 34. 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
|
||
docs/GoldenTests.md
|
||
schemas/
|
||
src/
|
||
tests/
|
||
```
|
||
|
||
Every adapter repository MUST document:
|
||
|
||
```text
|
||
Implemented adapter contract version
|
||
Conformance level
|
||
Supported actions
|
||
Emitted normalized events
|
||
Native event mappings
|
||
Evidence grading rules
|
||
Evidence ceiling
|
||
Endpoint quality model
|
||
Late event policy
|
||
Known limitations
|
||
Provider-specific assumptions
|
||
Security model
|
||
Privacy model
|
||
Standalone usage
|
||
coordination-engine integration mode
|
||
```
|
||
|
||
## 35. Versioning
|
||
|
||
### 35.1 Contract Version
|
||
|
||
Adapters MUST declare `adapter_contract_version`.
|
||
|
||
This document defines:
|
||
|
||
```text
|
||
adapter_contract_version: 1.1
|
||
```
|
||
|
||
### 35.2 Backward Compatibility
|
||
|
||
Minor extensions MAY add:
|
||
|
||
* optional fields
|
||
* new event types
|
||
* new action types
|
||
* new adapter types
|
||
* new evidence metadata
|
||
* new capability flags
|
||
|
||
Breaking changes include:
|
||
|
||
* removing required fields
|
||
* changing meaning of existing fields
|
||
* changing event semantics
|
||
* changing idempotency requirements
|
||
* changing evidence grade semantics
|
||
* changing weakest-safe-mapping requirements
|
||
|
||
Breaking changes require a new major version.
|
||
|
||
## 36. Minimal Compliance Checklist
|
||
|
||
An adapter is minimally compliant with AdapterInterfaceSpecification 1.1 if it:
|
||
|
||
1. Exposes an `AdapterDescriptor`.
|
||
2. Exposes an `AdapterCapabilityProfile`.
|
||
3. Declares supported actions.
|
||
4. Declares emitted event types.
|
||
5. Declares an `EvidenceCeiling`.
|
||
6. Declares `AssuranceCapability`.
|
||
7. Accepts `AdapterActionRequest` objects for supported actions.
|
||
8. Returns `AdapterActionResult` objects.
|
||
9. Supports idempotency keys.
|
||
10. Emits or maps to `EvidenceEvent` objects.
|
||
11. Provides `EvidenceGrade` and `ConfidenceGrade`.
|
||
12. Preserves `CorrelationContext`.
|
||
13. Exposes `AdapterHealth`.
|
||
14. Documents known limitations.
|
||
15. Does not overclaim result success.
|
||
16. Clearly separates provider-native events from normalized evidence.
|
||
17. Applies weakest safe mapping to ambiguous native events.
|
||
18. Preserves raw native event references where possible.
|
||
19. Declares late-event behavior.
|
||
20. Provides advisory `AdapterEvidenceAssessment` or explains why not.
|
||
|
||
## 37. 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.
|
||
|
||
## 38. 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.
|
||
|
||
Version 1.1 strengthens the interface by requiring adapters to declare what they can prove, what they cannot prove, how native statuses map to normalized evidence, and how ambiguity is handled.
|
||
|
||
The central rule is:
|
||
|
||
> Adapters must preserve facts, underclaim semantics, expose limitations, and let coordination-engine decide result meaning.
|
||
|
||
This distinction is essential for reliable, extensible, evidence-driven digital coordination.
|
||
|