# Disk pressure में agent audit logs को fail closed होना चाहिए

ऐसा agent gateway, जो अपने actions को स्थायी रूप से रिकॉर्ड करने की क्षमता खत्म होने के बाद भी काम करता रहे, अपनी ही security boundary तोड़ चुका है। Disk pressure observability की मामूली परेशानी नहीं है। इससे तय होता है कि अगली API request या SSH command ऐसा evidence छोड़ेगी या नहीं जिसे operators जांच और verify कर सकें।

सुरक्षित नियम सीधा है: audit writer की जगह खत्म होने से पहले नए credential वाले calls deny करें। पहले alert दें। जो काम admission boundary पार कर चुका है, उसे तभी पूरा होने दें जब gateway उसका completion या failure भी रिकॉर्ड कर सके। Appends fail होने पर disk पर मौजूद ciphertext सुरक्षित रखें और log को ऐसी सुविधाजनक file न समझें जिसे बाद में साफ किया जा सकता है।

## Audit logging authorization का हिस्सा होना चाहिए

अगर gateway का उद्देश्य agent actions के चारों ओर मानव-नियंत्रित boundary बनाना है, तो audit logging को «best effort» नहीं कहा जा सकता। जैसे ही agent credential वाले HTTP request या SSH command का अनुरोध कर सकता है, उस request का record authorization decision का हिस्सा बन जाता है। Gateway action कर दे लेकिन record खो जाए, तो operator बाद में legitimate run और बिना जवाबदेही वाले run में फर्क नहीं कर पाएगा।

यहां teams अक्सर दो अलग failures को मिला देती हैं:

- Derived index उपलब्ध न होने के कारण dashboard या activity view update नहीं हो पाता।
- Encrypted source log durable event append स्वीकार नहीं कर पाती।

पहली failure असुविधाजनक है। दूसरी failure यह बदल देती है कि gateway नया external action ले सकता है या नहीं। दोनों को एक ही severity label या recovery path न दें।

Sallyport का model इस अंतर को उपयोगी रूप देता है: उसके Sessions और Activity journals एक encrypted, hash-chained audit log से project होते हैं, न कि हर journal अलग source of truth होता है। Projection देर से आ सकती है या उसे rebuild करना पड़ सकता है; write-blind encrypted chain वह record है जिसे सुरक्षित रहना ही चाहिए।

इस व्यवस्था से admission rule भी स्पष्ट होता है। Action dispatch करने से पहले gateway को पता होना चाहिए कि उसके पास कम से कम attempt रिकॉर्ड करने के लिए पर्याप्त storage capacity और writer health है। Dispatch के बाद उसे result रिकॉर्ड करना होगा। यदि action का प्रभाव irreversible है, जैसे remote production setting बदलना, तो gateway को dispatch से पहले durable intent event और उसके बाद result event रिकॉर्ड करना चाहिए।

Storage layer जितनी chronology संभाल नहीं सकती, उतनी exact chronology का वादा न करें। इससे मजबूत और अधिक उपयोगी वादा करें: हर admitted action के request identity, authorization context और अंतिम ज्ञात outcome का durable, ordered record होगा। यदि gateway यह वादा निभा नहीं सकता, तो उसे कोई और action admit नहीं करना चाहिए।

## Alerting और denial अलग states हैं

जिस क्षण calls deny करना शुरू करेंगे, उसी क्षण alert करना खराब operational choice है। Operator को तब पता चलता है जब agent पहले ही block हो चुका होता है। फिर उसे दबाव में तय करना पड़ता है कि data हटाए, काम रोके या audit rule कमजोर करे। Storage policy में अलग states और उनके स्पष्ट transitions होने चाहिए।

चार states रखें:

1. **Normal**: Free capacity operating reserve से अधिक है और हाल की durability check सफल रही है।
2. **Warning**: Capacity warning threshold से नीचे आ गई है, लेकिन gateway के पास पूरा reserve अभी भी है। नए calls चलते रहते हैं और operators को एक alert मिलता है।
3. **Restricted**: Capacity reserve से नीचे आ गई है, या writer ने temporary failure देखी है जो अभी hard-failure boundary तक नहीं पहुंची। ऐसे actions admit न करें जो बड़े या कई events वाले records बना सकते हैं। पहले से admitted काम को ही चलने दें और writer को test करते रहें।
4. **Denied**: Gateway audit event को durably append नहीं कर सकता, या बची capacity minimum record budget को cover नहीं कर सकती। हर नए credential वाले call को deny करें।

