# SSH तैयारी चेकलिस्ट एजेंट की सुरक्षा कैसे बदलती है

एजेंट के लिए read-only HTTP एक सहज पहला चैनल है। अनुरोध में method, सीमित target, status code, headers और आम तौर पर तय आकार वाली body होती है। असफल GET आमतौर पर सेवा को नहीं बदलता। क्रेडेंशियल गलत तरीके से संभाले जा सकते हैं या संवेदनशील डेटा खुल सकता है, फिर भी execution model समीक्षक को जांचने के लिए एक स्पष्ट आधार देता है।

SSH जोखिम की इकाई बदल देता है। एजेंट किसी तय operation को कॉल नहीं करता। वह रिमोट shell को टेक्स्ट भेजता है, जिसका व्यवहार login account, shell, working directory, environment, operating system, installed tools, quoting rules और मशीन की मौजूदा स्थिति पर निर्भर करता है। कमांड आंशिक रूप से सफल हो सकती है, नतीजा बताने से पहले कनेक्शन टूट सकता है और अगली retry वही काम फिर कर सकती है।

इसका अर्थ यह नहीं कि SSH एजेंट के लिए अनुपयुक्त है। इसका मतलब है कि «HTTP चैनल काम कर गया» SSH जोड़ने का कमजोर प्रमाण है। अनुमति जांच में पांच अलग गुण होने चाहिए: भरोसेमंद result parsing, सत्यापित host identity, दोहराने पर सुरक्षित commands, असर बताने वाली approvals और अज्ञात remote state का स्पष्ट प्रबंधन। इनमें से एक भी न हो तो दूसरा चैनल बंद रखें।

## SSH को अलग execution model मानें

SSH तैयारी की शुरुआत इस बात से होती है कि रिमोट shell, अलग URL वाला HTTP transport नहीं है। HTTP API server के चुने हुए operations देती है। SSH रिमोट account के चुने interpreter को सामने रखता है और आपका client उसमें असंरचित command string पहुंचाता है।

Read-only HTTP call में समीक्षक अक्सर `GET`, host और path से असर समझ सकता है। 404 जैसे response की protocol में तय जगह होती है, भले application उसका अलग अर्थ निकाले। SSH में `test -f /srv/app/release && cat /srv/app/release` file न होने पर 1 दे सकता है, जबकि `cat /srv/app/release` permission न होने पर 1 दे सकता है। अगर parser दोनों को «command failed» बना दे, एजेंट सुरक्षित फैसला नहीं कर सकता।

रिमोट environment भी अर्थ बदल देता है। `sed -i` सामान्य operating systems पर अलग ढंग से चलता है। login shell startup files पढ़ सकती है जो stdout पर banner छापती हैं। `PATH` अपेक्षित binary की जगह wrapper खोज सकता है। locale से इंसानों के लिए बने diagnostics बदल सकते हैं। pseudo-terminal व्यक्ति के लिए बना व्यवहार parser के लिए बनी कमांड में मिला सकता है। सामान्य HTTP request schema में ऐसे variables नहीं होते।

Commands सक्षम करने से पहले channel contract लिखें। उसमें remote user, स्वीकार्य hosts, shell, शुरुआती directory, environment policy, pseudo-terminal निषिद्ध है या नहीं, अधिकतम runtime, output limits और सही result envelope लिखें। संवेदनशील कामों के लिए executable paths pin करें। टेक्स्ट पढ़ना हो तो ज्ञात locale तय करें। रिमोट program का machine output चुनें, लेकिन यह न मानें कि program का JSON option आसपास के shell को structured बना देता है।

पहले gate के रूप में non-interactive probe चलाएं:

```sh
/usr/bin/ssh \
  -o BatchMode=yes \
  -o StrictHostKeyChecking=yes \
  -o ConnectTimeout=10 \
  -T deploy@host.example \
  'umask 077; printf "%s\n" "{\"probe\":\"ssh-ready\",\"version\":1}"'
```

OpenSSH के अनुसार `BatchMode=yes` password और host-key confirmation समेत prompts बंद करता है। `-T` pseudo-terminal allocation बंद करता है। `StrictHostKeyChecking=yes` अज्ञात या बदली हुई keys को अस्वीकार करता है। अपेक्षित stdout एक JSON object है, stderr खाली है और रिमोट exit status zero है। हर विचलन की अलग जांच करें। जो सिस्टम unknown host और malformed JSON में फर्क नहीं कर सकता, वह इस gate से नहीं गुजरा।

