# स्थानीय और अपस्ट्रीम मंजूरी एजेंट नियंत्रण को कैसे बदलती है

मंजूरी का बटन अपने आप में कोई सुरक्षा गुण नहीं है। उसकी उपयोगिता इस पर निर्भर करती है कि फैसला कहां लागू होता है, समीक्षक क्या देख सकता है, सेवा किसकी पहचान दर्ज करती है और timeout या कनेक्शन टूटने के बाद क्या होता है।

API कॉल करने वाले AI एजेंट के लिए स्थानीय मंजूरी और अपस्ट्रीम मंजूरी अलग सवालों के जवाब देती हैं। स्थानीय गेट तय कर सकता है कि यह एजेंट प्रक्रिया किसी क्रेडेंशियल का उपयोग कर सकती है या तैयार अनुरोध भेज सकती है। अपस्ट्रीम गेट तय कर सकता है कि रिमोट सिस्टम अपने संसाधन पर मांगा गया बदलाव लागू करे या नहीं। जब API पहले से पुष्टि मांगता हो, तो सही डिज़ाइन शायद ही कभी "ज्यादा सख्त विकल्प चुनो" होता है। उस गेट को चुनें जिसके पास समीक्षा किए जा रहे तथ्य का अधिकार हो, फिर उसके प्रमाण को बाकी कार्रवाई से जोड़ें।

यह अंतर जरूरी है, क्योंकि साफ-सुथरी मंजूरी स्क्रीन बड़े authorization gap को छिपा सकती है। समीक्षक स्थानीय अनुरोध "release 184 deploy करें" को मंजूरी दे सकता है, जबकि अपस्ट्रीम सेवा को फिर इस्तेमाल होने वाला token और अलग payload मिलता है। या अपस्ट्रीम सेवा किसी डिप्लॉयमेंट मंजूरी को दर्ज कर सकती है, बिना यह जाने कि अनुरोध किसी अविश्वसनीय एजेंट प्रक्रिया ने बनाया था। दोनों रिकॉर्ड सही हो सकते हैं, फिर भी कार्रवाई को समझाने में नाकाम रह सकते हैं।

## स्थानीय और अपस्ट्रीम गेट अलग चीजों को अधिकृत करते हैं

स्थानीय मंजूरी, अनुरोध के मशीन सीमा पार करने से पहले क्षमता के उपयोग को अधिकृत करती है। अपस्ट्रीम मंजूरी, उस सेवा के भीतर संसाधन बदलाव को अधिकृत करती है जो उस संसाधन की मालिक है। इन्हें एक जैसा मानने पर आप या तो कॉलर का संदर्भ खो देंगे या संसाधन का संदर्भ।

स्थानीय गेट एजेंट, क्रेडेंशियल वॉल्ट, कमांड रनर या outbound action gateway के साथ होता है। यह executable, code signature, parent process, session start, चुना गया credential, target host, request method और प्रस्तावित arguments देख सकता है। यह secret को एजेंट से बाहर रखकर कॉल खुद भी कर सकता है। यह इस सवाल का मजबूत जवाब है कि "क्या इस स्थानीय प्रक्रिया को अभी इस क्षमता का उपयोग करने दिया जाए?"

अपस्ट्रीम गेट API provider या उससे जुड़े control plane में होता है। यह वर्तमान resource version, organization membership, protected environment, service policy, conflict state और मंजूरकर्ता की remote identity देख सकता है। यह इस सवाल का मजबूत जवाब है कि "क्या वर्तमान सेवा स्थिति में यही सटीक remote transition होना चाहिए?"

NIST Special Publication 800-207 policy decision point और policy enforcement point का वर्णन करता है और कहता है कि implicit trust zone छोटा रखने के लिए enforcement को संसाधन के करीब ले जाना चाहिए। यह सिद्धांत उन तथ्यों के लिए अपस्ट्रीम enforcement का समर्थन करता है जिन्हें केवल संसाधन का मालिक जान सकता है। इससे स्थानीय गेट अनावश्यक नहीं हो जाता। सेवा किसी स्थानीय प्रक्रिया की पहचान नहीं देख सकती, जब तक client उस पहचान को भेजकर बांधे नहीं। अधिकांश bearer token calls उस token के धारक की पहचान करती हैं, उस प्रक्रिया की नहीं जिसने कॉल कराई।

