Telegram ミニアプリ承認詳細カード
アクションの完全な説明・シミュレーションされた結果・残り時間まで確認し、Telegram の中でそのまま承認・拒否できる。
解決する課題
Section titled “解決する課題”高リスクなアクションに人間の同意が必要になると、DuDuClaw は承認・拒否の2つのボタンが付いたカードを Telegram にプッシュします。ボタン自体は十分ですが、判断に必要な情報——アクションの完全な説明、シミュレーションされた結果、自動拒否までの残り時間——はカードには載り切りません。これまでこれらはダッシュボードでしか見られず、「スマホで決める」は「ブラウザに切り替え、ログインし、該当の1件を探す」作業になっていました。
この機能は、その3つを Telegram の中に持ち込みます。カードに3つ目のボタン「🔎 查看詳情」(詳細を見る)が追加され、タップすると会話の上に小さな画面が展開されます。内容を確認したら、その場で承認または拒否——一連の流れは Telegram から一歩も出ません。
これは試作(spike)機能で、デフォルトはオフです。 対象はこの承認詳細カード1枚のみ:まず「チャネルの中にインターフェースを入れる」という道が成立するかを検証し、その後にタスク・支出・ステータスなど他の画面へ広げるかどうかを判断します。
高リスクアクションが人間の同意を待つ | vbot との1対1チャットにカードをプッシュ [承認] [拒否] [🔎 詳細を見る] | 3つ目のボタンをタップ v会話の上に Mini App が展開 | Telegram が署名済み initData を添付 vGateway が HMAC を再計算して検証 | 一致 --> 詳細が POST で届く v完全な説明+シミュレーション結果 +毎秒更新のカウントダウン | 承認 / 拒否 v画面は自動で閉じ、チャットのカードはその場で1行の結果に畳まれる画面に表示されるもの
Section titled “画面に表示されるもの”- どの種類の決定か:カードと同じ行のラベル(「⚠️ 高風險動作需要你同意」——高リスクなアクションにあなたの同意が必要です)。
- 誰が何をしようとしているか:AI 従業員の名前と、アクションの平易な説明(「高リスクツールを実行」「新しいスキル/ツールをインストール」…)。
- 内容:チャットの吹き出しのように切り詰められない、完全な説明。
- 承認したら次に何が起こるか:システムが事前にシミュレーションした1〜3ステップの結果。シミュレーション結果のない承認ではこのセクション自体が表示されず、でっち上げることはありません。
- 残り時間:毎秒更新されるカウントダウン。残りが3分の1を切ると赤に変わります。期限までに応答がなければ一律で自動拒否です。
- 2つの大きなボタン:このアクションを承認する/拒否する。送信に成功すると画面は自動で閉じ、会話に戻ります。
画面の配色は Telegram のテーマに追従します(ダークモード・ライトモード・カスタムテーマすべてに適用)。ダークなチャットに白い長方形が突き刺さることはありません。
有効化の条件(3つすべて必須)
Section titled “有効化の条件(3つすべて必須)”| 条件 | 設定方法 | 満たさない場合 |
|---|---|---|
| 機能スイッチ | config.toml に [miniapp] enabled = true |
エンドポイントは 404 を返し、カードは従来の2ボタンのまま |
| 公開 URL が https | config.toml の [dashboard] public_url = "https://あなたのドメイン" |
詳細ボタンは付かない(Telegram は Mini App に https を必須としている) |
| カードが 1対1のプライベートチャット に届く | プッシュ先で決まる | 詳細ボタンは付かない(Telegram は web_app ボタンをプライベートチャットのみに許可) |
[miniapp]enabled = true
[dashboard]public_url = "https://ai.example.com"変更後は gateway を再起動してください。3つの条件のどれか1つでも満たさなければ、カードはこの機能を有効化する前とまったく同じです——ボタンが欠けることも、メッセージが届かなくなることもありません。
http://localhost:18789 のようなローカルアドレスは、有効なダッシュボードの場所ではあっても、有効な Mini App の場所ではありません。公開 https ドメインを持たないデプロイ(ほとんどのローカルインストールがこれに該当)は何もする必要がなく、この機能は沈黙したままです。
セキュリティモデル
Section titled “セキュリティモデル”本人確認の仕組み
Section titled “本人確認の仕組み”Telegram が Mini App を開くとき、ユーザー id と開いた時刻を含む署名済みの initData が添付されます。署名鍵の素材はあなた自身の bot token です。DuDuClaw は公式ドキュメントどおりに再計算します:
data_check_string = hash 以外のすべてのフィールドをアルファベット順に並べ、\n で連結secret_key = HMAC_SHA256(<bot_token>, "WebAppData")hash = hex(HMAC_SHA256(data_check_string, secret_key))算出した値は Telegram が添付した hash と定数時間で比較します。一致しなければ何も返しません——この承認が存在するかどうかすら明かさず、簡略版を返すこともありません。
署名の他に、さらに3つの関門があります:
auth_dateが1時間を超えていれば期限切れ(画面を開いたまま放置した場合は会話から開き直す)。タイムスタンプがあり得ないほど未来を指す場合も同様に拒否。userフィールドに数値 id が含まれていなければ拒否。- エンドポイントには IP ごと・分ごとのリクエスト上限がある。
URL 上の ?id=<番号> は資格情報ではありません。番号を知っていても誰にも内容は見えません——ページ自体はデータを持たず、データは署名検証済みの POST を通じてのみ取得できます。
誰が決定できるか
Section titled “誰が決定できるか”第二の権限体系はありません。 Mini App が識別する Telegram ユーザー id は、カードのボタンを押したときに報告される id と同一なので、送信された決定はボタンとまったく同じ経路を通ります:
- ダッシュボードで検証済みのバインディングを持ち、役割が管理者/スーパーバイザーの人は決定できる;
- 一般従業員アカウントは不可(受信者本人であっても不可——職務分離のため);
- チャネルアカウントを誰もバインドしていないデプロイでは、「カードが届いたアカウント本人」だけが決定できる。
詳細の閲覧にも同じ判定が適用され、緩い読み取り専用ルールはありません:決定できない人は内容も見られません。
シークレットは漏れない
Section titled “シークレットは漏れない”bot token は HMAC の鍵素材としてのみ使われ、ログに書かれず、レスポンスに含まれず、ページにも入りません。ページ自体にバックエンドの詳細は一切なく、エラーメッセージはすべて「会話から開き直してください」のような人間向けの文言です。
- グループにはこのボタンが付きません。 Telegram は
web_appボタンをユーザーと bot のプライベートチャットのみに許可しています。グループにプッシュされたカードは従来の承認/拒否の2ボタンのまま——これは意図的です:無理に付けるとメッセージ全体が送信できなくなります。 - https は必須。 Telegram の規定であり、本プロジェクトの選択ではありません。
- 承認カード1枚のみ。 タスク・支出・ステータスのカードは、これまでどおり既存のボタンとダッシュボードのディープリンクを使います。
- Telegram のみ。 LINE LIFF・Teams Dialog・Feishu Web App には同等の能力がありますが、今回は実装していません。Slack・WhatsApp・Google Chat・Discord には同等の仕組みがなく、今後も「カードボタン+ネイティブフォーム」の路線のみです。
- ページは telegram.org からプラットフォーム SDK を取得します。 これは
Telegram.WebApp(initData・テーマパラメータ・ウィンドウを閉じる)を得る唯一のサポートされた方法です。SDK が取得できなくてもページは壊れません——URL フラグメント(tgWebAppData)から同じデータを読み、自動クローズだけが失われます。それ以外にページに外部リソースはありません:CSS・JS はすべてインラインで、CDN もフォントも画像もありません。
実機での検証手順
Section titled “実機での検証手順”ローカルマシンには公開 https がなく webview が開けないため、以下は公開デプロイのある環境で実行してください:
[miniapp] enabled = trueと https の[dashboard] public_urlを設定し、gateway を再起動する。- ブラウザで
https://あなたのドメイン/miniapp/approval?id=testを開く——「請從對話中開啟」(会話から開いてください)が表示されるはずです。ページが生きていて、身元なしにはデータを渡さない証拠です。 - 人間の承認が必要なアクションをトリガーし、bot とのプライベートチャットにカードを届かせる。
- カードに3つ目のボタン「🔎 查看詳情」が現れるはずです。開くと完全な内容とカウントダウンが見えます。
- 画面内で承認または拒否 → チャット内の元のカードがその場で1行の結果に畳まれます(ボタンを押したときと同じ挙動)。
- ネガティブテスト:同じ URL を決定権限のない人に渡す。開くと「您沒有查看這筆決定的權限」(この決定を閲覧する権限がありません)だけが表示されるはずです。