इनमें से किसी state को केवल percentage से define नहीं किया जा सकता। 4 TB volume पर 5 प्रतिशत free space पर्याप्त हो सकती है। छोटे volume पर वही 5 प्रतिशत एक agent run, system update या verbose remote command output के एक burst में खत्म हो सकती है। Storage policies तब fail होती हैं जब वे gateway के वास्तविक write behavior के बजाय monitoring template से numbers उठा लेती हैं।

Warning threshold operator को समय देता है। Reserve evidence trail की रक्षा करता है। Denied state इस दावे की रक्षा करती है कि हर admitted action रिकॉर्ड हुआ है। तीनों के काम अलग हैं, इसलिए इनका number भी एक जैसा नहीं होना चाहिए।

अच्छा state transition flapping से भी बचाता है। Free capacity threshold से नीचे जाते ही Warning में जाएं। वहां से तभी निकलें जब capacity ऊंचे recovery threshold से ऊपर आ जाए और writer एक durable test append पूरा कर दे। यही hysteresis Restricted पर भी लागू करें। इसके बिना boundary के पास चल रहा agent कुछ filesystem blocks के आधार पर permitted और denied calls के बीच बदलता रहेगा, जिससे स्थिति समझना और जांचना दोनों मुश्किल होते हैं।

## Reserve free-space का अनुमान नहीं, record budget है

Hard reserve इस आधार पर तय करें कि नए काम को रोकने के बाद भी कितने records बनाने पड़ सकते हैं। Calculation में नकली precision की जरूरत नहीं है। ऐसे conservative inputs चाहिए जिन्हें incident के दौरान समझाया जा सके।

इन सवालों से शुरू करें:

- सबसे बड़ा admitted action record कितना होगा, जिसमें encrypted payload, policy द्वारा रखे गए headers, result metadata और hash-chain fields शामिल हों?
- Gateway के Restricted में जाने के समय कितने actions in flight हो सकते हैं?
- क्या एक action अलग completion record, timeout record या retry record बना सकता है?
- Source log के साथ बढ़ने वाली local files कौन सी हैं, जैसे segment metadata, indexes, temporary files या crash reports?
- Condition को ठीक से report करने के लिए operating system और app को कितनी जगह चाहिए?

मान लें gateway 12 in-flight actions की अनुमति देता है, हर action को intent record और result record दोनों की जरूरत हो सकती है, और conservative encrypted record budget 128 KiB है। केवल action records 3 MiB लेंगे। यही reserve नहीं है। इसमें सबसे बड़े expected journal projection batch, file rollover overhead, failure marker और allocation behavior के लिए पर्याप्त safety margin जोड़ें। फिर इसे ऐसे number तक round up करें जिसे monitor करना आसान हो।

उपयोगी output कोई magic number नहीं, बल्कि लिखी हुई policy है:

```text
warning threshold: 2 GiB free on the audit volume
hard reserve:      512 MiB reserved for audit completion and recovery records
admission budget:  256 KiB minimum available per new action
recovery threshold: 3 GiB free plus one durable test append
```

ये values उदाहरण हैं, हर Mac के defaults नहीं। छोटे API calls वाली single developer machine, shared build machine से छोटा reserve justify कर सकती है, जहां autonomous agents लंबे SSH jobs चलाते हैं। Policy उस worst credible output पर आधारित होनी चाहिए जिसे gateway रिकॉर्ड करता है, न कि किसी शांत सप्ताह के average request size पर।

Apple के मौजूदा APFS documentation में इससे जुड़ी एक बात बताई गई है जिसे percentage alarm बनाते समय लोग भूल जाते हैं: यह जांचें कि किसी खास operation के लिए जरूरी space उपलब्ध है या नहीं, बजाय इसके कि partition पर उपलब्ध free space से एक भरोसेमंद total निकालने की कोशिश करें। APFS space sharing, clones और sparse files का भी इस्तेमाल करता है, इसलिए दिखाई देने वाली जगह और तुरंत इस्तेमाल की जा सकने वाली जगह हमेशा पुराने fixed-slice disk की तरह व्यवहार नहीं करती।

