# Agent action audit record: नियंत्रण के लिए एक व्यावहारिक मॉडल

एजेंट की कार्रवाइयों के लिए ऐसे रिकॉर्ड चाहिए जो केवल गतिविधि नहीं, अधिकार का भी विवरण दें। `POST /deploy returned 200` जैसी एक पंक्ति यह नहीं बता सकती कि अनुरोध सही प्रोसेस ने किया था या नहीं, किसी व्यक्ति ने उसे अनुमति दी थी या नहीं, अनुरोध किस सिस्टम तक गया, या बाद में किए गए revoke ने कुछ रोका था या नहीं।

व्यावहारिक इकाई एक अपरिवर्तनीय action record है, जिसे session, approval और revocation events से जोड़ा जाता है। Action record इतना छोटा रखें कि उसे खोजा और सत्यापित किया जा सके, लेकिन इतना विशिष्ट भी कि थका हुआ इंजीनियर अधूरे fields के आधार पर कहानी गढ़े बिना विवादित कॉल को फिर से समझ सके।

## ऑडिट एंट्री को अधिकृत प्रयास का विवरण देना चाहिए

**Agent action audit record** किसी बाहरी सिस्टम पर प्रभाव डालने की एक कोशिश और उस क्षण मौजूद अधिकार-संदर्भ को दर्ज करता है। कार्रवाई नेटवर्क तक पहुंचने से पहले विफल हो सकती है, डिलीवरी के दौरान विफल हो सकती है, target से अस्वीकृति मिल सकती है या सफलतापूर्वक पूरी हो सकती है। इन चारों स्थितियों को audit trail में रखें।

टीमें अक्सर दो अपर्याप्त चीजों में से एक लॉग करती हैं। वे chat transcript रखती हैं, जो इरादा बताता है लेकिन execution नहीं। या raw request traffic रखती हैं, जिसमें बहुत-सा secret material आ जाता है और फिर भी वह मानवीय निर्णय छूट जाता है जिसने कॉल की अनुमति दी थी। इनमें से कोई भी रिकॉर्ड यह नहीं बताता कि किसी actor को किसी operation का अधिकार था या नहीं।

इनको अलग objects मानें:

- **Session** एक चल रहे agent process और उसके lifetime की पहचान करता है।
- **Approval** तय scope के साथ किसी व्यक्ति का निर्णय दर्ज करता है।
- **Action** एक मांगी गई बाहरी operation और उसका परिणाम दर्ज करता है।
- **Revocation** किसी session या authorization को सटीक समय पर समाप्त करता है।

Incident के दौरान इस अंतर का सीधा असर पड़ता है। यदि किसी व्यक्ति ने 14:03 पर session revoke किया, तो आपको 14:03 से पहले की हर action, 14:03 के बाद की हर कोशिश और उन बाद की कोशिशों को अस्वीकार करने वाला स्थानीय निर्णय देखना होगा। `session approved: false` वाली एक mutable row यह पूरा इतिहास मिटा देती है।

Record model को इस बात पर निर्भर न बनाएं कि action सफल हुई या नहीं। Request खुद दुर्भावनापूर्ण इरादा, configuration defect या अपने task को गलत समझने वाले agent का प्रमाण हो सकती है। असफल calls अक्सर सबसे पहले उपयोगी सबूत देती हैं।

## Actor कोई दोस्ताना agent label नहीं, एक process है

वास्तव में action मांगने वाले process को दर्ज करें। Model name, workspace name या agent nickname रिपोर्ट पढ़ने वाले व्यक्ति के लिए उपयोगी हो सकते हैं, लेकिन इनमें से कोई भी उस executable की विशिष्ट पहचान नहीं करता जिसके पास उस समय connection था।

एक उपयोगी actor object में internal session identifier, process ID, executable path, launch timestamp और, जब operating system यह जानकारी देता हो, code signing authority रखें। विश्वसनीय रूप से मिल सके तो parent process ID और parent executable भी जोड़ें। Parent संबंध अक्सर बताता है कि agent को terminal ने शुरू किया, editor extension ने बनाया या किसी अनपेक्षित helper ने।

Process को बाद में resolve करने के बजाय उसकी identity का snapshot लें। Process IDs दोबारा इस्तेमाल हो सकते हैं और paths बदल सकते हैं। बाद में की गई lookup छूटी हुई observation को ठीक नहीं कर सकती।