## Result envelope को स्पष्ट रखें

Result parsing तभी तैयार है जब transport errors, remote termination, stdout और stderr अलग रहें। इन्हें एक text field में मिलाना खतरनाक झूठा भरोसा देता है।

RFC 4254 stdout को channel data और stderr को extended channel data कहता है। इसमें `exit-status` और `exit-signal` messages भी हैं, लेकिन exit status भेजना सुझाया गया है, अनिवार्य नहीं। OpenSSH इसके ऊपर उपयोगी local convention देता है: उसका `ssh` command रिमोट command का status देता है, या error पर 255।

इस convention को सार्वभौमिक सच न मानें। रिमोट program खुद 255 से exit कर सकता है, जो process boundary पर OpenSSH client error value से टकराता है। server या library exit-status message न भेजे। signal सामान्य nonzero exit जैसा नहीं होता। output आने के बाद भी terminal status पहुंचने से पहले channel बंद हो सकता है।

आपका internal result transcript नहीं, typed record जैसा होना चाहिए:

```json
{
  "phase": "completed",
  "transport": "ok",
  "host": "host.example",
  "host_key_fingerprint": "SHA256:verified-value",
  "exit_status": 0,
  "exit_signal": null,
  "stdout": "{\"state\":\"present\",\"release\":\"2026.07\"}\n",
  "stderr": "",
  "truncated": false,
  "started_at": "request timestamp",
  "finished_at": "result timestamp"
}
```

`exit_status` nullable रखें। `phase` कम से कम rejected, not-started, started, completed और unknown में अंतर करे। truncation को data के रूप में दर्ज करें, output चुपचाप काटकर बचे हिस्से को पूरा न बताएं। सिर्फ requested hostname नहीं, उस connection के लिए इस्तेमाल किया गया verified host fingerprint भी जोड़ें।

फिर outcome matrix जांचें। ऐसा command चलाएं जो खाली output के साथ सफल हो, ऐसा जो दोनों streams में लिखकर 7 से exit हो, signal से मारा जाए, deadline पार करे, bytes की अनुमति होने पर invalid UTF-8 निकाले और हर output limit पार करे। रिमोट command के सोते समय client connection गिराएं, फिर result देखें। adapter को `exit_status: 0` गढ़ना, stdout से success मानना या timeout को «failed» कहना नहीं चाहिए जब वह साबित नहीं कर सकता कि command चली या नहीं।

Shell composition की अलग जांच जरूरी है। POSIX के अनुसार `pipefail` सक्षम न हो तो pipeline सामान्यतः आखिरी command का status देती है। इसलिए `generate | upload` success बता सकती है, क्योंकि `generate` fail होने पर भी `upload` ने खाली input स्वीकार कर लिया। interactive shell defaults पर निर्भर न रहें। कई commands वाले काम स्पष्ट error handling और version वाली reviewed scripts में रखें, फिर एक script entry point चलाएं।

## एजेंट पहुंच से पहले hosts सत्यापित करें

Host verification inventory की समस्या है, कोई ऐसा prompt नहीं जिसका जवाब एजेंट दे। वैध user credential server को client की पहचान साबित करता है। server की host key client को बताती है कि जवाब किस server ने दिया। दोनों चाहिए।

Automation के समाधान के रूप में कभी `StrictHostKeyChecking=no` न लगाएं। OpenSSH documentation कहता है कि यह नई keys अपने आप जोड़ सकता है और कुछ सीमाओं के साथ बदली host key पर connection जारी रहने दे सकता है। `accept-new` बेहतर है क्योंकि वह बदली keys अस्वीकार करता है, लेकिन फिर भी पहली connection पर भरोसा करता है। एजेंट चैनल के लिए run से पहले trust provision करें और `StrictHostKeyChecking=yes` लगाएं।

`ssh-keyscan` public host keys इकट्ठा करने में मदद करता है, मगर उन्हें authenticate नहीं करता। उसका manual भी चेतावनी देता है कि network attacker key बदल सकता है और output को out-of-band verify करने या केवल trusted network पर इस्तेमाल करने को कहता है। live output को सीधे `known_hosts` में डालना verification को पहले जवाब देने वाले के record में बदल देता है।

Fingerprint स्वतंत्र control plane से लें: cloud instance console, image build record, host owner की reviewed configuration repository या administrator का सीधा handoff। hostname, port, allowed host-key algorithms, fingerprints, owner, environment और rotation procedure रखें। aliases और jump hosts भी review करें। अंतिम destination को पूरी तरह pin करने पर भी unpinned jump host trust path तोड़ सकता है।

