# API approval card वास्तविक target कैसे दिखाता है

कोई reviewer केवल ऐसी string देखकर HTTP action approve नहीं कर सकता जो destination जैसी दिखती हो। Card में वह request target दिखना चाहिए जिसका transport parsing के बाद और credentials के मशीन से बाहर जाने से पहले वास्तव में उपयोग करेगा।

यह बात तब तक स्पष्ट लगती है जब तक कोई agent `HTTPS://API.EXAMPLE.TEST:443/%76%31/../admin` submit न करे, client उसे स्वीकार न कर ले और इंसान को `api.example.test` जैसा छोटा label न दिखे। ऐसा card informed consent नहीं मांगता। वह व्यक्ति से ऐसे renderer पर भरोसा करने को कहता है जो HTTP stack से अलग व्यवहार कर सकता है।

इसका समाधान reviewers को URL syntax की हर बारीकी सिखाना नहीं है। समाधान है एक canonical request description बनाना, उसे सरल भाषा में दिखाना और यह सुनिश्चित करना कि executor भी उसी description का उपयोग करे। Scheme, host, effective port, method और path न्यूनतम जानकारी हैं। Query values, redirects, caller-controlled headers और body identity भी साथ दिखाने पड़ सकते हैं, क्योंकि वे action को उतना ही बदल सकते हैं।

## Approval card को स्वीकृति कैसे मिलती है

Approval card तभी भरोसेमंद बनता है जब वह network action को ऐसे शब्दों में बताए जिन्हें reviewer जाँच सके। केवल hostname एक identity claim है, request description नहीं। `POST https://billing.example.test/v1/invoices/481/refund` व्यक्ति को `billing API` या `example.test` से कहीं अधिक जानकारी देता है।

Action line सबसे ऊपर और हमेशा एक ही क्रम में रखें:

```text
POST https://billing.example.test/v1/invoices/481/refund
```

इसके ठीक नीचे वे विवरण रखें जो अर्थ बदलते हैं:

```text
Authorization: injected from vault entry "billing-production"
Query: dry_run=false
Body: JSON, 214 bytes, sha256: 7b1f...c0a9
```

जहाँ target होना चाहिए वहाँ credential value, authorization placeholder या friendly integration name न रखें। ये labels reviewer को context पहचानने में मदद कर सकते हैं, लेकिन destination का प्रमाण नहीं हैं।

Method पहली line में होना चाहिए, क्योंकि वही एक path के परिणाम को बदलता है। `GET /exports/481` और `DELETE /exports/481` एक action के दो रूप नहीं हैं। ये अलग कार्रवाइयाँ हैं और इन्हें कभी एक approval label में नहीं मिलाना चाहिए।

Path भी पहली line में रखें, क्योंकि API routing आमतौर पर वहीं होती है। यदि card केवल `api.example.test` दिखाए, तो reviewer को अनुमान लगाना पड़ेगा कि agent profile पढ़ रहा है, access token बना रहा है या project मिटा रहा है। Approval interruption से ऐसी अटकल की अपेक्षा नहीं होनी चाहिए।

## Canonicalization display contract है, permission matching नहीं

Canonicalization का सवाल है, «Parsed request के लिए इंसान को क्या दिखना चाहिए?» इसका सवाल यह नहीं है कि «कौन-से destinations की अनुमति है?» इन दोनों कामों को मिलाने पर friendly formatting के रूप में छिपी हुई brittle allowlist बन सकती है।

Approval card के लिए parsing के बाद एक structured target record बनाएं:

```json
{
  "method": "POST",
  "scheme": "https",
  "host": "api.example.test",
  "port": 443,
  "port_display": null,
  "path": "/v1/invoices/481/refund",
  "query": "dry_run=false",
  "raw_url": "HTTPS://API.EXAMPLE.TEST:443/v1/invoices/481/refund?dry_run=false"
}
```

Executor को इन्हीं structured fields से request बनानी चाहिए, या इनसे serialize किए गए URL का उपयोग करना चाहिए। Card के लिए एक बार parse करके बाद में original string को किसी दूसरी library में न भेजें। यहीं review screen महज़ दिखावा बन जाती है।

