oc_connect
Loading...
Searching...
No Matches
oc_connect.inbound.poller Namespace Reference

Classes

class  InboundTransport
class  PollResult
class  _Question
class  InboundPoller

Functions

tuple[str, str]|None parse_callback_data (Any data)

Variables

int FLOOD_LIMIT = 30
float FLOOD_WINDOW_SECONDS = 60.0
str INBOUND_LANE = "inbound-telegram"
str OUTBOUND_LANE = "outbound-telegram"
str CALLBACK_SEPARATOR = ":"
tuple CALLBACK_REFUSALS
str CALLBACK_ACK_KEY_PREFIX = "callback_ack-"

Detailed Description

Inbound transport gates: pinned sender, flood bound, hash-only drop log.

Proposal V1 §4 and §10.4. The poller is the only thing that turns a Telegram
update into a stored message, and it refuses far more than it accepts:

* **Pinned sender only.** The account id *and* the chat id must both match the
  destination pinned at setup, and the sender must not be a bot. Everything
  else is dropped, hash-logged, and never written to the inbox. Dropped
  updates still advance the cursor: re-reading a hostile sender's message on
  every poll would be a self-inflicted flood.
* **Text only.** A v1 message without text is dropped the same way. Widening
  to attachments is new attack surface and needs its own ruling.
* **Flood bound.** At most :data:`FLOOD_LIMIT` accepted messages per
  :data:`FLOOD_WINDOW_SECONDS`. Updates are processed oldest-first, and once
  the window is full the poller *stops* and leaves the cursor where it is, so
  the overflow is deferred rather than discarded and arrives in order on a
  later poll. The overflow itself is logged.
* **Taps are bound twice (plan 236).** A ``callback_query`` update is
  admitted only when its sender passes the same pinned check as a message
  AND its callback data names a SENT question whose transport message is the
  one the button sits under. Each failed binding is refused by name
  (:data:`CALLBACK_REFUSALS`), hash-logged, never stored, and never
  acknowledged. An admitted tap is stored as a structured reply, counts
  against the flood window like a message, and is acknowledged afterwards;
  a failed acknowledgement is logged and never loses the tap.

The transport is always injected. There is no code path in this module that
constructs an HTTP client, which is what keeps the suite free of live calls.

Dependencies
------------
- oc_connect.audit (AuditStore, AuditRecord, content_hash, timestamp, utc_now - hash-only received, dropped, overflow and tap-acknowledgement records)
- oc_connect.comms (CommsBus, new_ulid - the poll cursor path and inbound message ids)
- oc_connect.connectors.telegram.destinations (TelegramDestination - the pinned account and chat a sender must match)
- oc_connect.inbound.classify (classify - mechanical classification of each admitted message)
- oc_connect.inbound.inbox (InboxStore - stores admitted messages and counts the flood window)
- oc_connect.outbox (Outbox, OutboxItem - correlates replies and taps to the sent question)
- oc_diagnostics (_dbg structured logger)
- option_c_connector_contracts (InboundMessage, InboundCorrelation, REPLY_VOCABULARY, lane - message model, correlation and lane risk)

Function Documentation

◆ parse_callback_data()

tuple[str, str] | None oc_connect.inbound.poller.parse_callback_data ( Any data)
Return ``(token, audit_id)`` for well-formed callback data, else None.

Exact match only: the token must be a :data:`REPLY_VOCABULARY` member as
written, and the audit id must be a single non-blank run with no
whitespace and no second separator. Nothing is normalised.

Definition at line 119 of file poller.py.

Here is the caller graph for this function:

Variable Documentation

◆ CALLBACK_ACK_KEY_PREFIX

str oc_connect.inbound.poller.CALLBACK_ACK_KEY_PREFIX = "callback_ack-"

Definition at line 87 of file poller.py.

◆ CALLBACK_REFUSALS

tuple oc_connect.inbound.poller.CALLBACK_REFUSALS
Initial value:
1= (
2 "unpinned_sender",
3 "malformed_callback",
4 "uncorrelated_callback",
5 "callback_message_mismatch",
6)

Definition at line 77 of file poller.py.

◆ CALLBACK_SEPARATOR

str oc_connect.inbound.poller.CALLBACK_SEPARATOR = ":"

Definition at line 74 of file poller.py.

◆ FLOOD_LIMIT

int oc_connect.inbound.poller.FLOOD_LIMIT = 30

Definition at line 67 of file poller.py.

◆ FLOOD_WINDOW_SECONDS

float oc_connect.inbound.poller.FLOOD_WINDOW_SECONDS = 60.0

Definition at line 68 of file poller.py.

◆ INBOUND_LANE

str oc_connect.inbound.poller.INBOUND_LANE = "inbound-telegram"

Definition at line 70 of file poller.py.

◆ OUTBOUND_LANE

str oc_connect.inbound.poller.OUTBOUND_LANE = "outbound-telegram"

Definition at line 71 of file poller.py.