OpenSSH स्थानीय मामले को साफ करता है। OpenBSD ssh-add मैनुअल कहता है कि -c विकल्प, जोड़ी गई identity को agent द्वारा इस्तेमाल करने से पहले पुष्टि मांगता है। उस signature के बाद भी remote SSH server अपना authorization करता है। एक गेट पूछता है कि स्थानीय client कुंजी इस्तेमाल कर सकता है या नहीं। दूसरा पूछता है कि नतीजे वाला authentication server policy पूरी करता है या नहीं। किसी एक को duplicate कहना, उस सीमा को अनदेखा करना है जिसकी वह रक्षा करता है।

व्यावहारिक नियम सरल है: जिस घटक के पास उस कार्रवाई को रोकने की क्षमता हो, उसी को उसके लिए मंजूरी लागू करनी चाहिए। ऐसा स्थानीय notification जो credential या कॉल रोक नहीं सकता, केवल दिखावा है। बदलाव के बाद दर्ज की गई अपस्ट्रीम टिप्पणी समीक्षा है, authorization नहीं।

## मैट्रिक्स की शुरुआत समीक्षा वाले तथ्य से होती है

मुख्य गेट चुनते समय यह देखें कि वह क्या जान और लागू कर सकता है, प्रॉम्प्ट की गिनती न करें। किसी मंजूरी workflow को जोड़ने से पहले मैं नीचे दिया निर्णय मैट्रिक्स इस्तेमाल करता हूं।

<table>
<thead>
<tr><th>मापदंड</th><th>स्थानीय मंजूरी</th><th>अपस्ट्रीम मंजूरी</th><th>डिज़ाइन का नतीजा</th></tr>
</thead>
<tbody>
<tr><td>Latency</td><td>आमतौर पर एक स्थानीय इंटरैक्शन और कॉल का समय</td><td>नेटवर्क, provider queue, notification और समीक्षक का समय शामिल</td><td>स्थानीय संदर्भ पर्याप्त हो तो बार-बार होने वाली, वापस ली जा सकने वाली calls के लिए स्थानीय विकल्प चुनें</td></tr>
<tr><td>एजेंट संदर्भ</td><td>प्रक्रिया, session, executable authority, tool call और स्थानीय उपयोगकर्ता को बांध सकता है</td><td>आमतौर पर token, app, workload या service account दिखता है</td><td>प्रक्रिया का स्रोत फैसला बदलता हो, तो स्थानीय गेट रखें</td></tr>
<tr><td>संसाधन संदर्भ</td><td>केवल लाया गया या दिया गया state देखता है, जो पुराना हो सकता है</td><td>वर्तमान version, protection rules, ownership और conflicts जांच सकता है</td><td>ऐसे बदलावों के लिए अपस्ट्रीम समीक्षा करें जिनकी सुरक्षा live remote state पर निर्भर हो</td></tr>
<tr><td>मानवीय पहचान</td><td>डिवाइस पर मौजूद व्यक्ति को बांध सकता है</td><td>organization account, team role या separation of duties को बांध सकता है</td><td>जिस identity domain के पास जवाबदेही है उसे इस्तेमाल करें, या दोनों को रखें</td></tr>
<tr><td>क्रेडेंशियल एक्सपोजर</td><td>secret को एजेंट से बाहर रख सकता है और केवल कार्रवाई जारी कर सकता है</td><td>अक्सर तब शुरू होता है जब client के पास पहले से काम करने योग्य credentials हों</td><td>जब secret custody खतरे के मॉडल का हिस्सा हो, तो स्थानीय enforcement जरूरी है</td></tr>
<tr><td>सेवा आउटेज</td><td>स्थानीय रूप से अस्वीकार कर सकता है और लंबित इरादा बचा सकता है</td><td>सेवा या उसका approval plane उपलब्ध न हो तो मंजूरी नहीं दे सकता</td><td>समाप्ति और रद्द करने की नीति तय करें। आउटेज को कभी सहमति न मानें</td></tr>
<tr><td>स्थानीय आउटेज</td><td>उस डिवाइस पर gated calls रोकता है</td><td>किसी दूसरे भरोसेमंद client से उपलब्ध रह सकता है</td><td>तय करें कि वैकल्पिक clients मान्य हैं या वे bypass हैं</td></tr>
<tr><td>ऑडिट विवरण</td><td>प्रॉम्प्ट, अस्वीकृति, प्रक्रिया समाप्ति और कोशिश की गई calls दर्ज कर सकता है</td><td>स्वीकार किए अनुरोध और आधिकारिक संसाधन बदलाव दर्ज कर सकता है</td><td>दोनों रिकॉर्ड को स्थिर action identifier से जोड़ें</td></tr>
<tr><td>छेड़छाड़ सीमा</td><td>compromised host स्थानीय रिकॉर्ड या UI पर हमला कर सकता है</td><td>provider remote रिकॉर्ड नियंत्रित करता है</td><td>एक log से उसकी trust boundary के बाहर की घटनाएं साबित करने को न कहें</td></tr>
<tr><td>कवरेज</td><td>कई APIs को एक समान ढंग से wrap कर सकता है</td><td>केवल वे operations कवर करता है जिन्हें provider अपने गेट पर उपलब्ध कराता है</td><td>सिर्फ अपस्ट्रीम मंजूरी पर निर्भर होने से पहले असुरक्षित paths की सूची बनाएं</td></tr>
</tbody>
</table>