RFC 3986 normalization की कुछ सुरक्षित श्रेणियाँ अलग करता है। इसमें scheme और host को case-insensitive माना गया है, percent escapes में uppercase hexadecimal digits की सलाह दी गई है और dot segments हटाने का तरीका बताया गया है। यह भी चेतावनी दी गई है कि percent-encoded octets को decode करने से पहले URI components parse किए जाएँ, क्योंकि गलत समय पर decoding data को delimiters में बदल सकती है। यह व्यावहारिक engineering सलाह है।

Raw agent input के लिए अलग record रखें। उसे activity record और जाँच के समय details view में दिखाया जा सकता है। उसे reviewer का ध्यान खींचने वाली canonical action line से प्रतिस्पर्धा नहीं करनी चाहिए।

सरल नियम यह है: card normalized description दिखाए, journal description और input दोनों सुरक्षित रखे, और authorization decisions explicit scope rules के बिना इनमें से किसी को substitute न बनाएं। ये अलग data products हैं।

## पहले parse करें और अस्पष्ट input अस्वीकार करें

जब कोई इंसान parser के output को approve करता है, तब URL parser security boundary का हिस्सा बन जाता है। Supported URL schemes के लिए एक parser behavior चुनें और rendering तथा execution दोनों के लिए उसे source of truth बनाएं।

सामान्य HTTP APIs के लिए ऐसे inputs को स्वीकार न करें जिनका अर्थ अस्पष्ट हो। Relative references को host पाने से पहले explicit base URL चाहिए। Fragments HTTP request में नहीं जाते और उन्हें ऐसे नहीं दिखाना चाहिए जैसे वे server को प्रभावित करते हों। `https://alice@api.example.test/` जैसा userinfo API approval flow में लगभग हमेशा भ्रामक होता है। इसे चुपचाप छिपाने के बजाय reject करें।

एक स्पष्ट failure point वाला parse pipeline अपनाएं:

1. Outbound API channel के लिए केवल absolute `http` या `https` URL स्वीकार करें।
2. उसे action executor द्वारा चुने गए URL implementation से parse करें।
3. Userinfo, missing host, malformed port, unsupported schemes और invalid percent escapes को reject करें।
4. Parsed components और approved headers से वास्तविक request बनाएं।
5. उन्हीं components से card render करें और फिर वही exact request submit करें।

String splits से यह काम खुद न करें। हर position में पहला `@`, `:`, `/`, `?` और `#` एक ही अर्थ नहीं रखते। IPv6 authorities को brackets चाहिए। Bracket के बाद का colon port शुरू कर सकता है, जबकि brackets के अंदर के colons address का हिस्सा हैं। Parser यह अंतर समझता है, छोटी regular expression आमतौर पर नहीं।

WHATWG URL Standard URLs, hosts, domains और IP addresses के parsing तथा serialization behavior को परिभाषित करता है। इसकी security guidance यह भी बताती है कि bidirectional text host और path के बीच भ्रम पैदा कर सकता है और ऐसी स्थिति में केवल host दिखाने की सलाह देती है। Security product को इससे कड़ा नियम लेना चाहिए: हर card में authority और path को दृश्य रूप से अलग रखें।

यदि action layer में custom client है, तो test corpus पर साबित करें कि वह parser से सहमत है। यह मानकर न चलें कि दो mature libraries spaces, backslashes, Unicode hostnames या असामान्य numeric IP forms को एक ही तरह संभालती हैं। Agreement ऐसी property है जिसे test करना पड़ता है।

## Percent escapes decode करें, लेकिन route न बदलें

Percent encoding URL को भ्रामक बना सकती है। कोई URL casual decode के बाद harmless दिख सकता है, लेकिन router, proxy या upstream service के लिए उसका अर्थ अलग हो सकता है।

इन paths पर ध्यान दें:

```text
/v1/projects/%2E%2E/admin
/v1/projects/%252E%252E/admin
/v1/files/report%2Ffinal
```

पहले path में percent-encoded dots हैं। दूसरे में `2E` से पहले encoded percent sign है, इसलिए यह वही input नहीं है। तीसरे में एक path segment के भीतर encoded slash है। यदि display layer तीनों को बार-बार decode करे, तो वह ऐसी path structure दिखा सकती है जिसे client ने भेजा ही नहीं।

RFC 3986 एक सीमित सुरक्षित स्थिति बताता है: normalization के दौरान unreserved characters के percent escapes decode किए जा सकते हैं। Unreserved characters letters, digits, hyphen, period, underscore और tilde हैं। `/`, `?`, `#`, `@` और `:` जैसे reserved characters तब encoded रहने चाहिए जब decoding component boundaries या delimiters बदल दे। RFC यह भी कहता है कि implementation को एक ही string को एक से अधिक बार encode या decode नहीं करना चाहिए।