Audit writer के लिए इसका अर्थ है कि admission check पूछे, «क्या मैं अभी इस record budget को सुरक्षित रूप से afford कर सकता हूं?» उसे यह नहीं पूछना चाहिए, «क्या menu bar अभी भी nonzero free space दिखा रहा है?»

## Failed append को gateway का behavior तुरंत बदलना चाहिए

Append failure को debug log की एक line मानकर फिर से कोशिश न करें। इसे state transition मानें। Temporary interruption में retry उचित हो सकती है, लेकिन unrecorded calls भेजते रहने की अनुमति के रूप में retry का इस्तेमाल नहीं होना चाहिए।

एक संभव failure sequence देखें। Local development tool ने बड़ा cache बना दिया और audit volume reserve से नीचे चला गया। Agent gateway से HTTP deployment action चलाने को कहता है। Gateway intent event लिखता है, request dispatch करता है, successful response पाता है, फिर filesystem out-of-space error लौटाने के कारण completion event append नहीं कर पाता।

इस समय gateway तीन बातें जानता है: उसने action admit किया था, बाहरी system बदल चुका हो सकता है और सामान्य completion record missing है। सही behavior है durable intent event सुरक्षित रखना, यदि कोई safe channel बची हो तो failure marker रिकॉर्ड करना, नए calls रोकना और operator को action identifier तथा storage failure दिखाना। Request को चुपचाप दोबारा न चलाएं। Retry remote side effect को दोहरा सकती है।

अब इससे खराब sequence देखें। Dispatch से पहले intent append ही fail हो जाता है। Gateway को action deny करना होगा। उसके पास यह कहने का durable आधार नहीं है कि action requested, approved या executed था। Build के रुकने पर user को यह परेशान कर सकता है, लेकिन विकल्प ऐसा audit gap है जिसे कोई भरोसे से reconstruct नहीं कर पाएगा।

Synchronization के दौरान सामने आने वाली failures पर भी यही नियम लागू होता है। Apple के fsync manual के अनुसार fsync modified data और attributes को permanent storage की ओर भेजता है, और queued I/O operation के कारण fsync read या write से जुड़े errors के साथ fail हो सकता है। Manual यह भी चेतावनी देता है कि सामान्य flush power loss के दौरान physical media ordering की गारंटी नहीं देता। इसलिए software को अपनी durability boundary तय करनी चाहिए और in-memory append को committed event नहीं मानना चाहिए।

छोटा failure classifier रखें:

```text
append or sync succeeds                 -> action may proceed or complete normally
append fails before dispatch             -> deny the action
append fails after dispatch              -> deny new actions, preserve intent, raise incident
sync reports I/O failure                 -> deny new actions, preserve files, investigate storage health
space check below admission budget       -> deny this new action before dispatch
```

Current write सफल बनाने के लिए पुराने segments delete न करें। इससे capacity incident evidence destruction में बदल जाएगा।

## Writer को durable commit boundary चाहिए

Open file में bytes append कर देने वाला writer audit problem हल नहीं करता। उसे ऐसी boundary चाहिए जो gateway के बाकी हिस्से को बताए कि event durable chain का हिस्सा कब बना।

Boundary छोटी और स्पष्ट रखें। एक workable pattern में append-only segment files, हर event में previous event hash और एक छोटा segment manifest होता है। Exact encoding अलग हो सकती है, लेकिन operations का order नहीं।

```text
1. Serialize the next encrypted event with sequence number N and previous hash H(N-1).
2. Append the complete event frame to the active segment.
3. Sync the segment file and check the result.
4. Update the manifest with the new high-water sequence and segment hash.
5. Sync the manifest and check the result.
6. Only now mark event N as committed to the dispatcher.
```

Manifest जरूरी है क्योंकि recovery को यह उत्तर चाहिए कि «कौन से complete event frames count होते हैं?» Crash या full disk के बाद बचा trailing partial frame केवल इसलिए committed event नहीं है कि उसके कुछ bytes segment तक पहुंच गए। Frame length, authentication data, sequence number और manifest का committed high-water mark recovery को अनुमान लगाने के बजाय ambiguity reject करने देते हैं।