तालिका को universal winner वाला point system न बनाएं। कुछ पंक्तियां veto होती हैं। अगर एजेंट को कभी API key नहीं मिलनी चाहिए, तो अपस्ट्रीम confirmation credential exposure हल नहीं करता, भले संसाधन संदर्भ में उसके अंक बेहतर हों। अगर production deployment के लिए operations group के मंजूरकर्ता की जरूरत है, तो एजेंट चलाने वाले developer का स्थानीय Touch ID prompt separation of duties पूरा नहीं करता।

पैटर्न चुनने से पहले कार्रवाई को वर्गीकृत करें। कम disclosure risk वाली read only calls को session authorization चाहिए हो सकता है, हर कॉल पर prompt नहीं। वापस ली जा सकने वाली writes में local gate, short expiry और idempotency key इस्तेमाल हो सकती है। irreversible या regulated transitions में अक्सर upstream review चाहिए, क्योंकि सेवा के पास final state और organization identity होती है। secret use और irreversible transition, दोनों वाली command में दोनों गेट सही हो सकते हैं, बशर्ते हर prompt साफ बताए कि उसका फैसला किस बारे में है।

## Latency में इंतजार, expiry और मानवीय recovery शामिल हैं

स्थानीय मंजूरी में आमतौर पर interaction latency कम होती है, लेकिन सही माप सुरक्षित और स्पष्ट परिणाम तक का समय है। तेज prompt के बाद अनिश्चित retry हो, तो वह कम latency नहीं है।

Mac पर एजेंट की देखरेख कर रहे एक व्यक्ति के लिए, स्थानीय card तब दिख सकता है जब request context ताजा हो। मंजूरकर्ता तुरंत जवाब दे सकता है और gateway दूसरे notification round trip के बिना कॉल भेज सकता है। यह routine pull request खोलने, protected internal API पूछने या attended session में जाना-पहचाना SSH command चलाने जैसी कार्रवाइयों के लिए ठीक है, यदि कार्रवाई का नतीजा स्थानीय रूप से दिखता हो।

अपस्ट्रीम workflows में queueing points ज्यादा होते हैं। सेवा को pending object बनाना, eligible reviewers चुनना, notification भेजना या दिखाना, organization identity का इंतजार करना, current policy फिर जांचना और आखिर में transition लागू करना होता है। यह देरी तब उपयोगी है जब इससे सच में separation of duties बनता है या समीक्षक को आधिकारिक state दिखती है। जब वही व्यक्ति उसी payload को बिना नई जानकारी के दो बार मंजूर करे, तो यह केवल समय की बर्बादी है।

GitHub के environments दस्तावेज़ उपयोगी उदाहरण देते हैं। required reviewers वाले environment का संदर्भ लेने वाली job शुरू होने से पहले इंतजार करती है और मंजूरी मिलने तक उस environment के secrets नहीं पा सकती। GitHub किसी environment को self review रोकने भी देता है। ये बातें अपस्ट्रीम देरी को सार्थक बनाती हैं: गेट service state और secret release दोनों नियंत्रित करता है और initiator से अलग reviewer को बांध सकता है। स्थानीय मंजूरी, समीक्षक का email address दिखाकर इस organization संबंध को दोहरा नहीं सकती।

Production में कम से कम चार अंतराल मापें: intent बनाने से prompt तक, prompt से मानवीय निर्णय तक, निर्णय से execution तक और execution से authoritative result तक। अस्वीकृति और expiry को भी उसी data में रखें। abandoned requests को हटाकर निकाला गया median approval time, टूटे workflow को अच्छा दिखाएगा।

