generated from ben/template
90 lines
2.6 KiB
Org Mode
90 lines
2.6 KiB
Org Mode
#+title: 0.1.1 Relay Envelope and Anti-Loop Rules
|
|
#+created: [2026-04-14 Tue 14:40]
|
|
#+updated: [2026-04-14 Tue 14:55]
|
|
|
|
* envelope
|
|
#+begin_src python
|
|
from dataclasses import dataclass
|
|
from typing import Literal, Optional
|
|
|
|
Origin = Literal["zulip", "xmpp"]
|
|
Direction = Literal["zulip_to_xmpp", "xmpp_to_zulip"]
|
|
|
|
@dataclass(frozen=True)
|
|
class RelayEnvelope:
|
|
envelope_id: str
|
|
origin: Origin
|
|
source_message_id: str
|
|
sender_display_name: str
|
|
target_mapping: str
|
|
timestamp: str
|
|
body_text: str
|
|
sender_platform_id: Optional[str] = None
|
|
raw_direction: Optional[Direction] = None
|
|
receipt_time: Optional[str] = None
|
|
#+end_src
|
|
|
|
Required for v0:
|
|
| field | purpose |
|
|
|---------------------+-----------------------|
|
|
| origin | source platform |
|
|
| source_message_id | duplicate detection |
|
|
| sender_display_name | relay attribution |
|
|
| target_mapping | fixed bridge route |
|
|
| timestamp | event ordering / logs |
|
|
|
|
* relay output
|
|
| direction | plain-text shape |
|
|
|---------------+--------------------------|
|
|
| Zulip -> XMPP | [zulip] <sender>: <body> |
|
|
| XMPP -> Zulip | [xmpp] <sender>: <body> |
|
|
|
|
Optional machine stamp:
|
|
- bridge_id
|
|
- relayed_from
|
|
- relayed_source_id
|
|
|
|
* loop guards
|
|
1. self-authored
|
|
- Zulip sender == bridge account
|
|
- XMPP sender == bridge nick/jid
|
|
2. stamped bridge message
|
|
- inbound carries this bridge instance stamp
|
|
3. recent-seen duplicate
|
|
- key = (origin, source_message_id)
|
|
|
|
Order:
|
|
1. scope check
|
|
2. self/stamp check
|
|
3. duplicate check
|
|
4. normalize + relay once
|
|
5. record seen key after success
|
|
|
|
* failure policy
|
|
| case | action |
|
|
|--------------------------------+--------------------------------|
|
|
| empty body after normalization | drop + log |
|
|
| unknown origin | drop + log |
|
|
| unmapped target | drop + log |
|
|
| no usable id | synthesize fallback id, log it |
|
|
| non-chat event | drop + log |
|
|
| duplicate upstream event | drop, info/debug log |
|
|
|
|
* reconnect policy
|
|
- no history backfill
|
|
- only newly delivered events
|
|
- in-memory TTL cache suppresses short replay bursts
|
|
- restart may re-emit old events; acceptable for v0
|
|
|
|
* non-goals
|
|
- edits / deletes / reactions
|
|
- attachment mirroring
|
|
- presence / roster sync
|
|
- multi-room routing
|
|
- Hermes / Retcon integration
|
|
|
|
* exit condition
|
|
- envelope shape is frozen
|
|
- loop guards are explicit
|
|
- duplicate / malformed / reconnect behavior is explicit
|