---
read_when:
    - exec या Plugin की अनुमोदन जीवनचक्र, संग्रहण, प्रोटोकॉल या प्राधिकरण प्रक्रिया में परिवर्तन करना
    - किसी चैनल में अनुमोदन लिंक या मूल अनुमोदन नियंत्रण जोड़ना
    - चाइल्ड-सेशन अनुमोदनों को पैरेंट या ऑर्केस्ट्रेटर दृश्यों में प्रक्षेपित करना
summary: Control UI, नेटिव ऐप्स, चैनलों और पैरेंट सत्रों में टिकाऊ, सीधे लिंक किए जा सकने वाले अनुमोदनों का डिज़ाइन
title: बहु-सतही ऑपरेटर स्वीकृतियाँ
x-i18n:
    generated_at: "2026-07-16T17:04:31Z"
    model: gpt-5.6
    postprocess_version: locale-links-v1
    prompt_version: 32
    provider: openai
    source_hash: 9defdaada1911df1184f64429e1787c4881e735c433d6dbc30a5946e11cc7cce
    source_path: refactor/operator-approvals.md
    workflow: 16
---

# बहु-सतही ऑपरेटर अनुमोदन

यह डिज़ाइन [#103505](https://github.com/openclaw/openclaw/issues/103505) को ट्रैक करता है। यह प्रक्रिया-स्थानीय अनुमोदन प्राधिकार को Gateway के स्वामित्व वाले, SQLite-समर्थित एकल जीवनचक्र से बदलता है। Gateway के स्वामित्व वाले प्रत्येक exec या plugin/tool अनुमोदन को एक स्थिर ID, एक प्रमाणीकृत Control UI रूट, परमाण्विक पहले-उत्तर-की-जीत समाधान और उसके स्रोत तथा पूर्वज सत्र स्ट्रीम के लिए केवल-ऑपरेटर प्रक्षेपण मिलते हैं।

इनलाइन क्रियाएँ और डीप लिंक साथ-साथ मौजूद रहते हैं। कोई अनुमोदन-मोड टॉगल नहीं है।

## लक्ष्य

- exec और plugin/tool गेट के लिए एक टिकाऊ अनुमोदन ऑब्जेक्ट।
- स्थिर `${controlUiBasePath}/approve/{approvalId}` रूट।
- किसी भी अधिकृत Control UI, नेटिव ऐप या चैनल सतह से समाधान।
- समवर्ती सतहों पर परमाण्विक पहले-उत्तर-की-जीत व्यवहार।
- एकसमान पुनः प्रयास आइडेम्पोटेंट हैं; देर से आने वाले परस्पर-विरोधी उत्तर विजेता को अधिलेखित नहीं कर सकते।
- टाइमआउट, विकृत विश्वसनीय निर्णय, अनुपलब्ध रूट, रद्दीकरण और पुनः आरंभ विफल होने पर अनुमति नहीं देते।
- अनुरोधित और टर्मिनल घटनाएँ स्रोत सत्र तथा सभी प्रासंगिक पैरेंट/ऑर्केस्ट्रेटर स्वामियों तक पहुँचती हैं।
- चैनलों को टाइप की गई अनुमोदन और नेविगेशन क्रियाएँ मिलती हैं; ट्रांसपोर्ट कॉलबैक डेटा चैनल-निजी रहता है।
- मौजूदा exec/plugin Gateway विधियाँ संगत रहती हैं, जबकि उनका कार्यान्वयन एक सेवा पर अभिसरित होता है।

## गैर-लक्ष्य

- Gateway के पुनः आरंभ के बाद अवरुद्ध टूल निष्पादन को स्वयं बनाए रखना या फिर से शुरू करना।
- अनुमोदन ID या URL को बेयरर क्रेडेंशियल बनाना।
- मॉडल को दिखाई देने वाले ट्रांसक्रिप्ट में अनुमोदन प्रॉम्प्ट जोड़ना या पैरेंट एजेंटों को सक्रिय करना।
- अनुमोदन नीति, उत्पाद कमांड या समीक्षक प्राधिकरण को चैनल plugins में ले जाना।
- प्रत्येक चैनल, डिवाइस या पूर्वज के लिए अनुमोदन स्थिति की प्रतिलिपि बनाना।
- exec अनुमत-सूचियों, plugin नीति संयोजन या `allow-always` स्थायित्व को फिर से डिज़ाइन करना, सिवाय वहाँ जहाँ टर्मिनल परिणामों को असंदिग्ध बनाने के लिए यह आवश्यक हो।
- पहली वृद्धि में Gateway-रहित एम्बेडेड TUI को दूरस्थ रूप से पहुँच योग्य बनाना। यह केवल स्थानीय रहता है और कोई समीक्षक न होने पर इसे विफल होकर अनुमति नहीं देनी चाहिए।

## रोलआउट-पूर्व आधाररेखा और साक्ष्य मानचित्र

यह तालिका #103505 खोले जाने के समय की कार्यान्वयन स्थिति दर्ज करती है। नीचे दिए गए रोलआउट अनुभाग उस आधाररेखा पर निर्मित टिकाऊ रजिस्ट्री, टाइप की गई क्रियाओं, डीप-लिंक पृष्ठ और नेटिव-क्लाइंट वृद्धियों को ट्रैक करते हैं।

| सतह           | आधाररेखा प्रवेश बिंदु और स्वामी                                                                                                                                  | आधाररेखा व्यवहार और अंतर                                                                                                                                                                    |
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| एजेंट exec        | `src/agents/bash-tools.exec-approval-request.ts`, `src/agents/bash-tools.exec-host-shared.ts`                                                                   | दो-चरणीय `exec.approval.*` पंजीकरण शुरुआती `/approve` रेस को रोकता है, लेकिन टाइमआउट अब भी `askFallback` के माध्यम से अनुमति बन सकता है।                                                        |
| Plugin टूल गेट  | `src/agents/agent-tools.before-tool-call.ts`                                                                                                                    | `plugin.approval.*` का अनुरोध करता है; `timeoutBehavior: "allow"` समय-समाप्त गेट को अनुमोदित कर सकता है। एम्बेडेड मोड में `src/infra/embedded-plugin-approval-broker.ts` में अलग प्रक्रिया-स्थानीय प्राधिकार है। |
| Plugin Node गेट  | `src/gateway/node-invoke-plugin-policy.ts`                                                                                                                      | Plugin प्रबंधक के माध्यम से सीधे बनाता और प्रसारित करता है, जिससे सर्वर-विधि जीवनचक्र का एक हिस्सा दोहराया जाता है।                                                                                 |
| Gateway प्राधिकार | `src/gateway/server-aux-handlers.ts`, `src/gateway/exec-approval-manager.ts`, `src/gateway/server-methods/approval-shared.ts`                                   | अलग-अलग exec और plugin प्रबंधक प्रक्रिया-स्थानीय मैप का उपयोग करते हैं। टर्मिनल प्रविष्टियाँ 15 सेकंड तक बनी रहती हैं। पहले-उत्तर-की-जीत केवल एक प्रक्रिया के भीतर लागू होती है।                                          |
| Gateway प्रोटोकॉल  | `packages/gateway-protocol/src/schema/exec-approvals.ts`, `packages/gateway-protocol/src/schema/plugin-approvals.ts`, `src/gateway/methods/core-descriptors.ts` | exec में केवल-लंबित `get` है; plugin में कोई `get` नहीं है; डीप लिंक के लिए कोई प्रकार-अज्ञेय टर्मिनल लुकअप मौजूद नहीं है।                                                                                   |
| डिलीवरी          | `src/infra/exec-approval-channel-runtime.ts`, `src/infra/approval-native-runtime.ts`, `src/infra/approval-handler-runtime.ts`                                   | उद्गम रूटिंग, अनुमोदक DM, लंबित रीप्ले, नेटिव हैंडलर और प्रक्रिया-अंतर्गत टर्मिनल क्लीनअप का समर्थन करती है। एक अलग अनुवर्ती परिवर्तन टिकाऊ टर्मिनल सामंजस्य जोड़ता है।                          |
| पोर्टेबल क्रियाएँ  | `src/interactive/payload.ts`, `src/plugin-sdk/interactive-runtime.ts`, `src/plugin-sdk/approval-reply-runtime.ts`                                               | अनुमोदन बटन ऐसी कमांड क्रियाएँ हैं जिनमें `/approve ...` होता है; URL और Web App लक्ष्य बिना प्रकार वाले बटन फ़ील्ड हैं।                                                                           |
| Telegram          | `extensions/telegram/src/approval-handler.runtime.ts`, `extensions/telegram/src/button-types.ts`                                                                | रेंडरर निजी कॉलबैक डेटा उत्पन्न करने से पहले अनुमोदन अर्थविज्ञान पहचानने हेतु कमांड टेक्स्ट पार्स करता है।                                                                                     |
| Control UI        | `ui/src/app/exec-approval.ts`, `ui/src/app/overlays.ts`, `ui/src/components/exec-approval.ts`                                                                   | अनुमोदन UI एक वैश्विक मोडल है। `ui/src/app-route-paths.ts` और `ui/src/app-routes.ts` सटीक रूट का उपयोग करते हैं और अज्ञात पथों को चैट में पुनर्लिखते हैं।                                                    |
| सत्र स्वामित्व | `src/agents/subagent-registry.types.ts`, `src/agents/subagent-registry-read.ts`, `src/config/sessions/types.ts`                                                 | नियंत्रक, अनुरोधकर्ता, स्पष्ट पैरेंट और विरासती स्पॉन स्वामित्व मौजूद हैं, लेकिन अनुमोदन घटनाएँ उन सत्र स्ट्रीम में प्रक्षेपित नहीं होतीं।                                                    |
| साझा स्थिति      | `src/state/openclaw-state-schema.sql`, `src/state/openclaw-state-db.ts`                                                                                         | मौजूदा तत्काल ट्रांज़ैक्शन और Kysely सशर्त अपडेट `state/openclaw.sqlite` में टिकाऊ तुलना-और-सेट का समर्थन करते हैं।                                                                   |

प्रतिनिधि वर्तमान परीक्षणों में `src/gateway/exec-approval-manager.test.ts`, `src/gateway/server-methods/approval-shared.test.ts`, `src/agents/bash-tools.exec-gateway-approval.e2e.test.ts`, `extensions/telegram/src/approval-handler.runtime.test.ts` और `ui/src/e2e/approval-flow.e2e.test.ts` शामिल हैं।

plugin SDK एकमात्र चैनल/plugin सीमा बना रहता है। अनुमोदन रनटाइम और प्रस्तुति परिवर्तनों को मौजूदा `src/plugin-sdk/approval-*.ts` और `src/plugin-sdk/interactive-runtime.ts` उपपथों के माध्यम से निर्यात किया जाना चाहिए; plugin उत्पादन कोड को Gateway के आंतरिक भाग आयात नहीं करने चाहिए।

## पूर्व कला

Omnigent उपयोगी UX और विफलता अर्थविज्ञान प्रदान करता है:

- [`approval.py`](https://github.com/omnigent-ai/omnigent/blob/46e3cd9754c3b8567f7b09f4d19b6249dabe0e80/omnigent/runtime/policies/approval.py) ASK को रोककर रखता है, प्रति-नीति टाइमआउट लागू करता है और केवल सटीक स्वीकार को अनुमोदन मानता है।
- [`sessions.py`](https://github.com/omnigent-ai/omnigent/blob/46e3cd9754c3b8567f7b09f4d19b6249dabe0e80/omnigent/server/routes/sessions.py) में सर्वर-पक्षीय नेटिव हार्नेस गेट और पूर्वज अनुरोध/समाधान प्रक्षेपण शामिल हैं।
- [`ApprovePage.tsx`](https://github.com/omnigent-ai/omnigent/blob/46e3cd9754c3b8567f7b09f4d19b6249dabe0e80/web/src/pages/ApprovePage.tsx) स्वतंत्र मोबाइल अनुमोदन पृष्ठ प्रदान करता है।

इसके भंडारण दावे की बिना आलोचना किए नकल न करें। वर्तमान सक्रिय लंबित स्थिति [`_elicitation_registry.py`](https://github.com/omnigent-ai/omnigent/blob/46e3cd9754c3b8567f7b09f4d19b6249dabe0e80/omnigent/server/_elicitation_registry.py) में प्रक्रिया-स्थानीय है और अप्रयुक्त लंबित तालिका को [`e3b1f2a4c9d7_drop_pending_tool_calls_table.py`](https://github.com/omnigent-ai/omnigent/blob/46e3cd9754c3b8567f7b09f4d19b6249dabe0e80/omnigent/db/migrations/versions/e3b1f2a4c9d7_drop_pending_tool_calls_table.py) द्वारा हटा दिया जाता है। OpenClaw जानबूझकर इससे आगे जाता है: SQLite प्रामाणिक स्रोत है और प्रत्येक टर्मिनल संक्रमण एक डेटाबेस तुलना-और-सेट है।

## आर्किटेक्चर और स्वामित्व

Gateway जीवनचक्र का स्वामी है:

1. एक एजेंट, plugin हुक या Node नीति प्रकार-विशिष्ट अनुरोध और प्रक्रिया-स्थानीय निष्पादन बाइंडिंग प्रदान करती है।
2. Gateway इसे सत्यापित करता है और एक स्वच्छ समीक्षक प्रक्षेपण बनाता है।
3. अनुमोदन सेवा स्रोत/स्वामी ऑडियंस की गणना करती है, कैनोनिकल पंक्ति सम्मिलित करती है और फिर प्रक्रिया-अंतर्गत प्रतीक्षक पंजीकृत करती है।
4. टिकाऊ सम्मिलन के बाद Gateway मौजूदा अनुमोदन घटनाएँ, सत्र प्रक्षेपण, चैनल सूचनाएँ और नेटिव पुश प्रकाशित करता है।
5. प्रत्येक सतह उसी सेवा के माध्यम से समाधान करती है।
6. सेवा एक टर्मिनल संक्रमण कमिट करती है, रनटाइम प्रतीक्षक को सक्रिय करती है और टर्मिनल प्रक्षेपण प्रकाशित करती है।
7. विफल घटना डिलीवरी कभी भी कमिट किए गए निर्णय को रोल बैक नहीं करती; क्लाइंट `approval.get` या सूची रीप्ले के माध्यम से पुनर्प्राप्ति करते हैं।

स्वामित्व सीमाएँ:

- `src/gateway/`: अनुमोदन सेवा, प्राधिकरण, RPC अडैप्टर, URL निर्माण, प्रतीक्षक जीवनचक्र और घटना प्रकाशन।
- `src/state/`: साझा स्कीमा और जनरेट किए गए Kysely प्रकार।
- `src/infra/`: स्वच्छ अनुमोदन व्यू मॉडल और पोर्टेबल प्रस्तुति निर्माण।
- `src/agents/`: लौटाए गए निर्णय का अनुरोध करना, प्रतीक्षा करना और उसे लागू करना; कोई स्थायित्व नहीं।
- `src/channels/` और `extensions/*`: टाइप की गई क्रियाओं को रेंडर करना, चैनल उपयोगकर्ताओं को अधिकृत करना, निजी कॉलबैक को एनकोड करना और डिलीवर किए गए नियंत्रणों को अपडेट करना।
- `src/plugin-sdk/`: केवल सार्वजनिक अनुमोदन और प्रस्तुति अनुबंध।
- `ui/`: स्वतंत्र पृष्ठ और मौजूदा कतार/मोडल क्लाइंट।

प्रक्रिया-अंतर्गत प्रतीक्षक एक सूचना तंत्र है, प्राधिकार नहीं। पंजीकरण अनुरोध प्रकाशित करने से पहले पंक्ति सम्मिलित करता है और प्रतीक्षक को समकालिक रूप से स्थापित करता है, इसलिए कोई समाधानकर्ता उन चरणों के बीच इंटरलीव नहीं कर सकता। प्रत्येक बाद का समाधानकर्ता उस प्रतीक्षक का निपटारा करने से पहले SQLite के माध्यम से कमिट करता है।

## स्थायी रिकॉर्ड

साझा स्थिति डेटाबेस में एक `operator_approvals` तालिका जोड़ें।

| स्तंभ                                             | उद्देश्य                                                                                                                                       |
| -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `approval_id`                                      | वैश्विक रूप से अद्वितीय कैनॉनिकल ID। प्रोटोकॉल संगतता के लिए मौजूदा exec ID और `plugin:` ID बनाए रखें, लेकिन प्रीफ़िक्स से कभी भी प्रकार का अनुमान न लगाएँ।      |
| `resolution_ref`                                   | उन ट्रांसपोर्ट कॉलबैक के लिए अद्वितीय पूर्ण SHA-256 base64url लोकेटर, जो कैनॉनिकल ID नहीं ले जा सकते। यह प्राधिकरण या सार्वजनिक URL ID नहीं है। |
| `kind`                                             | बंद `exec \| plugin` विभेदक।                                                                                                        |
| `status`                                           | बंद `pending \| allowed \| denied \| expired \| cancelled` स्थिति।                                                                          |
| `presentation_json`                                | सत्यापित, प्रकार-टैग किया गया समीक्षक प्रोजेक्शन। कच्चे रनटाइम अनुरोध, कमांड बाइंडिंग और कॉलबैक पेलोड प्रक्रिया-स्थानीय रहते हैं।               |
| `source_agent_id`, `source_session_key`            | स्रोत पहचान और सत्र प्रोजेक्शन एंकर। सत्र कुंजी स्थायी है; परिवर्तित होता सत्र UUID स्थायी नहीं है।                                          |
| `audience_session_keys_json`                       | सीमित ब्रेड्थ-फ़र्स्ट स्वामित्व ट्रैवर्सल द्वारा निर्मित क्रमबद्ध, डुप्लिकेट-रहित JSON सरणी। अनुरोधित और टर्मिनल इवेंट इसी स्नैपशॉट का उपयोग करते हैं। |
| `requested_by_device_id`, `requested_by_client_id` | स्थायी अनुरोधकर्ता/ऑडिट मेटाडेटा। कनेक्शन ID मेमोरी में रहता है और क्रॉस-सर्फ़ेस प्रिंसिपल नहीं है।                                         |
| `reviewer_device_ids_json`                         | केवल विश्वसनीय अनुमोदन रनटाइम द्वारा प्रदान किए गए वैकल्पिक, स्पष्ट रूप से लक्षित समीक्षक डिवाइस।                                                  |
| `runtime_epoch`                                    | पार्क किए गए निष्पादन का स्वामी प्रक्रिया युग; पुनः आरंभ के बाद अनाथ पंक्तियों को रद्द करने के लिए उपयोग किया जाता है।                                                     |
| `created_at_ms`, `expires_at_ms`, `updated_at_ms`  | प्रामाणिक समय-निर्धारण।                                                                                                                         |
| `decision`                                         | स्पष्ट उपयोगकर्ता निर्णय, जब कोई मौजूद हो।                                                                                                       |
| `terminal_reason`                                  | बंद कारण, जैसे `user`, `timeout`, `malformed-verdict`, `no-route`, `run-aborted`, या `gateway-restart`।                                |
| `resolved_at_ms`, `resolver_kind`, `resolver_id`   | विजेता और ऑडिट पहचान सर्वर-साइड सुरक्षित रखे जाते हैं। समीक्षक प्रोजेक्शन कच्चे रिज़ॉल्वर पहचानकर्ताओं को छोड़ देते हैं।                                           |
| `consumed_at_ms`, `consumed_by`                    | `allow-once` के लिए अलग रीप्ले गार्ड; उपभोग से दर्ज निर्णय मिटना नहीं चाहिए।                                                       |

आवश्यक इंडेक्स:

| इंडेक्स                                      | उद्देश्य                                                                     |
| ------------------------------------------ | --------------------------------------------------------------------------- |
| अद्वितीय `(resolution_ref)`                  | सम्मिलन के दौरान क्रॉस-कॉलम `approval_id`/`resolution_ref` अस्पष्टता को अस्वीकार करें। |
| `(status, expires_at_ms)`                  | लंबित अनुमोदन खोजें और प्रामाणिक समय-सीमाओं का मिलान करें।               |
| `(source_session_key, created_at_ms DESC)` | एक स्रोत सत्र के लिए हाल के अनुमोदनों को रीप्ले करें।                             |
| `(resolved_at_ms)`                         | निर्धारित अवधारण नीति के अनुसार सुरक्षित रखे गए टर्मिनल अनुमोदनों को हटाएँ।  |

ऑडियंस सरणियाँ छोटी और सीमित होती हैं। सत्र-फ़िल्टर किया गया रीप्ले पहले Kysely के माध्यम से दृश्यमान लंबित पंक्तियाँ चुनता है, फिर एप्लिकेशन कोड में सीमित ऑडियंस सरणियों को डीकोड और फ़िल्टर करता है; यह स्ट्रिंग मिलान या कच्ची SQL JSON क्वेरी का उपयोग नहीं करता।

टर्मिनल पंक्तियों को 30 दिनों तक बनाए रखें, जो `src/audit/audit-event-store.ts` में मेटाडेटा ऑडिट अवधारण के अनुरूप है। हटाना एक निर्धारित रखरखाव नीति है, कोई नई कॉन्फ़िगरेशन सर्फ़ेस नहीं। डेटाबेस निजी स्थानीय कंट्रोल-प्लेन स्थिति है, लेकिन समीक्षक API को पूर्ण संग्रहीत अनुरोध या रनटाइम बाइंडिंग कभी उजागर नहीं करनी चाहिए।

## स्थिति मशीन और तुलना-एवं-सेट

केवल ये ट्रांज़िशन मान्य हैं:

- `pending -> allowed`: स्पष्ट `allow-once` या `allow-always`।
- `pending -> denied`: स्पष्ट अस्वीकृति, विश्वसनीय विकृत टर्मिनल निर्णय, या कोई डिलीवरी मार्ग नहीं।
- `pending -> expired`: प्रामाणिक समय-सीमा पूरी हुई।
- `pending -> cancelled`: रन निरस्त होना, व्यवस्थित शटडाउन, या पुनः आरंभ के बाद अनाथ निष्पादन की पुनर्प्राप्ति।

प्रत्येक गैर-अनुमत टर्मिनल स्थिति का प्रभावी निर्णय अस्वीकृति है।

समाधान एक तत्काल SQLite ट्रांज़ैक्शन और निम्न के समतुल्य Kysely सशर्त अपडेट का उपयोग करता है:

```sql
UPDATE operator_approvals
SET status = ?, decision = ?, terminal_reason = ?, resolved_at_ms = ?
WHERE approval_id = ?
  AND status = 'pending'
  AND expires_at_ms > ?;
```

यदि अपडेट किसी पंक्ति को प्रभावित नहीं करता, तो वही ट्रांज़ैक्शन रिकॉर्ड पढ़ता है:

- अनुपस्थित या अनधिकृत: नहीं मिला लौटाएँ; अस्तित्व प्रकट न करें।
- अभी भी लंबित, लेकिन समय-सीमा पूरी हो चुकी है: तुलना-एवं-सेट द्वारा इसे `expired` पर सेट करें, फिर वह टर्मिनल पंक्ति लौटाएँ।
- वही दर्ज निर्णय: दर्ज विजेता के साथ आइडेम्पोटेंट सफलता लौटाएँ।
- अलग निर्णय: एकीकृत API दर्ज विजेता के साथ `applied: false` लौटाता है; जहाँ उनके जारी किए गए अनुबंध द्वारा आवश्यक हो, लीगेसी अडैप्टर `APPROVAL_ALREADY_RESOLVED` बनाए रखते हैं।
- कोई भी टर्मिनल स्थिति: उसे कभी परिवर्तित न करें।

`now == expires_at_ms` की समय-सीमा समाप्त हो चुकी है। Gateway का समय प्रामाणिक है।

`allow-once` निष्पादन, मौजूदा सटीक कमांड/सिस्टम-रन संदर्भ से बंधे `consumed_at_ms IS NULL` पर दूसरे CAS का उपयोग करता है। उपभोग के बाद अनुमोदन पंक्ति ऑडिट रिकॉर्ड बनी रहती है।

विकृत HTTP/RPC इनपुट, जिसे प्रमाणित नहीं किया जा सकता या जो किसी अनुमोदन की पहचान नहीं कर सकता, बिना किसी परिवर्तन के अस्वीकार किया जाता है और कभी अनुमोदित नहीं कर सकता। किसी ज्ञात अनुमोदन के लिए विश्वसनीय हार्नेस/वेटर से प्राप्त विकृत टर्मिनल निर्णय `denied` में ट्रांज़िशन करता है।

## Gateway API

प्रकार-निरपेक्ष समीक्षक विधियाँ जोड़ें:

| विधि                                    | अनुबंध                                                                                                                                                                                                            |
| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `approval.get { id }`                     | दृश्यमान लंबित या सुरक्षित रखा गया टर्मिनल प्रोजेक्शन लौटाता है।                                                                                                                                                          |
| `approval.resolve { id, kind, decision }` | कैनॉनिकल ID या निश्चित आकार का ट्रांसपोर्ट संदर्भ स्वीकार करता है, फिर प्राधिकरण, प्रकार और अनुमत-निर्णय सत्यापन, समय-सीमा मिलान और टर्मिनल CAS चलाता है। प्रतिक्रिया में हमेशा कैनॉनिकल ID होता है। |

सफल CAS के बाद, प्रतिबद्ध प्रोजेक्शन तुरंत लौटाएँ। लीगेसी इवेंट, चैनल फ़ॉरवर्डर और पुश टर्मिनलाइज़र सर्वोत्तम-प्रयास वाले अनुवर्ती कार्य हैं; धीमी या विफल सर्फ़ेस को विजेता प्रतिक्रिया में विलंब या उसका रोलबैक नहीं करना चाहिए।

प्रकार-विशिष्ट अनुरोध सत्यापन `exec.approval.request` और `plugin.approval.request` में बना रहता है। मौजूदा `exec.approval.get/list/waitDecision/resolve` और `plugin.approval.list/waitDecision/resolve` कैनॉनिकल सेवा के प्रोटोकॉल-सीमा अडैप्टर बनते हैं, क्योंकि वे जारी किए गए Gateway API हैं। आंतरिक कॉलर उसी परिवर्तन में सेवा पर माइग्रेट होते हैं।

समीक्षक प्रोजेक्शन एक टैग किया गया यूनियन है:

```ts
type OperatorApproval = {
  id: string;
  status: OperatorApprovalStatus;
  presentation:
    | { kind: "exec"; commandText: string /* सुरक्षित exec पूर्वावलोकन */ }
    | { kind: "plugin"; title: string; description: string /* सुरक्षित plugin पूर्वावलोकन */ };
  // सामान्य जीवनचक्र फ़ील्ड
};
```

स्थिर पथ व्युत्पन्न होता है, संग्रहीत नहीं। `approval.get` `urlPath` लौटाता है; अनुमोदित सार्वजनिक ओरिजिन जानने वाली सर्फ़ेस को निरपेक्ष `url` भी प्राप्त हो सकता है। समीक्षक स्नैपशॉट स्रोत और ऑडियंस सत्र कुंजियों को छोड़ देते हैं। Gateway अलग `session.approval` प्रोजेक्शन के लिए उन रूटिंग कुंजियों को सर्वर-साइड रखता है।

## इवेंट और पोर्टेबल कार्रवाइयाँ

PR 1 जारी किए गए इवेंट नाम, पेलोड और मौजूदा रिकॉर्ड-स्तरीय प्राप्तकर्ता फ़िल्टर सुरक्षित रखता है:

- `exec.approval.requested`
- `exec.approval.resolved`
- `plugin.approval.requested`
- `plugin.approval.resolved`

उन लीगेसी इवेंट में पूर्ण रनटाइम अनुरोध हो सकता है, इसलिए उन्हें प्रत्येक अनुमोदन-स्कोप वाले क्लाइंट तक प्रसारित नहीं किया जाना चाहिए। PR 5 लीगेसी इवेंट डिलीवरी का विस्तार करने के बजाय स्वच्छ किए गए जीवनचक्र प्रोजेक्शन के माध्यम से टैग किए गए जीवनचक्र फ़ील्ड (`status`, `sourceSessionKey`, `urlPath`, टर्मिनल मेटाडेटा और प्रस्तुति-स्तरीय `kind`) जोड़ता है।

अनुमोदन-स्कोप वाला `session.approval` प्रोजेक्शन इवेंट जोड़ें। स्थायी ऑडियंस कुंजियों के साथ कैनॉनिकल इवेंट एक बार प्रकाशित करें; सटीक-सत्र सब्सक्राइबर प्रत्येक मेल खाती कुंजी के लिए वही इवेंट प्राप्त करते हैं:

- `sessionKey`: प्रोजेक्शन प्राप्त करने वाली स्ट्रीम।
- `sourceSessionKey`: गेट उत्पन्न करने वाला चाइल्ड/स्रोत।
- `phase`: `pending \| terminal`, अनुमोदन स्थिति के आधार पर विभेदित।
- एक सुरक्षित `OperatorApproval` प्रोजेक्शन।

क्लाइंट `sessions.messages.subscribe { key, agentId?, includeApprovals: true }` के साथ ऑप्ट इन करते हैं। सफल प्रतिक्रिया एक `approvalReplay` जोड़ती है, जिसमें उस सटीक स्ट्रीम कुंजी के अधिकतम 1,000 वर्तमान लंबित अनुमोदन होते हैं, जिनकी समीक्षा के लिए सब्सक्राइब करने वाला क्लाइंट रिकॉर्ड-स्तर पर भी अधिकृत है। `truncated: false` फ़िल्टर किए गए रीप्ले को प्रामाणिक बनाता है और पुनः कनेक्ट होने वाले क्लाइंट अपने स्थानीय लंबित सेट को उससे बदलते हैं; `truncated: true` एक ओवरलोड संकेत है और क्लाइंट को अदृश्य स्थानीय प्रविष्टियाँ तब तक बनाए रखनी चाहिए, जब तक कैनॉनिकल लुकअप या बाद के जीवनचक्र इवेंट उनका निपटारा न कर दें। रीप्ले के दौरान बाद में ज्ञात हुई स्थायी समय-समाप्ति, नया स्नैपशॉट लौटाए जाने से पहले, केवल सब्सक्राइब किए गए और रिकॉर्ड-अधिकृत ऑडियंस को टर्मिनल टूम्बस्टोन उत्सर्जित करती है। `operator.admin` सीधे ऑप्ट इन कर सकता है; अधिक सीमित क्लाइंट को युग्मित डिवाइस पहचान और `operator.approvals` दोनों की आवश्यकता होती है। केवल सत्र सदस्यता कभी अनुमोदन दृश्यता प्रदान नहीं करती।

`src/gateway/server-broadcast.ts` में इवेंट को `operator.approvals` के अंतर्गत पंजीकृत करें। प्रोजेक्शन अवलोकनात्मक है: यह कभी ट्रांस्क्रिप्ट पंक्तियाँ नहीं जोड़ता, `sessions.changed` उत्सर्जित नहीं करता, या किसी एजेंट को सक्रिय नहीं करता।

`src/interactive/payload.ts` में `MessagePresentationAction` का विस्तार करें:

```ts
type MessagePresentationAction =
  | { type: "command"; command: string }
  | { type: "callback"; value: string }
  | {
      type: "approval";
      approvalId: string;
      approvalKind: "exec" | "plugin";
      decision: ExecApprovalDecision;
    }
  | { type: "url"; url: string }
  | { type: "web-app"; url: string };
```

Core टाइप की गई निर्णय कार्रवाइयाँ और एक अलग Review लिंक बनाता है, जब कोई स्वीकृत पूर्ण Control UI मूल उपलब्ध हो। चैनल किसी अनुमोदन कार्रवाई को अपने कॉलबैक प्रारूप में एन्कोड करते हैं और समाधान को कैनोनिकल सेवा पर भेजते हैं। जब सटीक कैनोनिकल ID समा सकती है, तो कॉलबैक उसका उपयोग करता है; अन्यथा वह पंक्ति के अद्वितीय पूर्ण-डाइजेस्ट `resolution_ref` का उपयोग करता है। संदर्भ केवल एक संक्षिप्त लुकअप कुंजी है: सामान्य Gateway प्रमाणीकरण, रिकॉर्ड प्राधिकरण, स्पष्ट प्रकार, अनुमत-निर्णय सत्यापन, समय-सीमा सामंजस्य और पहले-उत्तर का CAS अब भी लागू होते हैं। चैनलों को IDs को छोटा नहीं करना चाहिए, हैश उपसर्गों का समाधान नहीं करना चाहिए, `/approve` टेक्स्ट को पार्स नहीं करना चाहिए या ID उपसर्ग से प्रकार का अनुमान नहीं लगाना चाहिए।

`button.url`, `button.webApp` और कमांड-समर्थित अनुमोदन नियंत्रणों को अप्रचलित plugin SDK संगतता इनपुट के रूप में बनाए रखें। उन्हें SDK सीमा पर सामान्यीकृत करें; उसी PR में प्रत्येक बंडल किए गए आंतरिक कॉलर को माइग्रेट करें। `/approve {id} {decision}` एक टेक्स्ट फ़ॉलबैक और CLI/चैट कमांड बना रहता है, बटन का अर्थगत अनुबंध नहीं।

## Control UI

रूट `${basePath}/approve/{approvalId}` है। ID ही एकमात्र पथ पैरामीटर है; स्रोत सत्र पहचान रिकॉर्ड से आती है।

चूँकि वर्तमान राउटर में सटीक स्थिर रूट हैं और वह अज्ञात पथों को Chat पर पुनर्लिखता है, इसलिए सामान्य रूट सामान्यीकरण से पहले `ui/src/app/bootstrap.ts` में इस डीप लिंक का पता लगाएँ। सामान्य Gateway/प्रमाणीकरण सेटअप का पुनः उपयोग करें, लेकिन साइडबार शेल और वैश्विक मोडल के बाहर एक स्वतंत्र अनुमोदन पृष्ठ रेंडर करें।

दस्तावेज़ का स्वामित्व उस Gateway के पास है जिसने उसका URL प्रस्तुत किया। उसका प्रारंभिक कनेक्शन पूर्ण ऐप के सहेजे गए दूरस्थ-Gateway चयन को अनदेखा करता है, बिना उस चयन की सेटिंग बदले या कॉपी किए; केवल प्रमाणीकरण ही प्रस्तुत करने वाले Gateway के लिए सत्र-स्कोप्ड रहता है। विश्वसनीय नेटिव प्रमाणीकरण या अलग से पुष्टि किया गया `gatewayUrl` ओवरराइड इसे पुनः लक्षित कर सकता है। Core, plugin HTTP रूट और स्थिर-एक्सटेंशन पहचान से पहले एक-खंड वाले `/approve` नेमस्पेस को आरक्षित करता है, जिसमें `.json` या `.js` पर समाप्त होने वाली IDs भी शामिल हैं; जब Control UI प्रस्तुति अक्षम होती है, तो आरक्षित रूट `404` के साथ सुरक्षित रूप से विफल होता है। पृष्ठ को मुख्य Control UI बंडल में रखें, ताकि विफल लेज़ी चंक किसी सुरक्षा निर्णय को स्पिनर पर अटका न दे।

पृष्ठ की अवस्थाएँ:

- लोड हो रहा है
- प्रमाणीकरण आवश्यक
- लंबित
- समाधान किया जा रहा है
- यहाँ स्वीकृत या अस्वीकृत
- अन्यत्र समाधान किया गया
- समय-सीमा समाप्त
- रद्द
- निषिद्ध/नहीं मिला
- पुनः प्रयास सहित कनेक्शन त्रुटि

पृष्ठ Gateway RPC को कॉल करता है, किसी दूसरी अप्रमाणित REST API को नहीं। ब्राउज़र रीफ़्रेश टिकाऊ अवस्था को दोबारा पढ़ता है। यह Gateway क्रेडेंशियल्स को कभी भी URL, क्वेरी या फ़्रैगमेंट में नहीं रखता।

## प्राधिकरण और गोपनीयता

URL एक लोकेटर है, अधिकार नहीं। समाधान के लिए आवश्यक हैं:

1. प्रमाणित Gateway कनेक्शन;
2. `operator.approvals` या `operator.admin`;
3. रिकॉर्ड-स्तरीय समीक्षक प्राधिकरण।

रिकॉर्ड-स्तरीय नियम:

- `operator.admin` समीक्षा कर सकता है।
- `reviewer_device_ids` मौजूद होने पर प्रामाणिक है। केवल सूचीबद्ध युग्मित
  `operator.approvals` डिवाइस समीक्षा कर सकता है; अनुरोध करने वाले डिवाइस के पास तब तक कोई अंतर्निहित
  पहुँच नहीं होती, जब तक वह भी सूचीबद्ध न हो।
- स्पष्ट समीक्षक सूची के बिना, अनुरोध करने वाला युग्मित
  `operator.approvals` डिवाइस अपने रिकॉर्ड की समीक्षा कर सकता है।
- वास्तविक रूप से लेगेसी रिकॉर्ड, जिनमें कोई अनुरोधकर्ता या समीक्षक बाइंडिंग नहीं है, व्यापक
  युग्मित-डिवाइस दृश्यता बनाए रखते हैं, ताकि अपग्रेड पहले से लंबित कार्य को अटका न दें।
- डिवाइस-रहित आंतरिक रनटाइम स्कोप्ड
  अनुमोदन-रनटाइम कनेक्शन के माध्यम से समाधान कर सकते हैं, लेकिन पढ़ नहीं सकते। वह अधिकार केवल
  सर्वर-प्रमाणित रनटाइम टोकन से आता है; सार्वजनिक `approval.resolve` फ़ील्ड इसे
  बना नहीं सकते।
- लाइव अनुरोधकर्ता कनेक्शन स्वामित्व लेगेसी अडैप्टरों के लिए वैध रहता है; इसका
  अनुमान कभी भी मेल खाते क्लाइंट नाम से नहीं लगाया जाता।
- ऑडियंस सदस्यता केवल प्रस्तुति बदलती है। यह प्राधिकरण को कभी विस्तृत नहीं करती।

`approval.get` केवल स्वच्छ की गई समीक्षक प्रोजेक्शन को उजागर करता है और आंतरिक स्रोत/ऑडियंस रूटिंग कुंजियों को छोड़ देता है। PR 5 का `session.approval` इवेंट अपना एक गंतव्य `sessionKey` और `sourceSessionKey` साथ रखता है, जब Gateway सहेजे गए ऑडियंस स्नैपशॉट को सर्वर-साइड लागू कर देता है। मौजूदा exec/plugin इवेंट अपने ऐतिहासिक पेलोड और प्रतिबंधित प्राप्तकर्ताओं को तब तक बनाए रखते हैं, जब तक उपभोक्ता माइग्रेट नहीं हो जाते। निष्पादन योग्य अनुरोध, कमांड बाइंडिंग और निरंतरता केवल प्रोसेस-लोकल वेटर में रहते हैं। टिकाऊ पंक्ति में सुरक्षित प्रस्तुति तथा जीवनचक्र, रूटिंग और ऑडिट मेटाडेटा होता है; यह कच्चे पर्यावरण मान, क्रेडेंशियल्स, प्रमाणीकरण हेडर या चैनल कॉलबैक डेटा कभी संग्रहीत नहीं करती।

## ऑडियंस प्रोजेक्शन

प्रविष्टि से पहले ऑडियंस की एक बार गणना करें और क्रमबद्ध स्नैपशॉट सहेजें। स्वामित्व एक ग्राफ़ है, हमेशा एकल पैरेंट शृंखला नहीं: किसी चाइल्ड के पास वर्तमान नियंत्रक और मूल अनुरोधकर्ता दोनों हो सकते हैं, और वे स्वामी अलग-अलग रूट तक ले जा सकते हैं।

नियतात्मक ब्रेड्थ-फ़र्स्ट वॉक का उपयोग करें:

1. कतार को स्रोत सत्र कुंजी से आरंभ करें।
2. प्रत्येक डीक्यू की गई कुंजी के लिए नवीनतम सबएजेंट रजिस्ट्री पंक्ति पढ़ें और दोनों अलग स्वामित्व किनारों को निश्चित क्रम में एनक्यू करें: `controllerSessionKey`, फिर `requesterSessionKey`।
3. जब उपयोग योग्य रजिस्ट्री पंक्ति मौजूद हो, तो सत्र-प्रविष्टि वंशावली का भी अनुसरण न करें, जो स्टीयरिंग के बाद पुरानी हो सकती है। अन्यथा एकल वर्तमान फ़ॉलबैक किनारे `parentSessionKey ?? spawnedBy` को एनक्यू करें।
4. एनक्यू करते समय सामान्यीकृत करें और डुप्लिकेट हटाएँ, ताकि पहला, सबसे छोटा पथ जीते।
5. 64 अद्वितीय कुंजियों पर रुकें; यह ऑडियंस-आकार सीमा ट्रैवर्सल की गहराई को भी सीमित करती है।

रजिस्ट्री स्रोत `src/agents/subagent-registry-read.ts` है; स्वामित्व फ़ील्ड `src/agents/subagent-registry.types.ts` में परिभाषित हैं। सत्र फ़ॉलबैक फ़ील्ड `src/config/sessions/types.ts` में परिभाषित हैं।

अनुरोधित और टर्मिनल प्रोजेक्शन समान सहेजे गए ऑडियंस का उपयोग करते हैं, भले ही अनुमोदन लंबित रहने के दौरान फ़ोकस/नियंत्रक स्वामित्व बदल जाए। यह अनुरोध प्रोजेक्शन प्राप्त करने वाली प्रत्येक ऑडियंस सत्र स्ट्रीम के लिए टर्मिनल क्लीनअप की गारंटी देता है। समाधान हमेशा स्रोत अनुमोदन ID को लक्षित करता है; ऑडियंस सत्रों को कभी क्लोन की गई अनुमोदन अवस्था नहीं मिलती। अग्रेषित चैनल-संदेश क्लीनअप नीचे दिया गया अलग डिलीवरी-लोकेटर अनुवर्ती कार्य बना रहता है।

केवल अनुमोदन के लिए ट्रांसक्रिप्ट संदेश न लिखें, सिस्टम प्रॉम्प्ट इंजेक्ट न करें, स्वामी टर्न शुरू न करें या `sessions.changed` उत्सर्जित न करें।

## डिलीवर की गई सतहों का अभिसरण

नेटिव अनुमोदन हैंडलर पहले से अपनी डिलीवर की गई संदेश प्रविष्टियों को इतनी देर तक बनाए रखते हैं कि सक्रिय नियंत्रणों को बदला या हटाया जा सके। सामान्य अग्रेषित अनुमोदन संदेश वर्तमान में `MessageReceipt` को छोड़ देते हैं, इसलिए किसी अन्य सतह पर निर्णय होने से उनके पुराने नियंत्रण लंबित दिखाई दे सकते हैं। एक अलग अनुवर्ती कार्य साझा स्टेट डेटाबेस में `operator_approval_deliveries` चाइल्ड तालिका के साथ इस कमी को पूरा करता है।

प्रत्येक पंक्ति अनुमोदन ID, एक अद्वितीय डिलीवरी ID, चैनल/अकाउंट/सटीक रूट, सीमित JSON-सत्यापित चैनल-निजी संदेश लोकेटर, डिलीवरी टाइमस्टैम्प और टर्मिनलाइज़ेशन अवस्था संग्रहीत करती है। यह कॉलबैक डेटा, निर्णय टोकन या कच्चे अनुमोदन अनुरोध कभी संग्रहीत नहीं करती। लोकेटर एन्कोडिंग और संदेश परिवर्तन का स्वामित्व चैनल के पास है; कैनोनिकल स्थिति, लक्ष्य चयन, पुनः प्रयास नीति और फ़ॉलबैक टर्मिनल टेक्स्ट का स्वामित्व Core के पास है।

डिलीवरी पंजीकरण और टर्मिनल समाधान रेस को सुरक्षित रूप से संभालते हैं:

1. लंबित प्रेषण की रसीद लौटने के बाद, डिलीवरी लोकेटर डालें और एक ट्रांज़ैक्शन में पैरेंट अनुमोदन स्थिति पढ़ें।
2. यदि पैरेंट पहले से टर्मिनल है, तो विलंबित डिलीवरी को लंबित छोड़ने के बजाय तत्काल टर्मिनलाइज़ेशन शेड्यूल करें।
3. प्रत्येक कमिट किया गया टर्मिनल ट्रांज़िशन सभी अपूर्ण डिलीवरी पंक्तियों को अलग से शेड्यूल करता है; छोड़े जा सकने वाले ब्रॉडकास्ट ट्रिगर नहीं हैं।
4. चैनल टर्मिनलाइज़र `replaced`, `retired` या `unsupported` रिपोर्ट करता है। बदला गया परिणाम डुप्लिकेट टर्मिनल संदेश को रोकता है; हटाया गया परिणाम मौजूदा टर्मिनल अनुवर्ती संदेश भेजता है; असमर्थित या विफलता अनुमोदन CAS को रोलबैक किए बिना फ़ॉलबैक करती है।
5. स्टार्टअप अधूरी डिलीवरी वाले टर्मिनल अनुमोदनों का पुनः प्रयास करता है, जिससे क्लीनअप Gateway पुनरारंभ के प्रति लचीला बनता है।

यह ट्रांसपोर्ट जीवनचक्र एक वैकल्पिक डिलीवरी अडैप्टर हुक है, रेंडरर या मॉडल-सामना करने वाली संदेश कार्रवाई नहीं। QQ C2C/समूह संदेशों में वर्तमान में संपादन, हटाने या कीबोर्ड-साफ़ करने की API नहीं है; वह अडैप्टर असमर्थित रहता है और ट्रांसपोर्ट को परिवर्तन API मिलने तक केवल बाद की क्लिक के बाद कैनोनिकल सत्य दिखा सकता है।

## पुनरारंभ, समय-समाप्ति और रूट अर्थविज्ञान

SQLite स्थायित्व निष्पादन पुनरारंभ को सूचित नहीं करता। कमांड/टूल बाइंडिंग मेमोरी में रहती हैं, क्योंकि उनमें सुरक्षा-संवेदनशील रनटाइम तथ्य हो सकते हैं और वे पुनरारंभ योग्य जॉब अनुबंध नहीं हैं।

Gateway स्टार्टअप पर:

- नया रनटाइम युग उत्पन्न करें;
- पुराने युगों की लंबित पंक्तियों को कारण `gateway-restart` सहित परमाण्विक रूप से `cancelled` में ट्रांज़िशन करें;
- पंक्तियाँ बनाए रखें, ताकि उनके URLs बता सकें कि क्या हुआ;
- गुम रनटाइम बाइंडिंग के विरुद्ध बाद का अनुमोदन कभी निष्पादित न करें।

टाइमर वेक-अप अनुकूलन हैं। समय-सीमा का प्राधिकार `expires_at_ms` में संग्रहीत है; पठन, प्रतीक्षा और समाधान सभी समय-समाप्ति सामंजस्य चलाते हैं।

अंतिम सख्त व्यवहार:

- समय-समाप्ति -> `expired`, अस्वीकार;
- कोई रूट नहीं -> `denied`, अस्वीकार;
- रन निरस्त -> `cancelled`, अस्वीकार;
- दोषपूर्ण विश्वसनीय निर्णय -> `denied`, अस्वीकार;
- केवल अनुमत स्पष्ट स्वीकृति निर्णय -> `allowed`।

वर्तमान जारी exec व्यवहार अब भी इस अनुबंध से टकराता है:

- `src/agents/bash-tools.exec-host-shared.ts`, `askFallback` लागू कर सकता है।
- `docs/tools/exec-approvals.md` और `docs/cli/approvals.md` उस सतह का दस्तावेज़ीकरण करते हैं।

Plugin अनुमोदन अब समय-समाप्ति और दोषपूर्ण निर्णयों पर सुरक्षित रूप से विफल होते हैं; लेगेसी
`timeoutBehavior` फ़ील्ड अब भी स्वीकार किया जाता है, लेकिन अनदेखा किया जाता है। exec सख्त-अर्थविज्ञान
अनुवर्ती कार्य को स्पष्ट स्वामी/सुरक्षा समीक्षा सहित कोड, प्रकार, दस्तावेज़, परीक्षण और चेंजलॉग
एक साथ अपडेट करने चाहिए। `askFallback` माइग्रेशन के दौरान
प्री-गेट नीति चयन का वर्णन जारी रख सकता है, लेकिन उसे बनाए गए
लंबित रिकॉर्ड की समय-समाप्ति को अनुमोदन में नहीं बदलना चाहिए।

## संगतता योजना

- योज्य Gateway प्रोटोकॉल; कोई प्रोटोकॉल संस्करण वृद्धि नहीं।
- बाहरी सीमा पर मौजूदा exec/plugin विधियाँ और इवेंट संरक्षित रखें।
- `plugin:` उपसर्गों सहित मौजूदा IDs बनाए रखें, लेकिन उपसर्गों का प्रकार जानकारी के रूप में उपयोग बंद करें।
- `/approve` टेक्स्ट कमांड व्यवहार बनाए रखें।
- लेगेसी बटन URL/Web App फ़ील्ड और कमांड कार्रवाइयों को plugin SDK संगतता इनपुट के रूप में बनाए रखें; नया Core आउटपुट टाइप किया गया है।
- सभी बंडल किए गए चैनलों और आंतरिक कॉलरों को उसी टाइप की गई कार्रवाई वाले परिवर्तन में माइग्रेट करें।
- नए URL/पृष्ठ और बाद के समय-समाप्ति व्यवहार परिवर्तन के लिए चेंजलॉग प्रविष्टि जोड़ें।
- इलिसिटेशन-मोड सेटिंग न जोड़ें।

## रोलआउट

### PR 1: टिकाऊ जीवनचक्र

- यह डिज़ाइन नोट।
- साझा SQLite स्कीमा, Kysely जनरेशन, स्टोर और 30-दिन की प्रूनिंग।
- Gateway अनुमोदन सेवा, रनटाइम वेटर ब्रिज और पुनरारंभ ऑर्फ़न प्रबंधन।
- एकीकृत `approval.get/resolve`।
- Exec/plugin विधि अडैप्टर।
- पहला-उत्तर-जीतता-है, आइडेम्पोटेंसी, समय-समाप्ति, प्राधिकरण और उपभोग परीक्षण।
- अभी कोई UI या चैनल व्यवहार परिवर्तन नहीं।

### PR 2: टाइप की गई कार्रवाइयाँ और चैनल कॉलबैक

- टाइप्ड अनुमोदन, URL और Web App क्रियाएँ।
- कोर प्रस्तुति बिल्डर और Plugin SDK एक्सपोर्ट।
- स्पष्ट स्वामी प्रकार के साथ ट्रांसपोर्ट-निजी कॉलबैक एन्कोडिंग।
- ट्रांसपोर्ट सीमाओं से परे कैनोनिकल ID के लिए टिकाऊ निश्चित-आकार के कॉलबैक संदर्भ।
- कमांड-टेक्स्ट और अनुमोदन-ID अनुमान से दूर बंडल किए गए चैनलों का माइग्रेशन।
- क्लिक किए गए सरफ़ेस पर कैनोनिकल प्रथम-उत्तर सत्य और सर्वोत्तम-प्रयास सक्रिय-नेटिव टर्मिनल अपडेट; टिकाऊ चैनल-संदेश टर्मिनलाइज़ेशन अभी अनुवर्ती कार्य है।
- SDK और बंडल किए गए चैनल के परीक्षण।

### PR 3: Control UI डीप लिंक

- स्वतंत्र प्रमाणीकृत अनुमोदन पृष्ठ और बेस-पाथ-सजग स्टार्टअप रूटिंग।
- ऑपरेटर के सहेजे गए रिमोट चयन को बदले बिना सर्विंग-Gateway बाइंडिंग।
- कोर-स्वामित्व वाला अनुमोदन HTTP नेमस्पेस, जिसमें एसेट-जैसी ID शामिल हैं।
- Gateway द्वारा निर्मित URL पेलोड और लाइफ़साइकल इवेंट उपलब्ध होने तक लंबित-स्थिति पोलिंग।
- मोबाइल-चौड़ाई, पुनःकनेक्ट, प्रतिस्पर्धी-उत्तर, रीलोड और माउंटेड-पाथ प्रमाण।

### PR 4: नेटिव क्लाइंट

- iOS और Android समीक्षा सरफ़ेस प्रकार-सजग `approval.get/resolve` का उपयोग करते हैं; watchOS युग्मित iPhone के माध्यम से समीक्षक-सुरक्षित प्रॉम्प्ट और निर्णय रिले करता है।
- Watch अपने कॉम्पैक्ट रिले अनुबंध द्वारा समर्थित निष्पादन निर्णय प्रदान करता है: एक बार अनुमति और अस्वीकार।
- कैनोनिकल प्रथम-उत्तर टर्मिनल सत्य स्थानीय प्रयास-किए-गए-निर्णय स्थिति का स्थान लेता है।
- खोई हुई या अस्पष्ट समाधान अभिस्वीकृतियाँ कैनोनिकल रीडबैक तक नियंत्रणों को फ़्रीज़ रखती हैं।
- पहले जारी किए गए Gateway v4 इंस्टेंस एक संकीर्ण लेगेसी-विधि फ़ॉलबैक के माध्यम से निष्पादन समीक्षा बनाए रखते हैं; संरक्षित क्रॉस-सरफ़ेस टर्मिनल स्थिति के लिए एकीकृत विधियाँ आवश्यक हैं।
- समीक्षक चेतावनियाँ और स्वामी संदर्भ iPhone, Watch और Android पर दृश्यमान रहते हैं।
- नेटिव यूनिट, बिल्ड और प्लेटफ़ॉर्म प्रमाण।

### PR 5: पूर्वज लाइफ़साइकल प्रसार

- `session.approval` की लंबित/टर्मिनल डिलीवरी, PR 1 में स्थायी किए गए ऑडियंस स्नैपशॉट से।
- ट्रांसक्रिप्ट परिवर्तन या एजेंट जागरण के बिना सटीक-सत्र सदस्यता, पुनःकनेक्ट रीप्ले और टर्मिनल टूम्बस्टोन।
- लाइफ़साइकल कॉलबैक टिकाऊ इंसर्ट/CAS के बाद चलते हैं और कभी अनुमोदन प्राधिकारी नहीं बनते।
- नेस्टेड-सबएजेंट और पुनःकनेक्ट प्रमाण।

### PR 6: विफलता पर बंद व्यवहार

- `node-invoke-plugin-policy.ts` और एम्बेडेड Plugin ब्रोकर को डुप्लिकेट प्राधिकार से दूर माइग्रेट करें।
- सख़्त टाइमआउट, विकृत, कोई-रूट-नहीं, बाइंडिंग और एक-बार-अनुमति उपभोग अर्थविज्ञान।
- कोई अनुरोध लंबित होने के बाद जारी की गई अनुमेय टाइमआउट सेटिंग का पालन किए बिना उन्हें अप्रचलित करें।
- बहु-सरफ़ेस प्रतिस्पर्धा और विफलता-इंजेक्शन प्रमाण।

### अनुवर्ती: टिकाऊ रिमोट-संदेश क्लीनअप

- अग्रेषित-डिलीवरी लोकेटर स्थायी करें और पुनरारंभ के बाद प्रत्येक डिलीवर किए गए चैनल संदेश को टर्मिनलाइज़ करें।
- इस ट्रांसपोर्ट लाइफ़साइकल को कैनोनिकल अनुमोदन प्राधिकार और टाइप्ड प्रस्तुति क्रियाओं से अलग रखें।

## परीक्षण

आवश्यक केंद्रित कवरेज:

- SQLite को दोबारा खोलना लंबित और टर्मिनल प्रोजेक्शन सुरक्षित रखता है।
- दो समवर्ती समाधानकर्ता ठीक एक CAS विजेता उत्पन्न करते हैं।
- समान-निर्णय पुनःप्रयास आइडेम्पोटेंट रूप से सफल होता है; परस्पर-विरोधी पुनःप्रयास रिकॉर्ड किए गए विजेता को लौटाता है।
- समय-सीमा पर या उसके बाद समाधान अनुमोदन नहीं कर सकता।
- `allow-once` टर्मिनल ऑडिट स्थिति मिटाए बिना ठीक एक बार उपभोग योग्य है।
- स्टार्टअप पुराने रनटाइम एपॉक रद्द करता है।
- अनधिकृत लुकअप और समाधान रिकॉर्ड के अस्तित्व को प्रकट नहीं करते।
- स्पष्ट समीक्षक अनुमति-सूची और सामान्य युग्मित `operator.approvals` व्यवहार।
- निष्पादन और Plugin की लेगेसी विधियाँ समान स्टोर साझा करती हैं।
- Gateway अनुरोध/सूची/प्राप्ति/समाधान स्कीमा और योगात्मक इवेंट पेलोड।
- टाइप्ड-क्रिया सामान्यीकरण, फ़ॉलबैक रेंडरिंग, SDK एक्सपोर्ट और बंडल किए गए चैनल स्विच।
- Telegram कॉलबैक एन्कोडिंग में ट्रांसपोर्ट-निजी डेटा होता है और कोई कमांड-स्ट्रिंग अनुमान नहीं होता।
- प्रत्यक्ष चाइल्ड, शाखित नियंत्रक/अनुरोधकर्ता स्वामी, नेस्टेड स्वामी, पुनःअसाइनमेंट, सत्र-फ़ील्ड फ़ॉलबैक, चक्र और ऑडियंस-आकार सीमा।
- अनुरोधित और टर्मिनल ऑडियंस ऐरे समान हैं।
- स्वामी प्रोजेक्शन ट्रांसक्रिप्ट परिवर्तन या एजेंट जागरण नहीं करते।
- Control UI रूट `/` और कॉन्फ़िगर किए गए बेस पाथ पर काम करता है; रीफ़्रेश लंबित या टर्मिनल सत्य दिखाता है।
- Control UI और Telegram के एक साथ दिए गए उत्तर एक विजेता और हारने वाले पर "अन्यत्र समाधान हो चुका है" दिखाते हैं।
- नेटिव अनुमोदन पहचानकर्ता और Gateway स्वामी पहचानकर्ता रूटिंग तथा समाधान-मिलान के दौरान सटीक UTF-8 बाइट सुरक्षित रखते हैं।
- नेटिव RPC-फ़ैमिली नेगोशिएशन प्रत्येक स्वीकृत Gateway रूट के लिए एक कैनोनिकल या लेगेसी फ़ैमिली निश्चित करता है और उपयोग के बाद कभी चुपचाप डाउनग्रेड नहीं करता।
- खोई हुई नेटिव समाधान अभिस्वीकृतियाँ कैनोनिकल रीडबैक तक क्रियाओं को फ़्रीज़ रखती हैं; विफल रीडबैक न तो विजेता गढ़ सकता है, न Watch रीफ़्रेश की अभिस्वीकृति दे सकता है।
- Watch स्नैपशॉट अनुरोध सहसंबंध केवल सटीक युग्मित Gateway स्वामी और पूर्ण कैनोनिकल iPhone रीडबैक के लिए स्वीकार किया जाता है।
- Testbox/Crabbox के माध्यम से उपयोगकर्ता-पथ प्रमाण, जिसमें मोबाइल-चौड़ाई अनुमोदन पृष्ठ, Telegram क्रिया क्लीनअप और Android, iPhone तथा Watch पर एक लंबित/समाधान/विलंबित-पराजित राउंड ट्रिप शामिल है।

## प्रेक्षणीयता

अनुमोदन ID, प्रकार, स्रोत सत्र कुंजी, स्थिति, कारण और विलंबता के साथ संरचित, सामग्री-रहित ट्रांज़िशन लॉग उत्सर्जित करें। पूर्वावलोकन या रॉ बाइंडिंग कभी लॉग न करें।

ट्रैक करें:

- प्रकार के अनुसार अनुरोधित संख्या;
- प्रकार/स्थिति/कारण के अनुसार टर्मिनल संख्या;
- लंबित गेज;
- अनुरोध-से-टर्मिनल विलंबता;
- समाधान रेस परिणाम: विजेता, आइडेम्पोटेंट पुनःप्रयास, विरोध, समय-सीमा समाप्त;
- डिलीवरी रूट संख्या और कोई-रूट-नहीं अस्वीकृतियाँ;
- स्टार्टअप-अनाथ रद्दीकरण;
- ऑडियंस आकार।

बाद की इवेंट डिलीवरी विफल होने पर भी प्रतिबद्ध ट्रांज़िशन सफल माना जाता है। लाइफ़साइकल सदस्य PR 5 रीप्ले और कैनोनिकल लुकअप के माध्यम से पुनर्प्राप्त होते हैं। टिकाऊ चैनल-संदेश टर्मिनलाइज़ेशन ऊपर दिया गया अलग अनुवर्ती कार्य बना रहता है।

## खुले निर्णय

1. **बाहरी रूप से पहुँच योग्य Control UI मूल।** प्रत्येक स्नैपशॉट स्थिर सापेक्ष `urlPath` वहन करता है। Gateway एक्सपोज़र सफल होने के बाद केवल कैश किए गए Tailscale Serve/Funnel स्थान से निरपेक्ष URL का विज्ञापन किया जा सकता है; `allowedOrigins`, अनुरोध Host हेडर, `gateway.remote.url` और केवल-प्रदर्शन लूपबैक/LAN प्रत्याशी कैनोनिकल मूल नहीं हैं। Telegram बूटस्ट्रैप के दौरान अनुमोदन पाथ बनाए रखने के लिए अपने प्रमाणीकृत Mini App रैपर का उपयोग कर सकता है। अलग से समीक्षित स्पष्ट सार्वजनिक-URL अनुबंध मौजूद होने तक मनमाने रिवर्स प्रॉक्सी केवल-सापेक्ष रहते हैं। किसी चैनल को कभी मूल का अनुमान न लगाने दें।
2. **निष्पादन सख़्त टाइमआउट संगतता कटओवर।** Plugin अनुमोदन टाइमआउट अब विफलता पर बंद होते हैं और `timeoutBehavior` अप्रचलित है। शेष जारी किए गए `askFallback` अनुबंध द्वारा लंबित अनुरोध का समय समाप्त होने के बाद निष्पादन को प्राधिकृत करना बंद करने से पहले स्पष्ट स्वामी/सुरक्षा समीक्षा, चेंजलॉग, दस्तावेज़ और माइग्रेशन/अप्रचलन निर्णय आवश्यक हैं।
3. **Gateway-रहित एम्बेडेड मोड।** अनुशंसित: प्रारंभ में इसे केवल स्थानीय रखें, फिर Gateway मौजूद होने पर इसे कैनोनिकल सेवा का क्लाइंट बनाएँ। ऐसे डीप लिंक का विज्ञापन न करें जिसे कोई सर्वर समाधान नहीं कर सकता।