Prompt frequency भी व्यवहार बदलती है। पचास एक जैसी read calls के loop में हर कॉल पर local prompt, समीक्षक को बिना पढ़े क्लिक करने की आदत देता है। सभी पचास prompts को upstream ले जाना भी इसे नहीं ठीक करता। केवल उन्हीं कार्रवाइयों को समूह में रखें जिनकी capability सीमित हो, target set साफ हो और lifetime छोटा हो। batching तेज हो तब भी destructive transitions को अलग रखें।

Expiry उस गति के अनुसार रखें जिस पर तथ्य बदल सकते हैं। तेजी से बदलती branch head से बने request के लिए दस मिनट बहुत ज्यादा हो सकते हैं और formal production review के लिए बहुत कम। मंजूरी को चुपचाप refresh न करें। payload, target version, credential या eligible reviewer set बदले, तो नया निर्णय बनाएं।

## संदर्भ तय करता है कि समीक्षक फैसला कर सकता है या नहीं

उपयोगी prompt में उसके निर्णय के लिए जरूरी तथ्यों का सबसे छोटा, पूरा सेट होता है। स्थानीय और अपस्ट्रीम systems अलग-अलग आधे हिस्से देखते हैं, इसलिए एक screen को दूसरी में कॉपी करना शायद ही सही रहता है।

स्थानीय पक्ष को यह दिखाना चाहिए कि मांग कौन कर रहा है, ऐसे शब्दों में जिन्हें इंसान जांच सके: executable identity, जहां उपलब्ध हो वहां signing authority, parent session, tool name, credential alias, destination, operation और पढ़ने योग्य payload summary। उसे gateway द्वारा देखे data को एजेंट दिए text से अलग बताना चाहिए। एजेंट का दिया "safe cleanup" जैसा explanation प्रमाण नहीं है।

अपस्ट्रीम पक्ष को authoritative object और प्रस्तावित transition दिखाना चाहिए: repository और environment, account और region, resource version, diff, policy checks, initiator identity और eligible approvers। जब उसे केवल bearer token मिला हो, तो उसे स्थानीय provenance जानने का दिखावा नहीं करना चाहिए।

Canonical action fields के digest से मंजूर intent को execution से बांधें। नीचे का envelope जानबूझकर इतना छोटा है कि इसे लागू किया जा सके। action_id systems को जोड़ता है, digest किसी बाद के payload को पुरानी मंजूरी उधार लेने से रोकता है।

```json
{
  "action_id": "act_01JQ7M6F4R2K",
  "session_id": "ses_01JQ7KZ9J1AA",
  "caller": {
    "executable": "/usr/local/bin/agent",
    "signing_authority": "Developer ID Application: Example Team"
  },
  "target": {
    "service": "deploy-api",
    "resource": "production/payments",
    "version": "184"
  },
  "request": {
    "method": "POST",
    "operation": "promote",
    "body_sha256": "98b0...e42c"
  },
  "approval": {
    "scope": "single_action",
    "expires_at": "2026-07-24T14:05:00Z"
  }
}
```

Executor को body_sha256 फिर से निकालना चाहिए, resource और version मिलाने चाहिए, expiry जांचनी चाहिए और single action approval को केवल एक बार इस्तेमाल करना चाहिए। मंजूरी के बाद एजेंट एक argument भी बदले, तो तुलना fail closed होनी चाहिए। जहां संभव हो, upstream request में provider समर्थित metadata या correlation field में action_id रखें। उसे ऐसे field में न छिपाएं जो business behavior बदल देता हो।

Screenshot कमजोर binding है। इससे इंसान को अनुरोध समझने में मदद मिल सकती है, लेकिन code को मंजूर bytes और भेजे गए bytes का संबंध लागू करना होगा। मैंने ऐसे systems देखे हैं जो एक object से अच्छा summary दिखाते हैं और बाद में बने दूसरे object को execute करते हैं। केवल interface नहीं, serialization path की समीक्षा करें।

## पहचान के तीन actor होते हैं, एक नहीं

एजेंट कार्रवाई में कम से कम तीन पहचानें होती हैं: इसे प्रस्तावित करने वाली प्रक्रिया, इसे चलाने वाला credential principal और मंजूरी देने वाला इंसान। इन्हें एक actor field में समेटने पर आकर्षक logs बनते हैं, जो गलत सवाल का जवाब देते हैं।

