generated from coulomb/repo-seed
1622 lines
59 KiB
Markdown
1622 lines
59 KiB
Markdown
# 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.
|
||
|