# XmppAdapterSpecification.md ## 1. Document Status **Document:** XmppAdapterSpecification.md **Project:** xmpp-connect **Target Integration:** coordination-engine **Adapter Contract:** AdapterInterfaceSpecification.md v1.0 **Status:** Draft v1.0 **Primary Scope:** XMPP messaging, presence, delivery receipts, displayed markers, multi-user chat, PubSub, and XMPP event normalization as a coordination-engine adapter ## 2. Purpose This document specifies how `xmpp-connect` models XMPP as a communication protocol and how it integrates with `coordination-engine`. `xmpp-connect` is an adapter for near-real-time messaging, presence-aware communication, system-to-system signaling, lightweight interaction, group communication, and publish-subscribe communication through XMPP. XMPP can provide richer interaction evidence than email or RSS because it has native concepts for authenticated sessions, JIDs, resources, presence, message stanzas, delivery receipts, displayed markers, chat state, group rooms, and PubSub nodes. However, XMPP still does not automatically prove human awareness, comprehension, legal receipt, payload retrieval, signature, payment, or coordination result satisfaction. The key design objective is to make XMPP useful as a notification, communication, presence, and lightweight interaction adapter while preserving uncertainty and avoiding overclaiming result success. ## 3. Core Principle XMPP is a presence-aware, near-real-time messaging and eventing protocol. It can provide stronger endpoint, session, and client-level evidence than email or RSS, but adapter events remain evidence, not coordination result satisfaction. The adapter MUST distinguish: ```text server acceptance routeability to bare JID or full JID resource/session availability presence evidence client delivery receipt displayed marker acknowledgement marker chat state MUC room delivery PubSub publication inbound reply or command identity-bound evidence from authenticated XMPP sessions result evidence from other action surfaces ``` Delivery to an XMPP client controlled by a recipient can be strong notification evidence. A displayed marker can be stronger awareness evidence. But coordination-engine remains responsible for deciding whether this satisfies the intended result. ## 4. Architectural Role ### 4.1 Standalone Role As a standalone component, `xmpp-connect` provides: * provider-neutral XMPP client or component integration * XMPP message sending * XMPP stanza tracking * delivery receipt request and processing * displayed marker request and processing where supported * presence observation * inbound message and command handling * MUC room message support * optional PubSub publication * message timeline and evidence assessment * JID endpoint diagnostics * XMPP server and stream health diagnostics * normalized XMPP evidence events ### 4.2 coordination-engine Adapter Role As a `coordination-engine` adapter, `xmpp-connect` provides: #### Actions * `notification.send` * `notification.send_reminder` * `notification.schedule` where supported externally * `notification.cancel` where queued locally and not yet sent * `interaction.request_acknowledgement` * `interaction.send_command_prompt` * `feed.publish_item` for XMPP PubSub where used * `notification.register_tracking_context` * `recipient.suppress` * `recipient.unsuppress` #### Signals * `notification.attempt.accepted_by_adapter` * `notification.attempt.rejected_by_adapter` * `notification.attempt.accepted_by_provider` * `notification.attempt.rejected_by_provider` * `notification.endpoint.accepted` * `notification.endpoint.deferred` * `notification.endpoint.rejected_temporary` * `notification.endpoint.rejected_permanent` * `notification.endpoint.unreachable` * `notification.endpoint.unknown` * `interaction.reply_received` * `interaction.acknowledgement_recorded` * `interaction.notification.opened` * `interaction.authenticated_actor_interaction` * `interaction.unverified_actor_interaction` * `identity.actor_authenticated` * `feed.item.published` * `feed.item.fetched` where PubSub subscriber evidence is available * `system.provider.degraded` * `system.provider.unavailable` ## 5. Relationship to coordination-engine `xmpp-connect` does not own: * `CoordinationCase` * intended result evaluation * participant-level success * case-level success * legal receipt interpretation * portal payload retrieval * payment settlement * contract signature * final acknowledgement policy * multi-channel escalation logic `xmpp-connect` owns: * XMPP connection and stream management * XMPP server/provider abstraction * JID and resource modeling * stanza sending * stanza IDs and correlation * delivery receipt handling * displayed marker handling * presence tracking * inbound message parsing * MUC and PubSub event mapping * XMPP-native message timeline * XMPP evidence mapping * XMPP-specific uncertainty classification The boundary rule is: > xmpp-connect reports what happened in the XMPP channel and what that may indicate. coordination-engine decides what that means for the coordination case. ## 6. XMPP as Notification, Communication, Presence, and Event Channel Within `coordination-engine`, XMPP can serve several roles: ```text notification channel interactive message channel presence-aware channel system-to-system event channel group/room channel PubSub publication channel lightweight acknowledgement channel ``` XMPP may carry a small payload inline, but for high-assurance or sensitive scenarios it should usually point to an authenticated action surface. Examples: ```text XMPP message: "A document is available." XMPP message: "Please acknowledge this incident." XMPP command prompt: "Reply ACK to confirm." MUC room message: "New incident case opened." PubSub item: "New coordination event available." ``` XMPP may provide stronger evidence than email if the recipient’s authenticated client sends a delivery receipt or displayed marker. Still, payload access and business result evidence should normally come from stronger domain adapters such as `portal-connect`, `signature-connect`, or `payment-connect`. ## 7. XMPP Technology Scope ### 7.1 Core XMPP The adapter should model XMPP’s core concepts: ```text XML stream message stanza presence stanza IQ stanza JID bare JID full JID resource server-to-server routing client-to-server routing authentication stream errors stanza errors ``` ### 7.2 Instant Messaging and Presence The adapter should support the basic instant messaging and presence semantics defined by XMPP IM: ```text one-to-one chat presence availability subscription state roster/contact availability where applicable offline message behavior where supported ``` ### 7.3 Delivery Receipts The adapter SHOULD support XEP-0184 Message Delivery Receipts where the remote client supports it. A delivery receipt indicates that a content message was delivered to a client controlled by the intended recipient. It does not prove human reading or result satisfaction. ### 7.4 Displayed Markers The adapter MAY support XEP-0333 Displayed Markers where the remote client supports it. A displayed marker can provide stronger evidence that the message was displayed to the user by a client, but it still does not prove comprehension, acceptance, or payload access. ### 7.5 Stream Management The adapter SHOULD support XEP-0198 Stream Management where available. Stream management can provide transport-level acknowledgement between client and server and improve reliability after connection interruptions. It should not be confused with recipient delivery or human awareness. ### 7.6 Chat State Notifications The adapter MAY support XEP-0085 Chat State Notifications. Chat states such as active, composing, paused, inactive, or gone can provide interaction context, but they are generally weak evidence and should not be used as result completion. ### 7.7 Message Archive Management The adapter MAY support XEP-0313 Message Archive Management where available. Message archive evidence can support reconstructability, but archived presence of a message does not necessarily prove recipient awareness. ### 7.8 Multi-User Chat The adapter MAY support XEP-0045 Multi-User Chat. MUC introduces room-level delivery and occupant-level uncertainty. A message sent to a room is not automatically delivered to every intended participant. ### 7.9 Publish-Subscribe The adapter MAY support XEP-0060 Publish-Subscribe. XMPP PubSub resembles RSS/WebSub in that publication and subscription evidence must be distinguished from participant-specific awareness. ## 8. XMPP Message Lifecycle Model `xmpp-connect` models an XMPP notification or message as a lifecycle with observable phases. ```text message.created message.rendered message.render_failed message.send_requested message.accepted_by_adapter message.rejected_by_adapter message.stream_available message.stream_unavailable message.sent_to_server message.server_acknowledged message.route_attempted message.endpoint_available message.endpoint_unavailable message.delivered_to_client message.displayed_by_client message.acknowledged_by_client message.reply_received message.command_received message.presence_observed message.deferred_offline message.offline_stored message.delivery_failed message.stanza_error_received message.expired message.unknown ``` The lifecycle is not strictly linear. XMPP messages may be routed to multiple resources, stored offline, archived, delivered later, or acknowledged by one resource but not another. ## 9. XMPP Message vs Attempt vs Stanza vs Resource The adapter MUST distinguish at least four layers. ### 9.1 XmppMessage The logical message created by a client or coordination case. ```yaml XmppMessage: xmpp_message_id: string coordination_case_id: string? participant_id: string? purpose: string? message_body_ref: string? template_ref: string? tracking_context: TrackingContext created_at: timestamp ``` ### 9.2 XmppAttempt One send attempt through one XMPP connection, account, component, or provider. ```yaml XmppAttempt: xmpp_attempt_id: string xmpp_message_id: string xmpp_account_ref: string xmpp_server_ref: string? from_jid: XmppEndpoint to_jid: XmppEndpoint message_type: chat | normal | headline | groupchat | error stanza_id: string? origin_id: string? server_id: string? state: XmppAttemptState created_at: timestamp updated_at: timestamp ``` ### 9.3 XmppStanza One protocol-level stanza associated with the attempt. ```yaml XmppStanza: stanza_ref: string stanza_type: message | presence | iq message_type: chat | normal | headline | groupchat | error | unknown stanza_id: string? origin_id: string? stable_id: string? from_jid: string to_jid: string payload_ref: string? sent_at: timestamp? received_at: timestamp? raw_stanza_ref: string? ``` ### 9.4 XmppEndpoint The XMPP target or sender endpoint. ```yaml XmppEndpoint: endpoint_id: string? endpoint_type: bare_jid | full_jid | muc_room_jid | pubsub_node | component_jid | unknown jid: string bare_jid: string? resource: string? display_name: string? verification_state: unknown | syntax_validated | roster_known | presence_known | authenticated | invalid suppression_state: active | suppressed | blocked | unsubscribed | unknown metadata: object? ``` A bare JID identifies an account. A full JID identifies a specific resource/session. This distinction is central to evidence interpretation. ## 10. XMPP Attempt States The adapter SHOULD support these attempt states: ```text created rendered render_failed send_requested accepted_by_adapter rejected_by_adapter stream_unavailable sent_to_server server_acknowledged route_attempted endpoint_available endpoint_unavailable offline_stored deferred delivered_to_client displayed_by_client acknowledged_by_client reply_received stanza_error_received failed expired unknown ``` These states are XMPP-native. They are not coordination result states. ## 11. XMPP Evidence Assessment `xmpp-connect` should provide an XMPP-native assessment separate from coordination-engine state. ```yaml XmppEvidenceAssessment: xmpp_message_id: string participant_id: string? category: success | fail | undef subclass: string confidence: low | medium | high strongest_signal: string? evidence_summary: - string recommended_coordination_interpretation: string? ``` The assessment categories are adapter-level hints. ### 11.1 XMPP Adapter Success XMPP-level `success` means the XMPP channel produced meaningful XMPP-channel evidence. Possible subclasses: ```text success.sent_to_server success.server_acknowledged success.delivered_to_client success.displayed_by_client success.acknowledged_by_client success.reply_received success.presence_observed success.pubsub_item_published ``` Important: These are not automatically coordination success. `success.delivered_to_client` is strong notification evidence but not human-awareness proof unless scenario policy accepts client delivery as sufficient. `success.displayed_by_client` can be stronger awareness evidence, but it still does not prove comprehension or business result satisfaction. ### 11.2 XMPP Adapter Fail XMPP-level `fail` indicates strong evidence that the XMPP channel failed or should not be used. Subclasses: ```text fail.invalid_jid fail.missing_jid fail.stream_unavailable fail.authentication_failed fail.authorization_failed fail.remote_server_unreachable fail.recipient_not_found fail.recipient_blocked fail.not_in_roster fail.policy_rejected fail.stanza_error fail.delivery_failed fail.muc_room_unavailable fail.muc_forbidden fail.pubsub_node_unavailable fail.expired fail.suppressed ``` ### 11.3 XMPP Adapter Undef XMPP-level `undef` is used when the adapter cannot determine final delivery, display, human awareness, or intended-recipient action. Subclasses: ```text undef.pending undef.sent_to_server_only undef.server_acknowledged_only undef.no_receipt_requested undef.receipt_requested_no_response undef.resource_unknown undef.bare_jid_routing_unknown undef.offline_stored undef.offline_delivery_unknown undef.presence_unavailable undef.presence_available_but_no_receipt undef.delivered_but_awareness_unproven undef.displayed_but_comprehension_unproven undef.reply_identity_uncertain undef.muc_room_message_participant_uncertain undef.pubsub_publication_only undef.conflicting_evidence undef.channel_degraded ``` The `undef` category must not be empty because XMPP delivery semantics depend on client support, resource routing, server behavior, offline storage, MUC behavior, and extension support. ## 12. Detailed XMPP Scenario Classification ### 12.1 Pre-Send Scenarios | Scenario | XMPP assessment | Normalized event | Notes | | -------------------------------------- | -------------------------------------------- | ------------------------------------------ | ----------------------------------------------------- | | Missing JID | `fail.missing_jid` | `notification.attempt.rejected_by_adapter` | No send possible | | Invalid JID syntax | `fail.invalid_jid` | `notification.attempt.rejected_by_adapter` | Strong local failure | | Template/rendering failure | `fail.stanza_error` or render fail | `notification.attempt.rejected_by_adapter` | Message unusable | | Missing XMPP account config | `fail.authentication_failed` | action error | Operational failure | | Adapter stream unavailable | `fail.stream_unavailable` or `undef.pending` | `system.provider.unavailable` | Depends on retry policy | | Recipient suppressed/blocked locally | `fail.suppressed` | `notification.channel.suppression_added` | Channel blocked | | Message requires unsupported extension | `fail.policy_rejected` or warning | action rejection or metadata | Example: mandatory receipt/display marker unsupported | ### 12.2 Stream and Server Scenarios | Scenario | XMPP assessment | Normalized event | Notes | | -------------------------- | ------------------------------------ | ------------------------------------------------------- | ----------------------------------------------- | | Adapter accepted request | `undef.pending` | `notification.attempt.accepted_by_adapter` | Adapter accepted work | | XMPP stream connected | neutral/positive health | `system.provider.degraded` cleared or metadata | Connection usable | | XMPP stream unavailable | `fail.stream_unavailable` or pending | `system.provider.unavailable` | Operational failure or retry | | SASL authentication failed | `fail.authentication_failed` | `notification.attempt.rejected_by_adapter` | Strong operational failure | | TLS/security failure | `fail.stream_unavailable` | `system.provider.unavailable` | Strong operational/security failure | | Message sent to server | `undef.sent_to_server_only` | `notification.attempt.accepted_by_provider` | Server accepted outbound stanza | | Stream management ack | `undef.server_acknowledged_only` | `notification.attempt.accepted_by_provider` | Server/stream-level ack, not recipient delivery | | Remote server unreachable | `fail.remote_server_unreachable` | `notification.endpoint.unreachable` | Strong or retryable depending error | | Stanza error received | `fail.stanza_error` | `notification.endpoint.rejected_permanent` or temporary | Depends on stanza error type | ### 12.3 Recipient and Resource Scenarios | Scenario | XMPP assessment | Normalized event | Notes | | ---------------------------------------------- | ----------------------------------- | ------------------------------------------------------- | --------------------------------------------- | | Recipient bare JID exists but resource unknown | `undef.bare_jid_routing_unknown` | `notification.endpoint.unknown` | Server may route to resource or store offline | | Full JID resource available | stronger endpoint evidence | `notification.endpoint.accepted` | Specific client/session target known | | Recipient presence available | `success.presence_observed` or weak | `notification.endpoint.accepted` with metadata | Presence does not prove message delivery | | Recipient presence unavailable | `undef.presence_unavailable` | `notification.endpoint.deferred` or unknown | Offline storage may apply | | Message stored offline | `undef.offline_stored` | `notification.endpoint.deferred` | Delivery pending/unknown | | Offline storage unsupported | `fail.delivery_failed` | `notification.endpoint.rejected_temporary` or permanent | Depends on server | | Recipient blocked sender | `fail.recipient_blocked` | `notification.endpoint.rejected_permanent` | Strong channel failure | | Recipient not in roster when required | `fail.not_in_roster` | `notification.endpoint.rejected_permanent` | Policy or server behavior | | Recipient account not found | `fail.recipient_not_found` | `notification.endpoint.rejected_permanent` | Strong endpoint failure | ### 12.4 Delivery Receipt Scenarios | Scenario | XMPP assessment | Normalized event | Notes | | --------------------------------- | ------------------------------------------------- | -------------------------------- | ---------------------------------- | | Receipt requested and received | `success.delivered_to_client` | `notification.endpoint.accepted` | Strong client-delivery evidence | | Receipt requested but no response | `undef.receipt_requested_no_response` | none or timeout event | Absence of receipt proves little | | Client does not support receipts | `undef.no_receipt_requested` or unsupported | metadata | Capability limitation | | Receipt from one resource only | `success.delivered_to_client` but resource-scoped | `notification.endpoint.accepted` | Bare-JID awareness still uncertain | | Receipt delayed | update evidence late | `notification.endpoint.accepted` | Must be accepted | | Receipt cannot be correlated | `undef.conflicting_evidence` | metadata or ignored/pending | Preserve raw event | | Receipt spoofing risk | confidence reduced | evidence grade notes | Depends on trust boundary | Delivery receipts should be strong endpoint/client evidence but not proof of reading. ### 12.5 Displayed Marker and Acknowledgement Scenarios | Scenario | XMPP assessment | Normalized event | Notes | | --------------------------------------------- | ------------------------------------------------------ | -------------------------------------------------------------- | ------------------------------------- | | Displayed marker received | `success.displayed_by_client` | `interaction.notification.opened` or authenticated interaction | Stronger awareness evidence | | Acknowledged marker received | `success.acknowledged_by_client` | `interaction.acknowledgement_recorded` | Scenario policy decides if sufficient | | Marker unsupported | `undef.display_marker_unavailable` | metadata | Capability limitation | | Marker from one resource only | `success.displayed_by_client` but scoped | event with resource metadata | Multi-device ambiguity | | Marker delayed | late evidence | event when received | Preserve timing | | Displayed marker in MUC | participant-specific only if occupant mapping reliable | interaction event | Room semantics matter | | Displayed marker does not prove comprehension | `undef.displayed_but_comprehension_unproven` | evidence notes | Avoid overclaiming | ### 12.6 Inbound Reply and Command Scenarios | Scenario | XMPP assessment | Normalized event | Notes | | ------------------------------------ | ------------------------------------------- | --------------------------------------------- | --------------------------------------- | | Free-text reply received | `success.reply_received` | `interaction.reply_received` | Strong awareness evidence | | ACK reply received | `success.acknowledged_by_client` | `interaction.acknowledgement_recorded` | May satisfy low/medium assurance policy | | Decline command received | result-relevant negative interaction | `interaction.decline_recorded` | coordination-engine decides | | Help/question received | `success.reply_received` | `interaction.reply_received` | May trigger support workflow | | Reply from unknown full JID resource | `undef.reply_identity_uncertain` | `interaction.reply_received` | Actor uncertainty | | Reply from known authenticated JID | strong | `interaction.authenticated_actor_interaction` | Stronger identity evidence | | Reply from delegated account | identity/authority uncertain unless modeled | `interaction.reply_received` | Requires participant model | ### 12.7 Multi-User Chat Scenarios | Scenario | XMPP assessment | Normalized event | Notes | | ---------------------------------- | ---------------------------------------------- | ----------------------------------------------------- | --------------------------------- | | Room message sent | `undef.muc_room_message_participant_uncertain` | `notification.endpoint.accepted` with room metadata | Room accepted message | | Room unavailable | `fail.muc_room_unavailable` | `notification.endpoint.unreachable` | Strong failure | | Sender forbidden | `fail.muc_forbidden` | `notification.endpoint.rejected_permanent` | Permission failure | | Participant present in room | medium evidence | `notification.endpoint.accepted` or presence metadata | Presence is not reading | | Occupant-specific displayed marker | stronger if reliable | `interaction.notification.opened` | Occupant mapping needed | | Anonymous room | identity uncertain | event confidence low | Cannot prove participant identity | | History replay later | `undef.delivery_pending` | metadata | Awareness timing uncertain | A MUC room is an action surface or group endpoint, not a guarantee of each participant’s awareness. ### 12.8 PubSub Scenarios | Scenario | XMPP assessment | Normalized event | Notes | | -------------------------------- | ------------------------------- | ------------------------------------------------------ | -------------------------------------- | | PubSub item published | `success.pubsub_item_published` | `feed.item.published` | Publication evidence | | Node unavailable | `fail.pubsub_node_unavailable` | `feed.hub.notification_failed` or endpoint failure | Publication failed | | Subscriber notification accepted | medium system evidence | `notification.endpoint.accepted` or webhook-like event | Not human awareness | | Subscriber fetches item | medium system evidence | `feed.item.fetched` | Identity depends on subscription model | | PubSub event to client | endpoint evidence | `notification.endpoint.accepted` | May be strong system/client evidence | | PubSub publication only | `undef.pubsub_publication_only` | `feed.item.published` | Awareness unproven | PubSub is closer to RSS/WebSub than direct chat, but can provide stronger system-level subscription evidence. ## 13. Adapter-to-Coordination Mapping ### 13.1 Core Mapping Table | XMPP-native event | XMPP assessment | coordination-engine event | Coordination interpretation | | ----------------------------- | ---------------------------------------------- | ---------------------------------------------- | --------------------------------- | | Message created | `undef.pending` | `notification.attempt.created` | Attempt exists | | Adapter accepted | `undef.pending` | `notification.attempt.accepted_by_adapter` | Work accepted | | Adapter rejected | adapter-specific fail | `notification.attempt.rejected_by_adapter` | Attempt failed | | Stream unavailable | `fail.stream_unavailable` | `system.provider.unavailable` | Channel unavailable | | Message sent to server | `undef.sent_to_server_only` | `notification.attempt.accepted_by_provider` | Server accepted outbound stanza | | Stream management ack | `undef.server_acknowledged_only` | `notification.attempt.accepted_by_provider` | Transport/server ack only | | Recipient presence available | `success.presence_observed` or weak | `notification.endpoint.accepted` with metadata | Availability evidence | | Recipient unavailable | `undef.presence_unavailable` | `notification.endpoint.deferred` or unknown | Delivery uncertain | | Offline stored | `undef.offline_stored` | `notification.endpoint.deferred` | Pending/unknown | | Delivery receipt received | `success.delivered_to_client` | `notification.endpoint.accepted` | Strong client-delivery evidence | | Displayed marker received | `success.displayed_by_client` | `interaction.notification.opened` | Strong display evidence | | Acknowledged marker received | `success.acknowledged_by_client` | `interaction.acknowledgement_recorded` | Result evidence if policy accepts | | Reply received | `success.reply_received` | `interaction.reply_received` | Strong awareness evidence | | Authenticated JID interaction | strong | `interaction.authenticated_actor_interaction` | Stronger identity evidence | | Stanza error permanent | `fail.stanza_error` | `notification.endpoint.rejected_permanent` | Strong endpoint failure | | Stanza error temporary | `undef.deferred` | `notification.endpoint.rejected_temporary` | Retryable | | MUC room message accepted | `undef.muc_room_message_participant_uncertain` | `notification.endpoint.accepted` | Room-level only | | PubSub item published | `success.pubsub_item_published` | `feed.item.published` | Publication evidence | ### 13.2 Coordination Undef Subclasses `coordination-engine` may derive these uncertainty classes from XMPP evidence: ```text undef.pending undef.technical_acceptance_only undef.endpoint_acceptance_only undef.delivered_but_awareness_unproven undef.displayed_but_comprehension_unproven undef.identity_uncertain undef.presence_available_but_no_receipt undef.offline_delivery_unknown undef.muc_participant_awareness_uncertain undef.pubsub_publication_only undef.conflicting_evidence undef.channel_degraded undef.delivery_pending undef.escalation_required ``` XMPP evidence commonly produces: ```text undef.sent_to_server_only undef.server_acknowledged_only undef.receipt_requested_no_response undef.delivered_but_awareness_unproven undef.displayed_but_comprehension_unproven undef.identity_uncertain ``` ## 14. Evidence Grading Rules ### 14.1 Server Acceptance / Stream Acknowledgement ```yaml event_type: notification.attempt.accepted_by_provider evidence_grade: strength: weak actor_certainty: none authority_certainty: none payload_certainty: low interaction_certainty: none timing_certainty: medium channel_certainty: medium non_repudiation_strength: none notes: - XMPP server or stream accepted the stanza. - Does not prove delivery to recipient client or human awareness. ``` ### 14.2 Presence Available ```yaml event_type: notification.endpoint.accepted evidence_grade: strength: medium actor_certainty: medium authority_certainty: none payload_certainty: none interaction_certainty: low timing_certainty: medium channel_certainty: medium non_repudiation_strength: low notes: - Recipient JID or resource appears available. - Presence indicates possible reachability, not message display or action. ``` ### 14.3 Delivery Receipt ```yaml event_type: notification.endpoint.accepted evidence_grade: strength: strong actor_certainty: medium authority_certainty: none payload_certainty: medium interaction_certainty: medium timing_certainty: high channel_certainty: high non_repudiation_strength: low notes: - XMPP delivery receipt indicates delivery to a client controlled by the intended recipient. - Does not prove human reading, comprehension, or payload access. ``` ### 14.4 Displayed Marker ```yaml event_type: interaction.notification.opened evidence_grade: strength: strong actor_certainty: medium authority_certainty: none payload_certainty: medium interaction_certainty: high timing_certainty: high channel_certainty: high non_repudiation_strength: low notes: - Displayed marker indicates the client displayed the message. - It is stronger awareness evidence than delivery receipt. - It still does not prove comprehension or result satisfaction. ``` ### 14.5 Acknowledgement Marker or ACK Reply ```yaml event_type: interaction.acknowledgement_recorded evidence_grade: strength: strong actor_certainty: medium authority_certainty: low payload_certainty: medium interaction_certainty: high timing_certainty: high channel_certainty: high non_repudiation_strength: low notes: - Client marker or explicit reply indicates acknowledgement-like interaction. - Whether this satisfies the intended result is scenario-policy dependent. ``` ### 14.6 Authenticated JID Reply ```yaml event_type: interaction.authenticated_actor_interaction evidence_grade: strength: strong actor_certainty: high authority_certainty: low payload_certainty: medium interaction_certainty: high timing_certainty: high channel_certainty: high non_repudiation_strength: medium notes: - Reply came from an authenticated XMPP account or known resource. - Authority still depends on participant and role modeling. ``` ### 14.7 MUC Room Message Accepted ```yaml event_type: notification.endpoint.accepted evidence_grade: strength: medium actor_certainty: low authority_certainty: none payload_certainty: medium interaction_certainty: low timing_certainty: high channel_certainty: high non_repudiation_strength: low notes: - MUC room accepted or relayed the message. - Does not prove that each intended participant saw it. ``` ### 14.8 PubSub Item Published ```yaml event_type: feed.item.published evidence_grade: strength: medium actor_certainty: none authority_certainty: none payload_certainty: medium interaction_certainty: none timing_certainty: high channel_certainty: high non_repudiation_strength: low notes: - XMPP PubSub item was published. - Publication does not prove subscriber or human awareness. ``` ## 15. Presence Model `xmpp-connect` SHOULD model presence as reachability context, not success. ```yaml XmppPresenceState: endpoint_ref: EndpointRef bare_jid: string resource: string? availability: available | unavailable | away | xa | dnd | chat | unknown priority: integer? status_text: string? observed_at: timestamp subscription_state: none | to | from | both | unknown confidence: low | medium | high ``` Presence can influence policy: ```text if presence available: prefer XMPP immediate notification if presence unavailable: send anyway with offline storage or use alternate channel if do-not-disturb: delay or use escalation policy ``` Presence MUST NOT be treated as proof of reading. ## 16. Delivery Receipt and Marker Model ```yaml XmppDeliveryReceipt: receipt_id: string original_stanza_id: string from_jid: string to_jid: string received_at: timestamp resource: string? confidence: low | medium | high ``` ```yaml XmppDisplayedMarker: marker_id: string original_stanza_id: string marker_type: displayed | acknowledged | received | unknown from_jid: string to_jid: string received_at: timestamp resource: string? confidence: low | medium | high ``` Receipts and markers should be correlated to original message IDs. If the marker uses cumulative semantics, the adapter SHOULD record that the marker applies to all relevant messages up to the marked message according to the extension semantics. ## 17. Inbound Message and Command Model ```yaml XmppInboundMessage: inbound_message_id: string from_jid: XmppEndpoint to_jid: XmppEndpoint message_type: chat | normal | groupchat | headline | error | unknown received_at: timestamp body_text: string? command_classification: none | acknowledgement | decline | help | free_text | unknown correlation: CorrelationContext? raw_stanza_ref: string? ``` Supported command classifications MAY include: ```text ACK OK CONFIRM YES NO DECLINE HELP STATUS STOP UNSUBSCRIBE ``` `STOP`/unsubscribe semantics in XMPP are not as standardized as SMS. The adapter MAY map such messages to suppression only if scenario policy or adapter configuration enables it. ## 18. MUC Model ```yaml XmppMucRoom: room_jid: string room_name: string? room_type: public | members_only | password_protected | anonymous | semi_anonymous | unknown occupant_mapping_confidence: low | medium | high supports_history: boolean? supports_markers: boolean? metadata: object? ``` ```yaml XmppMucEvent: room_jid: string occupant_jid: string? occupant_nick: string? participant_id: string? event_type: joined | left | message_sent | message_received | displayed | acknowledged | kicked | banned | error occurred_at: timestamp confidence: low | medium | high ``` MUC events require careful identity grading because room nicknames and occupant JIDs may not reliably identify real participants in all room configurations. ## 19. PubSub Model ```yaml XmppPubSubNode: service_jid: string node_id: string access_model: open | presence | roster | authorize | whitelist | unknown publisher_model: publishers | subscribers | open | unknown metadata: object? ``` ```yaml XmppPubSubItem: item_id: string service_jid: string node_id: string payload_ref: ResourceRef? published_at: timestamp publisher_jid: string? correlation: CorrelationContext ``` PubSub should map primarily to feed/publication evidence unless subscriber-specific delivery evidence is available. ## 20. Adapter Descriptor `xmpp-connect` MUST expose an `AdapterDescriptor` compatible with AdapterInterfaceSpecification.md v1.0. ```yaml adapter_id: xmpp-connect.default adapter_name: xmpp-connect adapter_version: 1.0.0 adapter_contract_version: 1.0 adapter_types: - notification - communication - interaction - feed provider_family: xmpp provider_name: configurable deployment_mode: external supported_channels: - xmpp - xmpp_muc - xmpp_pubsub supported_endpoint_types: - bare_jid - full_jid - muc_room_jid - pubsub_node - component_jid supported_actions: - action_type: notification.send mode: async idempotency_required: true - action_type: notification.send_reminder mode: async idempotency_required: true - action_type: interaction.request_acknowledgement mode: async idempotency_required: true - action_type: feed.publish_item mode: async idempotency_required: true - action_type: notification.register_tracking_context mode: sync idempotency_required: true - action_type: recipient.suppress mode: sync idempotency_required: true - action_type: recipient.unsuppress mode: sync idempotency_required: true emitted_event_types: - notification.attempt.created - notification.attempt.accepted_by_adapter - notification.attempt.rejected_by_adapter - notification.attempt.accepted_by_provider - notification.endpoint.accepted - notification.endpoint.deferred - notification.endpoint.rejected_temporary - notification.endpoint.rejected_permanent - notification.endpoint.unreachable - notification.endpoint.unknown - interaction.notification.opened - interaction.reply_received - interaction.acknowledgement_recorded - interaction.authenticated_actor_interaction - interaction.unverified_actor_interaction - identity.actor_authenticated - feed.item.published - feed.item.fetched - system.provider.degraded - system.provider.unavailable evidence_profile: strongest_evidence_level: medium_to_strong can_prove_human_awareness: partially can_prove_payload_delivery: false can_prove_identity: partially identity_profile: identity_strength: medium_to_high authority_strength: none_to_medium limitations: - Server acceptance does not prove client delivery. - Stream management acknowledgement does not prove recipient awareness. - Presence does not prove that a recipient read the message. - Delivery receipts depend on client support and do not prove reading. - Displayed markers provide stronger awareness evidence but not comprehension. - Bare JID routing can create multi-resource ambiguity. - MUC room delivery does not prove participant-specific awareness. - PubSub publication does not prove subscriber or human awareness. ``` ## 21. Action Request Handling ### 21.1 `notification.send` `notification.send` sends a new XMPP message. Required fields: ```text request_id action_type coordination_case_id participant_id target_endpoint content or template_ref tracking_context idempotency_key requested_at ``` Example: ```yaml request_id: req_001 action_type: notification.send coordination_case_id: case_123 participant_id: participant_456 channel: xmpp target_endpoint: endpoint_type: bare_jid value: recipient@example.net template_ref: secure-document-xmpp-notification variables: portal_link: https://portal.example.com/access/abc tracking_context: correlation_id: corr_789 coordination_case_id: case_123 participant_id: participant_456 notification_id: notif_001 payload_id: payload_777 idempotency_key: case_123:participant_456:xmpp:notif_001 requested_at: 2026-01-01T12:00:00Z ``` ### 21.2 Action Result The adapter returns: ```yaml request_id: req_001 adapter_id: xmpp-connect.default accepted: true action_state: accepted adapter_operation_id: xmppop_001 initial_events: - event_type: notification.attempt.accepted_by_adapter received_at: 2026-01-01T12:00:01Z ``` The result does not prove that the XMPP message was delivered or read. ## 22. Server / Provider Abstraction `xmpp-connect` SHOULD support a server/provider abstraction layer. Provider integration responsibilities: * open and maintain XMPP streams * authenticate * send stanzas * request delivery receipts * request/display markers where supported * observe presence * join or send to MUC rooms * publish PubSub items * ingest inbound messages * normalize stanza errors * expose server health Provider model: ```yaml XmppProvider: provider_name: string provider_account_ref: string supported_features: - client_to_server - component_connection - delivery_receipts - displayed_markers - stream_management - chat_state_notifications - message_archive_management - multi_user_chat - pubsub - end_to_end_encryption event_mapping_ref: string configuration_ref: string ``` The first implementation MAY use a simulated XMPP server/client. Real implementations SHOULD be added behind this abstraction. ## 23. Native XMPP Event Mapping The adapter MUST support XMPP-specific mapping modules. Common XMPP-native event groups: ```text stream_connected stream_disconnected stream_error authenticated authentication_failed message_sent message_error presence_available presence_unavailable receipt_received displayed_marker_received acknowledged_marker_received reply_received muc_message_sent muc_error pubsub_item_published pubsub_error ``` Important mapping rule: XMPP server acceptance or stream acknowledgement MUST NOT be interpreted as recipient client delivery. Delivery receipt and displayed marker evidence must be represented separately. ## 24. Stanza Error Classification `xmpp-connect` SHOULD classify stanza errors. ```yaml XmppStanzaError: error_type: cancel | continue | modify | auth | wait | unknown condition: string text: string? retryable: boolean classification: - bad_request - conflict - feature_not_implemented - forbidden - gone - internal_server_error - item_not_found - jid_malformed - not_acceptable - not_allowed - not_authorized - payment_required - recipient_unavailable - redirect - registration_required - remote_server_not_found - remote_server_timeout - resource_constraint - service_unavailable - subscription_required - undefined_condition - unexpected_request ``` Suggested mappings: | Error class | XMPP assessment | Normalized event | | ----------------------- | -------------------------------- | ------------------------------------------ | | jid_malformed | `fail.invalid_jid` | `notification.attempt.rejected_by_adapter` | | item_not_found | `fail.recipient_not_found` | `notification.endpoint.rejected_permanent` | | forbidden | `fail.authorization_failed` | `notification.endpoint.rejected_permanent` | | not_authorized | `fail.authorization_failed` | `notification.endpoint.rejected_permanent` | | recipient_unavailable | `undef.presence_unavailable` | `notification.endpoint.deferred` | | remote_server_not_found | `fail.remote_server_unreachable` | `notification.endpoint.unreachable` | | remote_server_timeout | `undef.deferred` | `notification.endpoint.rejected_temporary` | | service_unavailable | `undef.deferred` or fail | `notification.endpoint.rejected_temporary` | | resource_constraint | `undef.deferred` | `notification.endpoint.rejected_temporary` | | feature_not_implemented | capability limitation | metadata or action rejection | ## 25. Endpoint Quality `xmpp-connect` SHOULD maintain JID endpoint quality signals. ```yaml XmppEndpointQuality: endpoint_ref: EndpointRef jid_valid: boolean? domain_resolves: boolean? server_reachable: boolean? roster_known: boolean? subscription_state: none | to | from | both | unknown last_presence_available_at: timestamp? last_presence_unavailable_at: timestamp? last_delivery_receipt_at: timestamp? last_displayed_marker_at: timestamp? last_reply_at: timestamp? last_stanza_error_at: timestamp? suppression_state: string? ``` Endpoint quality may be emitted as diagnostics but should not by itself create coordination success. ## 26. Channel Health `xmpp-connect` SHOULD expose XMPP channel health. ```yaml XmppChannelHealth: xmpp_account_ref: string server_ref: string? status: healthy | degraded | failing | unknown stream_status: connected | disconnected | reconnecting | failed | unknown authentication_status: authenticated | failed | expired | unknown tls_status: active | failed | unavailable | unknown server_reachability: healthy | degraded | unavailable | unknown supported_extensions: - string known_degradations: - string ``` Health-related normalized events: ```text system.provider.degraded system.provider.unavailable system.adapter.health_changed ``` ## 27. Security Requirements `xmpp-connect` MUST: * protect XMPP credentials and tokens * use TLS where required * validate server identity where applicable * preserve idempotency * avoid duplicate sends for repeated idempotency keys * avoid logging sensitive message content by default * protect tracking and correlation IDs * sanitize inbound messages before processing * support tenant/account separation where applicable * carefully model end-to-end encryption limitations If messages are end-to-end encrypted, the adapter may be unable to inspect content or some markers. This limitation MUST be declared in the descriptor or channel health metadata. ## 28. Privacy Requirements `xmpp-connect` SHOULD: * store message content only when necessary * support metadata-only mode * support raw stanza redaction * support configurable retention of raw stanzas * store endpoint references instead of full JIDs where possible * avoid unnecessary retention of presence history * separate operational diagnostics from coordination evidence * support deletion or anonymization workflows where applicable * avoid overcollection of MUC occupant data ## 29. Reliability Requirements `xmpp-connect` MUST support: * idempotent send requests * duplicate stanza/event detection * out-of-order event handling * late receipt/marker handling * reconnect logic * stream interruption handling * provider/server timeout handling * correlation preservation * dead-letter handling for unprocessable events * explicit timeout/expiry handling for missing receipts Late events MUST be preserved. Example: ```text Message sent to server at 10:00 No receipt by 10:05 Participant unresolved at 10:30 Delivery receipt arrives at 11:00 ``` The late receipt must still be recorded and emitted as evidence. ## 30. Raw Event Preservation `xmpp-connect` SHOULD preserve raw stanzas or references to them. ```yaml RawXmppEventRef: raw_event_id: string source: stream | server | client | muc | pubsub | archive | operator storage_ref: string? received_at: timestamp redacted: boolean ``` Normalized events should reference raw event data where available: ```yaml raw_event_ref: raw_xmpp_event_123 ``` ## 31. Minimal API Surface `xmpp-connect` SHOULD expose a headless API. ### 31.1 Adapter Contract API Required conceptual operations: ```text GET /adapter/descriptor GET /adapter/health POST /adapter/actions POST /adapter/events/provider GET /adapter/events GET /adapter/messages/{id}/timeline GET /adapter/messages/{id}/assessment ``` The actual transport may differ, but these conceptual operations should exist. ### 31.2 Standalone API Useful standalone operations: ```text POST /xmpp/send GET /xmpp/messages/{id} GET /xmpp/messages/{id}/timeline GET /xmpp/messages/{id}/assessment GET /xmpp/endpoints/{id}/quality GET /xmpp/presence/{jid} POST /xmpp/muc/{room}/send POST /xmpp/pubsub/{node}/publish GET /xmpp/channel-health ``` ## 32. Example End-to-End Flows ### 32.1 Secure Document Notification 1. `coordination-engine` creates a coordination case. 2. `portal-connect` creates an authenticated document action surface. 3. Policy selects XMPP for a participant with a known JID. 4. `coordination-engine` sends `notification.send` to `xmpp-connect`. 5. `xmpp-connect` sends an XMPP message requesting a delivery receipt. 6. XMPP server accepts the stanza. 7. `xmpp-connect` emits `notification.attempt.accepted_by_provider`. 8. Recipient client returns a delivery receipt. 9. `xmpp-connect` emits `notification.endpoint.accepted`. 10. Recipient clicks or opens the portal link. 11. `portal-connect` emits `identity.actor_authenticated`. 12. Recipient downloads document. 13. `portal-connect` emits `delivery.payload.downloaded`. 14. `coordination-engine` marks participant complete. ### 32.2 Displayed Marker as Awareness Evidence 1. XMPP message is sent with displayed marker request or marker-supporting context. 2. Recipient client displays the message. 3. `xmpp-connect` receives displayed marker. 4. `xmpp-connect` emits `interaction.notification.opened`. 5. If scenario policy accepts displayed marker as sufficient awareness evidence, `coordination-engine` marks notification awareness successful. 6. If payload access is required, participant remains incomplete until delivery evidence appears. ### 32.3 XMPP ACK Reply 1. Incident alert sent via XMPP. 2. Recipient replies `ACK`. 3. `xmpp-connect` emits `interaction.acknowledgement_recorded`. 4. If scenario policy accepts XMPP acknowledgement, `coordination-engine` marks participant acknowledged. 5. If stronger identity or authority is required, the case remains open until additional evidence is received. ### 32.4 MUC Room Notification 1. Incident notification is sent to an operations MUC room. 2. Room accepts the message. 3. `xmpp-connect` emits room-level `notification.endpoint.accepted`. 4. Specific occupants may later send displayed markers or replies. 5. `coordination-engine` treats the room event as group-channel evidence and occupant events as participant evidence only where occupant mapping is reliable. ### 32.5 PubSub Publication 1. `coordination-engine` requests `feed.publish_item`. 2. `xmpp-connect` publishes item to an XMPP PubSub node. 3. `xmpp-connect` emits `feed.item.published`. 4. Subscriber delivery evidence may follow if available. 5. `coordination-engine` treats publication as PubSub/feed evidence, not human awareness. ## 33. Provider Implementation Guidance The first real implementation SHOULD be selected based on: * client library maturity * XEP-0184 support * XEP-0333 support if needed * XEP-0198 support * MUC support * PubSub support * message archive support * server reliability * webhook/event bridge options * operational simplicity * security model * integration with existing identity systems The implementation SHOULD avoid hardcoding server-specific semantics into the core XMPP model. Implementation mapping should follow: ```text XMPP stanza / server event → XMPP-native event → XmppEvidenceAssessment → EvidenceEvent for coordination-engine ``` ## 34. Channel Separation `xmpp-connect` SHOULD support separate XMPP accounts, components, rooms, or PubSub nodes for different purposes. Recommended streams: ```text transactional notification incident_alert operations_room machine_eventing legal_or_high_assurance_notice test ``` l separation may affect: * XMPP account * component JID * sender identity * MUC room * PubSub node * roster and presence policy * archive policy * encryption policy * retention policy * participant mapping ## 35. Legal and Compliance Disclaimer `xmpp-connect` does not by itself provide legal proof of delivery, legal notice, acceptance, signature, payment, or contract closure. It provides evidence from the XMPP channel. Scenario-specific applications and `coordination-engine` policies may combine XMPP evidence with stronger evidence from portal, identity, signature, payment, archive, or manual processes. The adapter MUST avoid naming technical XMPP events in ways that imply legal success. Use: ```text notification.endpoint.accepted interaction.notification.opened interaction.acknowledgement_recorded ``` Avoid: ```text recipient_legally_notified human_read_confirmed legal_delivery_completed ``` ## 36. MVP Scope The first useful version of `xmpp-connect` should implement: 1. Adapter descriptor. 2. Adapter health endpoint. 3. `notification.send`. 4. Idempotent send request handling. 5. Simulated XMPP provider or one real XMPP server/client. 6. XMPP message and attempt records. 7. XMPP stanza correlation. 8. Basic delivery receipt support. 9. Basic inbound reply support. 10. Basic presence observation. 11. Basic stanza error classification. 12. Evidence event generation. 13. Message timeline. 14. Message assessment. 15. Mapping to AdapterInterfaceSpecification.md v1.0. ### MVP Required XMPP Events ```text notification.attempt.accepted_by_adapter notification.attempt.rejected_by_adapter notification.attempt.accepted_by_provider notification.endpoint.accepted notification.endpoint.deferred notification.endpoint.rejected_temporary notification.endpoint.rejected_permanent notification.endpoint.unknown interaction.reply_received interaction.acknowledgement_recorded interaction.authenticated_actor_interaction interaction.unverified_actor_interaction system.provider.degraded system.provider.unavailable ``` ### MVP Acceptance Criteria The MVP is acceptable when it can: 1. Accept a coordination-compatible XMPP send request. 2. Dispatch or simulate an XMPP message. 3. Preserve correlation and idempotency. 4. Record server acceptance separately from recipient delivery. 5. Ingest or simulate delivery receipts. 6. Classify delivery receipt as strong client-delivery evidence but not human-awareness proof. 7. Record inbound replies as interaction evidence. 8. Record missing receipts as unresolved, not failure by default. 9. Provide a message timeline. 10. Provide an XMPP evidence assessment. 11. Integrate with coordination-engine without overclaiming success. ## 37. Future Extensions Potential future capabilities: * XEP-0333 displayed marker support * XEP-0198 stream management support * XEP-0313 message archive integration * XEP-0085 chat state notifications * XEP-0045 Multi-User Chat support * XEP-0060 PubSub support * XMPP component mode * OMEMO-aware evidence limitations * roster and subscription management * advanced participant-to-JID mapping * MUC occupant identity resolution * command bot integration * escalation bot workflows * natural-language reply classification * bridge to Matrix/Slack/Mattermost adapters * compliance archive integration * signed stanza/event audit trail ## 38. Non-Goals `xmpp-connect` is not: * a full chat application * a general collaboration platform * a workflow engine * a legal notice system by itself * a document portal * a payment system * a signature system * a full identity provider * the owner of coordination case success It may integrate with such systems or be used by them. ## 39. Summary `xmpp-connect` models XMPP as a presence-aware, near-real-time notification, communication, interaction, group, and PubSub channel. Its job is to: * send XMPP messages * observe presence and routeability * request and ingest delivery receipts * ingest displayed markers where supported * record inbound replies and commands * classify stanza and stream errors * normalize XMPP evidence * expose JID endpoint and channel diagnostics * integrate cleanly with `coordination-engine` The key rule is: > XMPP events are evidence, not result satisfaction. xmpp-connect reports XMPP-channel facts and uncertainty. coordination-engine evaluates intended results.