```json
{
  "actor": {
    "session_id": "ses_01J8Q1F9K9Z3",
    "pid": 48217,
    "started_at": "2025-02-18T21:14:06Z",
    "executable": "/usr/local/bin/agent-runner",
    "signing_authority": "Developer ID Application: Example Developer",
    "parent_pid": 48091,
    "parent_executable": "/Applications/Terminal.app"
  }
}
```

`signing_authority` का मान platform की signing assessment से आना चाहिए, agent द्वारा दी गई string से नहीं। कोई agent खुद को `claude-code`, `deploy-helper` या `trusted-agent` कह सकता है। जब तक operating system उस नाम को executable identity से न जोड़े, label केवल सजावट है।

Process identity को authorship का झूठा दावा न बनाएं। Prompt injection, compromised plugin या लापरवाह instruction के बाद signed binary भी गलत व्यवहार कर सकती है। यह field बताती है कि request किस code authority ने शुरू की। इससे request की समझदारी प्रमाणित नहीं होती।

RFC 5424, यानी syslog protocol specification, application name और process ID जैसे header fields को structured data से अलग रखता है। Agent records के लिए भी यह विभाजन उपयोगी है। Stable identity और timing को अलग fields में रखें जिन्हें machines query कर सकें। Repository या task reference जैसे बदलते context को namespaced object में रखें। सब कुछ एक message string में डालने पर हर जांच text parsing बन जाती है।

## Target को address और अर्थ, दोनों चाहिए

दर्ज करें कि action कहां गई और वह किस resource या command को प्रभावित करना चाहती थी। ये जुड़े हुए तथ्य हैं, लेकिन एक-दूसरे के बदले इस्तेमाल नहीं किए जा सकते।

HTTP में network destination `api.example.internal` हो सकता है, जबकि meaningful operation `POST /v1/releases/{release_id}/promote` है। Host, port, protocol, HTTP method और route template रखें। अपनी टीम द्वारा नियंत्रित target system identifier भी जोड़ें, जैसे `release-service-prod`। Hostname बदलने पर identifier बना रहता है, जबकि hostname उस request की जांच में मदद करता है जो मशीन से वास्तव में निकली।

SSH के लिए host alias या host name, port, host key fingerprint या known-host entry का reference और, जहां सुरक्षित हो, remote account label रखें। Target में मांगी गई command class भी लिखें। `restart-worker`, `ssh succeeded` से ज्यादा बताता है, लेकिन customer paths और environment variables वाली पूरी shell command से कम जानकारी उजागर करता है।

Persistence से पहले redaction करें, analyst द्वारा log खोलने के बाद नहीं। URL query strings, request headers, shell arguments और JSON bodies में अक्सर tokens होते हैं। जो logging library debugging के लिए उन्हें capture करती है, वह अंततः credentials से भरी incident file बनाएगी।

यह record shape request content की पूरी नकल किए बिना target facts को queryable रखती है:

```json
{
  "target": {
    "kind": "http",
    "system_id": "release-service-prod",
    "endpoint": {
      "scheme": "https",
      "host": "api.example.internal",
      "port": 443,
      "method": "POST",
      "route_template": "/v1/releases/{release_id}/promote"
    }
  },
  "operation": {
    "name": "promote_release",
    "request_fingerprint": "sha256:8e8c...",
    "request_bytes": 286,
    "redacted_parameters": {
      "environment": "production",
      "release_id": "rel_7b2"
    }
  }
}
```

Fingerprint तभी उपयोगी है जब canonicalization परिभाषित हो। Object fields को sort करें, redaction policy से बाहर रखे गए fields हटाएं, text encoding normalize करें और फिर resulting bytes का hash बनाएं। Canonicalization version भी दर्ज करें। वरना दो समान requests अलग digests दे सकती हैं और schema बदलने पर पुराने records संदिग्ध लग सकते हैं।

जब regulator, contract या incident process को original request चाहिए, तब digest retained evidence की जगह नहीं ले सकता। ऐसी स्थिति में evidence को अलग encrypt करें, access सीमित करें और उसका content digest action record में रखें। Storage सस्ता है, इसलिए original body को सामान्य searchable journal में न डालें।