उपयोगी admission check trust बदले बिना observed और approved keys की तुलना करता है:

```sh
ssh-keyscan -T 5 -t ed25519 host.example > observed.keys
ssh-keygen -lf observed.keys
```

Fingerprint output में bit length, fingerprint, host label और key type होते हैं। कोई व्यक्ति या trusted inventory service इसे स्वतंत्र रूप से दिए मान से मिलाती है। match होने के बाद ही automation known-hosts entry स्थापित करे। scan तुलना का साक्ष्य है, भरोसे का नहीं।

Pin लागू करने से पहले rotation की योजना बनाएं। पहले से trusted key के साथ server authenticate होने के बाद OpenSSH का `UpdateHostKeys` अतिरिक्त keys सीख सकता है, जिससे क्रमिक rotation संभव होती है। इस extension का उपयोग करें या नई known-hosts set बांटें, overlap period और emergency path तय करें। बदली key execution रोके और अलग identity error दे। उसे generic retry, पुरानी entry की automatic deletion या जल्दबाजी में reviewer से unexplained fingerprint स्वीकार कराने वाले approval card तक नहीं पहुंचना चाहिए।

## प्रभाव की सीमा पर idempotency मांगें

Command को तभी retry करना सुरक्षित है जब किसी भी partial execution के बाद उसे दोहराने से प्रभाव दुहराए बिना वही इच्छित state बने। Read-only syntax से यह गुण नहीं आता और zero exit status इसे साबित नहीं करता।

कुछ commands स्वाभाविक रूप से repeatable हैं: तय file पढ़ना, service state जांचना या controlled permissions में `mkdir -p` से directory बनाना। दूसरी commands को guards चाहिए। `echo ... >> file` से line जोड़ना, notification भेजना, generated identifier से user बनाना, local tool से account charge करना और service restart करना सिर्फ shell command छोटी होने से सुरक्षित नहीं होते।

«Transient SSH errors retry करें» वाली सलाह इस स्तर पर गलत है। reconnecting कई network failures ठीक कर देता है और HTTP libraries retries को सामान्य बनाती हैं। लेकिन SSH में रिमोट process बदलाव commit करने के बाद और client को exit status मिलने से पहले connection खो सकता है। automatic retry फिर पूरा हो चुका action दुहराती है।

Repeat safety को remote operation में रखें। हर mutating request को approval से पहले बनी stable operation ID दें। जहां संभव हो, उसी transaction में ID को effect के साथ store करें। operation दोबारा चले तो mutation फिर लगाने के बजाय recorded result लौटाएं। जहां marker और effect एक transaction में नहीं हो सकते, reconciliation query जोड़ें जो बता सके कि कौन-सा हिस्सा पूरा हुआ।

छोटी deployment script contract को स्पष्ट कर सकती है:

```sh
#!/bin/sh
set -eu

op_id=$1
release=$2
state_dir=/var/lib/agent-ops
record="$state_dir/$op_id"

test -d "$state_dir" || exit 70
if test -f "$record"; then
  cat "$record"
  exit 0
fi

current=$(/usr/bin/readlink /srv/app/current || true)
if test "$current" = "/srv/app/releases/$release"; then
  /usr/bin/printf '{"operation":"%s","state":"already-current"}\n' "$op_id"
  exit 0
fi

test -d "/srv/app/releases/$release" || exit 66
/usr/bin/ln -sfn "/srv/app/releases/$release" /srv/app/current.new
/usr/bin/mv -f /srv/app/current.new /srv/app/current
/usr/bin/printf '{"operation":"%s","state":"changed","release":"%s"}\n' \
  "$op_id" "$release" > "$record.tmp"
/usr/bin/mv -f "$record.tmp" "$record"
cat "$record"
```

यह example हर जगह atomic नहीं है। symlink swap और operation record दो filesystem changes हैं, इसलिए इनके बीच crash होने पर gap रहेगा। स्पष्ट `current` check इस खास gap को reconcile करता है। आपके operation को अपने effect से जुड़ा guard चाहिए, इस script से लिया generic marker नहीं।

हर allowed command को read-only, convergent, deduplicated या non-repeatable मानें। Convergent का अर्थ है कि बार-बार चलने पर एक घोषित state की ओर बढ़े, जैसे configuration value set करना। Deduplicated में remote side operation ID पहचानती है। Non-repeatable actions को uncertainty के बाद अलग status query और मानवीय निर्णय चाहिए। owner command को classify न कर सके तो उसे अनुमति न दें।