प्रक्रिया की पहचान में executable path, hash, signing authority, parent process, agent protocol session और स्थानीय operating system user शामिल हो सकते हैं। इनमें से कोई भी अपने आप remote identity नहीं बनता। API को आमतौर पर OAuth client, service account, deploy key, role session या user token दिखता है।

मंजूरी देने वाला इंसान भी एक identity domain में होता है। स्थानीय biometric confirmation, operating system के mechanism के आधार पर, यह साबित कर सकती है कि enrolled person डिवाइस पर मौजूद था, लेकिन इससे यह साबित नहीं होता कि उस व्यक्ति के पास अभी कौन-सी organization role है। अपस्ट्रीम reviewer account team membership और initiator से अलग होना साबित कर सकता है, लेकिन उसे यह नहीं पता कि किस स्थानीय binary ने कार्रवाई मांगी।

तीनों identities रखें और binding method बताएं।

<table>
<thead>
<tr><th>पहचान</th><th>उदाहरण प्रमाण</th><th>जिस सवाल का जवाब देती है</th></tr>
</thead>
<tbody>
<tr><td>प्रस्तावक</td><td>Process signature, executable hash, session ID</td><td>किस चल रहे code ने अनुरोध किया?</td></tr>
<tr><td>निष्पादक</td><td>API principal, SSH public key fingerprint, role session</td><td>किस authority ने कॉल की?</td></tr>
<tr><td>मंजूरकर्ता</td><td>स्थानीय user presence या अपस्ट्रीम organization account</td><td>किस व्यक्ति ने कौन-सा जोखिम स्वीकार किया?</td></tr>
</tbody>
</table>

Bearer credentials इस बात को खासा महत्वपूर्ण बनाते हैं। पांच एजेंट processes एक token साझा करें, तो अपस्ट्रीम audit trail सही रूप से token principal का नाम दे सकता है और फिर भी processes में फर्क नहीं कर पाएगा। स्थानीय gateway यह गायब provenance दे सकता है, मगर तभी जब उसके session records को आसानी से बदला न जा सके और वे remote event से correlate हों।

जब इंसान ने क्लिक किया हो, तो एजेंट को approver न लिखें। जब service account ने request चलाई हो, तो इंसान को API caller न लिखें। Delegation को सीधे दर्ज करें: proposer P ने action A मांगी, approver H ने scope S को अधिकृत किया, executor E ने result R लागू किया।

जब सेवा group membership की मालिक हो और self approval रोकती हो, तो separation of duties अपस्ट्रीम की ताकत है। user presence और process provenance के लिए स्थानीय मंजूरी मजबूत है। जब policy में दोनों चाहिए हों, तो एक ही डिवाइस पर एक ही व्यक्ति के दो clicks के बजाय अलग प्रमाण मांगें।

## आउटेज के बाद एक टिकाऊ state रहनी चाहिए

Network errors को UI समस्या मानने पर approval systems बहुत खराब तरीके से विफल होते हैं। कार्रवाई के लिए ऐसी durable state machine चाहिए जो process exit, खोए हुए responses और सेवा recovery के बाद भी बनी रहे।

created, locally_approved, submitted, upstream_pending, executing, succeeded, denied, expired और unknown जैसी स्पष्ट states इस्तेमाल करें। Terminal states terminal ही रहें। हर transition को action digest और समय के साथ रखें। स्थानीय restart किसी upstream pending request को देखना फिर शुरू कर सकता है, मगर retry rules की अनुमति के बिना नया mutation नहीं बना सकता।

सुरक्षित outage rules सख्त हैं:

1. स्थानीय गेट उपलब्ध न हो, तो gated actions मशीन से बाहर नहीं जातीं।
2. अपस्ट्रीम approval plane उपलब्ध न हो, तो जिन कार्रवाइयों को उसकी जरूरत है वे pending रहती हैं या expire हो जाती हैं।
3. मंजूरी सफल हो लेकिन execution status अज्ञात हो, तो retry से पहले action या idempotency identifier से query करें।
4. मंजूरी के इंतजार में संसाधन बदल जाए, तो निर्णय अमान्य करें या अपस्ट्रीम सेवा से उसका दोबारा मूल्यांकन कराएं।
5. समीक्षक अस्वीकार या revoke करे, तो हर pending execution रद्द करें और दर्ज करें कि cancellation सेवा तक पहुंची या नहीं।