इससे display का अच्छा नियम निकलता है:

```text
Raw path:       /v1/%75sers/alice%7Eops/report%2Ffinal
Card path:      /v1/users/alice~ops/report%2Ffinal
Wire path:      /v1/users/alice~ops/report%2Ffinal
```

Card `%75` और `%7E` को readable बनाता है, क्योंकि वे unreserved characters हैं। `%2F` दिखाई देता रहता है, क्योंकि slash path segments की structure बदल देगा। Card और wire form में harmless अंतर हो सकता है, लेकिन routing meaning एक ही रहना चाहिए।

Path को indiscriminately decode करने के बाद dot segments न हटाएं। Encoded structure के अनुसार path parse करें, defined normalization procedure लागू करें और reserved characters को data के रूप में रखने वाले escapes को सुरक्षित रखें। यदि downstream service अलग decode order अपनाती है, तो यह compatibility और security problem है, जिसे tests में सामने लाना चाहिए।

## Host पूरी authority नहीं है

HTTP target की authority में host और, जब वह default न हो, port शामिल होता है। Port छोड़ देने से approval card omission के ज़रिए गलत जानकारी देता है।

इन targets को अलग समझें:

```text
https://api.example.test/v1/keys
https://api.example.test:8443/v1/keys
http://api.example.test/v1/keys
```

पहला सामान्यतः port 443 इस्तेमाल करता है। दूसरा 8443 पर जाता है। तीसरे का scheme अलग है और उसका सामान्य port 80 है। Reviewer HTTPS पर production API call स्वीकार कर सकता है और custom test port पर जाने वाले request को अस्वीकार कर सकता है। Card को यह निर्णय संभव बनाना चाहिए।

Scheme और hostname को lowercase करें। Port को तभी छिपाएँ जब वह parsed scheme का default हो: `http` के लिए 80 और `https` के लिए 443। केवल इसलिए port न छिपाएँ कि DNS record किसी परिचित जगह तक पहुँचता है।

Internationalized domain names के साथ भी सावधानी चाहिए। Human-friendly Unicode form पढ़ने में आसान हो सकती है, जबकि DNS wire form ASCII labels इस्तेमाल करती है। Unicode दिखाएँ तो details में उसी समय ASCII form भी दिखाएँ और defined host-processing algorithm वाला parser इस्तेमाल करें। Equivalence तय करने के लिए अपना punycode conversion या display strings की तुलना न बनाएं।

IP literals के लिए brackets में IPv6 दिखाएँ, non-default port रखें और literal address को IP literal के रूप में label करें। `https://[2001:db8::9]/v1/keys` को केवल इसलिए named production service जैसा न दिखाएँ कि agent ने note field में कोई अच्छा alias दिया है।

Aliases अलग समस्या पैदा करते हैं। `api.internal`, `api` और `10.0.0.9` आज एक server तक पहुँच सकते हैं, लेकिन DNS बदलने पर अलग हो सकते हैं। Approval के लिए एक को चुपचाप दूसरे में rewrite न करें। Client ने जिस parsed authority का अनुरोध किया है वही दिखाएँ। यदि system connection से पहले DNS resolve करता है, तो selected address को connection context में दिखाएँ और audit trail में दर्ज करें। HTTP request जिस authority को नाम देती है, वह वही रहती है।

HTTP इस अंतर को स्पष्ट करता है। RFC 9110 के अनुसार `Host` field target URI से host और port की जानकारी देती है, जबकि HTTP/2 और HTTP/3 यह जानकारी `:authority` में ले जा सकते हैं। RFC 9113 के अनुसार HTTP/2 authority से `Host` बनाने वाला intermediary `:authority` का उपयोग करे, जब तक वह request target न बदल रहा हो। इसलिए card को caller द्वारा दिए गए authority field को decorative metadata नहीं, routing material मानना चाहिए।

## Method और path को अपना दृश्य महत्व दें

HTTP method, authority और path को साथ रखें, क्योंकि reviewer action को वाक्य की तरह पढ़ता है। Method और खतरनाक path segments को इतना contrast दें कि तेज़ नज़र में वे लंबे URL में गुम न हों।

