ഒരു രോഗി “Disconnect My Data” എന്ന് എഴുതിയ ബട്ടണിൽ ക്ലിക്ക് ചെയ്യുന്നു. വെബ് ആപ്പ് ഒരു പച്ച ടിക്ക് മാർക്കും സന്തോഷകരമായ ഒരു സ്ഥിരീകരണവും കാണിക്കുന്നു. എന്നാൽ ബാക്ക്ഗ്രൗണ്ടിലെ ഒരു ക്യൂവിൽ, രാത്രികാല സിങ്കിനായി ഒരു വർക്കർ പ്രോസസ്സ് ഉണരുന്നു, ഇന്നലെ സൃഷ്ടിച്ച ഒരു ജോബ് എടുക്കുന്നു, കൂടാതെ രണ്ട് വർഷത്തെ മരുന്ന് ഉപയോഗിച്ചതിന്റെ ചരിത്രം ഒരു ഡൗൺസ്ട്രീം അനലിറ്റിക്സ് ക്ലസ്റ്ററിലേക്ക് സ്ട്രീം ചെയ്യാൻ തുടങ്ങുന്നു. ഉപയോക്താവ് ആ ഇന്റർഫേസിനെ വിശ്വസിച്ചു. എന്നാൽ സിസ്റ്റം ആ വിശ്വാസത്തെ വഞ്ചിച്ചു.
ആരോഗ്യ ഡാറ്റാ ആർക്കിടെക്ചറുകളിൽ ഈ പ്രത്യേക പരാജയ രീതി വലിയ ആശങ്കയുണ്ടാക്കുന്നു, കാരണം ഇതിന്റെ പ്രത്യാഘാതങ്ങൾ വളരെ വലുതാണ്. കാലഹരണപ്പെട്ട ഒരു അനുമതി (stale permission) എന്നത് ചെറിയൊരു ബഗ്ഗല്ല; അതൊരു സജീവമായ ലംഘനമാണ് (active breach). ഇതിനുള്ള പരിഹാരം ഓരോ ഡാറ്റാ അഭ്യർത്ഥനയെയും ഒരു കൺസെന്റ് റെസീപ്റ്റുമായി (consent receipt) ബന്ധിപ്പിക്കുക എന്നതാണ്: ഇത് ഉപയോക്താവിന്റെ ഉദ്ദേശ്യം UI-ൽ നിന്ന് നിങ്ങളുടെ പോളിസി എഞ്ചിൻ, ഡാറ്റാബേസ് ഇടപാടുകൾ, ഓരോ ബാക്ക്ഗ്രൗണ്ട് വർക്കർ എന്നിവയിലേക്ക് എത്തിക്കുന്ന ഒരു ചെറിയ, ഘടനാപരമായ റെക്കോർഡാണ്. ഇത് ഒരിക്കലും ക്ലിനിക്കൽ മൂല്യങ്ങൾ സംഭരിക്കാറില്ല. പകരം, അവ ആക്സസ് ചെയ്യാനുള്ള അവകാശം മാത്രമാണ് ഇത് സൂക്ഷിക്കുന്നത്, കൂടാതെ ഇതിന് പിന്നിൽ രഹസ്യമായി മാറ്റം വരുത്താൻ കഴിയാത്ത ഒരു വേർഷനും ഇതിനുണ്ടാകും.
റെസീപ്റ്റിൽ യഥാർത്ഥത്തിൽ എന്താണുള്ളത്
റെസീപ്റ്റിനെ ഒരു സെഷൻ ഫ്ലാഗായിട്ടല്ല, മറിച്ച് ഒരു സ്കോപ്പ് ചെയ്ത കരാറായി (scoped contract) കാണുക. ഇതിൽ ഒരു ഗ്രാന്റ് ഐഡന്റിഫയർ (grant identifier), ഡാറ്റാ സബ്ജക്ട് (data subject), ആക്സസിന്റെ കൃത്യമായ സ്കോപ്പ് (ലാബ് ഫലങ്ങൾ, വൈറ്റൽസ്, മരുന്ന് ഉപയോഗിച്ചതിന്റെ ചരിത്രം), സമയപരിധിയുള്ള സാധുത (time-bound validity window), ഒരു വേർഷൻ നമ്പർ എന്നിവ അടങ്ങിയിരിക്കുന്നു. ഒരു ഫ്രണ്ട്എൻഡ് ഉപയോക്താവിന് വേണ്ടി ആക്സസ് അഭ്യർത്ഥിക്കുമ്പോൾ, API ഈ റെസീപ്റ്റ് നൽകുന്നു. ഫ്രണ്ട്എൻഡ് ഇത് കൈവശം വെക്കുന്നു. ആരോഗ്യ ഡാറ്റ വായിക്കാൻ ആഗ്രഹിക്കുന്ന ഓരോ ഡൗൺസ്ട്രീം സർവീസും ഒരു സെൻട്രൽ പോളിസി ലെയറിന് മുന്നിൽ ഈ റെസീപ്റ്റ് ഹാജരാക്കുകയും റെക്കോർഡ് തുറക്കുന്നതിന് മുമ്പ് വ്യക്തമായ അനുമതി സ്വീകരിക്കുകയും വേണം.
ഇത് പ്രധാനമാണ്, കാരണം ആരോഗ്യ സംവിധാനങ്ങൾ പലപ്പോഴും ഒരു യൂസർ അക്കൗണ്ട് ടോക്കണിനെ (user account token) സമ്മതമായി (consent) തെറ്റിദ്ധരിക്കാറുണ്ട്. ഒരു ടോക്കൺ നിങ്ങൾ ആരാണെന്ന് പറയുന്നു. എന്നാൽ ഒരു റെസീപ്റ്റ് നിങ്ങൾക്ക് ഇപ്പോൾ എന്തൊക്കെ ചെയ്യാൻ അനുവാദമുണ്ടെന്ന് പറയുന്നു. ഇവ രണ്ടും തമ്മിൽ വ്യത്യാസം വന്നാൽ, റെസീപ്റ്റ് എപ്പോഴും വിജയിക്കണം.
എല്ലാം വേർഷൻ ചെയ്യുക
നിങ്ങളുടെ കൺസെന്റ് സ്റ്റോർ ഒരു അപ്പെൻഡ്-ഒൺലി ലോഗ് (append-only log) ആയി നിർമ്മിക്കുക. ഒരു ഉപയോക്താവ് ആദ്യമായി അവരുടെ പ്രതിരോധ കുത്തിവെപ്പ് രേഖകൾക്ക് (immunization records) അനുമതി നൽകുമ്പോൾ, അത് വേർഷൻ ഒന്ന് ആണ്. പിന്നീട് അവർ ചില പ്രത്യേക സേവനങ്ങളെ ഒഴിവാക്കിക്കൊണ്ട് സ്കോപ്പ് കുറയ്ക്കുകയോ അല്ലെങ്കിൽ പൂർണ്ണമായും റദ്ദാക്കുകയോ ചെയ്താൽ, ആദ്യത്തെ എൻട്രി ഓവർറൈറ്റ് ചെയ്യരുത്. പകരം വേർഷൻ രണ്ട് എഴുതുക. വർക്കറുടെ കയ്യിലുള്ള റെസീപ്റ്റ് ഇപ്പോഴും വേർഷൻ ഒന്ന് എന്ന് കാണിക്കുന്നുണ്ടാകും, വേർഷൻ ഒന്ന് എന്തൊക്കെ അനുവദിച്ചിരുന്നുവെന്നും അത് ഒരു പ്രത്യേക സമയത്ത് മാറ്റപ്പെട്ടുവെന്നും പോളിസി എഞ്ചിന് കൃത്യമായി കാണാൻ കഴിയും.
ഈ മാറ്റമില്ലായ്മ (immutability) നിങ്ങളുടെ ഓഡിറ്റിംഗ് നട്ടെല്ലാണ്. ആറ് മാസത്തിന് ശേഷം, ഒരു കംപ്ലയൻസ് ഓഫീസർ ഒരു പ്രത്യേക ETL ജോബ് എന്തുകൊണ്ടാണ് വ്യാഴാഴ്ച ഉച്ചകഴിഞ്ഞ് പ്രവർത്തിച്ചതെന്ന് ചോദിച്ചാൽ, ആ ജോബ് ഉപയോഗിച്ച കൃത്യമായ ഗ്രാന്റ് വേർഷൻ നിങ്ങൾക്ക് കണ്ടെത്താനും ജോബ് ആരംഭിച്ച സമയത്ത് അത് സാധുവായിരുന്നുവെന്ന് തെളിയിക്കാനും കഴിയും. ഉപയോക്താവിന്റെ പ്രൊഫൈലിൽ കൺസെന്റ് ഒരു സിംഗിൾ ബൂളിയൻ ഫ്ലാഗ് (boolean flag) ആയി സൂക്ഷിക്കുകയാണെങ്കിൽ, നിങ്ങൾ ആ ചരിത്രം ഇല്ലാതാക്കുന്നു. 'ഇതിന് ഒരിക്കലും അനുമതി നൽകിയിരുന്നില്ല' എന്നും 'ജോബ് ആരംഭിച്ച സമയത്ത് അനുമതി ഉണ്ടായിരുന്നുവെങ്കിലും രണ്ട് മണിക്കൂർ കഴിഞ്ഞ് ഉപയോക്താവ് മനസ്സ് മാറ്റി' എന്നും തമ്മിലുള്ള വ്യത്യാസം തിരിച്ചറിയാനുള്ള കഴിവ് നിങ്ങൾക്ക് നഷ്ടപ്പെടുന്നു.
സത്യസന്ധതയ്ക്കായി എൻഡ്പോയിന്റുകൾ രൂപകൽപ്പന ചെയ്യുക
ഒരു കൺസെന്റ് API വ്യക്തവും കൃത്യവുമായ റൂട്ടുകൾ പ്രദാനം ചെയ്യണം. POST /grants ഉപയോഗിച്ച് പുതിയ അനുമതി സൃഷ്ടിക്കാം. GET /grants/{id} ഉപയോഗിച്ച് ഒരു പ്രത്യേക റെസീപ്റ്റിന്റെ നിലവിലെ അവസ്ഥ അറിയാം. POST /grants/{id}/revoke ഉപയോഗിച്ച് ഒരു റദ്ദാക്കൽ നടപടി ആരംഭിക്കാം. റദ്ദാക്കൽ (revoke) ബട്ടൺ അമർത്തിയ ഉടൻ നിങ്ങളുടെ പൈപ്പ്ലൈനുകളിൽ ഒഴുകിനടക്കുന്ന ആരോഗ്യ ഡാറ്റയുടെ എല്ലാ കോപ്പികളും ഇല്ലാതാകുന്നു എന്ന് കരുതരുത്. പകരം, ഒരു 202 Accepted സ്റ്റാറ്റസോടെ ഒരു റിക്കോവേഷൻ ഓപ്പറേഷൻ ഐഡി (revocation operation ID) നൽകുക. ഇത് അഭ്യർത്ഥന യഥാർത്ഥമാണെന്നും അത് ആരംഭിച്ചുവെന്നും അവ ട്രാക്ക് ചെയ്യാമെന്നും ഉപയോക്താവിനെ അറിയിക്കുന്നു.
ഇന്റർഫേസ് സാവധാനത്തിലാണെന്ന് തോന്നി ഉപയോക്താവ് ഡബിൾ ക്ലിക്ക് ചെയ്യുമ്പോൾ ആ ഓപ്പറേഷൻ ഐഡി നിർണ്ണായകമാകുന്നു. അവർ രണ്ടാമതൊരു റിക്കോവേഷൻ അഭ്യർത്ഥന സമർപ്പിച്ചാൽ, യഥാർത്ഥ ഓപ്പറേഷൻ ഐഡി തന്നെ തിരികെ നൽകുക. ഇവിടെ ഐഡെംപൊട്ടൻസി (Idempotency) എന്നത് വെറുമൊരു സൗകര്യമല്ല; അത് ആവർത്തിച്ചുള്ള പരിഭ്രാന്തി ഒഴിവാക്കുകയും ഉപയോക്താവിന് അവരുടെ അഭ്യർത്ഥനയുടെ നിലവാരം അറിയാൻ ഒരു ഏകീകൃത സ്രോതസ്സ് നൽകുകയും ചെയ്യുന്നു.
അവസാന നിമിഷം വരെ അനുമതി ചോദിക്കുക
API ഗേറ്റ്വേയിൽ കൺസെന്റ് പരിശോധിക്കുകയും തുടർന്ന് ഒരു വർക്കറുടെ ഉള്ളിലെ കാഷഡ് ഫ്ലാഗ് (cached flag) വിശ്വസിക്കുകയും ചെയ്യുക എന്നത് ഒരു സാധാരണ തെറ്റാണ്. ഇത് ചെയ്യരുത്. വർക്കർ അതിന്റെ ജോബ് ലൈഫ് സൈക്കിളിലുടനീളം റെസീപ്റ്റ് കൈവശം വെക്കണം. ഹെൽത്ത് റെക്കോർഡ് സ്റ്റോറിനെതിരെയുള്ള ക്വറി നടത്തുന്നതിന് തൊട്ടുമുമ്പ്, അത് പോളിസി ലെയറിനോട് ചോദിക്കണം: “ഈ പ്രത്യേക ഗ്രാന്റിന്റെ വേർഷൻ മൂന്ന് ഇപ്പോഴും ഈ സ്കോപ്പിന് സാധുവാണോ?” ഉത്തരം 'അല്ല' എന്നാണെങ്കിൽ, വർക്കർ നിൽക്കണം. അത് ജോബ് പരാജയപ്പെടുത്തണം. അത് വീണ്ടും ശ്രമിക്കരുത് (retry).
ഇവിടെ റീട്രൈ ലോജിക് (retry logic) ഒരു വിഷമാണ്. വേർഷൻ വ്യത്യാസം എന്നത് ഒരു നെറ്റ്വർക്ക് തകരാറല്ല. അതൊരു മനുഷ്യന്റെ തീരുമാനമാണ്. ഉപയോക്താവ് അനുമതി റദ്ദാക്കി, അല്ലെങ്കിൽ ഗ്രാന്റ് കാലാവധി കഴിഞ്ഞു, അല്ലെങ്കിൽ സ്കോപ്പ് കുറഞ്ഞു. നിങ്ങൾ മൂന്ന് തവണ ശ്രമിക്കുകയും നാലാമത്തെ തവണ ഒരു റേസ് കണ്ടീഷൻ (race condition) കാരണം വിജയിക്കുകയും ചെയ്താൽ, നിങ്ങൾ കൺസെന്റ് ലംഘിച്ചിരിക്കുകയാണ്. ഈ വ്യത്യാസത്തെ ഒരു കഠിനമായ പരാജയമായി (hard failure) കണക്കാക്കുക, അത് നിങ്ങളുടെ ഡെഡ്-ലെറ്റർ ക്യൂവിലേക്കോ (dead-letter queue) ഓപ്പറേഷൻസ് ഡാഷ്ബോർഡിലേക്കോ മാറ്റുക, തുടർന്ന് ഒരു മനുഷ്യനെക്കൊണ്ട് അത് അന്വേഷിപ്പിക്കുക.
സങ്കീർണ്ണമായ സാഹചര്യങ്ങൾ കൈകാര്യം ചെയ്യുക
യഥാർത്ഥ സിസ്റ്റങ്ങൾ കൃത്യമായ ഘട്ടങ്ങളിലൂടെയല്ല പ്രവർത്തിക്കുന്നത്. ഉപയോക്താക്കൾ പഴയ ബ്രൗസർ ടാബുകൾ തുറന്നു വെക്കാറുണ്ട്. ബൾക്ക് ഇംപോർട്ടുകൾ (Bulk imports) ഇരുപത് മിനിറ്റോളം നീണ്ടുനിൽക്കാം. ഒരു സിങ്ക് (sync) പകുതി വഴിയിൽ നിൽക്കുമ്പോൾ തന്നെ സ്കോപ്പുകൾ (Scopes) മാറാം. ഇത്തരം സാഹചര്യങ്ങൾ കൈകാര്യം ചെയ്യാൻ നിങ്ങളുടെ കൺസെന്റ് എപിഐക്ക് (consent API) വ്യക്തമായ നിയമങ്ങൾ ആവശ്യമാണ്.
പഴയ ബ്രൗസർ ടാബുകൾ (Stale browser tabs). ഒരു ഉപയോക്താവ് പുതുതായി തുറന്ന ഒരു ടാബിൽ ആക്സസ് റദ്ദാക്കുന്നു (revokes). എന്നാൽ പഴയൊരു ടാബിൽ, മുൻപത്തെ പേജ് ലോഡിൽ നിന്നുള്ള ഒരു ഗ്രാന്റ് ഒബ്ജക്റ്റ് (grant object) ഇപ്പോഴും ഉണ്ടെങ്കിൽ, അത് വീണ്ടും കണക്ട് ചെയ്യാൻ ശ്രമിച്ചേക്കാം. നിങ്ങളുടെ ബാക്കെൻഡ് ആ പഴയ രസീത് (stale receipt) ഉടൻ തന്നെ നിരസിക്കുകയും പുതിയൊരു കൺസെന്റ് റിവ്യൂ നിർബന്ധമാക്കുകയും വേണം. റദ്ദാക്കപ്പെട്ട ഒരു ഗ്രാന്റ്, റദ്ദാക്കപ്പെട്ട ഒരു പാസ്പോർട്ട് പോലെയായിരിക്കണം: അതിന്റെ ഉടമ ഒരു പഴയ കോപ്പി ഡ്രോയറിൽ നിന്ന് കണ്ടെത്തിയതുകൊണ്ട് മാത്രം അത് വീണ്ടും പ്രാബല്യത്തിൽ വരില്ല.
നടന്നുകൊണ്ടിരിക്കുന്ന ഇംപോർട്ടുകൾ (In-flight imports). ഒരു ബൾക്ക് ഇംപോർട്ട് നടന്നുകൊണ്ടിരിക്കുമ്പോൾ ഉപയോക്താവ് ആക്സസ് റദ്ദാക്കുകയാണെങ്കിൽ, ഒരേസമയം രണ്ട് കാര്യങ്ങൾ സംഭവിക്കണം. ഒന്നാമതായി, ആ വേർഷൻ നിരസിക്കപ്പെടുന്ന നിമിഷം തന്നെ പുതിയ ഡാറ്റ എഴുതുന്നത് (writes) നിർത്തണം. രണ്ടാമതായി, ഓപ്പറേഷൻ ഐഡി (operation ID) വഴി ക്ലീനപ്പ് പ്രക്രിയയുടെ യഥാർത്ഥ പുരോഗതി ഉപയോക്താവിന് കാണിച്ചുകൊടുക്കണം. അവർക്ക് കൃത്യമായ ഒരു സ്റ്റാറ്റസ് പേജ് നൽകുക: “റദ്ദാക്കൽ സ്വീകരിച്ചു. പതിനെട്ട് പെൻഡിംഗ് എഴുത്തുകൾ നീക്കം ചെയ്തുകൊണ്ടിരിക്കുന്നു (purging).” ഇതിനകം അസാധുവാക്കിയ ഒരു ഗ്രാന്റ് വേർഷൻ ഉപയോഗിച്ച് ഡാറ്റ സേവ് ചെയ്യാൻ വർക്കർമാരെ അനുവദിക്കരുത്.
സ്കോപ്പ് മാറ്റങ്ങൾ (Scope changes). ഒരു ഉപയോക്താവ് ആദ്യം അഞ്ച് വർഷത്തെ ഹിസ്റ്ററിയിലേക്ക് ആക്സസ് നൽകുകയും പിന്നീട് അത് ആറ് മാസമായി കുറയ്ക്കുകയും ചെയ്യുന്നു എന്ന് കരുതുക. അപ്പോൾ യഥാർത്ഥ ഗ്രാന്റിൽ മാറ്റം വരുത്തരുത്. വേർഷൻ ഒന്ന് ക്ലോസ് ചെയ്യുക, കുറഞ്ഞ സമയപരിധിയുള്ള വേർഷൻ രണ്ട് നൽകുക, കൂടാതെ നിലവിലുള്ള പ്രക്രിയകളെ പുതിയ പരിധിക്കനുസരിച്ച് ക്രമീകരിക്കാൻ (reconcile) നിർബന്ധിക്കുകയും ചെയ്യുക. പഴയ വേർഷൻ നിങ്ങളുടെ ലോഗിൽ ഒരു ചരിത്രപരമായ വസ്തുതയായി നിലനിൽക്കണം, അല്ലാതെ നിലവിലുള്ള ഒരു അനുവാദമായി (living permission) മാറരുത്.
കർശനമായ സുരക്ഷാ നിയമങ്ങൾ (Hard Security Rules)
രസീതുകൾ (Receipts) സ്വയം സെൻസിറ്റീവ് ആണ്, എന്നാൽ അവ ക്ലിനിക്കൽ ഡാറ്റയല്ല. നിങ്ങളുടെ ആർക്കിടെക്ചറിൽ അവയെ വേർതിരിച്ചു നിർത്തുക. രോഗിക്കോ അല്ലെങ്കിൽ നിയമപരമായ രക്ഷാകർത്താവ് അല്ലെങ്കിൽ അംഗീകൃത കെയർഗിവർ തുടങ്ങിയ പ്രത്യേക ചുമതല നൽകപ്പെട്ട വ്യക്തിക്കോ മാത്രമേ ഒരു രസീത് കാണാനോ റദ്ദാക്കാനോ കഴിയാവൂ. ഇത് വെറും UI റൂട്ടിംഗ് ടേബിളിൽ മാത്രമല്ല, ഡാറ്റ ലെയറിലും (data layer) നടപ്പിലാക്കണം.
ജോബുകൾ പരാജയപ്പെടുമ്പോൾ നിങ്ങളുടെ എറർ ലോഗുകൾ (error logs) ആരോഗ്യ വിവരങ്ങൾ (health data) ഉൾക്കൊള്ളാൻ ശ്രമിച്ചേക്കാം. ഈ പ്രവണതയെ ശക്തമായി പ്രതിരോധിക്കുക. ഒരു അസാധുവായ കൺസെന്റ് രസീത് സമർപ്പിച്ചതിനാൽ ഒരു വർക്കർ പരാജയപ്പെടുമ്പോൾ, ഗ്രാന്റ് ഐഡി (grant ID), വേർഷൻ, എറർ എന്നിവ മാത്രം ലോഗ് ചെയ്യുക. രോഗിയുടെ ഐഡന്റിഫയർ (patient identifier), രോഗനിർണ്ണയ കോഡ് (diagnosis code), അല്ലെങ്കിൽ വർക്കർ ശേഖരിക്കാൻ ശ്രമിച്ച ലാബ് വാല്യൂ (lab value) എന്നിവ ഒരിക്കലും ലോഗ് ചെയ്യരുത്. ലോഗുകളിലെ ആരോഗ്യ വിവരങ്ങൾ പൂപ്പൽ പോലെ പടരും: അവ ബാക്കപ്പ് ചെയ്യപ്പെടുകയും ഇൻഡക്സ് ചെയ്യപ്പെടുകയും ചെയ്യും, ഇത് നിങ്ങളുടെ സാധാരണ ആക്സസ് കൺട്രോളുകളെ മറികടന്നുകൊണ്ട് മറന്നുപോകാൻ കാരണമാകും.
അവസാനമായി, സിസ്റ്റം റിക്കവറി സമയത്ത് പഴയ ഒരു ആക്റ്റീവ് ഗ്രാന്റ് ഒരിക്കലും പുനഃസ്ഥാപിക്കരുത്. നിങ്ങൾ ഒരു ഡാറ്റാബേസ് റോൾബാക്ക് ചെയ്യുകയോ അല്ലെങ്കിൽ റദ്ദാക്കുന്നതിന് മുമ്പുള്ള ഒരു ഗ്രാന്റ് ടേബിൾ അടങ്ങിയ സ്നാപ്പ്ഷോട്ട് (snapshot) പുനഃസ്ഥാപിക്കുകയോ ചെയ്താൽ, പുതിയ ട്രാഫിക് സ്വീകരിക്കുന്നതിന് മുമ്പ് നിങ്ങളുടെ റൺബുക്ക് (runbook) അത്തരം പുനരുജ്ജീവിപ്പിക്കപ്പെട്ട അനുമതികൾ (resurrected permissions) സ്വയമേവ പ്രവർത്തനരഹിതമാക്കണം. ചരിത്രപരമായ കൺസെന്റ് അവസ്ഥകൾ ഓഡിറ്റ് ലോഗിൽ (audit log) മാത്രമേ ഉണ്ടാകാവൂ, ഒരിക്കലും ആക്റ്റീവ് റൂൾ സെറ്റിൽ (active rule set) ഉണ്ടാകരുത്.
