Files
coordination-engine/spec/XmppAdapterSpecification.md

1622 lines
59 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 recipients 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 XMPPs 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 participants 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.