परिवर्तन लॉग
क्या नया है.
यह जहाज के रूप में, प्लेटफार्म के हर सुधार.
· kamo-signer-monorepo
सार्वजनिक ब्रांडेड कोट/estimate दस्तावेज़ at /{locale}/q/{token}
व्यापार उद्धरण प्रणाली के लिए ग्राहक-facing सतह। सर्वर-रेंडर इसलिए ऑर्ग का ब्रांडिंग पहला पेंट में है - एक वाणिज्यिक दस्तावेज़ पर एक ब्रांडेड फ्लैश वास्तव में क्या करना चाहिए, और यही कारण है कि पृष्ठ ब्रांड कस्टम का उत्सर्जन करता है गुण QuoteBrandVars के माध्यम से इनलाइन के बजाय उन्हें हाइड्रेशन के बाद स्वैप करने के बजाय। Kamo-signer में रहता है क्योंकि उस ऐप में पहले से ही HostRegexp प्रवेश, autocert है। कवरेज, DNS उपनाम और होस्टनाम ओवरराइड के साथ थीम पैकेज - और क्योंकि बोली -> स्वीकार -> ई-सिग्न तो एक हॉप है, क्योंकि EsignGenericEnvelope किसी भी तरह से बांधता है रिकॉर्ड के माध्यम से (context type, reference id). इसका उपयोग केवल तभी किया जा सकता है जब /{locale}/ i18n वर्क लैंड; सभी 31 स्ट्रिंग्स शब्दकोश से स्रोत अनुवाद कुंजी हैं। मुद्रा और तिथियां प्रारूप अगली-intl के माध्यम से उद्धरण की अपनी मुद्रा और तिथियों का उपयोग करके सर्वर-रिसोल्ड टाइमज़ोन (recipient Member -> org -> UTC), कभी दर्शक का उपकरण नहीं। गलत क्षेत्र में प्रस्तुत एक समाप्ति उस तारीख का नाम दे सकता है जिस पर प्रस्ताव पहले से ही है। मृत। प्लेटफॉर्म का पहला असली @मीडिया प्रिंट ब्लॉक जोड़ता है। Kamo-internal में "प्रिंट इनवॉइस" हमेशा पूरे ऐप क्रोम को मुद्रित किया है क्योंकि कोई @मीडिया प्रिंट नियम मौजूद नहीं है कहीं भी; यहां ब्रांड के साथ एक साफ पत्र दस्तावेज़ के रूप में एक ही मार्कअप प्रिंट उच्चारण संरक्षित (प्रिंट-रंग-समायोजन: सटीक - एक रंगहीन उद्धरण एक ड्राफ्ट के रूप में पढ़ा), एक्शन बार दबाया और पेज ब्रेक-इनसाइड: पंक्तियों और कुलों पर बचें। टर्मिनल राज्यों को जानबूझकर असममित किया जाता है: EXPIRED को एक ईमानदार ब्रांडेड पेज मिलता है तारीख और ऑर्ग के संपर्क विवरण का नामकरण करते हुए, सुरक्षित क्योंकि कॉलर पहले से ही एक 256 बिट टोकन का कब्जा साबित हुआ; अज्ञात / रद्द / गलत-ऑर्ग सभी एक के लिए पतन सामान्य पृष्ठ इसलिए सतह की जांच नहीं की जा सकती। ग्राहक कारणों को व्हाइटलिस्ट करता है प्रस्तुत करने से पहले। टोकन कभी भी यूआरएल में आगे की यात्रा नहीं करता है - सर्वर-साइड उसे एक यूआरएल में पोस्ट करता है बॉडी, और BFF ने रियल क्लाइंट IP को स्पष्ट रूप से आगे बढ़ाया क्योंकि APIService टिकट X-Forwarded-For अपने स्वयं के इनबाउंड अनुरोध से, जो अन्यथा हर जगह डालेगा दर्शक एक दर सीमा बाल्टी में फली आईपी की कुंजी है। SECURITYSERVICE URL को configmap में जोड़ता है (verified: kamowssecurity-service मौजूद है) कामो नेमस्पेस में)।.
· SecurityService
उद्धरण REST सतह - स्टाफ प्रबंधन और सार्वजनिक शेयर लिंक
कर्मचारी / एपीआई / सुरक्षा / वाणिज्य / कोट्स और एक unauthenticated हलक में समापन बिंदुओं /api/security/public/quotes. QuoteController ने POSController की प्रतिलिपि के बजाय BaseLosController का विस्तार किया Preamble: CallerSessionResolver X-OTK विशेषता को स्वीकार करता है, X-*** टोकन हेडर और *** कुकी, जहां POSकंट्रोलर का निजी getOrgId केवल पढ़ता है OTK विशेषता। प्रत्येक हैंडलर अधिकार-पत्र (देखें/प्रबंधन/Send QUOTES) है। अधिकांश वाणिज्य की सतह सत्र-केवल है - किसी भी ऑर्ग के किसी भी प्रामाणिक सदस्य को म्यूट कर सकते हैं आदेश - और यह जानबूझकर यहां दोहराया नहीं जाता है, क्योंकि एक उद्धरण करता है एक ग्राहक के सामने एक कीमत के लिए org। QuotepublicController को सुरक्षा-config carve-out की आवश्यकता नहीं है: स्प्रिंग चेन है anyRequest().permitAll() और OTKPreAuth Filter केवल X-OTK हेडर पर कार्य करता है, जो X-OTK हेडर पर कार्य करता है। कभी कभी नहीं भेजे जाने वाले ईमेल लिंक के बाद एक ब्राउज़र। डिजाइन अंक: - टोकन POST बॉडी में आता है, कभी भी यूआरएल नहीं। APIApp.forward() लॉग अनुरोध रेखाएं, और एक पथ में एक बियरर क्रेडेंशियल उन लॉग्स में उतरेगा। - एक एनमेशन ऑरेकल नहीं: अज्ञात, रद्द और org-mismatched tokens all एक निर्दोष जेनेरिक विफलता वापस लौटें। केवल EXPIRED एक विशिष्ट हो जाता है, ईमानदार जवाब, जो सुरक्षित है क्योंकि कॉलर पहले से ही एक के कब्जे साबित हुआ 256-बिट टोकन। - अनुरोध होस्ट से व्युत्पन्न ऑर्ग को ऑर्ग के खिलाफ क्रॉस-चेक किया जाता है लिंक पंक्ति इसके बिना, ऑर्ग ए के लिए एक वैध लिंक ऑर्ग बी के होस्ट के तहत खोला जाएगा A के मूल्य निर्धारण को B के ब्रांडिंग - एक फ़िशिंग प्राइमिटिव पहने हुए प्रस्तुत करता है। - नो-स्टोर / रेफरर-नीति: नो-रेफरर / एक्स-रोबोट-टैग: हर पर noindex प्रतिक्रिया। पृष्ठ थीम से लोगो लोड करता है। <org>, और एक रेफरी ले जाएगा Token off-origin. PublicLinkRateLimiter Redis समर्थित है क्योंकि सुरक्षा सेवा बहु प्रतिकृति है — इन-प्रोसेस काउंटर केवल नाम में सीमित होगा। यह स्पष्ट रूप से डोस है और लॉग-हाइजीन संरक्षण, एंटी-गेजिंग कंट्रोल नहीं: 256 बिट एनट्रॉपी है। असफलताओं को सफलता की तुलना में कहीं अधिक सख्ती से गिना जाता है, क्योंकि एक कार्यालय ने एक कार्यालय खोलने के बाद से एक कार्यालय शुरू किया अग्रेषित उद्धरण पचास बार सामान्य है जबकि पचास मिस नहीं है। यह खुला रहता है, इसलिए एक Redis आउटेज उद्धरण पृष्ठ को नीचे नहीं ले सकता है। QuoteEmailClient ईमेल सेवा लेन-देन पथ (X-Internal-Auth) का पुन: उपयोग करता है, QUOTE SENT टेम्पलेट) और केवल शीर्षक आंकड़ा प्लस लिंक भेजता है - कभी नहीं इसलिए एक अग्रेषित ईमेल स्वयं प्रकटीकरण नहीं है। पूर्व मौजूदा परीक्षण विफलताओं को इस प्रतिबद्धता द्वारा अपरिवर्तित किया गया (इस कार्य को स्थगित करके सत्यापित) और स्वच्छ HEAD पर फिर से चल रहा है: ************* NPE on a null EntityManager, and legacy com.retval SecurityApplicationTests @BootConfiguration. इन समापन बिंदुओं के काम से पहले एक KamoInitializer सेवा चलाने की आवश्यकता है: उद्धरण तालिका नए हैं और डीडीएल-ऑटो यहां कोई नहीं है, इसलिए सेवा सामान्य रूप से जूते और केवल उद्धरण 500 के दशक के अंत में जब तक कि केआई चला गया है, तब तक एक लापता संबंध।.
· kamo-shared-library
Quote/estimate डोमेन - संस्थाओं, मूल्य निर्धारण इंजन, शेयर लिंक
मौजूदा वाणिज्य रीढ़ के साथ एक प्रथम श्रेणी का उद्धरण जोड़ता है। पूर्व मौजूदा "serviceQuote" एक इरादा प्लस एक JSON ब्लब है जो एक पेशकश और एक फ्लैट ले जाता है राशि, कोई प्राप्तकर्ता, कोई समाप्ति और कोई यूआई नहीं; यह एक नींव नहीं है। विस्तार Intent सीधे अस्वीकार कर दिया गया था: commerce intents को LOAN APPLICATION द्वारा साझा किया गया है, RENTAL REQUEST, SUBSCRIPTION SIGNUP और PURCHASE REQUEST, so ~25 उद्धरण स्तंभ बंधक और किराये के पथ पर स्थायी NULL डाल दिया जाएगा। संस्था ************* उद्धरण सगाई से जुड़े, संस्करण, मान्य until + मान्य for days QuoteLineItem snapshots name/sku/price इसलिए भेजे गए उद्धरण कभी नहीं फिर से खरीदे QuoteShareLink bearer क्रेडेंशियल, SHA-256 बाकी पर, रद्द/expiry/view गिनती QuoteLinkView प्रति खुला लेखा परीक्षा (आईपी, उपयोगकर्ता एजेंट) QuoteEvent append-only lifecycle trail कुल सर्वर-लेखक हैं। QuoteTotals हर पैसे का एकल लेखक है क्षेत्र और अनुरोध डीटीओ सभी पर कोई कुल नहीं ले जाते हैं - जानबूझकर विपरीत निर्माणरिटेलऑर्डर, जो उप-total/tax/total verbatim लेता है और उसे सौंपा जा सकता है कुल = 0 के साथ जनसंख्या क्रम। लाइन छूट उद्धरण स्तर से पहले लागू होते हैं छूट, छूट कभी भी उनके आधार से अधिक नहीं हो सकती है, मध्यवर्ती गणित कभी नहीं रह सकते हैं। स्केल 4 और केवल मुद्रा की छोटी इकाई के लिए भव्य कुल राउंड। साझा टोकन: 32 bytes of SecureRandom as 43 base64url chars (256 बिट्स)। समान E-sign signer token लेकिन 21 chars shorter के रूप में entropy, ईमेल URL रखने 76-char सादे पाठ रैप सीमा के तहत। केवल SHA-256 जारी रखा गया है। कर का आविष्कार करने के बजाय ईमानदार है: मंच में कोई कर इंजन नहीं है (टैक्सक्लास/टैक्सक्लास/टैक्सक्लास/टैक्सक्लास/टैक्सक्लास/टैक्सक्लास/टैक्सक्लास/टैक्सक्लास/टैक्सक्लास/टैक्सक्लास/टैक्सक्लास/टैक्सक्लास/टैक्स) TaxZone/TaxRate अधिकृत हैं और कोई गणना के द्वारा पढ़ा जाता है), तो इंजन मोड एक वाणिज्यिक दस्तावेज़ पर एक आंकड़े बनाने के बजाय नोट CONFIGURED की रिपोर्ट करता है। QuoteLineItem.taxClassId UUID है, जो टैक्सक्लास के वास्तविक PK से मेल खाता है - Offering.taxClassId एक UUID-keyed तालिका के खिलाफ एक लंबा है और संरचनात्मक रूप से असुरक्षित है। इसके अलावा: अधिकार 178-180 (view/MANAGE/SEND QUOTES) और QUOTE SENT canonical ईमेल टेम्पलेट, CANONICAL KEYS में पंजीकृत (इसमें एक स्थायी 404) का मतलब है। मूल्य निर्धारण इंजन और टोकन स्वच्छता को कवर करने वाले 35 परीक्षण। पूर्ण सूट: 896 उत्तीर्ण। स्कीमा नोट: ये नए टेबल हैं। KamoInitializerसेवा पहले चलाने के लिए सुरक्षा सेवा उद्धरण समापन बिंदुओं को पूरा करती है - डीडीएल-ऑटो वहाँ नहीं है, इसलिए सेवा जूते ठीक और समापन बिंदु 500 एक लापता संबंध पर जब तक यह करता है।.
· KlusterServices
अवतार संकल्पक के लिए आक्रामक रोकथाम, एक CiliumNetworkनीति के रूप में
8f6c672 reverted, केवल वही रूप में जो वास्तव में यहां काम करता है। पहले प्रयास विफल रहा क्योंकि एक सादे नेटवर्कनीति इस बात को व्यक्त नहीं कर सकती क्लस्टर की टोपोलॉजी। तीन सुरक्षा सेवा की चार महत्वपूर्ण निर्भरताएं नोड, पॉड नेटवर्क में नहीं - cockroachdb-0 और nats-k1m1-0 रन होस्टनेटवर्क, MinIO एक मेजबान प्रक्रिया है - इसलिए एक पॉडसेलर उन्हें कभी मैच नहीं कर सकता है। The गैर-घर्षण हिस्सा, और कारण पहला पैच प्रयास भी विफल हो गया है, यह है कि एक नोड सबनेट के लिए IPBlock इसे ठीक नहीं करता है: Cilium नोड को वर्गीकृत करता है क्योंकि आरक्षित होस्ट / रिमोट नोड पहचान, और सीआईडीआर नियम जानबूझकर मैच नहीं करते हैं आरक्षित पहचान toEntity एकमात्र निर्माण है जो इसे व्यक्त करता है। दोनों विफलता मोड लेखन से पहले एक फेंकने वाले कैनरी पॉड के खिलाफ पुन: उत्पन्न किए गए थे इसके बजाय उत्पादन के खिलाफ। कैनरी ने एक ही नियम के तहत सेट किया एक विशिष्ट लेबल, जो कि कैसे ipBlock संस्करण चुपचाप अवरुद्ध हो गया था CockroachDB, NATS और MinIO. कैनरी पर सत्यापित, फिर सुरक्षा सेवा पर कोई पुनरारंभ और कोई पुनरारंभ नहीं होने की पुष्टि की। कनेक्शन त्रुटियां: ALLOW dns, crdb:26257, nats:4222, minio:9000, redis:6379, siblings:80, दुनिया:443 BLOCK node:22, node:443, kube-api:443, redis-via-node:6379, 169.254.169.254, लूपबैक:9000 पिछले चार बिंदु हैं: एक एसएसआरएफ इन हलकों में अब कहीं नहीं जाना है। The इन-कोड गार्ड प्राथमिक नियंत्रण रहता है - यह एकमात्र परत है जो समझता है डीएनएस रीबाइंडिंग - और यह इसके पीछे रक्षा है। हैडर कैनरी प्रक्रिया करता है। किसी को यह बदलने के बजाय इसे फिर से शुरू करना चाहिए इसके कारण से, Cilium की पहचान मॉडल सादे तरीके से व्यवहार नहीं करता है नेटवर्कनीति अंतर्ज्ञान सुझाव देता है, और कोई स्थिर वातावरण नहीं है।.
· kamo-internal
समूह बातचीत के लिए एक फेसपाइल दिखाएं
इसके पांच लोगों के साथ एक धागा एक मनमाने ढंग से प्रतिनिधित्व किया गया था चेहरा, जो एक व्यक्ति से संदेश के रूप में पढ़ता है। अब तक तीन प्रतिभागियों ने ओवरलैप किया, इसलिए "कई लोग" नाम रेखा को पार करने की आवश्यकता के बिना एक नज़र में वैध है। तीनों पर कैप्ड: अतीत में कि सर्कल पुन: प्रयोज्यता और पंक्ति के नीचे सिकुड़ते हैं जानकारी के बजाय बनावट बन जाती है, और शेष पहले से ही कहा जाता है "और एन दूसरों" पाठ ठीक इसके बगल में। रीडर को अपनी खुद की थ्रेड सूची से फ़िल्टर किया जाता है, और अन्य पार्टी लीड्स - चेहरे को सही करने के लिए छोड़ दिया, इसलिए प्राथमिक संवाददाता को सबसे बाएं होना चाहिए और वह अपठित बैज ले जाता है। प्रत्येक चेहरे को पंक्ति में एक अंगूठी मिलती है पृष्ठभूमि रंग; इसके बिना समान तस्वीरों का एक स्टैक एक आकार में विलय हो जाता है। अब संकल्प केवल लीड के बजाय पहले कुछ प्रतिभागियों को कवर करता है, अन्यथा दूसरे और तीसरे चेहरे स्थायी रूप से मोनोग्राम के रूप में बैठेंगे।.
· SecurityService
उपकरण श्रृंखला, वापसी समाप्त प्रविष्टियों, रिकॉर्ड प्रकटीकरण
इस सुविधा में हर विफलता मोड चुप है। एक जाली सर्किट ब्रेकर, एक कार्यकर्ता प्रत्येक कार्य को त्यागने वाले कतार, एक प्रदाता जिसने HTML को वापस करना शुरू किया - प्रत्येक लुक वास्तव में "इस संवाददाता के पास कोई फोटो नहीं है", जो भी सही है व्यवहार जैसा दिखता है। काम करने के बीच कोई उपयोगकर्ता- व्यवहार्य अंतर नहीं है और पूरी तरह से मृत, इसलिए इसे मापा जाना चाहिए। मैट्रिक्स (प्रोमेथेस पहले से ही वायर्ड हो गया था, इसलिए यह ज्यादातर नामकरण है): कैश हिट अनुपात, श्रृंखला अवधि जिसे टियर ने उत्तर दिया था, प्रति प्रदाता हिट/miss, कार्यकर्ता कतार गहराई, और एक discarded-task कुल। पहले इस्तेमाल किया DiscardPolicy, जो डिजाइन द्वारा चुपचाप छोड़ देता है; यह अब एक काउंटर को बढ़ाता है, और काउंटर को निष्पादक से पहले घोषित किया जाता है क्योंकि क्षेत्र प्रारंभकर्ता में भाग लेते हैं स्रोत आदेश और आलसी कैप्चर पर भरोसा एक हानिरहित आदेश पर टूट जाएगा। प्रकटीकरण अपने स्वयं के लॉगर में जाते हैं। केवल पहचान स्तर एक व्यक्तिगत है प्रकटीकरण - डोमेन टियर्स एक पते के दाहिने हाथ की ओर संचारित करते हैं, जो कोई नहीं पहचानता - और इसके बाद कॉल करने से पहले रिकॉर्ड किया जाता है, इसलिए जब भी अनुरोध विफल हो जाता है तो भी निशान मौजूद है। पता पूर्ण में लिखा जाता है और जानबूझकर: बिंदु का जवाब देना है "यह कौन था कि इस व्यक्ति का डेटा साझा किया गया था", और एक हैश उसे जवाब नहीं दे सकता। रीपर एक लीक बंद कर देता है: हटाएंExpiredBefore अस्तित्व में है और इसे कुछ भी नहीं कहा जाता है, इसलिए प्रेषक identity हमेशा के लिए बढ़ी। एक व्यस्त मेलबॉक्स हजारों संवाददाताओं को छूता है एक बार प्रत्येक व्यक्ति के लिए नकारात्मक पंक्ति छोड़ देता है। टेस्ट एक वास्तविक सॉकेट के खिलाफ प्राप्तकर्ता को कवर करते हैं, क्योंकि दिलचस्प मामले हैं तर्क के बजाय सभी प्रदाता व्यवहार: एक 404 एक वैध छवि ले जाना (DuckDuckGo), एक सॉफ्ट-404 सेवारत HTML, एक मूल understating Content-Length, एक 1x1 स्टब और पॉड नेटवर्क के उद्देश्य से एक पुनर्निर्देशित। उत्पादन ग्राहक नहीं कर सकते एक लूपबैक परीक्षण सर्वर पर इंगित किया जा सकता है - इसके DNS पिन कुछ भी हल करने से मना कर देता है निजी, जो पूरा बिंदु है - इसलिए वे एक आराम से ग्राहक और आराम से ग्राहक के खिलाफ दौड़ते हैं पिन को अलग से कहा जाता है।.
· kamo-internal
कंसोल से समायोजन में एक ingested एलएलपीए मैट्रिक्स को बढ़ावा देना
Ingestion पैनल केवल एक दर शीट प्रकाशित कर सकता है। एक एलएलपीA MATRIX स्रोत के लिए यह अब एक "एलएलपीए समायोजन" कार्ड दिखाता है: मौजूदा चुनें रेट-शीट संस्करण एलएलपीए समायोजित (+ एक वैकल्पिक समूह) और प्रत्येक अनुमोदित FICO/LTV बाल्टी एक सशर्त मूल्य समायोजन बन जाता है। परिणाम का नाम कैसे कई लेखक थे और ईमानदारी से, कितने पंक्तियों को छोड़ दिया गया क्योंकि एक बाल्टी सुरक्षित रूप से पढ़ा नहीं जा सकता है या पहले से ही उपस्थित थे। ingestionApi.promoteAdjustment नए गेटवे रिले के लिए पोस्ट।.
· SecurityService
एक एलएलपीए मैट्रिक्स को सशर्त समायोजन में बढ़ावा देने के लिए गेटवे रिले
**************** प्रोमोशन प्राप्त करें, मिरर करना पदोन्नत-rate-sheet रिले: भगवान-योग्य गेट, संगठनआईडी सर्वर-स्टाम्प ऑन (information) के माध्यम से पेलोड, डाउनस्ट्रीम 4xx ने क्रियाशीलता को रिलेटेड किया। चलो एक स्टीवर्ड बारी कंसोल से वास्तविक प्रति परिदृश्य मूल्य समायोजन में एलएलपीए मैट्रिक्स की समीक्षा की।.
· VOIPService
रिकॉर्ड कॉल रिकॉर्डिंग, वॉयसमेल और ट्रांसक्रिप्ट एक्सेस
रिकॉर्डिंग प्लेबैक कोई निशान छोड़ दिया। एक रिकॉर्ड कॉल घनी PHI है मंच स्टोर — unredacted बातचीत — और "जो इस बात को सुनते हैं कॉल" अप्रयुक्त था, जो §164.402 उल्लंघन का पहला सवाल है आकलन पूछता है। तार CallRecordingAuditor प्रत्येक पढ़ा है कि यह खुलासा में: - गेट / रिकॉर्डिंग / {id} / ऑडियो CALL RECORDING / डाउनलोड ************* CALL RECORDING/डाउनलोड - गेट / रिकॉर्डिंग /{id} CALL RECORDING + TRANSCRIPT /VIEW ************* CALL RECORDING/डाउनलोड - GET/instances/{id}/voicemail TRANSCRIPT/LIST, per row ट्रांसक्रिप्ट वह है जो छुपाता है। यह मीडिया डाउनलोड नहीं है; यह सवारी करता है मेटाडाटा JSON के अंदर और हर आवाज मेल पंक्ति के अंदर, और यह वही है PHI एक रूप में ऑडियो के रूप में जो greps. यह अपनी खुद की घटना है क्योंकि एक प्रकटीकरण का लेखांकन प्रति संसाधन इकट्ठा किया जाता है। Byte सेवा बंद विफल रहता है, इसलिए PhiAuditAvailabilityAdvice एक unloggable बदल जाता है 500 के बजाय 503 में पढ़ा - अनुरोध ठीक था, हम करने के लिए decoderd हम PHI की सेवा नहीं कर सकते। Refusals भी दर्ज कर रहे हैं; जांच है क्या पता लगाने के लिए लग रहा है। इसके अलावा, यह वायर करते समय एक प्राधिकरण अंतराल को बंद कर देता है: POST /Recordings/lookup ने अनुरोध निकाय से एक उदाहरण लिया और कभी नहीं कॉलर के ऑर्ग की जांच करने के लिए, इसलिए यह एक और किरायेदार के प्रदाता को हल करता है उनके रिकॉर्डिंग ids के लिए आईडी कॉल करें। प्रत्येक अन्य उदाहरण-स्किप्ड समापन बिंदु में सेवा पहले से ही findByIdAndOrgId के माध्यम से चला जाता है; यह अब भी करता है। रिकॉर्डिंग प्लेबैक प्राधिकरण के रूप में है छोड़ दिया है और जगह में दस्तावेज: org स्वामित्व एकमात्र जांच है, इसलिए कोई भी सदस्य किसी भी रिकॉर्डिंग को वापस कर सकता है उनका org. यह तय करने का मतलब है कि "डाउन एक्सटेंशन" क्या है? सीमा और जो सही इसे उठाता है - यह एक उत्पाद निर्णय नहीं है, एक नहीं है यहाँ बनाने के लिए अनुमान लगाया गया है, और हर तरह की पहुंच अभी कम से कम दर्ज की गई है।.
· AIService
Record PHI access on every read of stored AI conversation history
Wires the shared §164.312(b) spine into the paths that read persisted prompts and completions. The assistant is the module the compliance assessment put OUTSIDE the boundary — prompts fan out to external providers under no BAA and are then kept indefinitely — so reads of that store are the disclosures most in need of a trail, and they had none. Audited: the session list and history search (one event per conversation, not one per request), a single conversation's metadata and its messages, the public widget reading its own transcript back, and the handoff bundle. Refusals are recorded too — probing another org's guids is what detection looks for — and an unauthenticated attempt is attributed to the sentinel org rather than dropped, since the recorder rejects what it cannot attribute and that is the event most worth keeping. The handoff bundle is a DISCLOSE, not a VIEW: it carries a visitor's conversation out of AIService and in front of a human in another product. That kind fails closed, so a lost record now withholds the transcript and answers 503 rather than serving data it cannot account for. Identifiers only. Never a message body, a title, or the search term — a member searching their assistant history types the borrower's name into it, and an audit trail that reproduced the prompt would just have moved the PHI into the log stream. Completes d428ee3, which a concurrent session swept up mid-change: the auditor was missing recordDeniedInternalView, and PublicAiChatController's new constructor argument had not reached its test.
· MediaService
रिकॉर्ड चैट संदेश उन समापन बिंदुओं पर पढ़ता है जो शरीर वापस लौटते हैं
एक संदेश भेजने के लिए एक पंक्ति छोड़ दिया; एक छोड़ दिया कुछ भी नहीं पढ़ने। प्रत्येक चैट, समर्थन और मंच पर सामाजिक धागा यहां एक मुट्ठी भर समापन बिंदुओं से प्रस्तुत करता है, और कोई नहीं उनमें से कुछ ने रिकॉर्ड किया, इसलिए "यह कौन पढ़ता है" का कोई जवाब नहीं था - जो पहला सवाल 164.402 उल्लंघन आकलन पूछता है। ChatMessageAccessAuditor पांच से एक PhiAccessEvent (CHAT MESSAGE) उत्सर्जित करता है वह पथ जो एक कॉलर संदेश पाठ को सौंपते हैं: ************* सूची GET/api/media/session/chat LIST पोस्ट ************* दृष्टिकोण ************* सूची पोस्ट ************* दृष्टिकोण प्रति संदेश एक घटना, प्रति अनुरोध एक नहीं। "उन्होंने धागा खोला" एक नहीं है "इस व्यक्तिगत संदेश का खुलासा किया गया था" का जवाब दें, और संदेश आईडी हैं प्रत्येक कॉल साइट पर पहले से ही हाथ में, इसलिए अनुरोध के आकार की पंक्ति एक होगी एक सीमा के बजाय विकल्प। थ्रेड ने रिकॉर्ड किया AFTER mute फिल्टर, इसलिए एक पंक्ति का मतलब है कि कॉलर वास्तव में हाथ था। चैट सूची गुंजाइश में है क्योंकि प्रत्येक पंक्ति में 140 वर्ण हैं थ्रेड का अंतिम संदेश — यह सामग्री है, मेटाडाटा नहीं। एक खाली पूर्वावलोकन के साथ पंक्तियाँ कुछ भी रिकॉर्ड करें। स्पष्ट रूप से दर्ज नहीं किया गया: अपठित गिनती, उपस्थिति, अंतिम दृश्य, टाइपिंग, पढ़ा प्राप्तियों, सत्र-सदस्य सूचियों, mutes, टिकट विस्तार (metadata प्लस स्थिति) इतिहास, कोई निकाय नहीं) और रिपोर्टिंग समुच्चय का समर्थन करते हैं। यदि कोई एक ट्रेल उपयोगी होता है तो एक ट्रेल केवल उपयोगी होता है। पंक्ति का मतलब है कि किसी ने सामग्री देखी; पंक्तियां जो कुछ भी ऐसा करने वाले लोगों को दफनाने के लिए खड़े हैं। Refusals भी दर्ज कर रहे हैं, धागा गाइड के खिलाफ - कोई संदेश आईडी अभी तक मौजूद नहीं है इनकार करने का बिंदु, और थ्रेड guids के खिलाफ बार-बार इनकार करना आकार है जांच पड़ता है। एक अनधिकृत रीडर को एक भावुक ऑर्ग के लिए जिम्मेदार ठहराया जाता है। गिरा दिया: रिकॉर्डर अप्राप्य घटनाओं को अस्वीकार करता है, और यह एकल सबसे अधिक है दिलचस्प घटना यह निशान पकड़ सकता है। ग्राहक आईपी एक्स-Forwarded-for दूरस्थ योजक के साथ गिरने के रूप में आता है - सब कुछ Traefik के माध्यम से आता है, इसलिए दूरस्थ योजक अकेले प्रवेश फली रिकॉर्ड करता है। सार्वजनिक चैट APIService के माध्यम से दूसरी हॉप लेता है, जो X-Forwarded-Forwarded-For the आगंतुक को सेट करता है। ब्राउज़र के उपयोगकर्ता-एजेंट को X-Original-User-Agent को संबोधित और स्थानांतरित करता है, इसलिए लेखा परीक्षक उस हेडर को पसंद करता है; उस हॉप पर शाब्दिक उपयोगकर्ता-एजेंट एपीआई सर्विस की है अपने HTTP क्लाइंट को पहचानता है और किसी को भी पहचानता है। आगंतुक रीडिंग को ऑर्ग के लिए जिम्मेदार ठहराया जाता है X-पब्लिक-Chat-Org-Id से कोई सदस्य आईडी के साथ: एक आगंतुक की कोई सदस्य पहचान नहीं है उनके स्वयं के, लेकिन ऑर्ग रिकॉर्ड का मालिक है, इसलिए पढ़ने के लिए हानिकारक रहता है। केवल पहचानकर्ता, कभी संदेश पाठ नहीं। एक ऑडिट ट्रेल जो संदेश को पुन: उत्पन्न करता है इसने पीएचआई को लॉग स्ट्रीम में कॉपी किया है। इसके अलावा eed3817 को पूरा करता है, जो मध्य-शिक्षा और बाएं मीडिया कंट्रोलर में इस काम को घुमाता है आयात अस्तित्व से पहले PhiAccessKind को संदर्भित करना - वह संशोधन नहीं करता है संकलन यह एक करता है: mvn -o परीक्षण 16/16 हरा है।.
· DocsService
चार दस्तावेज़ पथों पर रिकॉर्ड बाइट एक्सेस जो कुछ भी दर्ज नहीं हुआ
**************** मंच का एकमात्र उप-एक्सेस इंजेक्शन साइट है। भाई बहन अंत बिंदुओं की सेवा ठीक उसी बाइट्स — /stream, /bulk-download, टेम्पलेट परिवर्तित-PDF और टेम्पलेट पेज थंबनेल - कुछ भी दर्ज नहीं किया गया है, इसलिए कोई भी दस्तावेज़ बाइट चाहता है एक निशान छोड़ने के बिना केवल एक अलग यूआरएल चुनना पड़ा। सभी चार अब बिंदु पहुंच पर एक PhiAccessEvent का उत्सर्जन करते हैं और सत्यापित किए गए हैं। बाइट्स को परोसा जा सकता है। थोक डाउनलोड प्रति दस्तावेज़ एक प्रति अनुरोध के बजाय प्रति एक घटना का उत्सर्जन करता है। "They निर्यात किए गए 400 दस्तावेज़ "इस व्यक्ति के रिकॉर्ड के बारे में उत्तर नहीं है खुलासा किया गया है, और प्रति दस्तावेज पंक्तियाँ क्या है कि जवाबदेह छह साल बाद 164.528 के तहत। ग्राहक IP, X-Forwarded-Forwarded-for, दूरस्थ योजक के साथ गिर वापसी के रूप में आता है: हर अनुरोध Traefik के माध्यम से आता है, इसलिए दूरस्थ योजक अकेले प्रवेश पॉड रिकॉर्ड करेगा प्रत्येक पहुँच और पता लगाने के लिए बेकार होना। एक अनौपचारिक प्रयास को एक भावुक संगठन के लिए जिम्मेदार ठहराया जाता है बजाय गिरा दिया - रिकॉर्डर असफल घटनाओं को अस्वीकार करता है, और दस्तावेज़ के लिए अनुरोध करता है कोई सत्र के साथ बाइट्स वास्तव में रखने की घटना है। यह मौजूदा ImgLogDownload पंक्तियों के साथ उनके स्थान के बजाय बैठता है: वे इमेजिंग-डोमेन रिकॉर्ड हैं, यह क्रॉस-सतह का एक लेखांकन है प्रकटीकरण से इकट्ठा किया जाता है। नोट ImgLog Service, जो उन पंक्तियों को पढ़ती है, फिर भी प्लेटफॉर्म में कहीं भी शून्य कॉलर है।.
· KlusterServices
अवतार हलकों से प्रवेश करना; ध्यान दें कि रेडिस eviction पूल
सिक्योरिटी सर्विस अब एक ऐसा रिवर चलाता है जिसका लक्ष्य URL को अविश्वास से चुना जाता है पार्टी - एक BIMI रिकॉर्ड DNS सामग्री है जिसे हर कोई एक भेजने वाले डोमेन का मालिक है। और कोई भी एक किरायेदार ईमेल करके डोमेन भेजता है। इस क्लस्टर में कुछ भी नहीं जहां इस तरह के एक अनुरोध जा सकता है बाधित: Redis जवाब 6379 पर unauthenticated, मिनियो ऑन 9000 रूट क्रेडेंशियल, कॉकरोचDB ऑन 26257, और नोड मेटाडाटा समापन बिंदु किसी भी फली से पहुंच योग्य है। हल करने वाला कोड में अपने नियंत्रण को लागू करता है, और वे प्राथमिक रहते हैं रक्षा क्योंकि वे एकमात्र परत हैं जो DNS रिबाइंडिंग को समझते हैं। यह है दूसरा, इसलिए एक बग अभी भी एक निजी पते तक नहीं पहुंच सकता है। अनुमति-सूची के बजाय जानबूझकर अनुमति-सबसे अधिक। इन सेवाओं को विधिवत पहुंच मेजबान, इसलिए गंतव्यों को नामांकित करना अपरिहार्य होगा और टूट जाएगा चुपचाप। इसके बजाय यह सार्वजनिक इंटरनेट को छोड़कर हर निजी रेंज के साथ अनुमति देता है, फिर वास्तविक रूप से आवश्यक विशिष्ट इन-क्लस्टर बंदरगाहों को फिर से निर्धारित किया जाता है। फली के लिए दायर कि अविश्वास प्राप्त करता है - इसे लागू करने के लिए नेमस्पेस चौड़ा काट दिया जाएगा जिन सेवाओं की प्रवेश परीक्षा कभी नहीं हुई है। रेडिस परिवर्तन एक टिप्पणी है और एक डेटाबेस टक्कर है, व्यवहार परिवर्तन नहीं। यह रिकॉर्ड क्यों प्रेषक अवतार कैश स्टोर केवल लघु मेटाडाटा स्ट्रिंग्स: maxmemory 2 जीबी allkeys-lru evicts के साथ पूरे उदाहरण में, और डीबी 0 हर लाइव रखता है सत्र, इसलिए यहां एक थोक बाइट कैश उपयोगकर्ताओं को दबाव में यादृच्छिक रूप से साइन आउट करेगा और दिनों के लिए गलत माना जाता है।.
· kamo-internal
प्रेषक और प्राप्तकर्ता फ़ोटो दिखाएं
मेलबॉक्स ने सभी के लिए एक एकल साझा ढाल पर एक एकल पत्र प्रदान किया, इसलिए प्रत्येक पंक्ति को एक ही देखा गया और सर्कल ने कोई जानकारी नहीं दी। यह अब दिखाता है जब एक ज्ञात होता है तो संवाददाता की वास्तविक तस्वीर, और एक दो अक्षर मोनोग्राम जब यह ज्ञात होता है नहीं। एक सेंडरअवाटर सात हाथ से शुरू होने वाले चक्रों की जगह लेता है। इसके लिए मामला स्थिरता से अधिक: प्रत्येक ने अपने विचार को पूरा किया कि कैसे एक पते को विभाजित किया जाए, और कैसे किया जाए अवतार कैश उस विभाजन पर कुंजी है, इसलिए सूची के बीच कोई असहमति और पढ़ने वाले फलक चुपचाप हिट दर को हल करेंगे और उसी व्यक्ति को दो दिखाएंगे। एक स्क्रीन पर विभिन्न तरीके। parseAddress अब केवल एक ही जगह एक RFC 5322 है पता अलग किया जाता है। सूची और धागा दृष्टिकोण भी कच्चे हेडर मुद्रण बंद जैसे "Jane Doe <jane@acme.com>" और नाम दिखाएं। पहचान अपने स्टोर में कभी संदेश वस्तुओं पर ध्यान नहीं देता है। दोनों सूची विचारों हर 30s पर और हर websocket अधिसूचना पर मतदान, हर बार अपने संदेश सरणी थोक की जगह - संदेश पर विलय होने वाली कुछ भी संदेश के लिए किया जाएगा एक मिनट में दो बार पोंछे, इसलिए एक निष्क्रिय इनबॉक्स मोनोग्राम और बैक के लिए फ़्लिकर फोटो होगा हमेशा के लिए पते से की भी मतलब है कि देर से चलने वाला जवाब पेंट नहीं कर सकता है गलत पंक्ति, क्योंकि पंक्तियां नहीं हैं कि यह क्या है? अनुरोधों को गठबंधन कर रहे हैं प्रति स्क्रीन एक बैच में: स्वतंत्र रूप से पूछने वाली पचास पंक्तियां पचास होगी अनुरोध करता है, और चूंकि इस सेवा के लिए प्रत्येक कॉल पहले एक बार की कुंजी को मिंट करता है। वास्तव में सौ। 45s के बाद एक बार याद किया जाता है, क्योंकि सर्वर-साइड संकल्प दो चरण है और एक अज्ञात पता केवल एक बाद कॉल पर उत्तर दिया जाता है। बातचीत लिस्टव्यू अब वर्चुअलाइज्ड है। यह 50 पंक्तियों को एक पृष्ठ और फिर से प्रस्तुत करता है उनमें से सभी प्रत्येक मतदान पर एक प्रति इंडेक्स के साथ एक AnimatePresence के अंदर हैं; प्रत्येक के लिए एक छवि जोड़ने के लिए यह मेलबॉक्स में सबसे भारी सतह बनाया। नो-रिप्लाई और मेलर-डेमन प्रेषकों को मोनोग्राम के बजाय एक तटस्थ निशान मिलता है - एक एक बाउंस नोटिस के बगल में चेहरा सक्रिय रूप से भ्रामक है। तस्वीरें सजावटी हैं (alt = ") क्योंकि नाम हमेशा उनके बगल में दिखाई देने वाला पाठ है, और ले जाना रेफररपॉलिसी="no-referrer" इसलिए एक धागा पहचानकर्ता कभी एक छवि होस्ट तक नहीं पहुंचता। प्रत्येक अवतार को अपने मूल से परोसा जाता है - तीसरे पक्ष के चित्र प्राप्त होते हैं, मान्य और फिर से होस्ट सर्वर-साइड - जो कि प्रति-निर्धारित नया होने देता है img-src नीति किरायेदार के अपने डोमेन के लिए पिन किया गया। यह नीति बनाई गई है अगले बजाय प्रॉक्सी। विन्यास क्योंकि यह मंच सफेद-लेबल है: एक स्थैतिक नीति को एक किरायेदार नाम देना होगा और बाकी के लिए छवियों को तोड़ देगा। यह संपर्क के बाद से एक पूर्व मौजूदा संग्रहीत ट्रैकिंग पिक्सेल वेक्टर को भी बंद कर देता है। फोटो एक मुफ्त टेक्स्ट URL है जो सीधे कई <img src> में प्रदान किया जाता है। अगले / छवि अब रिमोट एसवीजी स्वीकार नहीं करती है। यह एक स्वीकार्य जोखिम था जब केवल SVG हमारे अपने थीम लोगो थे; अब यह नहीं है कि मंच ingests अंक तीसरे पक्ष के DNS में प्रकाशित हुआ। संपर्ककर्ता हार्डकोडेड ORG ID = 1 और orgId क्वेरी पैरामीटर को छोड़ देते हैं, बैकेंड परिवर्तन से मेल खाती है जो सत्र से किरायेदारों को प्राप्त करती है।.
· EmailService
Avatar endpoints; fix unauthenticated reachability and contact tenancy
Adds the mailbox side of sender avatars, and fixes three pre-existing holes this work would otherwise have built on top of. AUTHENTICATION. OTKPreAuthFilter used to reject a *bad* OTK but treat *no* OTK as anonymous-and-allowed, falling straight through to the filter chain — and the Spring Security chain here is anyRequest().permitAll(). Every mailbox, contact and calendar endpoint was therefore readable by anything that could reach the ClusterIP. Protected prefixes now fail closed. The fix lives in the filter rather than in the security chain deliberately: reshaping the chain would touch thirty unrelated surfaces at once, including two servlets and the DAV endpoints. The exempt list is the complete set of genuinely session-less entry points — the CAN-SPAM opt-out link, the OAuth redirect target where the tenant rides in the signed state parameter, and the server-to-server surfaces that authenticate with X-Internal-Auth. CONTACT TENANCY. Every contacts endpoint took orgId as a query parameter, or reached a book by id with no ownership check at all, so changing a number in the URL read another tenant's contacts — names, addresses, phone numbers, notes. The org now comes from the session and every book- or group-scoped operation proves the target belongs to it. Absent targets return 404 rather than 403 so an id in another tenant is not confirmed to exist. orgId is still accepted on the two list endpoints and ignored, so clients do not break mid-deploy. That change also fixes a silent bug: searchContacts derived orgId from bookId and passed null when no book was selected, into a query whose first predicate is contactBook.organization.id = :orgId. Book-less search therefore always returned nothing — which is exactly how the mail recipient autocomplete calls it. EMAILLOGOSERVICE. It fetched an operator-supplied URL with no scheme or address check, and transcoded the result on a Batik that resolves external references by default. A logo SVG containing <image **************** would have been dereferenced from inside the cluster. Now guarded on both ends. MESSAGEINDEXER. resolveMemberIdFromEmail pulled the entire members table into heap and filtered it in Java, once per indexed message, on a 1Gi pod — the code said so in a TODO. Same semantics, one indexed query. The avatar surface is one batched endpoint rather than a field on the message DTOs. Both list views poll every 30s and replace their message array wholesale, so an avatar carried on a message would be wiped twice a minute and the UI would flicker forever; and EmailMessage is shared by the folder list, reading pane, thread view and search, so changing its shape would touch all of them at once. The directory-photo endpoint is server-to-server only — exposed to a browser it would be a directory-enumeration oracle for the tenant.
· SecurityService
Sender-avatar resolution chain for the mailbox
Resolves a correspondent's email address to a picture, working outward from what Kamo already knows: member photo, then a photo someone attached to a contact, then the tenant's connected Microsoft/Google directory, then the sender domain's BIMI mark, then its favicon, then Gravatar. Anything unresolved renders a monogram, so the chain always terminates locally. The directory tier is worth calling out: the connect flows here already request admin.directory.user (Google) and User.ReadWrite.All + Directory.Read.All (Microsoft) alongside the mail scopes, so for Workspace and 365 tenants this returns authoritative photos with no re-consent and no third party involved. It should beat anything on the public internet and usually will. Two phases, never one. A request reads cache only; unknowns go to a bounded worker with DiscardPolicy — running an overflowed task on the caller would hand a request thread to a third-party host, and a discarded resolve costs nothing because the next poll asks again. A full-miss chain is DNS plus four HTTP calls, and a page carries dozens of addresses; nothing about opening a folder may depend on third-party availability. Decoupling also keeps resolution from correlating with a human opening a message, which would make it a read receipt — the exact behaviour the mailbox already blocks by default for remote images. This is the platform's first fetcher whose target URL is chosen by an untrusted party: a BIMI record is DNS content published by whoever owns a sending domain, and anyone becomes a sending domain by emailing a tenant. There is no egress NetworkPolicy and no forward proxy, so the controls are in code. SafeImageFetcher pins DNS — a custom resolver hands OkHttp only the addresses that passed PublicHostGuard, closing the rebinding window that defeats a naive pre-flight check — refuses redirects, caps bytes as they stream rather than trusting Content-Length, and requires an image content-type. SvgSanitizer parses and re-serializes against an allowlist instead of rasterizing. Batik 1.17 resolves external resources by default, so handing it a hostile SVG would dereference <image **************** from inside the cluster after the URL check already passed. The Tiny PS profile forbidding that is a statement about conforming files, not about bytes fetched from an attacker's URL. Provider miss semantics are all different and all cache-poisoning if treated as hits: Gravatar is asked with d=404 because every other default returns 200 with a placeholder; Google's no-match is a 404 carrying a byte-identical globe, so it is rejected by content hash; DuckDuckGo returns 404 with a real image body, so status decides. Bytes are re-hosted under a random name — never one derived from the address, which would let anyone probe whether a given person corresponds with this platform — and served through an authenticated route. Redis holds metadata only. That instance is 2GB with allkeys-lru on an emptyDir, sharing a keyspace with every live session; caching image bytes there would evict sessions and sign users out at random.
· kamo-shared-library
Sender identity model + org-scoped batch email lookups
Backing store and queries for the mailbox sender-avatar chain. SenderIdentityEntity is the durable tier of the avatar cache. org_id is part of the natural key rather than decoration: USERS.EMAIL is unique only per security provider, so an answer derived from tenant data must not be visible to another tenant. External-tier answers (BIMI/favicon/Gravatar) are genuinely global and share a sentinel org so every tenant shares the hit rate. Misses are stored as rows, not absences — without that, every unresolvable sender re-runs the whole provider chain on every inbox poll. OrgAvatarSettingsEntity splits the chain by what actually leaves the building. The identity tier defaults OFF because it discloses a digest of a correspondent's full address to a third party, which on a lending CRM is a decision about a borrower identifier rather than a display preference. The repository additions exist because none of this was reachable before: - ContactEmailRepository had no lookup by address at all — only substring LIKE for the autocomplete — so a contact that had a photo could not be resolved from a From: header. - Member/User batch lookups are org-scoped and take pre-lowercased input. LOWER() is applied to the stored column only; emails are persisted verbatim (EmbEmail has no normalizer) and CockroachDB equality is case-sensitive. - The avatar-id projections return ids rather than entities on purpose. Both Member.avatar and User.avatar are lazy associations onto a JOINED hierarchy: a caller outside a transaction gets LazyInitializationException, and one inside gets a base-type proxy that never narrows to AvatarPhoto, putting the file extension needed to build the URL out of reach. - **************** replaces a findAll() full-table scan that ran once per indexed message. PublicHostGuard is shared rather than duplicated because it is a security control: it decides whether an address is somewhere we will send a request that an untrusted party chose. Tested against the real bypass techniques — IPv4-mapped IPv6, 6to4, NAT64, CGNAT and link-local metadata. Right 177 gates the disclosure decision.
· kamo-shared-library
Audit spine for PHI access — §164.312(b)
The Security Rule requires recording access to ePHI, which means reads. The platform records changes well — LeadHistory, SystemAccessLog, UserHistory, LoanAuditEvent — and reads almost nowhere, which is why "who viewed this record" is currently unanswerable. That is also the first question a §164.402 breach assessment asks, so this one gap blocks both the audit control and the four-factor analysis. Capture layer only; no schema. The durable store sits behind PhiAccessLogWriter so call sites can be wired now and the sink can evolve — plain table, then append-only with a hash chain, then a signed export to object-locked storage — without rippling back through hundreds of call sites. Two properties carry the weight: - Failure handling belongs to the access kind, not the caller. EXPORT, DOWNLOAD and DISCLOSE fail closed: an unlogged bulk export is exactly the event you cannot reconstruct afterwards, and "we served the data but lost the record" is the worst answer to give an investigator. VIEW, LIST and SEARCH fail open and log loudly, because losing one line is not worth taking the product down. That asymmetry is deliberate and wants signing off rather than assuming. Callers under pressure resolve policy questions in whichever direction unblocks them, so the policy is not at the call site. - A denied read is still a read. Refused attempts are recorded, because the access pattern of someone probing records they cannot reach is what detection needs and is invisible if only successes are logged. Startup safety, which nearly went wrong: PhiAccessRecorder is a @Component and every service component-scans com.kamo, so a hard dependency on a writer bean would have failed context startup across ~40 services at once — a whole-platform outage from a feature nothing had called. The first fix, a @Configuration with @ConditionalOnMissingBean, does not work: component-scanned configuration is processed alongside user configuration rather than after it, so both writers register and injection fails on ambiguity. PhiAuditContextWiringTest caught that. The fallback now lives in the recorder via ObjectProvider.getIfUnique, where no ordering question exists, and ambiguous writers degrade to the default rather than failing startup. The default Slf4j writer is a starting point, not the destination — log lines are not tamper-evident and retention is 14 days against a six-year obligation. It exists so call-site wiring does not wait on the store. Identifiers are logged, content never is: an audit trail that reproduces the record it audits has just moved the PHI into the log stream.
· SecurityService
500 के बजाय जब अनुपालन सीमा मना कर देती है
सुविधा के दो कॉल साइट्सService.enableFeature अब HIPAA सीमा को समझते हैं: - /सक्षम नक्शे PhiModuleNotPermittedException to 403 कारण, एप्लाइड मॉडलविओलेशन एक्सेप्शन को सीधे इसके ऊपर संभालना। बिना यह व्यापक पकड़ नीचे एक जानबूझकर नीति 500 में इनकार कर दिया। - लिस्टिंग पथ में ऑटो-सक्षम लूप पूर्व जांच के साथ isPhiPermitted और छोड़ो। यह प्रत्येक पूर्ण सेवाटाइप पर चलता है जबकि केवल * लिस्टिंग * संगठन की विशेषताएं, इसलिए पहले अवरुद्ध मॉड्यूल पर फेंकने के लिए बनाया जाएगा एक प्रविष्टि छिपाने के बजाय PHI किरायेदार के लिए पृष्ठ अनलोड करने योग्य सुविधाएँ। Inert आज - हर संगठन संभालती हैPhi=false.
· kamo-shared-library
Enforce the compliance boundary at the feature switch
Wires PhiTenantGuard into FeatureService, the single choke point through which a module is switched on for an organization. This is where the boundary stops being a policy object and starts being enforcement. Both halves, because either alone leaves a gap: - enableFeature throws PhiModuleNotPermittedException, so a PHI tenant cannot switch on a module Kamo cannot stand behind as a business associate. - isFeatureEnabled(Organization, ServiceType) reports a module disabled whenever the tenant handles PHI and the module is outside the boundary, whatever the OrgFeature row says. The row can legitimately say active — it was enabled before the tenant became a PHI tenant, and enableFeature does not run again on that transition. isPhiPermitted is the non-throwing form for callers that iterate. FeatureController auto-enables every completed feature while *listing*, so a throw on the first blocked module would fail the whole features page rather than skip one entry. PhiServiceTypeMapping binds ServiceType to PhiModule and is total, with a test that fails the build on any unmapped value. That test earned its keep on first run: it caught ServiceType.STORAGE, which a grep of the enum had missed, and then AI_CHAT, DOC_MANAGER, DOCS_EDITOR and DOC_CLASSIFIER. Without it, five service types would have been silently outside the boundary — the same omission failure PhiModule's constructor closes, reintroduced one layer up. New modules for the previously unmapped service types, each with an explicit disposition: object storage, document editor and classifier, support tickets, HR, inventory, legal, calculator and activity feed are inside; clubhouse and games are BLOCKED_PENDING_WORK on the grounds that they have not been assessed, which is a reason to block rather than to assume. Every organization is handlesPhi=false today, so this changes no behaviour in production. It becomes load-bearing the moment the first tenant is flagged.
· kamo-shared-library
आवेदन निर्माण पर एक MERS-संगत ऋण संख्या को ऑटो-assign करें
LoanFile.loanNumber निर्माण (दोनों रिक्त-create और lead-promote) पर null था। और केवल कभी सेट जब एक स्ट्वर्ड टाइप किया गया था - जो हार्ड-ब्लॉकेड MERS MIN मिंटिंग (A MIN's 10-digit section is the ऋण संख्या) और हर डाउनस्ट्रीम एक headless-originated ऋण के लिए पहचानकर्ता। AppMortgageService अब दोनों निर्माण स्थलों पर ऋण संख्या निर्धारित करता है: एक स्वच्छ 10-अंक संख्यात्मक (MinMinter स्ट्रिप्स गैर-अंकों और एक <= 10-अंक खंड की जरूरत है, इसलिए एक शुद्ध संख्यात्मक एकमात्र सुरक्षित आकार है, जो प्रति ऑर्ग के माध्यम से अद्वितीय है (org id, loan number) सूचकांक एक बाउंड्री के साथ। यह FAILS OPEN एक पर null करने के लिए टकराव streak या एक अनुपलब्ध रेपो - पूर्व मैनुअल में गिरावट कभी-कभी अनुप्रयोग निर्माण को तोड़ने के बजाय व्यवहार। एक lender-supplied संख्या अभी भी ऋण फ़ाइल पैच पथ के माध्यम से ओवरराइड करती है। कोई स्कीमा परिवर्तन नहीं स्तंभ पहले से ही मौजूद है।.
· kamo-signer-monorepo
रेंडर हस्ताक्षरकर्ता प्राप्तकर्ता के हल समयक्षेत्र में तारीख
SigningSession gains a required `timeZone` (आईएएनए id) that ESigService solution प्राप्तकर्ता के सदस्य क्षेत्र से, फिर org, फिर UTC। अब आपका स्वागत है इसे स्पष्ट रूप से प्रारूपित करने के लिए गुजरता है, इसलिए समाप्ति तिथि न तो निर्भर करती है दर्शक की डिवाइस सेटिंग्स और न ही प्रदाता की UTC डिफ़ॉल्ट। क्षेत्र बनाना वैकल्पिक बजाय आवश्यक एक साक्षर सत्र निर्माण स्थल पकड़ा (preview.ts) इसके अलावा: - स्थानीय लेआउट में कॉल सेटRequestLocale इसलिए अनुवाद URL से जुड़ा हुआ है अकेले मिडलवेयर हेडर पर भरोसा करने के बजाय सेगमेंट - डॉकरफ़ाइल में जोर देते हैं कि संदेश / जीवित रहने वाले `turbo prune`, और दस्तावेज़ क्यों .dockerignore निर्माण संदर्भ से बाहर .gitignore रखना चाहिए; उसके बिना युग्मन प्रून ने अनुवाद को छोड़ दिया और कच्चे कुंजी को प्रस्तुत करने वाले छवि जहाजों को छोड़ दिया जब तक कोई हस्ताक्षरकर्ता दस्तावेज़ खोलता है तब तक विफल नहीं होता
· ESigService
सदस्य से साइनर डिस्प्ले टाइमज़ोन को हल करें, फिर ऑर्ग
साइनिंग तिथियां किसी भी क्षेत्र में प्रस्तुत की गई थीं जो क्लाइंट डिफ़ॉल्ट रूप से, इसलिए एक लिफाफाफा 2026-08-03T05:00Z को प्रशांत हस्ताक्षरकर्ता को "अगस्त 3" पढ़ा जा सकता है जिसके लिए लिंक पहले से ही अगस्त 2 की शाम को मर चुका है। SigningSession अब एक सर्वर-रिसोल्ड IANA timeZone: प्राप्तकर्ता के पास जब वे एक सदस्य होते हैं और एक सेट करते हैं, तो स्वयं सदस्य। टाइमज़ोन संगठन.टाइमज़ोन, अन्य UTC। SignerZone परीक्षण के साथ एक शुद्ध संकल्पक है, प्रत्येक टाइमज़ोन टाइप मैप्स को अपने स्वयं के जोनआईडी पर जोर देते हुए एक नया एनम वैल्यू क्लाइंट-साइड रेंज इरोर को जहाज नहीं कर सकता है। इसके अलावा SigningSession.locale, जो enum नाम ("SPANISH") उत्सर्जित BCP-47 कोड ("es") के बजाय संकेत URL के स्थानीय खंड में इस्तेमाल किया।.
· InitializerService
HANDLES PHI और PHI EFFECTIVE DATE on orgs
ऑर्गेबेंडिंगफील्ड्सMigration के बाद, दो नए संगठन क्षेत्रों को मिरर करता है सम्मेलन, इसलिए स्तंभ केवल बजाय किसी भी वातावरण पर प्रत्यावर्ती हैं मौजूदा जहां एक ddl ऑटो पास रन करने के लिए हुआ था। HANDLES PHI नहीं है, इसलिए मौजूदा किरायेदार स्पष्ट रूप से बाहर हैं। अनुपालन सीमा। PHI EFFECTIVE DATE टाइमस्टैम्प है, नहीं टाइमस्टैम्प्ट्ज, क्योंकि इकाई क्षेत्र एक स्थानीय समय है। परीक्षण एक बहाव गार्ड है, एक विश्राम नहीं है: यह कॉलम नामों को पढ़ता है प्रतिबिंब द्वारा इकाई और बिल्ड को विफल करता है जब एक इकाई क्षेत्र में कोई ALTER नहीं होता है। कि यह सम्मेलन का वास्तविक विफलता मोड है - कोई फ़ील्ड जोड़ता है, भूल जाता है माइग्रेशन, और डीडीएल-ऑटो के साथ: सेवाओं में कोई भी यह एक उत्पादन के रूप में सतही नहीं है निर्माण समय के बजाय क्वेरी त्रुटि। उत्परिवर्तन द्वारा सत्यापित: हटाना PHI EFFECTIVE DATE ALTER यह कार्रवाई योग्य संदेश के साथ विफल बनाता है, इसे बहाल करता है हरा हो जाता है। दोनों स्तंभ पहले से ही क्लस्टर में मौजूद हैं; ये ALTER idempotent हैं।.
· kamo-shared-library
Persist संभालती हैPhi और phiEffectiveDate संगठन पर
एक वास्तविक स्तंभ के साथ पीठ PhiTenantGuard। HANDLES PHI (HANDLES) नहीं है। ******************* पैटर्न, तो हर मौजूदा किरायेदार स्पष्ट रूप से इसके अंदर चुपचाप के बजाय अनुपालन सीमा के बाहर है। PHI EFFECTIVE DATE एक उल्लंघन मूल्यांकन और एक अवधारण दायित्व के दायरे में आता है सही विंडो - "जब तक" पहले सवाल "क्या उजागर किया गया था" के बाद पूछा जाता है। ************* गार्ड स्वयं इकाई से मुक्त रहता है, इसलिए एक कॉलर केवल एक सत्र-कक्षित ध्वज धारण करता है एक पंक्ति लोड करने के लिए नहीं है। पुश करने के लिए सुरक्षित: दोनों कॉलम पहले से ही क्लस्टर में मौजूद हैं और प्रत्येक 12 में से प्रत्येक संगठन झूठ पढ़ते हैं। लैंडिंग से पहले information schema के खिलाफ सत्यापित - handle phi boolean not NULL DEFAULT झूठ, phi प्रभावी date timestamp NULL. Reproducible form के लिए KamoInitializer प्रवास देखें।.
· kamo-shared-library
PhiTenantGuard और मॉड्यूल अनुपालन सीमा
HIPAA अनुपालन सीमा: जो मॉड्यूल एक किरायेदार तक पहुंच सकता है, यह देखते हुए कि क्या उस किरायेदार ने स्वास्थ्य की सुरक्षा की है। सब कुछ इसे डाउनस्ट्रीम कुंज - कौन से एकीकरण अक्षम हैं, क्या MFA मजबूर है, जो सत्र सख्त टाइमआउट प्राप्त करते हैं, क्या लेखा परीक्षा रीढ़ को कवर करना चाहिए। कोई स्कीमा निर्भरता नहीं है। पहले के प्रयास ने इसे एक नया रूप दिया संगठन.handlesPhi स्तंभ और फिर से परिवर्तित किया जाना चाहिए: सेवा CI clones निर्माण समय में साझा-library मुख्य, जबकि KamoInitializer हाथ से चलाया जाता है, इसलिए एक इकाई स्तंभ मुख्य रूप से अगली सेवा को तोड़ने पर तब तक तैनात किया गया जब तक कि कोई प्रवासी न हो। इकाई से पॉलिसी को डीकूपलिंग का मतलब है कि यह भूमि है और इसे अब लागू किया जा सकता है, और स्तंभ एक स्वतंत्र कदम बन जाता है। तीन गुण डिजाइन के आसपास बनाया गया है: - विफल रहता है। Phimodule के निर्माता को एक PhiDisposition और एक कारण की आवश्यकता होती है, इसलिए एक मॉड्यूल जोड़ा बाद में चूक द्वारा अनुमति प्राप्त नहीं कर सकता - यह नहीं होगा बिना किसी निर्णय के संकलित करें, और किसी अन्य व्यक्ति के अलावा निजी डेनिज़। यही है विफलता मोड एक अनुपालन सीमा जीवित रहने के लिए है: एक मॉड्यूल जहाजों, कोई भी PHI के बारे में सोचता है, एक क्लिनिक इसका उपयोग शुरू होता है। - एक असुरक्षित किरायेदार एक सुरक्षित किरायेदार नहीं है। गार्ड एक त्रि-राज्य लेता है PhiTenantStatus बजाय एक boolean, तो "मैं संगठन को लोड नहीं कर सकता" "यह संगठन PHI नहीं है" के रूप में एक ही तरह से spelled नहीं किया जा सकता है। एक साथ बोलान, त्रुटि पथ isPermitted (false, ...) — के लिए पहुँचना आसान है, समीक्षा में स्पॉट करना असंभव है। UNKNOWN हर चीज़ को अस्वीकार करता है। - ऊंचा करने के लिए कुछ नहीं। निर्णय (स्टेटस, मॉड्यूल) का शुद्ध कार्य नहीं है कॉलर, सत्र, दाएं या भगवान मोड पैरामीटर। "हमारे समर्थन कर्मचारी इसे बदल सकते हैं "" वह जवाब है जो एक कवर इकाई की समीक्षा में विफल रहता है। Dispositions Kamo-internal में scoping विश्लेषण का पालन करें ************* अनुमति: CRM, संपर्क, दस्तावेज़ वॉल्ट, स्व-होस्टेड ईमेल, ई-सिग्न, नोट्स, कार्य, कैलेंडर, आंतरिक चैट, इन-क्लस्टर ट्रांसक्रिप्शन / ट्रांसलेशन स्टैक, एमएलओएस। कोई प्राप्त करने योग्य BAA के साथ अवरुद्ध: सामाजिक मैसेजिंग, Canva, ई-कॉमर्स सिंक, MCP गेटवे। अवरुद्ध लंबित नामित कार्य: एआई राउटर, आरएजी खोज, बैठक रिकॉर्डिंग, वीओआईपी रिकॉर्डिंग, विपणन अभियान, एनालिटिक्स निर्यात। अभी तक गार्ड को कॉल नहीं करता है, इसलिए यह वायर्ड होने तक निष्क्रिय है।.
· InitializerService
HANDLES PHI और PHI EFFECTIVE DATE on orgs
कामो साझा पुस्तकालय में संगठन इकाई पर दो नए क्षेत्रों को मिरर करता है, ऑर्गेब्रैंडिंगफील्ड्स माइग्रेशन कन्वेंशन के बाद। HANDLES PHI नहीं है इसलिए हर मौजूदा किरायेदार स्पष्ट रूप से अनुपालन के बाहर है इसके बजाय चुपचाप इसके अंदर सीमा। PHI EFFECTIVE DATE टाइमस्टैम्प है, नहीं TimeSTAMPTZ, क्योंकि इकाई क्षेत्र एक स्थानीय समय है। SEQUENCING - यह अगली सेवा तैनाती से पहले चलाने की जरूरत है। सेवा पिन एक निश्चित संस्करण में कामो-शेयर्ड-library जो जगह पर पुनर्प्रकाशित है, इसलिए पहला उस पुस्तकालय परिवर्तन के बाद पुनर्निर्माण करने के लिए सेवा इन स्तंभों का चयन शुरू होती है, और डीडीएल-ऑटो के साथ: उन सेवाओं में कोई नहीं जो इस धावक को निष्पादित होने तक विफल रहता है। परीक्षण एक बहाव गार्ड है, एक विश्राम नहीं: यह स्तंभ पढ़ता है प्रतिबिंब द्वारा इकाई का नाम बंद कर दिया गया है और यदि किसी इकाई क्षेत्र में कोई इकाई क्षेत्र नहीं है तो बिल्ड को विफल कर देता है ALTER. यही कारण है कि विफलता मोड इस पूरे सम्मेलन में है - कोई फ़ील्ड जोड़ता है, माइग्रेशन को भूल जाता है, और यह इसके बजाय उत्पादन क्वेरी त्रुटि के रूप में सतहों को भूल जाता है समय का निर्माण। उत्परिवर्तन द्वारा सत्यापित: PHI EFFECTIVE DATE ALTER को हटाकर इसे बनाता है कार्रवाई योग्य संदेश के साथ विफल, इसे बहाल करना हरा हो जाता है।.
· ESigService
हस्ताक्षर करने वाले लिंक में हस्ताक्षर करने वाले स्थानीय खंड का अनुकरण करें
Byte-for-byte डुप्लिकेट buildSignLink in SignLinkBuilder और संगठन.language से सोर्स किए गए स्थानीय खंड को जोड़ता है, गिर रहा है अनुवाद के बिना चार भाषाओं के मूल्यों के लिए वापस अंग्रेजी में। केमो-signer /{locale} / रूटिंग को पहले तैनात करने की आवश्यकता है।.
· kamo-shared-library
हैंडल जोड़ेंफ़ाई किरायेदार ध्वज और फ़िटेनेंटगार्ड
HIPAA अनुपालन सीमा: एक प्रतिसंगठन ध्वज प्लस एक गार्ड यह तय करते हुए कि कौन से मॉड्यूल तक पहुंच सकते हैं। डाउनस्ट्रीम इसे बंद कुंजी — कौन से एकीकरण विकलांग हैं, क्या MFA मजबूर है, जो सत्र सख्त टाइमआउट प्राप्त करते हैं, क्या लेखा परीक्षा की रीढ़ को कवर करना पड़ता है। संगठन लाभ HANDLES PHI (BOOL DEFAULT FALSE) और PHI EFFECTIVE DATE, मौजूदा ******************* पैटर्न का पालन करें। डिफ़ॉल्ट झूठी, इसलिए यह मौजूदा बंधक और सीआरएम पुस्तक के लिए निष्क्रिय है। तीन गुण डिजाइन के आसपास बनाया गया है: - विफल रहता है। Phimodule के निर्माता को एक PhiDisposition और एक कारण की आवश्यकता होती है, इसलिए एक मॉड्यूल जोड़ा बाद में चूक द्वारा अनुमति प्राप्त नहीं कर सकता - यह नहीं होगा बिना किसी निर्णय के संकलित करें, और किसी अन्य व्यक्ति के अलावा निजी डेनिज़। यही है विशिष्ट विफलता मोड एक अनुपालन सीमा जीवित रहने के लिए है: एक मॉड्यूल जहाजों, कोई भी PHI के बारे में नहीं सोचता, एक क्लिनिक इसका उपयोग शुरू होता है। - बाईपास करने योग्य नहीं। निर्णय (संगठन, मॉड्यूल) का एक शुद्ध कार्य है जिसके साथ कोई कॉलर, सत्र, सही या भगवान मोड पैरामीटर नहीं है, इसलिए कुछ भी नहीं है प्रासंगिक "हमारे समर्थन कर्मचारी इसे बंद कर सकते हैं" जवाब है कि एक कवर विफल रहता है इकाई की समीक्षा। - डेनियल एक कारण लेते हैं, क्योंकि एक नंगे "denied" समर्थन द्वारा उपयोग करने योग्य नहीं है इंजीनियर या ग्राहक। Dispositions Kamo-internal में scoping विश्लेषण का पालन करें ************* आज अनुमति दी: CRM, संपर्क, दस्तावेज़ वॉल्ट, सेल्फ-होस्टेड ईमेल, ई-सिग्न, नोट्स, कार्य, कैलेंडर, आंतरिक चैट, In-cluster transcription/translation stack, and MLOS. कोई प्राप्त करने योग्य के साथ अवरुद्ध BAA: सामाजिक संदेश, Canva, ई-कॉमर्स सिंक, MCP गेटवे। अवरुद्ध लंबित नाम कार्य: एआई राउटर, आरएजी खोज, बैठक रिकॉर्डिंग, वीओआईपी रिकॉर्डिंग, विपणन अभियान, विश्लेषण निर्यात। स्कीमा नोट: HANDLES PHI और PHI EFFECTIVE DATE सामग्री अगले पर है। कामोइनिटियलाइज़र रन, सीआई के बाद इस साझा पुस्तकालय निर्माण को प्रकाशित करता है। कुछ पढ़ाया नहीं अभी तक ध्वज, इसलिए ऑर्डरिंग सुरक्षित है।.
· kamo-signer-monorepo
स्थानीय तारीख स्वरूपण और प्रति स्थान मेटाडाटा

तुम्हारा ब्रह्मांड इंतजार कर रहा है.
मिनटों में मुफ्त शुरू करें. जब भी आप तैयार हों तो उत्पाद जोड़ें - कोई माइग्रेशन नहीं, कोई नया लॉगइन नहीं.
हमेशा के लिए मुफ्त - कोई क्रेडिट कार्ड की आवश्यकता नहीं