## Approver को shell text नहीं, प्रभाव दिखाएं

Approval तभी उपयोगी है जब समीक्षक कार्रवाई से पहले target, authority, intended effect और सबसे खराब संभावित नतीजा पहचान सके। Raw shell text जरूरी evidence है, पर अच्छा summary नहीं।

`systemctl restart api` की तुलना उस मंजूरी से करें जो कहती है: production host `api-03`, remote user `deploy`, service `api` restart करें, active connections टूट सकती हैं, operation ID `rel-2026-07-24-04`, command version `restart-service/v2`। दूसरे वर्णन में वे तथ्य हैं जिन्हें reviewer change से मिला सकता है। उसमें missing context भी दिखता है। एजेंट अगर host या service का असर नहीं बता सकता, उसे मंजूरी नहीं मिलनी चाहिए।

Approval payload को exact execution request से बांधें। canonical host और port, verified fingerprint, remote account, command या reviewed script digest, normalized arguments, working directory, environment additions, timeout, requested privilege change, operation ID और action repeatable है या नहीं शामिल करें। उस payload का hash बनाएं और सिर्फ approved hash चलाएं। वरना एजेंट एक command की मंजूरी लेकर dispatch से पहले argument बदल सकता है।

Shell quoting ठीक-ठीक दिखाएं, मगर reviewer से उसे मन में चलाने की उम्मीद न रखें। केवल अपने command forms parse करें। arbitrary shell text scope में बचा हो तो उसे arbitrary label करें और पूरी string बिना काटे दिखाएं। redirections, command substitution, pipes, backgrounding, `sudo`, file deletion, permission changes, package operations, service control और network download flag करें। Flag verdict नहीं है, वह reviewer को बताता है कि परिणाम कहां छिप सकते हैं।

Effects बढ़ने पर approval scope और संकीर्ण होना चाहिए। approved inventory के against fixed read-only probes के लिए session approval उचित हो सकती है। state changes, privileged remote account या target चुनने वाले arguments वाली commands के लिए per-call approval रखें। एक harmless `uname` की मंजूरी उसी SSH key से बाद के deployment को चुपचाप अनुमति न दे।

Sallyport के fixed controls इस विभाजन से मेल खाते हैं: session authorization नया agent process पहचानता है, जबकि per-call key हर use पर approval मांग सकती है। असली design काम request में है: card को remote effect बताना चाहिए, क्योंकि approved channel का होना यह नहीं बताता कि command क्या करेगी।

सिर्फ appearance नहीं, approval integrity जांचें। approved argument का एक byte बदलें और execution रुकना चाहिए। एक operation ID दो requests में उपयोग करके race कराएं। approval और dispatch के बीच session revoke करें। card दिखने के बाद credential store lock करें। हर test recorded denial या फिर से approval मांगने वाली request पर खत्म हो, best-effort continuation पर नहीं।

## Remote unknown state को first-class result मानें

जब client साबित नहीं कर सकता कि remote effect पूरा हुआ या नहीं, `unknown` वैध outcome है। उसे failure कहना retries को बुलाता है। उसे success कहना अधूरा काम छिपाता है।

एक सामान्य क्रम देखें। एजेंट connect होता है, script शुरू करता है और script configuration file बदल देती है। service reload शुरू होता है। उसी समय network path टूटता है। client को न exit status मिलता है, न अंतिम stdout। local timeout call को failed कह देता है। एजेंट retry करता है। दूसरा run नई file देखता है, एक और reload भेजता है और शायद पहले run का diagnostic record मिटा देता है। client ने completion न देखी, फिर भी पहले call ने असली काम किया।

RFC 4254 में यह अस्पष्टता स्वाभाविक है। Protocol command output, exit status, exit signal, EOF और channel close को अलग messages में ले जाता है। exit status लौटाने की सिफारिश है, गारंटी नहीं। साफ channel close भी केवल channel के बारे में बताता है, यह नहीं कि external system ने requested business state पाई या नहीं।

Release से पहले state machine तय करें:

1. `not_started`: dispatch से पहले connection, identity, authentication या approval fail हुई।
2. `started`: remote side ने command स्वीकार की, पर terminal result नहीं है।
3. `completed`: terminal status और पूरा bounded output मिल गया।
4. `unknown`: dispatch हुआ हो सकता है, पर client ने completion का प्रमाण खो दिया।
5. `reconciled`: बाद की independent query ने परिणामी state स्थापित कर दी।

