Add Telegram webhook support with credential injection

Enable instant message delivery for Telegram via webhooks instead of polling.

Key changes:
- Add tunnel URL configuration for local development (ngrok, cloudflare)
- Auto-register webhook with Telegram API on startup using setWebhook
- Implement webhook secret validation via X-Telegram-Bot-Api-Secret-Token header
- Add credential injection for bot token via URL placeholder substitution
- Fix metadata preservation in respond() to route replies correctly
- Fix serde flatten with Option<T> issue in capabilities schema parsing

The credential injection pattern replaces {TELEGRAM_BOT_TOKEN} placeholders
in URLs with the actual token from the secrets store, keeping credentials
out of WASM module memory until the HTTP request is made.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
This commit is contained in:
Illia Polosukhin
2026-02-04 21:19:42 -08:00
co-authored by Claude Opus 4.5
parent 4ab20ff939
commit 7955c9742e
17 changed files with 1769 additions and 509 deletions
Generated
+290 -3
View File
@@ -84,6 +84,12 @@ version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]]
name = "ambient-authority"
version = "0.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9d4ee0d472d1cd2e28c97dfa124b3d8d992e10eb0a035f33f5d12e3a177ba3b"
[[package]]
name = "android_system_properties"
version = "0.1.5"
@@ -426,6 +432,84 @@ version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3"
[[package]]
name = "cap-fs-ext"
version = "3.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5528f85b1e134ae811704e41ef80930f56e795923f866813255bc342cc20654"
dependencies = [
"cap-primitives",
"cap-std",
"io-lifetimes",
"windows-sys 0.59.0",
]
[[package]]
name = "cap-net-ext"
version = "3.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20a158160765c6a7d0d8c072a53d772e4cb243f38b04bfcf6b4939cfbe7482e7"
dependencies = [
"cap-primitives",
"cap-std",
"rustix 1.1.3",
"smallvec",
]
[[package]]
name = "cap-primitives"
version = "3.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6cf3aea8a5081171859ef57bc1606b1df6999df4f1110f8eef68b30098d1d3a"
dependencies = [
"ambient-authority",
"fs-set-times",
"io-extras",
"io-lifetimes",
"ipnet",
"maybe-owned",
"rustix 1.1.3",
"rustix-linux-procfs",
"windows-sys 0.59.0",
"winx",
]
[[package]]
name = "cap-rand"
version = "3.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8144c22e24bbcf26ade86cb6501a0916c46b7e4787abdb0045a467eb1645a1d"
dependencies = [
"ambient-authority",
"rand 0.8.5",
]
[[package]]
name = "cap-std"
version = "3.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6dc3090992a735d23219de5c204927163d922f42f575a0189b005c62d37549a"
dependencies = [
"cap-primitives",
"io-extras",
"io-lifetimes",
"rustix 1.1.3",
]
[[package]]
name = "cap-time-ext"
version = "3.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "def102506ce40c11710a9b16e614af0cde8e76ae51b1f48c04b8d79f4b671a80"
dependencies = [
"ambient-authority",
"cap-primitives",
"iana-time-zone",
"once_cell",
"rustix 1.1.3",
"winx",
]
[[package]]
name = "cassowary"
version = "0.3.0"
@@ -936,13 +1020,33 @@ dependencies = [
"dirs-sys-next",
]
[[package]]
name = "dirs"
version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
dependencies = [
"dirs-sys 0.3.7",
]
[[package]]
name = "dirs"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e"
dependencies = [
"dirs-sys",
"dirs-sys 0.5.0",
]
[[package]]
name = "dirs-sys"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
dependencies = [
"libc",
"redox_users 0.4.6",
"winapi",
]
[[package]]
@@ -1074,6 +1178,17 @@ version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
[[package]]
name = "fd-lock"
version = "4.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78"
dependencies = [
"cfg-if",
"rustix 1.1.3",
"windows-sys 0.59.0",
]
[[package]]
name = "filetime"
version = "0.2.27"
@@ -1112,6 +1227,17 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "fs-set-times"
version = "0.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94e7099f6313ecacbe1256e8ff9d617b75d1bcb16a6fddef94866d225a01a14a"
dependencies = [
"io-lifetimes",
"rustix 1.1.3",
"windows-sys 0.59.0",
]
[[package]]
name = "funty"
version = "2.0.0"
@@ -1698,6 +1824,22 @@ dependencies = [
"syn 2.0.114",
]
[[package]]
name = "io-extras"
version = "0.18.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2285ddfe3054097ef4b2fe909ef8c3bcd1ea52a8f0d274416caebeef39f04a65"
dependencies = [
"io-lifetimes",
"windows-sys 0.59.0",
]
[[package]]
name = "io-lifetimes"
version = "2.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06432fb54d3be7964ecd3649233cddf80db2832f47fec34c01f65b3d9d774983"
[[package]]
name = "ipnet"
version = "2.11.0"
@@ -1916,6 +2058,12 @@ version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
[[package]]
name = "maybe-owned"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4"
[[package]]
name = "md-5"
version = "0.10.6"
@@ -1973,7 +2121,7 @@ dependencies = [
"clap",
"crossterm",
"deadpool-postgres",
"dirs",
"dirs 6.0.0",
"dotenvy",
"futures",
"hkdf",
@@ -2007,6 +2155,7 @@ dependencies = [
"uuid",
"wasmparser 0.220.1",
"wasmtime",
"wasmtime-wasi",
]
[[package]]
@@ -2856,6 +3005,16 @@ dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "rustix-linux-procfs"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fc84bf7e9aa16c4f2c758f27412dc9841341e16aa682d9c7ac308fe3ee12056"
dependencies = [
"once_cell",
"rustix 1.1.3",
]
[[package]]
name = "rustls"
version = "0.23.36"
@@ -3158,6 +3317,15 @@ dependencies = [
"lazy_static",
]
[[package]]
name = "shellexpand"
version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ccc8076840c4da029af4f87e4e8daeb0fca6b87bbb02e10cb60b791450e11e4"
dependencies = [
"dirs 4.0.0",
]
[[package]]
name = "shlex"
version = "1.3.0"
@@ -3360,6 +3528,22 @@ dependencies = [
"syn 2.0.114",
]
[[package]]
name = "system-interface"
version = "0.27.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc4592f674ce18521c2a81483873a49596655b179f71c5e05d10c1fe66c78745"
dependencies = [
"bitflags 2.10.0",
"cap-fs-ext",
"cap-std",
"fd-lock",
"io-lifetimes",
"rustix 0.38.44",
"windows-sys 0.59.0",
"winx",
]
[[package]]
name = "tap"
version = "1.0.1"
@@ -4383,6 +4567,36 @@ dependencies = [
"syn 2.0.114",
]
[[package]]
name = "wasmtime-wasi"
version = "28.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a8e04b9a4c68ad018b330a4f4914b82b01dc3582d715ce21a93564c7f26b19f"
dependencies = [
"anyhow",
"async-trait",
"bitflags 2.10.0",
"bytes",
"cap-fs-ext",
"cap-net-ext",
"cap-rand",
"cap-std",
"cap-time-ext",
"fs-set-times",
"futures",
"io-extras",
"io-lifetimes",
"rustix 0.38.44",
"system-interface",
"thiserror 1.0.69",
"tokio",
"tracing",
"url",
"wasmtime",
"wiggle",
"windows-sys 0.59.0",
]
[[package]]
name = "wasmtime-winch"
version = "28.0.1"
@@ -4412,6 +4626,15 @@ dependencies = [
"wit-parser",
]
[[package]]
name = "wast"
version = "35.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ef140f1b49946586078353a453a1d28ba90adfc54dde75710bc1931de204d68"
dependencies = [
"leb128",
]
[[package]]
name = "wast"
version = "244.0.0"
@@ -4431,7 +4654,7 @@ version = "1.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbf35b87ed352f9ab6cd0732abde5a67dd6153dfd02c493e61459218b19456fa"
dependencies = [
"wast",
"wast 244.0.0",
]
[[package]]
@@ -4474,6 +4697,48 @@ dependencies = [
"web-sys",
]
[[package]]
name = "wiggle"
version = "28.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b23e3dc273d1e35cab9f38a5f76487aeeedcfa6a3fb594e209ee7b6f8b41dcc"
dependencies = [
"anyhow",
"async-trait",
"bitflags 2.10.0",
"thiserror 1.0.69",
"tracing",
"wasmtime",
"wiggle-macro",
]
[[package]]
name = "wiggle-generate"
version = "28.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8738c5a7ef3a9de0fae10f8b84091a2aa4e059d8fef23de202ab689812b6bc6e"
dependencies = [
"anyhow",
"heck",
"proc-macro2",
"quote",
"shellexpand",
"syn 2.0.114",
"witx",
]
[[package]]
name = "wiggle-macro"
version = "28.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e882267ac583e013a38a5aaeb83a49b219456ba3aa6e6772440f7213b176e8ff"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"wiggle-generate",
]
[[package]]
name = "winapi"
version = "0.3.9"
@@ -4821,6 +5086,16 @@ dependencies = [
"memchr",
]
[[package]]
name = "winx"
version = "0.36.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f3fd376f71958b862e7afb20cfe5a22830e1963462f3a17f49d82a6c1d1f42d"
dependencies = [
"bitflags 2.10.0",
"windows-sys 0.59.0",
]
[[package]]
name = "wit-bindgen"
version = "0.46.0"
@@ -4845,6 +5120,18 @@ dependencies = [
"wasmparser 0.221.3",
]
[[package]]
name = "witx"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e366f27a5cabcddb2706a78296a40b8fcc451e1a6aba2fc1d94b4a01bdaaef4b"
dependencies = [
"anyhow",
"log",
"thiserror 1.0.69",
"wast 35.0.2",
]
[[package]]
name = "writeable"
version = "0.6.2"