Fail open कोई recovery strategy नहीं है। Teams कभी-कभी emergency bypass जोड़ती हैं क्योंकि approval service critical path पर होती है। Bypass सही हो सकता है, लेकिन वह नामित इंसान, सीमित दायरे, कम अवधि और अपने अलग durable record वाली अलग privileged operation है। उसे "बिना मंजूरी retry करें" के पीछे छिपाने से नियंत्रण उसी समय खत्म हो जाता है जब incidents में समीक्षा सबसे जरूरी होती है।

स्थानीय और अपस्ट्रीम outages एक जैसे नहीं हैं। नेटवर्क बंद हो तब भी स्थानीय गेट अस्वीकृत कोशिश दर्ज कर सकता है। Provider को वह request दर्ज नहीं हो सकती जो उसे मिली ही नहीं। उलटे, स्थानीय प्रक्रिया crash होने के बाद provider कार्रवाई पूरी कर सकता है और स्थानीय record submitted पर अटक सकता है। Reconciliation को मानना होगा कि दोनों पक्षों के पास अधूरी जानकारी है।

Launch से पहले cancellation डिज़ाइन करें। पूछें कि मंजूर लेकिन queued action वापस ली जा सकती है या नहीं, execution चलते समय मंजूरी समाप्त हो सकती है या नहीं और denial तथा completion की race में कौन-सी state जीतेगी। क्या हुआ, इसके लिए remote resource state निर्णायक है। मंजूरी record फिर भी बताता है कि वह अधिकृत था या नहीं।

## Retries में एक मंजूरी दो बार खर्च नहीं होनी चाहिए

मंजूरी और execution अलग operations हैं, इसलिए retry इनमें से किसी को भी duplicate कर सकती है। सबसे बड़ा जोखिम तब है जब client को मंजूरी मिलती है, वह mutation भेजता है, response खो देता है और mutation फिर भेज देता है।

RFC 9110 किसी identical request को दोहराने के intended effect के आधार पर idempotent method तय करता है। यह कहता है कि clients को non idempotent request अपने आप retry नहीं करनी चाहिए, जब तक वे न जानते हों कि semantics idempotent हैं या यह तय न कर सकें कि मूल request लागू नहीं हुई। मंजूरी से यह नियम नहीं बदलता। किसी payment, deployment या deletion के लिए इंसान की सहमति, कोशिशों की अज्ञात संख्या के लिए सहमति नहीं है।

Idempotency key तब बनाएं जब immutable intent बने, execution शुरू होने पर नहीं। उसे payload digest से बांधें और सुरक्षित retries में भी बचाए रखें। Upstream service को duplicate key के लिए मूल result लौटाना चाहिए या status lookup देना चाहिए। API इनमें से कुछ न दे, तो gateway को ambiguous mutations को unknown में ले जाना चाहिए और अंदाजा लगाने के बजाय reconciliation मांगनी चाहिए।

Approval identifiers को idempotency identifiers से अलग रखें। मंजूरी एक execution attempt, एक जैसे retries के सीमित set या session capability को अधिकृत कर सकती है। Idempotency key सेवा को बताती है कि किस mutation का केवल एक effect होना चाहिए। दोनों अर्थ एक token में मिलाने से expiration, revocation और investigation मुश्किल हो जाते हैं।

उपयोगी test sequence के लिए failure injection framework नहीं चाहिए:

1. एक मंजूर action बनाएं, जिसका action_id, digest और idempotency key स्थिर हो।
2. इसे भेजें, फिर request body निकलने के बाद client connection काट दें।
3. स्थानीय agent फिर शुरू करें और recovery को stored state देखने दें।
4. जांचें कि किसी retry से पहले वह provider को query करता है।
5. एक authoritative resource transition और कोशिश records की एक linked chain की पुष्टि करें।

यही sequence तब चलाएं जब upstream approval pending हो और जब disconnect के दौरान मंजूरी expire हो जाए। अगर restart नया identifier लेकर दूसरा prompt बनाता है, तो recovery path पहले ही chain of custody तोड़ चुका है।

Confirmation endpoint इस्तेमाल करने वाली APIs में उसकी semantics जांचें। prepare फिर confirm जैसा two call pattern तभी सुरक्षित है जब confirmation immutable server object को एक बार consume करे या idempotency key लागू करे। अगर confirm केवल client दिए fields को दोहराता है, तो वह भरोसा जगाने वाला नाम पहने एक और mutation endpoint हो सकता है।