आम तौर पर केवल `not_started` automatic retry के लिए सुरक्षित है, और वह label भी भरोसेमंद boundary से आना चाहिए। command वाले bytes server तक पहुंचे हो सकते हैं तो `unknown` रखें। Deadline रिमोट process को cancel नहीं करती, जब तक confirmed cancellation protocol न हो। Client socket बंद करना ऐसा protocol नहीं है।

हर mutating command के लिए approval से पहले reconciliation plan तय करें। वह operation record query कर सकता है, deployed release identifier मिला सकता है, service manager की state पढ़ सकता है या downstream system से stable operation ID पूछ सकता है। जहां संभव हो reconciliation read-only credential से चलाएं। original request, partial output, timestamps, host fingerprint और operation ID बचाकर रखें, ताकि follow-up सही प्रश्न का जवाब दे।

Unknown-state budget तय करें। system कितनी देर रुकेगा, alert किसे मिलेगा, unresolved operation के पीछे कौन-से actions रुकेंगे और कब मानव नियंत्रण लेगा, यह लिखें। एक ही resource पर दो uncertain operations को race न करने दें। resource के आधार पर serialize करें या owner और expiry policy वाला remote lock इस्तेमाल करें जो client disconnect पर भी बना रहे।

## Commands बढ़ाने से पहले remote account सीमित करें

SSH तैयारी client intent से ज्यादा remote authority पर निर्भर है। ऐसा login account जो host को फिर लिख सकता है, उसे perfect approval screen भी सुरक्षित नहीं बना सकती।

Agent channel के लिए dedicated account बनाएं। admitted operations के लिए जितनी filesystem access और service permissions जरूरी हों, उतनी ही दें। general administrator account से बचें। elevation जरूरी हो तो fixed paths और controlled arguments वाले named commands ही दें। unrestricted `sudo`, allowed programs में shell escapes, writable script directories और writable executables को व्यापक access के बराबर रास्ते मानें।

OpenSSH की `authorized_keys` restrictions credential के exposure को घटा सकती हैं। आपके design के अनुसार forced command हर connection को dispatcher तक भेज सकता है और options pseudo-terminals, agent forwarding, X11 forwarding और port forwarding बंद कर सकते हैं। Server configuration forwarding सीमित कर सकता है। Server का वास्तविक manual देखें और effective configuration जांचें, क्योंकि एक permissive include या match block आपकी धारणा पलट सकता है।

Dispatcher को छोटा operation name और data लेना चाहिए, दोनों validate करने चाहिए और arbitrary shell text फिर बनाए बिना absolute path से executable चलाना चाहिए। उदाहरण के लिए `read-release` कोई arguments न ले, जबकि `activate-release` केवल strict format वाला release identifier माने। SSH channel carrier बना रहता है, पर remote surface defined API जैसा होने लगता है।

Developer का authentication agent autonomous session में forward न करें। Agent forwarding रिमोट side को connection रहने तक forwarded socket के जरिए signatures मांगने देता है। Compromised remote host private key न निकाल पाए, फिर भी signing capability इस्तेमाल कर सकता है। Channel को dedicated credential दें, जिसकी server-side authorization पहले से सीमित हो।

हर executable और configuration file तक filesystem ownership जांचें। Restricted account parent directory बदल सकता है, dispatcher replace कर सकता है, sourced startup file प्रभावित कर सकता है या `PATH` के जरिए binary आगे लगा सकता है तो allowlist सिर्फ दिखावा है। Interpreters भी जांचें। Broad interpreter चलाने की permission का अर्थ अक्सर account जितना कुछ भी करने की permission है।

पहला command set साधारण रखें: fixed inventory reads, bounded output वाली health queries और tested reconciliation path वाला एक convergent mutation। Port forwarding, interactive shells, arbitrary uploads, package management और free-form root commands बाद की reviews के विषय हैं, अगर कभी हों।

## Truncation और disconnects में observability साबित करें

Audit evidence तभी तैयार है जब agent के अपने summary पर निर्भर हुए बिना authorization, dispatch, remote identity और observed result फिर बनाए जा सकें। Logs को uncertainty छिपानी नहीं चाहिए।