इसे rewrite-in-place JSON file से हल न करें। जब filesystem के पास नई file के लिए जगह हो लेकिन rename के लिए न हो, या crash के बाद पुराने index के साथ नया segment रह जाए, तब यह तरीका मुश्किल पैदा करता है। Append-only segments और छोटा manifest failure behavior को समझना और offline verify करना आसान बनाते हैं।

यहां एक और अंतर महत्वपूर्ण है: encryption event contents की रक्षा करता है, जबकि hash chain ordered continuity की। इनमें से कोई भी property अपने आप यह साबित नहीं करती कि append durable था। Writer को पहले durability स्थापित करनी होगी, फिर verifier यह स्थापित कर सकता है कि retained sequence बदली नहीं गई है।

Sallyport का `sp audit verify` vault key के बिना ciphertext पर offline उसकी encrypted hash chain verify कर सकता है। Storage incident के बाद यह उपयोगी है, क्योंकि operator vault unlock करने या agent work restart करने से पहले preserved evidence जांच सकता है।

## Drill disposable audit volume पर चलाएं

Disk pressure drill को केवल यह नहीं दिखाना चाहिए कि write अंततः error देती है। उसे हर state transition पर behavior साबित करना चाहिए। Disk image या isolated test volume इस्तेमाल करें, केवल nonproduction gateway instance को वहां audit data रखने दें और exercise के बाद उसे हटा दें। अपने सामान्य Mac volume को न भरें। Test disposable environment को असुविधा दे, उस machine को जोखिम में न डाले जिस पर source code और credentials हैं।

macOS पर drill के लिए छोटा APFS disk image बनाकर mount करें:

```sh
hdiutil create -size 2g -fs APFS -volname AuditDrill /tmp/audit-drill.dmg
hdiutil attach /tmp/audit-drill.dmg
df -h /Volumes/AuditDrill
```

यदि उसी नाम का volume पहले से मौजूद हो तो exact mount path अलग हो सकता है। Test configuration बदलने से पहले `df` से इसकी पुष्टि करें। Expected output में mounted filesystem और लगभग 2 GiB capacity दिखनी चाहिए:

```text
Filesystem        Size   Used  Avail Capacity  Mounted on
/dev/diskXsY      2.0G   ...   ...     ...%    /Volumes/AuditDrill
```

Test instance की audit storage को mounted path पर point करें। पहले कुछ known-good actions चलाएं। उनके action identifiers लिखें और chain verifier चलाएं। यह baseline जरूरी है, क्योंकि बाद में failed verification setup की वजह से भी हो सकती है, disk pressure की वजह से ही नहीं।

फिर केवल mounted disk image के भीतर space भरें:

```sh
dd if=/dev/zero of=/Volumes/AuditDrill/fill.bin bs=1048576
```

Volume में और blocks allocate न हो पाने पर `dd` रुक जाएगा। यह command जानबूझकर सीधी है। इस test के लिए sparse-file command न चलाएं, क्योंकि sparse file बड़ी दिखाई दे सकती है लेकिन वह उन blocks को consume नहीं करती जिन्हें इस condition को trigger करना है।

सीधे zero space तक जाने के बजाय drill stages में चलाएं:

1. Warning threshold trigger होने तक भरें। Confirm करें कि नए छोटे actions अभी काम करते हैं और operator alert एक बार आता है।
2. Hard reserve trigger होने तक भरें। Confirm करें कि gateway admission budget के अनुसार नए actions deny करता है।
3. यदि test design अनुमति दे, तो Restricted से ठीक पहले एक controlled action admit करें और देखें कि उसका अंतिम event सफलतापूर्वक रिकॉर्ड होता है या नहीं।
4. Append या sync वास्तव में fail होने तक भरें। Confirm करें कि gateway Denied में जाता है और failure reason दिखाता है।
5. Process रोकें, जरूरत हो तो image को remount करें और filler file delete करने से पहले encrypted chain verify करें।

उद्देश्य ENOSPC error को देखना नहीं है। उद्देश्य यह जानना है कि gateway सही moment पर fail करता है या नहीं, उसके journals बाद में सच बताते हैं या नहीं और operator के पास बिना अनुमान लगाए काम करने के लिए पर्याप्त evidence है या नहीं।