यह layout स्थिर क्रम बनाए रखता है:

```text
DELETE
https://api.example.test/v1/projects/acme/production
```

जो request किसी object को बदलती है, उसमें visible path पर identifier दिखाएँ। Card में जगह कम होने पर `/v1/projects/acme/production` के अंत को काटना गलत है। पहले लंबे query values या body previews को छोटा करें, अंतिम path segment को कभी नहीं।

Path में case सुरक्षित रहना चाहिए। RFC 3986 कहता है कि generic URI syntax scheme और host के अलावा components को case-sensitive मानता है, जब तक scheme कुछ और न कहे। कई frameworks case-sensitive routing करते हैं। `/Admin/DeleteUser` को `/admin/deleteuser` में बदलना ऐसे request का वर्णन है जो कभी भेजा ही नहीं गया।

कभी path harmless दिखता है, लेकिन query उसका प्रभाव बदल देती है:

```text
POST https://api.example.test/v1/invoices/481/refund?dry_run=false
POST https://api.example.test/v1/invoices/481/refund?dry_run=true
```

जब parameters scope, behavior या identity बदलते हों, तो action line के नीचे छोटा query summary दिखाएँ। Unstructured या बहुत लंबी query के लिए full encoded query expandable details में रखें और main card में redacted, decoded summary दें। Card को friendly बनाने के लिए token को readable secret में decode न करें।

Request body path से भी अधिक महत्वपूर्ण हो सकती है। `PATCH /v1/users/alice` की approval बहुत कम अर्थ रखती है यदि body administrator role दे सकती है। कम से कम content type, byte length और stable digest दिखाएँ। JSON जैसी structured formats में बदले गए fields का छोटा preview उपयोगी हो सकता है, बशर्ते preview उन्हीं bytes से बना हो जो wire पर जाएँगे। Signing या hashing के बाद display के लिए object को फिर serialize करना URL को दोबारा parse करने जैसी split-brain समस्या पैदा करता है।

## Headers और redirects request का गंतव्य बदल सकते हैं

Canonical URL approval flow को सुरक्षित नहीं बनाता, यदि कोई दूसरा request field connection को steer कर सकता हो। Card को इन fields को सीमित करना चाहिए या उनका प्रभाव दिखाना चाहिए।

`Host` और `:authority` से शुरुआत करें। HTTP client सामान्यतः इन्हें target URL से बनाता है। यदि action interface caller को override करने देता है, तो documented transport reason के बिना override reject करें। Support करना हो तो approval line में connection destination और requested authority दोनों दिखाएँ, ताकि व्यक्ति उनकी तुलना कर सके।

Proxy configuration भी इसी तरह दिखनी चाहिए। Proxy immediate peer बदलता है, लेकिन origin target ज़रूरी नहीं बदलता। Card पर origin की जगह proxy address न रखें। Approved action के रूप में origin और transport context के रूप में proxy दिखाएँ। यदि proxy destination fields rewrite कर सकती है, तो उसे tests, logging और अलग trust decision वाले executor component की तरह संभालें।

जब redirect target बदलता है, redirect नया action है। कुछ redirect behavior में `POST` `GET` बन सकता है या request नई authority पर फिर भेजी जा सकती है। Original approval केवल original target तक सीमित होनी चाहिए। Redirect follow करने से पहले `Location` parse करें, अगला request बनाएं, उसके scheme, authority, method, path, query और body behavior की तुलना करें, फिर किसी अर्थपूर्ण बदलाव पर दोबारा पूछें।

Run की अवधि के लिए किसी «site» को approve करके उसके हर redirect को harmless मानना आसान shortcut है। इससे interruptions कम लगते हैं, लेकिन URL parsing और redirect policy अदृश्य privilege expansion बन जाती है। Broad permission चाहिए तो उसे approval wording में स्पष्ट करें। Redirects को वह अनुमति चुपचाप न लेने दें।

## Raw input record में रखें, decision line में नहीं

Audit trail को दो अलग सवालों का उत्तर देना चाहिए: agent ने क्या माँगा और executor ने क्या करने की कोशिश की? एक URL string हमेशा दोनों का उत्तर नहीं दे सकती।