## Requested operation और observed result के लिए अलग fields चाहिए

Agent request intent बताती है। Result यह बताता है कि उस intent को execute करने की कोशिश के बाद gateway ने क्या देखा। दोनों को `completed` जैसे अस्पष्ट status में न मिलाएं।

Network call के लिए execution किस transport phase में रुकी, उपलब्ध होने पर protocol status, सीमित response summary और लगा समय दर्ज करें। SSH के लिए connection outcome, authentication outcome, remote exit code तथा सीमित standard output और error summaries रखें। Target request स्वीकार करके asynchronous job बाद में चला सकता है, इसलिए 202 response का अर्थ यह नहीं कि बाहरी बदलाव हो गया।

ऐसी outcome vocabulary रखें जो failure का स्थान बताए। उदाहरण के लिए:

- `denied_vault_locked` का अर्थ है कि स्थानीय secret boundary ने call रोक दी।
- `denied_approval` का अर्थ है कि जरूरी human decision ने अनुमति नहीं दी।
- `network_error` का अर्थ है कि gateway connection बना या बनाए नहीं रख सका।
- `target_rejected` का अर्थ है कि remote service ने अस्वीकृति लौटाई।
- `target_accepted` का अर्थ है कि remote service ने request स्वीकार की।

Raw transport error को primary status field में न रखें। उसके साथ `dns_lookup_failed` या `tls_validation_failed` जैसा normalized code और छोटा, redacted diagnostic रखें। Engineers को aggregation चाहिए, incident responders को इतना स्थानीय context चाहिए कि वे expired certificate और blocked hostname में अंतर कर सकें।

एक पूरा result object ऐसा हो सकता है:

```json
{
  "result": {
    "outcome": "target_accepted",
    "started_at": "2025-02-18T21:19:42.184Z",
    "finished_at": "2025-02-18T21:19:43.021Z",
    "duration_ms": 837,
    "http_status": 202,
    "response_fingerprint": "sha256:2a64...",
    "response_summary": "promotion job accepted",
    "evidence_ref": null
  }
}
```

Schema में `target_accepted` को success न कहें। बाद में यही शब्द परेशानी पैदा करेगा। यदि service ने job स्वीकार की और job विफल हो गई, तो gateway ने अपना काम ठीक किया था, लेकिन business operation पूरी नहीं हुई। Job ID से जुड़े अलग remote completion event से बाद का उत्तर मिल सकता है।

## Approval records में साफ होना चाहिए कि व्यक्ति ने क्या मंजूर किया

Approval record में decision, scope, subject और timestamps चाहिए। `User approved agent` बहुत कम जानकारी देता है। इससे समीक्षक अनुमान लगाते रहते हैं कि व्यक्ति ने एक API call, कोई credential, एक session या समान नाम वाले process के हर भविष्य के session को अनुमति दी थी।

Session approval आम तौर पर एक पहचाने गए process की calls को उसके समाप्त होने या revoke किए जाने तक अनुमति देता है। Per-call approval किसी credential या operation के एक उपयोग पर लागू होता है। Scope सीधे दर्ज करें, क्योंकि दोनों controls का risk बहुत अलग है।

```json
{
  "approval": {
    "approval_id": "apr_01J8Q1P4Y5D6",
    "decision": "approved",
    "scope": "session",
    "subject_session_id": "ses_01J8Q1F9K9Z3",
    "approved_at": "2025-02-18T21:14:11Z",
    "expires_at": "2025-02-18T22:02:53Z",
    "approver_presence": "local_user_confirmation"
  }
}
```

Interface जितनी निश्चितता देती है, उससे अधिक दावा न करें। यदि application को local confirmation event मिला, तो वही तथ्य दर्ज करें। किसी व्यक्ति का नाम, identity provider account या biometric method तभी लिखें जब system वास्तव में उस identity को authenticate और documented policy के तहत retain करता हो। बनाई हुई identity detail झूठा भरोसा पैदा करती है और privacy obligations भी लाती है।

जिस approval ने action को नियंत्रित किया, उसका identifier action record में रखें। Execution से ठीक पहले हुआ authorization decision भी दर्ज करें। Timing edge case की जांच तक यह दोहराव लग सकता है: पुराना session approval मौजूद हो सकता है, लेकिन per-call requirement action को रोक सकती है। Action को दोनों तथ्य चाहिए।