## केवल full volume नहीं, timing windows भी test करें

सतही drill volume भरती है, denial देखती है, space खाली करती है और success घोषित कर देती है। इससे वे timing windows छूट जाती हैं जो audit gaps बनाती हैं।

ऐसा action test करें जिसका external side effect जल्दी पूरा हो लेकिन audit completion record देर से आए। Controlled target कोई test HTTP endpoint हो सकता है जो unique request identifier लौटाए। Intent event के लिए जगह रहते action शुरू करें, फिर gateway के result event commit करने से पहले test volume की बची space भर दें। Expected outcome साफ success या failure status होना जरूरी नहीं है। Gateway को बताना पड़ सकता है कि external action की final state का reconciliation अभी जरूरी है।

यह ईमानदार outcome है। Gateway को durable intent record, यदि मिला हो तो remote request identifier और local storage failure दिखानी चाहिए। उसे subsequent calls deny करनी चाहिए। Operator test target की जांच करके तय कर सकता है कि remote action सफल हुआ या नहीं। Uncertainty को दूसरी request में बदलना नहीं चाहिए।

Audit segment rotate करते समय आने वाली failure भी test करें। Segment rollover metadata consume करता है और इसमें नई file, directory update तथा manifest update शामिल हो सकते हैं। जो design regular append में टिकता है लेकिन rollover के दौरान fail हो जाता है, उसने storage pressure की समस्या हल नहीं की।

Restart behavior भी test करें। Append failure के बाद केवल disposable test instance को force-close करें, फिर volume full रहते उसे शुरू करें। उसे safe denied condition में रहना चाहिए, न कि fresh process होने के कारण storage को healthy मान लेना चाहिए। मापी हुई मात्रा में space खाली करें, फिर दोबारा शुरू करें और confirm करें कि नया segment खोलने से पहले वह last committed sequence verify करता है।

अंत में permission या I/O failure inject करें, यदि test harness ऐसा कर सकता हो। Capacity exhaustion और I/O error durable audit writes रोकने पर एक ही तत्काल admission response मांगते हैं, लेकिन investigation अलग होती है। Space खाली करने से ENOSPC ठीक हो सकता है। इससे failing volume, filesystem error या interrupted storage device ठीक नहीं होता।

## Repair से पहले ciphertext सुरक्षित रखें

Audit write fail होने पर लोग agent को unblock करने के लिए cleanup करने लगते हैं। यही reflex recoverable incident को विवादित incident बना देता है। पहले preserve करें, फिर repair।

Affected audit directory को freeze करें। Segments compact न करें, manifest regenerate न करें, आखिरी file truncate न करें, encryption material rotate न करें और activity view को पूरा दिखाने के लिए action दोबारा न चलाएं। Storage device अस्वस्थ लगे तो read errors report करने वाली method से directory copy करें और copy पर काम करें। Original यह दिखाने वाला एकमात्र evidence हो सकती है कि कौन से records storage तक पहुंचे थे।

Preservation checklist को इन पांच सवालों का उत्तर देना चाहिए:

- पहली write fail होने पर कौन सा audit segment और manifest active था?
- Verifier किस last sequence को स्वीकार करता है?
- किन admitted actions का intent record है लेकिन result record नहीं?
- कौन से external systems इन actions की स्वतंत्र पुष्टि कर सकते हैं?
- Failure के बाद किसी process ने audit directory में बदलाव किया था?

Hash-chain verification result evidence है, repair instruction नहीं। यदि verification sequence 8,412 पर रुकती है, तो उस तथ्य को सुरक्षित रखें। बाद के partial frame को अपने आप truncate न करें, जब तक documented recovery procedure ऐसा न कहती हो और original artifact सुरक्षित न रखा गया हो। Crash के बाद partial encrypted frame expected हो सकता है, लेकिन यह writer bug भी दिखा सकता है। अंतर समझने के लिए original bytes चाहिए।