## पूरे ऑडिट intent, decision, attempt और result को जोड़ते हैं

कोई एक log तब तक पूरा नहीं है, जब तक एक घटक प्रस्तावित intent, approval decision, outbound attempt, provider acceptance और final resource state नहीं देखता। ज्यादातर वास्तविक systems में trust boundaries के पार जुड़े records से पूर्णता मिलती है।

स्थानीय audit में rejected और expired requests शामिल हों, क्योंकि वे कभी upstream नहीं दिखतीं। इसमें process और session identity, displayed summary version, canonical payload digest, secret के बजाय credential alias, human decision, outbound attempt, response code और कोई भी uncertainty दर्ज हो। Upstream audit में authoritative principal, approval object, reviewer identity, policy version, resource version, execution event और final status होना चाहिए।

जहां भी आपका नियंत्रण हो, वहां एक स्थिर action_id इस्तेमाल करें और उपलब्ध होने पर provider event IDs भी रखें। केवल timestamps से न जोड़ें। Clock skew, batching और concurrent calls आखिरकार गलत match बना देंगे।

पहले implementation के लिए यह event shape काफी है:

```json
{
  "event_id": "evt_01JQ7N2AZ8S4",
  "action_id": "act_01JQ7M6F4R2K",
  "phase": "upstream_result",
  "observed_by": "local_gateway",
  "principal": "service-account:deploy-agent",
  "approver": "org-user:release-reviewer",
  "payload_sha256": "98b0...e42c",
  "provider_event_id": "dep_91358",
  "outcome": "succeeded",
  "recorded_at": "2026-07-24T14:02:18Z"
}
```

Hash chaining या append only storage बाद में हुए edits दिखा सकते हैं, मगर कोई घटना छूट गई थी, यह साबित नहीं कर सकते। Coverage tests को हर action class के expected phases की तुलना करनी चाहिए। किसी read में intent, local decision, attempt और response चाहिए हो सकते हैं। Protected deployment में upstream pending, upstream decision, execution और final resource version भी चाहिए हो सकते हैं।

AWS CloudTrail का दस्तावेज़ provider पक्ष के identity evidence का उदाहरण देता है: उसके IAM Identity Center events बता सकते हैं कि request user, role, federated user या किसी दूसरे service से आई थी और कुछ events में Identity Center identifiers होते हैं। यह उपयोगी authoritative evidence है, मगर फिर भी यह नहीं बताता कि किस स्थानीय agent process ने request बनाई, जब तक आप correlation data न भेजें और local record न रखें।

Bypass paths का audit मुख्य path जितनी सख्ती से करें। Credential का direct use, alternate CLI profiles, बिना protection वाले API endpoints, administrator bypass और मंजूर server object का replay, सभी perfect approval log को बेकार कर सकते हैं। आपके coverage statement में साफ होना चाहिए कि गेट किन channels को नियंत्रित करता है। बिना सूची के "सभी actions मंजूर हैं" का दावा न करें।

## दो गेट तभी उपयोगी हैं जब वे स्वतंत्र रहें

जब local और upstream approval अलग तथ्यों या अलग लोगों को नियंत्रित करें, तो उन्हें layer करें। अगर एक केवल दूसरे का फैसला दोहराता है और थकान बढ़ाता है, तो उसे हटा दें।

मजबूत layered deployment flow ऐसा हो सकता है। Local gate agent process जांचता है और developer से एक immutable release candidate के लिए deployment capability इस्तेमाल करने की मंजूरी मांगता है। वह credential दिखाए बिना उस candidate को submit करता है। फिर upstream environment eligible operations reviewer से current checks और protected environment state के आधार पर promotion मंजूर करने को कहता है। Final log दोनों decisions को एक action और एक deployed version से जोड़ता है।

कमजोर layered flow स्थानीय रूप से "production deploy करें?" दिखाता है, फिर वही शब्द उसी व्यक्ति को upstream दिखाता है। किसी prompt में digest या version नहीं, दोनों मंजूरियां अनिश्चित समय तक रहती हैं और एजेंट के पास पूरे समय token होता है। दूसरा click trust boundary जोड़े बिना latency बढ़ाता है।