Approval fatigue design defect है, approval evidence हटाने का कारण नहीं। यदि व्यक्ति को हर harmless request मंजूर करनी पड़े, तो वह पढ़े बिना approve करेगा। Per-call confirmation उन credentials या operations के लिए रखें जिनके दुरुपयोग पर सीधे ध्यान चाहिए, और record में बताएं कि gateway ने confirmation क्यों मांगी।

## Revocation cutoff time वाला event है

Revocation आगे के लिए authority समाप्त करता है। यह session मिटाता नहीं, पहले से भेजी गई request वापस नहीं लेता और पांच मिनट पहले मौजूद approval decision नहीं बदलता।

Revocation target, initiator type, observed timestamp और enforcement result दर्ज करें। Gateway active session को terminate या block कर सकता हो तो यह भी लिखें कि उसने ऐसा किया या नहीं। यदि action network boundary पार कर चुकी थी, तो स्पष्ट लिखें कि revoke उसे वापस नहीं बुला सकता। Response के दौरान engineers को यह अप्रिय तथ्य चाहिए, सांत्वना देने वाला लेकिन गलत `revoked` label नहीं।

इस failure sequence पर विचार करें:

1. Agent process को 09:00 पर session approval मिलता है और वह 09:17 पर production change भेजता है।
2. Operator अनपेक्षित target देखता है और 09:18:04 पर session revoke करता है।
3. Target 09:17 वाली request का उत्तर 09:18:07 पर देता है, क्योंकि उसने काम पहले ही queue कर दिया था।
4. Agent 09:18:09 पर एक और call करता है और gateway उसे अस्वीकार कर देता है।

अच्छा journal चारों events सुरक्षित रखता है। 09:17 वाली action शुरू होने पर अधिकृत थी। Revocation के बाद आया response उसी पुरानी action का हिस्सा है। Denied attempt साबित करती है कि revoke बाद के काम पर लागू हो गया। पहले की हर action पर `revoked` stamp लगा देने से वास्तविक exposure समझाने वाला क्रम खो जाता है।

Wall-clock time के साथ monotonic sequence number भी रखें। Clocks drift कर सकती हैं, users local time बदल सकते हैं और events की timestamp resolution समान हो सकती है। Sequence number बताता है कि journal ने records किस क्रम में स्वीकार किए। कई hosts पर काम करते समय प्रत्येक host का local sequence सुरक्षित रखें और correlation IDs इस्तेमाल करें, wall clocks को perfect global order मानकर न चलें।

## Tamper evidence append-only अनुशासन पर निर्भर है

Hash chain हर नए record में पिछले record का digest शामिल करके बिना पता चले editing को कठिन बनाती है। यह साधारण log file को इस बात का प्रमाण नहीं बनाती कि हर अपेक्षित event मौजूद है। Writer और stored chain head पर नियंत्रण रखने वाला व्यक्ति suffix मिटा सकता है, नई chain शुरू कर सकता है या records को durable storage तक पहुंचने से रोक सकता है।

इस सीमा के कारण hash chains बेकार नहीं होतीं। वे एक सीमित लेकिन उपयोगी सवाल का उत्तर देती हैं: system द्वारा लिखे जाने के बाद क्या इन records में बदलाव हुआ, बीच से कुछ गायब हुआ या उनका क्रम बदला? Chain fields स्पष्ट रखें।

```json
{
  "journal": {
    "sequence": 1842,
    "recorded_at": "2025-02-18T21:19:43.024Z",
    "previous_hash": "sha256:68b1...",
    "record_hash": "sha256:93f4...",
    "hash_format": "canonical-json-v1"
  }
}
```

`record_hash` को छोड़कर पूरे canonical record का hash बनाएं। ऐसे pretty printed representation का hash न बनाएं जिसकी whitespace, field order या timestamp formatting versions के बीच बदल सकती है। Canonical format को version दें और हर emitted format के लिए verifier सुरक्षित रखें।