Raw URL string को जैसा मिला था वैसा दर्ज करें, secret redaction rules के अधीन। Canonical target अलग दर्ज करें। Executor ने resolution किया हो तो final connection authority और resolved address भी जोड़ें। HTTP/2 या HTTP/3 के लिए effective `:authority`, और HTTP/1.1 के लिए effective `Host` दर्ज करें। Redirect hops को individual attempted requests की तरह record करें, पहले call की footnote की तरह नहीं।

Journal entry का आकार ऐसा हो सकता है:

```json
{
  "request_id": "req_01J...",
  "agent_input_url": "HTTPS://API.EXAMPLE.TEST:443/v1/%75sers/alice%7Eops",
  "approved_target": "GET https://api.example.test/v1/users/alice~ops",
  "effective_authority": "api.example.test",
  "effective_port": 443,
  "connection_ip": "203.0.113.42",
  "result": "200"
}
```

इस sample में documentation address space का connection IP इस्तेमाल हुआ है। वास्तविक log में data को किसी लंबे समय के record तक पहुँचने से पहले query secrets, authorization material और sensitive bodies को सुरक्षित करें। Digest approved content को executed content से जोड़ने में मदद करता है, बिना private payloads को हर screen पर copy किए।

Raw input और canonical target का अंतर investigation में उपयोगी होता है। यदि card ने सामान्य path दिखाया लेकिन raw input में layered encodings थीं, तो पता लगाया जा सकता है कि parser, renderer या HTTP client में असहमति कहाँ हुई। केवल pretty URL रखने पर defect खोजने का प्रमाण खो जाता है।

Sallyport का Activity journal और Sessions journal एक encrypted, hash-chained audit log से project किए जाते हैं। इसलिए target representation को UI strings से बाद में फिर बनाने के बजाय action record के हिस्से के रूप में एक बार लिखना चाहिए। Offline `sp audit verify` check तभी उपयोगी है जब execution के समय recorded action fields ईमानदार थे।

## उन असहमतियों को test करें जो सामान्य URLs नहीं दिखाते

महत्वपूर्ण unit tests दस सामान्य `https://api.example.test/v1/users` examples नहीं हैं। महत्वपूर्ण वे cases हैं जिनमें raw string, card renderer और transport library अलग निष्कर्ष निकाल सकते हैं।

Table-driven corpus बनाएं जो parsed fields, visible target, wire target और decision को assert करे। कम से कम ये families शामिल करें:

- scheme और host के case changes, default और non-default ports के साथ;
- dot segments और unreserved तथा reserved characters के percent escapes;
- encoded percent signs, encoded slashes और malformed escape sequences;
- IPv6 literals, Unicode host input और reject किए जाने वाले userinfo;
- action behavior बदलने वाली query values और दूसरी authority वाले redirect targets।

Test case में expected representation स्पष्ट होनी चाहिए:

```json
{
  "input": "HTTPS://API.EXAMPLE.TEST:443/v1/%75sers/alice%7Eops?role=viewer",
  "decision": "approve",
  "card": "GET https://api.example.test/v1/users/alice~ops?role=viewer",
  "wire_url": "https://api.example.test/v1/users/alice~ops?role=viewer"
}
```

फिर ऐसे negative cases जोड़ें जिन्हें approval से पहले fail होना चाहिए:

```json
{
  "input": "https://alice@api.example.test/v1/users",
  "decision": "reject",
  "reason": "userinfo is not supported for outbound API actions"
}
```

Corpus को उसी exact client code से चलाएँ जो connection खोलता है। केवल parser वाला test suite rendering mistakes पकड़ सकता है, लेकिन empty path normalize करने, default authority जोड़ने या अपने redirect rules लागू करने जैसे transport behavior को छोड़ देगा।

अंत में UI को reviewer के वास्तविक उपयोग के अनुसार test करें। सामान्य window sizes पर पूरा method, host, मौजूद होने पर port और final path segment दिखाई देना चाहिए। जब किसी व्यक्ति को यह जानने के लिए hover, expand या scroll करना पड़े कि request production data मिटाती है, तो security copy विफल हो जाती है। Approval button पर focus जाने से पहले card को महत्वपूर्ण अंतर स्पष्ट कर देना चाहिए।

Human approval मजबूत control हो सकता है, लेकिन उसकी शक्ति उतनी ही होती है जितनी request description की, जो इंसान के सामने रखी गई है। इस description को parsed components से बनाएं, उन्हीं components को execute करें, raw input को बाद की जाँच के लिए सुरक्षित रखें और अस्पष्टता को सजाने के बजाय उसे reject करें।
