added basic envelope data model and message handling

This commit is contained in:
ben
2026-04-14 15:16:01 -04:00
parent 5ad2b6b9b7
commit c72b1d8aba
3 changed files with 95 additions and 7 deletions

89
pm/relay-model.org Normal file
View File

@@ -0,0 +1,89 @@
#+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