NIST Special Publication 800-92, Guide to Computer Security Log Management, log generation, storage, analysis और retention को अलग responsibilities मानता है। यह एक आम गलती साफ करता है: teams entries में hash जोड़कर काम पूरा समझ लेती हैं। आपको durable storage, writer के आसपास access controls, retention decision, नियमित verification और failed check की investigation procedure भी चाहिए।

Sallyport अपने Sessions और Activity journals को एक write-blind encrypted, hash-chained audit log से तैयार करता है। इसका `sp audit verify` command vault key के बिना ciphertext पर offline chain verify करता है। इससे journal integrity जांचने की क्षमता और credentials इस्तेमाल करने की क्षमता अलग रहती है।

## एक correlation ID दबाव में record को उपयोगी बनाती है

Gateway द्वारा authorization evaluate करने से पहले हर requested action को action ID दें। इसे local decision, network attempt, response handling और बाद के remote completion callback तक साथ ले जाएं। जब engineer किसी disputed deployment को देखे, तो एक identifier खोजकर पूरी timeline मिल जानी चाहिए।

अलग संबंधों के लिए related IDs रखें। Action अपने session, approval, credential reference, target और journal sequence की ओर संकेत करे। Task या conversation reference action को agent context से जोड़ सकता है, लेकिन conversation transcript को source of truth न बनाएं। Prompt text बदल सकता है, private material रख सकता है और अक्सर eventual request का सटीक विवरण नहीं देता।

एक compact complete record ऐसा हो सकता है:

```json
{
  "schema_version": "1.0",
  "action_id": "act_01J8Q2ABR8M7",
  "event_type": "action.completed",
  "actor": {"session_id": "ses_01J8Q1F9K9Z3", "pid": 48217},
  "target": {"kind": "http", "system_id": "release-service-prod"},
  "operation": {"name": "promote_release", "request_fingerprint": "sha256:8e8c..."},
  "authorization": {"vault": "unlocked", "approval_id": "apr_01J8Q1P4Y5D6", "decision": "approved"},
  "result": {"outcome": "target_accepted", "http_status": 202},
  "journal": {"sequence": 1842, "previous_hash": "sha256:68b1..."}
}
```

Correlation ID को authorization token न बनाएं। इसे स्वतंत्र रूप से generate करें, external callers इसे देख सकें तो unpredictable बनाएं और केवल ID अपने पास होने को action पढ़ने या follow-up call जारी करने की permission न मानें।

## Retention को evidence सुरक्षित रखना चाहिए, दूसरा secret store नहीं बनाना चाहिए

Redaction के बाद भी audit data private material जमा करता है। Target names customers के बारे में बता सकते हैं, route parameters internal projects दिखा सकते हैं, response summaries account state उजागर कर सकती हैं और process paths developer habits प्रकट कर सकते हैं। तय करें कि records कौन खोज सकता है, कौन export कर सकता है और प्रत्येक category कितने समय तक उपलब्ध रहेगी।

Searchable action metadata को encrypted request या response evidence से अलग रखें। जांच की जरूरत समाप्त होने पर detailed evidence के लिए छोटी retention लागू करें। Hashes और linkage records इतनी देर रखें कि यह साबित किया जा सके कि बचे हुए summaries system द्वारा दर्ज सामग्री से जुड़े हैं।

Incident review का वास्तविक सवाल लेकर model जांचें: «किस signed process ने इस production target तक access मांगा, किस approval के तहत, और क्या revoke के बाद कोई कोशिश जारी रही?» यदि query के लिए analyst को unstructured messages जोड़ने, client debug logs देखने या agent से उसकी memory पूछने की जरूरत पड़ती है, तो model अधूरा है।

Sallyport की fixed decision ladder इस model को स्पष्ट सीमाएं देती है: vault gate, session authorization और per-call credential approval अलग authorization facts बनाते हैं। अपने audit design में भी इन्हें अलग रखें। Record को दिखाना चाहिए कि authority कहां रुकी, हर denial को generic failure code में नहीं छिपाना चाहिए।

Agents को broad credentials मिलने से पहले schema बनाएं। Incident के बाद actor identity, approval scope और revoke ordering जोड़ना gaps से authority reconstruct करने जैसा है। यह धीमा काम है और अंत में अक्सर कोई कहता है, «हमें लगता है», जबकि record को साफ-साफ बताना चाहिए था कि वास्तव में क्या हुआ।
