एक मरीज़ "Disconnect My Data" लेबल वाले बटन पर क्लिक करता है। वेब ऐप एक हरा टिक (checkmark) और एक उत्साहजनक पुष्टि दिखाता है। बैकग्राउंड क्यू (queue) में कहीं, एक वर्कर प्रोसेस अपनी रात की सिंक (sync) के लिए जागता है, कल बनाया गया एक जॉब निकालता है, और दो साल का मेडिकेशन हिस्ट्री (medication history) डाउनस्ट्रीम एनालिटिक्स क्लस्टर (analytics cluster) को स्ट्रीम करना शुरू कर देता है। उपयोगकर्ता ने इंटरफ़ेस पर भरोसा किया था। सिस्टम ने उस भरोसे को तोड़ दिया।
यह विशिष्ट विफलता मोड (failure mode) हेल्थ डेटा आर्किटेक्चर के लिए एक बड़ी चुनौती है क्योंकि इसमें जोखिम बहुत अधिक हैं। एक पुराना (stale) परमिशन कोई मामूली बग नहीं है; यह एक सक्रिय उल्लंघन (active breach) है। इसका समाधान हर एक डेटा अनुरोध को एक 'कंसेंट रिसीप्ट' (consent receipt) से जोड़ना है: एक छोटा, स्ट्रक्चर्ड रिकॉर्ड जो UI से लेकर आपके पॉलिसी इंजन, आपके डेटाबेस ट्रांजेक्शन और हर बैकग्राउंड वर्कर तक उपयोगकर्ता के इरादे (intent) को ले जाता है। यह कभी भी क्लिनिकल वैल्यूज़ (clinical values) को स्टोर नहीं करता है। यह केवल उन तक पहुँचने के अधिकार को स्टोर करता है, जिसे एक ऐसे वर्शन (version) के साथ स्टैम्प किया जाता है जो पर्दे के पीछे चुपचाप बदल न सके।
रिसीप्ट वास्तव में क्या ले जाती है
रिसीप्ट को एक सेशन फ्लैग (session flag) के बजाय एक स्कोप किए गए कॉन्ट्रैक्ट (scoped contract) के रूप में सोचें। इसमें एक ग्रांट आइडेंटिफायर (grant identifier), डेटा सब्जेक्ट (data subject), एक्सेस का सटीक स्कोप (लैब परिणाम, वाइटल्स, मेडिकेशन हिस्ट्री), एक समय-बद्ध वैधता विंडो (time-bound validity window), और एक वर्शन नंबर होता है। जब कोई फ्रंटएंड किसी उपयोगकर्ता की ओर से एक्सेस का अनुरोध करता है, तो API यह रिसीप्ट जारी करता है। फ्रंटएंड इसे अपने पास रखता है। हर डाउनस्ट्रीम सर्विस जो हेल्थ डेटा पढ़ना चाहती है, उसे रिकॉर्ड खोलने से पहले एक सेंट्रल पॉलिसी लेयर (central policy layer) के सामने रिसीप्ट पेश करनी होगी और स्पष्ट अनुमति प्राप्त करनी होगी।
यह महत्वपूर्ण है क्योंकि हेल्थ सिस्टम अक्सर उपयोगकर्ता अकाउंट टोकन (user account token) को सहमति (consent) समझ लेते हैं। एक टोकन बताता है कि आप कौन हैं। एक रिसीप्ट बताती है कि आपको अभी क्या करने की अनुमति है। यदि दोनों में अंतर आता है, तो हमेशा रिसीप्ट की ही जीत होनी चाहिए।
हर चीज़ को वर्शन करें
अपने कंसेंट स्टोर को एक 'अपेन्ड-ओनली लॉग' (append-only log) के रूप में बनाएं। जब कोई उपयोगकर्ता पहली बार अपने टीकाकरण रिकॉर्ड (immunization records) तक पहुँच प्रदान करता है, तो वह वर्शन एक होता है। यदि वे बाद में विशिष्ट प्रदाताओं (providers) को बाहर करने के लिए स्कोप को सीमित करते हैं, या यदि वे इसे पूरी तरह से रद्द कर देते हैं, तो पहली प्रविष्टि (entry) को ओवरराइट न करें। वर्शन दो लिखें। वर्कर के हाथ में मौजूद रिसीप्ट अभी भी वर्शन एक ही दिखाएगी, और पॉलिसी इंजन ठीक से देख पाएगा कि वर्शन एक ने क्या अनुमति दी थी और उसे एक विशिष्ट टाइमस्टैम्प पर बदल दिया गया था।
यह अपरिवर्तनीयता (immutability) आपके ऑडिट की रीढ़ है। छह महीने बाद, जब कोई अनुपालन अधिकारी (compliance officer) पूछे कि किसी विशेष ETL जॉब को गुरुवार दोपहर को क्यों चलाया गया था, तो आप उस सटीक ग्रांट वर्शन का पता लगा सकते हैं जिसे जॉब में इस्तेमाल किया गया था और साबित कर सकते हैं कि जॉब शुरू होने के समय वह वैध था। यदि आप उपयोगकर्ता प्रोफ़ाइल में सहमति को केवल एक सिंगल बुलियन फ्लैग (boolean flag) के रूप में स्टोर करते हैं, तो आप उस इतिहास को मिटा देते हैं। आप इस अंतर को पहचानने की क्षमता खो देते हैं कि "इसकी कभी अनुमति नहीं थी" और "जब जॉब शुरू हुआ तब इसकी अनुमति थी लेकिन दो घंटे बाद उपयोगकर्ता ने अपना मन बदल लिया।"
ईमानदारी के लिए एंडपॉइंट्स डिज़ाइन करें
एक कंसेंट API को स्पष्ट और विशिष्ट रूट्स (routes) एक्सपोज़ करने चाहिए। POST /grants को एक नई अनुमति बनाने दें। GET /grants/{id} को किसी विशिष्ट रिसीप्ट की वर्तमान स्थिति वापस करने दें। POST /grants/{id}/revoke को रद्दीकरण (revocation) शुरू करने दें। यह दिखावा न करें कि 'रिवोक' (revoke) दबाते ही आपके पाइपलाइनों में तैरते हेल्थ डेटा की हर कॉपी तुरंत मिट जाती है। इसके बजाय, 202 Accepted स्टेटस के साथ एक रद्दीकरण ऑपरेशन आईडी (revocation operation ID) वापस करें। यह उपयोगकर्ता को बताता है कि अनुरोध वास्तविक है, यह शुरू हो रहा है, और वे इसे ट्रैक कर सकते हैं।
वह ऑपरेशन आईडी तब महत्वपूर्ण हो जाती है जब उपयोगकर्ता इंटरफ़ेस धीमा महसूस होने के कारण दो बार क्लिक करता है। यदि वे दूसरा रद्दीकरण अनुरोध सबमिट करते हैं, तो मूल ऑपरेशन आईडी ही वापस करें। यहाँ आइडम्पोटेंसी (idempotency) कोई 'अच्छा-तो-है' (nice-to-have) फीचर नहीं है; यह डुप्लिकेट घबराहट को रोकता है और उपयोगकर्ता को उनके अनुरोध की स्थिति के लिए सत्य का एक एकल स्रोत (single source of truth) प्रदान करता है।
अंतिम संभव क्षण पर अनुमति मांगें
एक सामान्य गलती यह है कि सहमति की जाँच API गेटवे पर की जाती है और फिर वर्कर के भीतर गहराई में स्थित एक कैश किए गए फ्लैग (cached flag) पर भरोसा कर लिया जाता है। ऐसा न करें। वर्कर को जॉब लाइफसाइकिल (job lifecycle) के दौरान अपनी रिसीप्ट साथ रखनी चाहिए। हेल्थ रिकॉर्ड स्टोर के विरुद्ध क्वेरी चलाने से ठीक पहले, उसे पॉलिसी लेयर से पूछना चाहिए: "क्या इस विशिष्ट ग्रांट का वर्शन तीन अभी भी इस सटीक स्कोप के लिए वैध है?" यदि उत्तर 'नहीं' है, तो वर्कर रुक जाता है। वह जॉब को विफल कर देता है। वह उसे दोबारा प्रयास (retry) नहीं करता है।
यहाँ 'रिट्राय लॉजिक' (retry logic) ज़हर के समान है। वर्शन मिसमैच (version mismatch) कोई नेटवर्क की समस्या नहीं है। यह एक मानवीय निर्णय है। उपयोगकर्ता ने अनुमति वापस ले ली, या ग्रांट समाप्त हो गया, या स्कोप कम हो गया। यदि आप तीन बार प्रयास करते हैं और रेस कंडीशन (race condition) के कारण चौथी बार सफल हो जाते हैं, तो आपने अभी-अभी सहमति का उल्लंघन किया है। मिसमैच को एक हार्ड फेलियर (hard failure) के रूप में मानें, इसे अपने डेड-लेटर क्यू (dead-letter queue) या ऑपरेशंस डैशबोर्ड पर भेजें, और किसी इंसान को इसकी जांच करने दें।
जटिल स्थितियों को संभालें
वास्तविक सिस्टम व्यवस्थित चरणों में काम नहीं करते हैं। उपयोगकर्ता पुराने ब्राउज़र टैब खुले छोड़ देते हैं। बल्क इम्पोर्ट (Bulk imports) बीस मिनट तक चलते हैं। सिंक (sync) आधा होने के दौरान स्कोप (scopes) बदल जाते हैं। आपके कंसेंट API को इन क्षणों के लिए स्पष्ट नियमों की आवश्यकता होती है।
पुराने ब्राउज़र टैब (Stale browser tabs)। एक उपयोगकर्ता नए खुले टैब में एक्सेस वापस ले लेता है। एक पुराना टैब, जिसमें पिछले पेज लोड से अभी भी एक ग्रांट ऑब्जेक्ट (grant object) मौजूद है, फिर से कनेक्ट करने की कोशिश करता है। आपके बैकएंड को उस पुरानी रसीद (stale receipt) को तुरंत अस्वीकार करना चाहिए और नए सिरे से कंसेंट रिव्यू (consent review) के लिए मजबूर करना चाहिए। एक रद्द किया गया ग्रांट (revoked grant) एक रद्द किए गए पासपोर्ट की तरह व्यवहार करना चाहिए: यह इसलिए पुनर्जीवित नहीं होता क्योंकि धारक को दराज में एक पुरानी प्रति मिल गई है।
इन-फ़्लाइट इम्पोर्ट (In-flight imports)। यदि कोई बल्क इम्पोर्ट चल रहा है और उपयोगकर्ता एक्सेस वापस ले लेता है, तो आपको एक साथ दो चीजें करने की आवश्यकता है। पहला, जैसे ही वर्ज़न (version) को अस्वीकार किया जाए, नए राइट्स (writes) की अनुमति देना तुरंत बंद कर दें। दूसरा, ऑपरेशन आईडी (operation ID) के माध्यम से उपयोगकर्ता को वास्तविक क्लीनअप प्रोग्रेस (cleanup progress) दिखाएं। उन्हें एक सच्चा स्टेटस पेज दें: “रद्दीकरण स्वीकार कर लिया गया है। अठारह लंबित राइट्स (pending writes) को हटाया जा रहा है।” वर्कर्स (workers) को उस ग्रांट वर्ज़न का उपयोग करके डेटा कमिट (commit) न करने दें जिसे पहले ही अमान्य (invalid) घोषित किया जा चुका है।
स्कोप परिवर्तन (Scope changes)। मान लीजिए कि किसी उपयोगकर्ता ने मूल रूप से पांच साल के इतिहास तक पहुंच प्रदान की थी और बाद में इसे छह महीने में समायोजित कर दिया। मूल ग्रांट में बदलाव न करें। वर्ज़न एक को बंद करें, संकीर्ण विंडो (narrower window) के साथ वर्ज़न दो जारी करें, और किसी भी चल रही प्रक्रिया को नई सीमा (boundary) के अनुसार तालमेल बिठाने के लिए मजबूर करें। पुराना वर्ज़न आपके लॉग में एक ऐतिहासिक तथ्य के रूप में बना रहता है, न कि एक सक्रिय अनुमति के रूप में।
सख्त सुरक्षा नियम (Hard Security Rules)
रसीदें (Receipts) स्वयं संवेदनशील होती हैं, लेकिन वे क्लिनिकल डेटा (clinical data) नहीं हैं। उन्हें अपने आर्किटेक्चर में अलग रखें। केवल रोगी या विशेष रूप से सौंपे गए रोल—जैसे कि कानूनी अभिभावक या अधिकृत देखभाल करने वाला—ही रसीद देख या रद्द कर पाने में सक्षम होना चाहिए। इसे केवल UI रूटिंग टेबल में ही नहीं, बल्कि डेटा लेयर (data layer) पर लागू करें।
जब जॉब्स (jobs) विफल होते हैं, तो आपके एरर लॉग्स (error logs) स्वास्थ्य डेटा को खींचने की कोशिश करेंगे। इस प्रवृत्ति का आक्रामक रूप से मुकाबला करें। जब कोई वर्कर (worker) इसलिए विफल हो जाता है क्योंकि उसने एक अमान्य कंसेंट रसीद पेश की थी, तो ग्रांट आईडी (grant ID), वर्ज़न और एरर को लॉग करें। रोगी की पहचानकर्ता (patient identifier), निदान कोड (diagnosis code), या लैब वैल्यू (lab value) को कभी भी लॉग न करें जिसे वर्कर प्राप्त करने का प्रयास कर रहा था। लॉग्स में स्वास्थ्य डेटा फफूंद की तरह फैलता है: यह बैकअप, इंडेक्स और इस तरह से भुला दिया जाता है जो आपके सामान्य एक्सेस कंट्रोल (access controls) को दरकिनार कर देता है।
अंत में, सिस्टम रिकवरी के दौरान कभी भी पुराने सक्रिय ग्रांट को बहाल न करें। यदि आप डेटाबेस को रोलबैक (roll back) करते हैं या स्नैपशॉट (snapshot) को रिस्टोर करते हैं जिसमें ग्रांट टेबल का रद्दीकरण-पूर्व वर्ज़न शामिल है, तो आपके रनबुक (runbook) को सेवा द्वारा नया ट्रैफिक स्वीकार करने से पहले उन पुनर्जीवित अनुमतियों को स्वचालित रूप से अक्षम कर देना चाहिए। ऐतिहासिक कंसेंट स्टेट्स (Historical consent states) ऑडिट लॉग (audit log) में होने चाहिए, सक्रिय नियम सेट (active rule set) में कभी नहीं।