Stable request ID और operation ID, agent process या session identity, approval decision, approver method, approved payload hash, canonical target, host-key fingerprint, remote account, start time, dispatch time, terminal time, exit status या signal, हर stream की byte counts, truncation flags और final state classification रिकॉर्ड करें। stdout और stderr अलग रखें। Policy full output रखने से रोके तो अनुमत हिस्सा, digest और साफ retention metadata रखें।

Output limits में दो व्यवहार चाहिए: local collection रोकना और तय करना कि remotely क्या होगा। एक megabyte के बाद channel बंद करने से process चलता रह सकता है। Remote wrapper output cap कर सकता है, उसे controlled file में भेज सकता है और digest दे सकता है, मगर wrapper को disk quotas और cleanup भी चाहिए। ऐसा command जांचें जो stdout कभी बंद न करे, ऐसा child जो parent के बाद भी जिंदा रहे और ऐसा process जो हमेशा stderr लिखे।

Logs को वे चीजें भी दिखानी चाहिए जो नहीं हुईं। Host-key mismatch, locked vault, rejected approval, expired session, malformed request या disallowed command return से पहले denial record बनाए। नहीं तो operators को gap दिखेगा और वे quiet system तथा bypass में फर्क नहीं कर पाएंगे।

Sallyport एक encrypted, hash-chained audit log में agent runs और individual calls रिकॉर्ड करता है, और `sp audit verify` key के बिना ciphertext पर offline chain जांचता है। इससे channel को tamper-evident local evidence मिलता है, फिर भी remote operation IDs और reconciliation results request तथा result में होने चाहिए ताकि operator call को machine state से जोड़ सके।

वही evidence इकट्ठा करते हुए failure injection चलाएं जो incident reviewer को मिलेगा। dispatch से पहले, तुरंत बाद, stdout के बीच में और remote process exit होने के बाद local completion से पहले client kill करें। Inventory update किए बिना host key rotate करें। Marker write से पहले remote filesystem भर दें। malformed structured output के साथ successful exit लौटाएं। हर case में पूछें: क्या reviewer बता सकता है कि कौन-सा authority इस्तेमाल हुआ, क्या बदल सकता है और अगला काम क्या होना चाहिए?

## Gates पास होने पर ही SSH को अनुमति दें

दूसरा channel तब तैयार है जब team उसका failure behavior दिखा सके, केवल तब नहीं जब happy-path command test host तक पहुंच जाए। Owners और सुरक्षित evidence वाला written gate रखें।

Admission record में यह होना चाहिए:

1. Shell, account, directory, environment, timeouts, output caps और result schema वाला channel contract।
2. Independent fingerprint source, jump-host coverage और tested rotation process वाली verified host inventory।
3. ऐसा command catalog जो repeat behavior classify करे और हर mutation की reconciliation query बताए।
4. Exact host, account, command version, arguments, privilege, timeout और operation ID से बंधी approval specification।
5. Failure-injection results जो unknown states, denials, truncation, revocation और audit reconstruction साबित करें।

पहले read-only probes पास करें। फिर disposable environment में एक convergent write अनुमति दें। हर boundary पर उसे disconnect करें और result reconcile करें। फिर harmless resource वाले production-जैसे host पर दोहराएं। Evidence को उस व्यक्ति के साथ review करें जो उस host का owner है, केवल agent gateway बनाने वाली team के साथ नहीं।

Rollback को retry से अलग रखें। Rollback अपनी approval, operation ID, preconditions और possible unknown state वाला नया explicit mutation है। Timeout के बाद inverse command अपने आप चलाने से ऐसा बदलाव नुकसान पा सकता है जो वास्तव में सही तरह पूरा हुआ था। System को state फिर बदलने से पहले मौजूदा state स्थापित करनी होगी।

Admission criteria के साथ removal criteria भी तय करें। अगर script digest बिना review बदले, host inventory छोड़ दे, reconciliation काम करना बंद कर दे, output unbounded हो जाए या operators unknown result न समझा सकें तो operation बंद करें। Channel access स्थायी graduation badge नहीं है।

SSH को एक बार में एक operation के लिए अनुमति मिलती है। अगर आप server pin नहीं कर सकते, effect नहीं बता सकते, उसे सुरक्षित रूप से दोहरा नहीं सकते, हर result state में फर्क नहीं कर सकते और बाद में call का पुनर्निर्माण नहीं कर सकते, तो सही checklist result «तैयार नहीं» है। Read-only HTTP channel रखें और missing boundary ठीक करें, इससे पहले कि रिमोट shell अस्पष्ट retry को production के दूसरे बदलाव में बदल दे।
