# 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.