इसी वजह से source log को user-facing journal से अलग रखना चाहिए। Projection resume होने तक journal incomplete rows दिखा सकती है। यह स्वीकार्य है, यदि वह operator को बताए कि वह catch up कर रही है। Derived views को rebuild या hide करने के लिए source evidence को कभी rewrite न करें। किसी screen को साफ दिखाने के लिए evidence न बदलें।

## Alerts में यह स्पष्ट होना चाहिए कि gateway ने क्या decision लिया

«Disk almost full» action gateway के लिए कमजोर alert है। यह operator को machine condition बताता है, लेकिन नहीं बताता कि agent activity जारी रह सकती है या नहीं, audit evidence जोखिम में है या नहीं और पिछली notification के बाद क्या बदला।

Gateway के Warning, Restricted, Denied और verified recovery में जाने पर alert भेजें। इसमें वे fields शामिल हों जिनसे operator कार्रवाई कर सके:

```text
state: denied
reason: audit append failed with ENOSPC
audit path: /configured/audit/path
free bytes observed: 41,943,040
hard reserve: 536,870,912
last committed sequence: 8412
unresolved admitted actions: 1
new credentialed calls: denied
existing action handling: completion record could not be committed
first failure time: 2026-07-22T14:37:18Z
```

इस alert में secrets, request bodies या credentials न रखें। Alert को ऐसे identifiers चाहिए जो encrypted evidence से जुड़ सकें, न कि sensitive activity data की दूसरी copy जो notification systems में बिखरी हो।

हर low-space sample पर page न करें। Restricted या Denied में प्रवेश पर page करें, फिर condition जारी रहने या state खराब होने पर ही reminder भेजें। Normal से Warning transition पर noisy warning ticket या visible local notification हो सकती है। Denied में transition operational incident है, क्योंकि gateway ने जानबूझकर नए external actions रोक दिए हैं।

Alert में यह भी लिखा होना चाहिए कि gateway पहले से admitted records की रक्षा कर रहा है या नहीं। इससे response बदलता है। यदि in-flight records पूरा करने के लिए जगह है, तो operators space खाली करते समय runs को settle होने दे सकते हैं। यदि dispatch के बाद append fail हो चुका है, तो automation resume करने से पहले unresolved actions की जांच करनी होगी।

## Recovery को writer के फिर स्वस्थ होने का प्रमाण चाहिए

Space खाली करना जरूरी है, लेकिन इससे यह साबित नहीं होता कि audit writer सुरक्षित रूप से Normal में लौट सकता है। Recovery procedure को gateway से यह transition कमाना चाहिए।

पहले incident artifacts सुरक्षित रखें और लिखें कि space कैसे खाली हुई। Unrelated build cache हटाना audit files हटाने से अलग घटना है, और incident record में यह स्पष्ट होना चाहिए कि कौन सा काम हुआ। फिर retained chain को offline verify करें। Verification fail हो तो gateway को Denied में रखें और नए actions की अनुमति देने से पहले evidence की जांच करें।

इसके बाद bounded recovery append चलाएं। Gateway को ऐसा recovery event लिखना चाहिए जो पिछली denied state की पहचान करे, उसे नए या documented recovery segment में append करे, sync करे, manifest update करे और resulting sequence verify करे। उसे failed segment के बीच से चुपचाप resume नहीं करना चाहिए।

यह append सफल होने के बाद ही derived journals को rebuild या catch up करें। Journal work स्वतंत्र रूप से fail हो सकती है। ऐसा होने पर source evidence सुरक्षित रखें और बताएं कि view incomplete है। केवल इसलिए कि activity row अभी दिखाई नहीं दी, यह न कहें कि action हुआ ही नहीं।

फिर recovery threshold लागू करें। यदि Warning 2 GiB, hard reserve 512 MiB और recovery 3 GiB पर configured है, तो केवल इसलिए 600 MiB पर calls फिर न खोलें कि writer ने एक append कर लिया। Higher threshold तुरंत relapse रोकता है और operator को pressure का स्रोत खोजने का समय देता है।

Storage pressure drill तब उपयोगी साबित होती है जब वह एक concrete decision बदलती है: वह exact point जहां gateway नए काम को authorize करना बंद करता है। इस point को लिखें, disposable volume पर test करें और हर failed append को हटाए जाने वाले clutter के बजाय सुरक्षित रखे जाने वाला evidence मानें।