लोकप्रिय सलाह "हमेशा संसाधन के जितना संभव हो उतना करीब मंजूरी दें" अधूरी है। यह sound enforcement principle से आती है, मगर capability custody और local process identity को अनदेखा करती है। Resource truth के लिए upstream approval करें। कौन-सी प्रक्रिया capability बुला सकती है नियंत्रित करनी हो या प्रक्रिया को secret देखने से रोकना हो, तो local enforcement रखें।

Sallyport HTTP API और SSH actions के लिए वही स्थानीय भूमिका निभाता है: एजेंट अपने MCP shim से जुड़ता है, जबकि secrets encrypted vault में रहते हैं और app कार्रवाई चलाता है। इसकी per session authorization और हर उपयोग पर वैकल्पिक मंजूरी, API provider के protected environment या organization reviewer की जगह नहीं लेती। यह स्थानीय पक्ष पर process और credential use evidence जोड़ती है।

दो गेट जारी करने से पहले, हर एक के लिए एक वाक्य लिखें: "यह गेट X को रोकता है क्योंकि केवल यह Y को देखता है और Z को लागू करता है।" दोनों वाक्यों में वही X, Y और Z हों, तो उन्हें एक करें। कोई घटक बताई गई कार्रवाई को वास्तव में रोक न सके, तो उसके prompt को चमकाने से पहले enforcement point ठीक करें।

## एक deployment walkthrough गायब joins दिखाता है

ऐसे autonomous coding agent पर विचार करें जो release 184 को उस production environment में promote कर रहा है जिसकी API पहले से review मांगती है। सुरक्षित flow स्थानीय मंजूरी, upstream waiting, execution और reconciliation में एक intent को सुरक्षित रखता है।

एजेंट पहले environment, release version, expected current version और idempotency key वाला canonical request प्रस्तावित करता है। Local gateway action_id देता है, process session और payload digest दर्ज करता है और तय करता है कि local approval चाहिए या नहीं। मंजूरी केवल उसी digest को short expiry तक अधिकृत करती है। Gateway फिर credential लगाकर तैयार request submit करता है।

Provider pending deployment object बनाता है। उसका reviewer current checks, protected environment, सटीक release और operation शुरू करने वाली organization identity देखता है। मंजूरी उस pending object को consume करती है। अगर production expected version से आगे बढ़ चुका हो, तो provider पुरानी consent लागू करने के बजाय request reject करता है या review फिर खोलता है।

अब upstream approval के बाद connection तोड़ दें। Local side को success नहीं लौटाना चाहिए और उसे तुरंत दूसरी promotion submit नहीं करनी चाहिए। वह unknown state रखता है, pending deployment ID या idempotency key से provider को query करता है और authoritative result दर्ज करता है। Provider success बताए, तो local journal मौजूदा action बंद करता है। Provider के पास record न हो, तो approval अभी valid रहने पर gateway मूल idempotency contract के तहत retry कर सकता है।

यह walkthrough वे सवाल पकड़ता है जो UI reviews से छूट जाते हैं। क्या agent local click के बाद release बदल सकता है? क्या दूसरा client pending deployment confirm कर सकता है? क्या upstream denial local authorization revoke करता है? क्या provider administrator bypass joined record में दिखता है? क्या investigators, एजेंट के अपने लिखे label पर भरोसा किए बिना साबित कर सकते हैं कि release किस process ने प्रस्तावित की थी?

आर्किटेक्चर इन्हीं जवाबों से चुनें। केवल local approval तब इस्तेमाल करें जब local capability use ही पूरा जोखिम हो और remote action routine, सीमित और recoverable हो। केवल upstream approval तब इस्तेमाल करें जब trusted clients के पास स्वीकार्य credentials पहले से हों और सिर्फ current resource state या organization role फैसला कर सके। दोनों तब इस्तेमाल करें जब local स्तर पर secret custody या process provenance जरूरी हो और remote स्तर पर authoritative transition review जरूरी हो।

यह वादा न करें कि दो मंजूरियां कार्रवाई को सुरक्षित बना देती हैं। वे दो decisions को दिखाती हैं। सुरक्षा तब मिलती है जब हर decision को immutable intent से बांधा जाए, उसे उस boundary पर लागू किया जाए जिसके पास तथ्य का अधिकार है, uncertainty को duplicate effects के बिना संभाला जाए और इतना joined evidence बचाया जाए कि prompt भूल जाने के बाद भी result दोबारा समझा जा सके।
