Testnet only (Arkiv Tiramisu). OpenTrigger 0.1 has not had an outside audit.
OpenTrigger

Sealing

How a Telegram chat ID goes into a public rule without being public.

Rules are public, but a Telegram rule needs a chat ID, which is personal. So the chat ID is sealed: encrypted to one worker's public key, on the user's device, before it goes into a rule.

const chat = sealForWorker(chatCode, worker.sealKey) // "sealed:v1:…"
  • Algorithm: ECIES with X25519 (a fresh ephemeral key per seal), HKDF-SHA256 and XChaCha20-Poly1305.
  • Who can open it: only the worker whose sealKey it was sealed to. Its sealing key pair is derived from the worker's wallet key with HKDF, so it survives restarts with no extra secret, and the private half never leaves the worker.
  • What is stored: only the sealed:v1: text. validateRule refuses a Telegram rule with anything else.

What this does and does not hide

HiddenStill public
The chat IDThat a rule exists, who created it, when it fires
The message text, the rule name, the action
Which worker it was sealed to

Keep messages and names generic if they would say too much. The Private Pager example gives rules a random name and keeps the user's own label in the browser.

The dashboard seals in the browser and keeps the sealed text (not the code) in local storage. Nothing about the connection reaches Arkiv until you create a rule.

On this page