০৮ অক্টো, ২০২৫·8 মিনিট পড়তে

ডেটা লিক ছাড়াই অনুমতি-সচেতন গ্লোবাল সার্চ ডিজাইন

দ্রুত ইনডেক্সিং এবং প্রতিটি রেকর্ডে কঠোর অ্যাক্সেস চেক রেখে কীভাবে অনুমতি-সচেতন গ্লোবাল সার্চ ডিজাইন করবেন, যাতে ব্যবহারকারীরা দ্রুত ফল পায় কিন্তু ডেটা লিক না হয় তা শিখুন।

ডেটা লিক ছাড়াই অনুমতি-সচেতন গ্লোবাল সার্চ ডিজাইন

কেন গ্লোবাল সার্চ ডেটা ফাঁস করতে পারে

গ্লোবাল সার্চ সাধারণত মানে একটি সার্চ বক্স যা পুরো অ্যাপ স্ক্যান করে: গ্রাহক, টিকিট, ইনভয়েস, ডকুমেন্ট, ব্যবহারকারী এবং আরও যা-ই মানুষ কাজ করে। এটা প্রায়শই অটোকমপ্লিট এবং দ্রুত রেজাল্ট পেজ চালায় যাতে ব্যবহারকারীরা সরাসরি কোনো রেকর্ডে যেতে পারে।

ডেটা লিক তখন ঘটে যখন সার্চ এমন কিছু ফিরিয়ে দেয় যা ব্যবহারকারী দেখার অধিকার রাখে না। তারা রেকর্ড খুলতে না পারলেও, একটি এক লাইনের শিরোনাম, কারো নাম, ট্যাগ বা হাইলাইটেড স্নিপেটই সংবেদনশীল তথ্য ফাঁস করতে পারে।

সার্চকে অনেকেই "শুধু পড়ার মতো" মনে করে, তাই টিমগুলো এটি অবমূল্যায়ন করে। কিন্তু রেজাল্ট শিরোনাম ও প্রিভিউ, অটোকমপ্লিট সাজেশন, মোট ফলাফল সংখ্যা, "Customers (5)"-এর মতো ফ্যাসেট, এমনকি টাইমিং পার্থক্য—এসবের মাধ্যমে ডেটা ফাঁস হতে পারে।

এটি সাধারণত প্রথম দিনেই দেখা যায় না। শুরুতে টিমগুলো সার্চ লঞ্চ করে যখন কেবল একটি রোল আছে, বা যখন টেস্ট ডাটাবেসে সবাই সবকিছু দেখতে পারে। প্রডাক্ট বেড়ে উঠলে রোল যোগ করেন (সাপোর্ট বনাম সেলস, ম্যানেজার বনাম এজেন্ট) এবং শেয়ারড ইনবক্স, প্রাইভেট নোট, রেস্ট্রিক্টেড কাস্টমার, "শুধু আমার অ্যাকাউন্ট"-এর মতো ফিচার আসে। যদি সার্চ তখনও পুরানো অনুমানগুলোর ওপর নির্ভর করে, তখন এটি ক্রস-টিম বা ক্রস-কাস্টমার হিন্ট দেখাতে শুরু করে।

একটি সাধারণ ব্যর্থতা হল দ্রুততার জন্য "সবকিছু" ইনডেক্স করা, তারপর অ্যাপে কোয়েরির পরে রেজাল্ট ফিল্টার করা। এটা খুব দেরি। সার্চ ইঞ্জিন ইতিমধ্যেই ঠিক করে ফেলেছে কী ম্যাচ করে, এবং সীমাবদ্ধ রেকর্ডগুলো সাজেশন, কাউন্ট বা আংশিক ফিল্ডের মাধ্যমে উন্মোচন করতে পারে।

ভাবুন—একজন সাপোর্ট এজেন্ট যাকে কেবল তাদের অ্যাসাইন করা কাস্টমারের টিকিট দেখতে দেওয়া। সে "Acme" টাইপ করে এবং অটোকমপ্লিট দেখায় "Acme - Legal escalation" বা "Acme breach notification"। ক্লিক করলে যদি "access denied" মেসেজ দেখায় তবুও শিরোনামই একটি ডেটা লিক।

অনুমতি-সচেতন গ্লোবাল সার্চের লক্ষ্য বলা সহজ কিন্তু বাস্তবে কঠিন: দ্রুত, প্রাসঙ্গিক রেজাল্ট দিন একই সময়ে প্রতিটি রেকর্ড খোলার সময় যে নিয়মই প্রয়োগ করেন তেমনই অ্যাক্সেস নিয়ম আরোপ করুন। প্রতিটি কোয়েরির আচরণ এমন হওয়া উচিত যে ব্যবহারকারী কেবল তাদের ডেটার অংশই দেখতে পায়, এবং UI-টি অতিরিক্ত ইঙ্গিত (যেমন কাউন্ট) সেই অংশের বাইরে ফাঁস না করে।

আপনি কী ইনডেক্স করছেন এবং কী রক্ষা করতে হবে

গ্লোবাল সার্চ সহজ মনে হয় কারণ ব্যবহারকারী শব্দ টাইপ করে উত্তর আশা করে। আড়ালে, আপনি ডেটা এক্সপোজারের জন্য একটি নতুন সারফেস তৈরি করছেন। কোনো ইনডেক্স বা ডাটাবেস ফিচার বেছে নেওয়ার আগে দুটি বিষয় পরিষ্কার করুন: আপনি কোন বস্তুকে সার্চ করাচ্ছেন (entities), এবং সেই বস্তুগুলোর কোন অংশ সংবেদনশীল।

একটি entity হলো কোনো রেকর্ড যা কেউ দ্রুত খুঁজতে চায়। বেশিরভাগ ব্যবসায়িক অ্যাপে এখানে গ্রাহক, সাপোর্ট টিকিট, ইনভয়েস, অর্ডার, এবং ফাইল (বা ফাইল মেটাডেটা) থাকে। এতে মানুষ রেকর্ড (users, agents), অভ্যন্তরীণ নোট, এবং ইন্টিগ্রেশন বা API কী-র মত সিস্টেম অবজেক্টও থাকতে পারে। যদি এতে নাম, আইডি, বা স্ট্যাটাস থাকে যা কেউ টাইপ করতে পারে, সেটা সাধারণত গ্লোবাল সার্চে আসে।

প্রতি-রেকর্ড নিয়ম বনাম প্রতি-টেবিল নিয়ম

Per-table নিয়মগুলি সরল: টেবিল সমগ্র অ্যাক্সেসযোগ্য বা না—দুইটাই। উদাহরণ: কেবল ফাইন্যান্স বিভাগ Invoices পেজ খুলতে পারবে। এটা বোঝা সহজ, কিন্তু একই টেবিলের বিভিন্ন সারি আলাদা লোক দেখবে এমন ক্ষেত্রে এটি ভেঙে যায়।

Per-record নিয়ম সারিটি সারি ধরে দৃশ্যমানতা নির্ধারণ করে। উদাহরণ: একটি সাপোর্ট এজেন্ট তাদের টিমের অ্যাসাইন করা টিকিটগুলো দেখতে পাবে, যখন একটি ম্যানেজার তাদের অঞ্চলের সব টিকিট দেখতে পারবে। আরেকটি সাধারণ নিয়ম হলো tenant ownership: মাল্টি-টেন্যান্ট অ্যাপে, ব্যবহারকারী কেবল সেই রেকর্ডগুলো দেখতে পারে যেখানে customer_id = their_customer_id

এসব per-record নিয়মই যেখানে সার্চ সাধারণত লিক করে। যদি আপনার ইনডেক্স কোনো হিট ফিরিয়ে দেয় এবং তার আগে সারি অ্যাক্সেস না চেক করেন, আপনি ইতিমধ্যেই কিছু কিছুর অস্তিত্ব ফাঁস করে দিয়েছেন।

বাস্তবে "দেখার অনুমতি" কী বোঝায়

"অনুমতি আছে" বিরলভাবে কেবল একটি হ্যাঁ/না সুইচ। সাধারণত এটি ownership (আমার দ্বারা তৈরি, আমার কাছে অ্যাসাইন করা), membership (আমার টিম, আমার ডিপার্টমেন্ট, আমার ভূমিকা), scope (আমার অঞ্চল, বিজনেস ইউনিট, প্রজেক্ট), রেকর্ড অবস্থা (published, non-archived), এবং বিশেষ কেস (VIP গ্রাহক, legal holds, restricted tags) মিলিয়ে কাজ করে।

এই নিয়মগুলো প্রথমে সহজ ভাষায় লিখুন। পরে আপনি এটিকে একটি ডেটা মডেল ও সার্ভার-সাইড চেকসে রূপান্তর করবেন।

রেজাল্ট প্রিভিউতে কী দেখানো নিরাপদ

সার্চ রেজাল্ট প্রায়শই একটি প্রিভিউ স্নিপেট দেখায়, এবং স্নিপেট ব্যবহারকারী রেকর্ড খুলতে না পারলেও সংবেদনশীল তথ্য ফাঁস করতে পারে।

নিরাপদ ডিফল্ট হলো অ্যাক্সেস নিশ্চিত হওয়া পর্যন্ত কেবল ন্যূনতম, অ-সংবেদনশীল ফিল্ড দেখানো: একটি ডিসপ্লে নাম বা টাইটেল (প্রয়োজনে মাস্ক করা), একটি সংক্ষিপ্ত আইডেন্টিফায়ার (অর্ডার নম্বরের মতো), উচ্চ-স্তরের স্ট্যাটাস (Open, Paid, Shipped), একটি তারিখ (তৈরি বা আপডেট), এবং একটি সাধারণ entity লেবেল (Ticket, Invoice)।

কনক্রিট উদাহরণ: কেউ "Acme merger" সার্চ করলে যদি একটি রেস্ট্রিক্টেড টিকিট থাকে, "Ticket: Acme merger draft - Legal" দেখানো ইতিমধ্যেই লিক। নিরাপদ ফলাফল হতে পারে "Ticket: Restricted" কোনো স্নিপেট ছাড়াই, অথবা আপনার নীতি অনুযায়ী কোনও ফলাফল না দেখানো।

প্রথম থেকেই এগুলো ঠিক করে নিলে পরের সিদ্ধান্তগুলো সহজ হয়: কী ইনডেক্স করবেন, কীভাবে ফিল্টার করবেন, এবং কী প্রকাশ করতে রাজি আছেন।

নিরাপদ ও দ্রুত সার্চের মৌলিক দাবি

মানুষ গ্লোবাল সার্চ ব্যবহার করে যখন তারা দ্রুত খুঁজছেন। এক সেকেন্ডের বেশি যদি লাগে, তারা সেটার ওপর বিশ্বাস হারায় এবং ম্যানুয়াল ফিল্টারে ফিরে যায়। কিন্তু দ্রুততা কেবল আধা কাজ। দ্রুত কিন্তু একে-দ্বিতীয় গোপন রেকর্ড শিরোনাম, গ্রাহকের নাম বা টিকিট সাবজেক্ট ফাঁস করে তা সার্চ না থাকা থেকে খারাপ।

কোর রুল অ-আলোচ্য: পারমিশনগুলো কোয়েরি সময়ে প্রয়োগ করা হবে, কেবল UI-তে নয়। একটি সারি আপনার কাছে এনে পরে লুকানো হলে সেটা অনেক বড় ভুল — সিস্টেম ইতিমধ্যেই এমন ডেটা স্পর্শ করেছে যা এটা ফিরিয়ে দেওয়া উচিত ছিল না।

এটি শুধু চূড়ান্ত রেজাল্ট তালিকার জন্য নয়—সাজেশন, টপ হিট, কাউন্ট এবং এমনকি "কোনো রেজাল্ট নেই" আচরণও তথ্য ফাঁস করতে পারে। অটোকমপ্লিট যা কাউকে দেখতে না দেওয়া কিছু সাজেস্ট করে তা লিক। একটি ফ্যাসেট যা বলে "১২ মিলছে" যদি ব্যবহারকারী কেবল ৩টি দেখতে পারে তা লিক। এমনকি টাইমিংও লিক করতে পারে যদি রেস্ট্রিক্টেড ম্যাচ কোয়েরি ধীর করে।

একটি নিরাপদ গ্লোবাল সার্চে চারটি দরকারি বিষয়:

  • সঠিকতা: প্রতিটি ফিরে আসা আইটেম ব্যবহারকারীর জন্য, এই টেন্যান্টের জন্য এবং এই মুহূর্তে অনুমোদিত।
  • গতি: রেজাল্ট, সাজেশন, এবং কাউন্ট বড় স্কেলে নিয়মিত দ্রুত থাকতে হবে।
  • ধারাবাহিকতা: যখন অ্যাক্সেস বদলায় (রোল আপডেট, টিকিট পুনরায় অ্যাসাইন), সার্চ আচরণ দ্রুত ও পূর্বানুমেয়ভাবে বদলায়।
  • অডিটযোগ্যতা: ব্যাখ্যা করতে পারবেন কেন আইটেমটি ফিরেছে, এবং তদন্তের জন্য সার্চ কার্যকলাপ লগ করতে পারবেন।

একটি মনোভাবগত শিফট দরকার: সার্চকে আরেকটি ডেটা API হিসেবে বিবেচনা করুন, UI ফিচার হিসেবে নয়। এর মানে আপনি একই অ্যাক্সেস নিয়মগুলো যেভাবে লিস্ট পেজে প্রয়োগ করেন, একইভাবে ইনডেক্স বিল্ডিং, কোয়েরি এক্সিকিউশন, এবং সংশ্লিষ্ট এন্ডপয়েন্ট (অটোকমপ্লিট, রিসেন্ট সার্চ, পপুলার কোয়েরি) সব জায়গায় প্রয়োগ করবেন।

তিনটি প্রচলিত ডিজাইন প্যাটার্ন (কখন কোনটি ব্যবহার করবেন)

একটি সার্চ বক্স বানানো সহজ। অনুমতি-সচেতন গ্লোবাল সার্চ কঠিন কারণ ইনডেক্স তাত্ক্ষণিকভাবে ফলাফল ফিরিয়ে দিতে চায়, কিন্তু আপনার অ্যাপ কখনোই এমন রেকর্ড প্রকাশ করবে না যা ব্যবহারকারী দেখতে পারবেন না, এমনকি পরোক্ষভাবে।

নীচে তিনটি প্যাটার্ন দেওয়া হলো যা টিমগুলো প্রায়শই ব্যবহার করে। সঠিক পছন্দ নির্ভর করবে আপনার অ্যাক্সেস নিয়মগুলো কত জটিল এবং আপনি কত ঝুঁকি নিতে চান।

Approach A: index only "safe" fields, then fetch after a permission check. আপনি ইনডেক্সে একটি ন্যূনতম ডকুমেন্ট সংরক্ষণ করেন—যেমন আইডি প্লাস এমন একটি অ-সংবেদনশীল লেবেল যা যে কেউ সার্চ UI-তে প্রবেশ করতে পারে তাদের দেখানো নিরাপদ। ব্যবহারকারী রেজাল্টে ক্লিক করলে, আপনার অ্যাপ প্রধান ডাটাবেস থেকে পূর্ণ রেকর্ড লোড করে এবং বাস্তব পারমিশন নিয়ম সেখানে প্রয়োগ করে।

এতে লিকের ঝুঁকি কমে, কিন্তু রেজাল্ট পাতাগুলো পাতলা লাগতে পারে কারণ ব্যবহারকারীকে কম প্রাসঙ্গিক কন্টেক্সট দেয়। UI-তে সাবধানে লেখা দরকার যাতে "safe" লেবেল ভুল করে গোপন তথ্য প্রকাশ না করে।

Approach B: store permission attributes in the index and filter there. আপনি প্রতিটি ইনডেক্সড ডকুমেন্টে tenant_id, team_id, owner_id, role flags, বা project_id-এর মতো ফিল্ডগুলো রাখেন। প্রতিটি কোয়েরিতে বর্তমানে ব্যবহারকারীর স্কোপ মিলানোর জন্য ফিল্টার যোগ করা হয়।

এতে দ্রুত, সমৃদ্ধ রেজাল্ট এবং ভালো অটোকমপ্লিট মেলে, কিন্তু এটি তখনই কাজ করে যখন অ্যাকসেস নিয়মগুলো ফিল্টার হিসেবে প্রকাশযোগ্য। যদি পারমিশন জটিল লজিকের উপর নির্ভর করে (উদাহরণ: "assigned OR on-call this week OR part of an incident"), তাহলে সঠিক রাখা কঠিন হয়ে যায়।

Approach C: hybrid. Coarse filter in the index, final check in the database. আপনি ইনডেক্সে স্থিতিশীল, বৃহত্তর অ্যাট্রিবিউট (tenant, workspace, customer) দিয়ে ফিল্টার করেন, তারপর প্রাথমিক ডাটাবেসে ক্যান্ডিডেট আইডিগুলোর ছোট সেটের উপর পুনরায় পারমিশন চেক চালান before returning anything.

বাস্তবে অনেক অ্যাপের জন্য এটি সবচেয়ে নিরাপদ পথ: ইনডেক্স দ্রুত থাকে, এবং ডাটাবেস সত্যতা (source of truth) হিসেবে থাকে।

প্যাটার্ন নির্বাচন

পছন্দ করুন A যখন আপনি সবচেয়ে সহজ সেটআপ চান এবং ন্যূনতম স্নিপেট নিয়ে যেতে পারবেন। B পছন্দ করুন যখন আপনার স্পষ্ট, বেশিরভাগ সময় স্থির স্কোপ আছে (মাল্টি-টেন্যান্ট, টিম-ভিত্তিক অ্যাক্সেস) এবং খুব দ্রুত অটোকমপ্লিট দরকার। C বেছে নিন যখন আপনার অনেক রোল, এক্সসেপশন বা রেকর্ড-নির্দিষ্ট নিয়ম আছে যা প্রায়শই বদলায়। উচ্চ-ঝুঁকির ডেটা (HR, ফাইন্যান্স, মেডিকেল) হলে C প্রাধান্য দিন কারণ "প্রায় সঠিক" এখানে গ্রহণযোগ্য নয়।

ধাপে ধাপে: এমন একটি ইনডেক্স ডিজাইন করুন যা অ্যাকসেস নিয়ম সম্মান করে

রোল-ভিত্তিক অ্যাপ দ্রুত তৈরি করুন
শুরু থেকেই বাস্তব ভূমিকা ও সারি-স্তরের নীতির সঙ্গে দ্রুত role-based অ্যাপ ডিজাইন করুন।
অ্যাপ তৈরি করুন

নতুন টিমমেটকে বোঝানোর মতো ভাষায় আপনার অ্যাকসেস নিয়মগুলো লিখে শুরু করুন। "অ্যাডমিন সবকিছু দেখতে পারে" এড়িয়ে চলুন যদি এটা সত্যিই না হয়। স্পষ্ট করে লিখুন কেন কেউ একটি রেকর্ড দেখতে পারে: "সাপোর্ট এজেন্টরা তাদের টেন্যান্ট থেকে টিকিট দেখতে পারে। টিম লিডরা তাদের অর্গ ইউনিটের টিকিটও দেখতে পারে। কেবল টিকিট মালিক এবং অ্যাসাইন করা এজেন্ট প্রাইভেট নোট দেখতে পারে।" যদি আপনি বলতে না পারেন কেন কেউ রেকর্ড দেখতে পায়, তা নিরাপদভাবে এনকোড করা কঠিন হবে।

এরপর, একটি স্থির আইডেন্টিফায়ার বেছে নিন এবং একটি ন্যূনতম সার্চ ডকুমেন্ট নির্ধারণ করুন। ইনডেক্স আপনার ডাটাবেস রো-র পূর্ণ কপি হওয়া উচিত নয়। কেবল যা খুঁজতে ও রেজাল্টে দেখাতে প্রয়োজন এমনটুকুই রাখুন—যেমন টাইটেল, স্ট্যাটাস, এবং সম্ভব হলে ছোট একটি নন-সেন্সিটিভ স্নিপেট। সংবেদনশীল ফিল্ডগুলো দ্বিতীয়.Fetch-এর পিছনে রাখুন যা পারমিশন চেক করে।

তারপর সিদ্ধান্ত নিন কোন পারমিশন সিগন্যালগুলো দ্রুত ফিল্টার করা যাবে। এগুলো সেই অ্যাট্রিবিউট পুরোটাই যা অ্যাক্সেস গেট করে এবং প্রতিটি ইনডেক্সড ডকুমেন্টে রাখা যায়, যেমন tenant_id, org_unit_id, এবং কয়েকটি স্কোপ ফ্ল্যাগ। লক্ষ্য হলো প্রতিটি কোয়েরি ইনডেক্সে ফিল্টার প্রয়োগ করতে পারবে, অটোকমপ্লিটসহ।

একটি বাস্তবসম্মত ওয়ার্কফ্লো দেখায়:

  1. প্রতিটি entity (টিকিট, কাস্টমার, ইনভয়েস) জন্য দৃশ্যমানতার নিয়মগুলো plain language-এ নির্ধারণ করুন।
  2. record_id সহ একটি সার্চ ডকুমেন্ট স্কিমা তৈরি করুন যেটাতে কেবল নিরাপদ, সার্চযোগ্য ফিল্ড থাকবে।
  3. প্রতিটি ডকুমেন্টে filterable permission ফিল্ড (tenant_id, org_unit_id, visibility_level) যোগ করুন।
  4. এক্সসেপশনগুলো explicit grants দিয়ে হ্যান্ডল করুন: allowlist (user IDs) বা গ্রুপ IDs সংরক্ষণ করুন শেয়ারড আইটেমগুলোর জন্য।

শেয়ারড আইটেম এবং এক্সসেপশনই ডিজাইন ভাঙে। যদি একটি টিকিট টিম জুড়ে শেয়ার করা যায়, কেবল "একটি বুলিয়ান" যোগ করবেন না। এক্সপ্লিসিট গ্র্যান্ট ব্যবহার করুন যা ফিল্টার দিয়ে চেক করা যাবে। যদি allowlist বড় হয়, ব্যক্তিগত ইউজার আইডি বদলে গ্রুপ-ভিত্তিক গ্র্যান্ট প্রাধান্য দিন।

ইনডেক্সকে অবাক করা ছাড়াই সায়ংক্রোনাইজ রাখা

বিল্ড থেকে ডেপ্লয় পর্যন্ত যান
আপনার নিরাপদ সার্চ সার্ভিস AppMaster Cloud-এ বা নিজস্ব ক্লাউডে ডেপ্লয় করুন যখন প্রস্তুত।
ডেপ্লয় করুন

একটি নিরাপদ সার্চ অভিজ্ঞতার জন্য একটাই বিরক্তিকর বিষয় দরকার: ইনডেক্সকে বাস্তবতার সাথে সিঙ্কে রাখা। যদি একটি রেকর্ড তৈরি, পরিবর্তন, মুছে ফেলা বা তার পারমিশন বদলে যায়, সার্চ রেজাল্টগুলিও দ্রুত ও পূর্বানুমেয়ভাবে চলা উচিত।

create, update, delete-র সাথে তাল মিলিয়ে চলুন

ইনডেক্সিংকে আপনার ডেটা লাইফসাইকেলের অংশ হিসেবে বিবেচনা করুন। একটি ভাল মানসিক মডেল: সোর্স অফ ট্রুথ বদলিলে আপনি ইভেন্ট এমিট করবেন এবং ইনডেক্সার সেই অনুযায়ী প্রতিক্রিয়া জানাবে।

ডাটাবেস ট্রিগার, অ্যাপ্লিকেশন ইভেন্ট, বা একটি জব কিউ—কমন অ্যাপ্রোচগুলো। সবচেয়ে গুরুত্বপূর্ণ বিষয় হলো ইভেন্টগুলো লস্ট না হয়। যদি আপনার অ্যাপ রেকর্ড সেভ করতে পারে কিন্তু ইনডেক্স করতে ব্যর্থ হয়, তখন বিভ্রান্তিকর আচরণ হবে—"আমি জানি এটি আছে কিন্তু সার্চ এটা খুঁজে পাচ্ছে না।"

পারমিশন পরিবর্তন মানেই ইনডেক্স পরিবর্তন

অনেক লিক ঘটে যখন কনটেন্ট সঠিকভাবে আপডেট হয়, কিন্তু অ্যাক্সেস মেটাডেটা নয়। পারমিশন পরিবর্তন আসে রোল আপডেট, টিম মুভ, ওনারশিপ ট্রান্সফার, কাস্টমার reassignment, বা টিকিট মার্জের ফলে।

পারমিশন পরিবর্তনগুলোকে প্রথম শ্রেণির ইভেন্ট বানান। যদি আপনার পারমিশন-সচেতন সার্চ tenant বা team ফিল্টারের ওপর নির্ভর করে, নিশ্চিত করুন ইনডেক্সড ডকুমেন্টগুলোতে সেই ফিল্ডগুলো আছে (tenant_id, team_id, owner_id, allowed_role_ids)। যখন সেগুলো বদলায়, reindex করুন।

কঠিন অংশ হচ্ছে ব্লাস্ট রেডিয়াস: একটি রোল পরিবর্তন সম্ভবত হাজার হাজার রেকর্ড প্রভাবিত করবে। একটি বাল্ক রি-ইন্ডেক্স পথ পরিকল্পনা করুন যা প্রোগ্রেস, রিট্রাই এবং বিরতি দেয়ার উপায় রাখে।

ইভেন্টুয়াল কনসিসটেন্সির জন্য পরিকল্পনা

ভাল ইভেন্ট থাকলেও ইনডেক্স পিছিয়ে থাকবে এমন একটি উইন্ডো থাকবে। পরিবর্তনের কয়েক সেকেন্ড পর ব্যবহারকারীরা কী দেখতে পাবে এই বিষয়ে সিদ্ধান্ত নিন।

দুইটি নিয়ম সাহায্য করে:

  • বিলম্বগুলোর বিষয়ে ধারাবাহিক থাকুন। যদি ইনডেক্সিং সাধারণত 2-5 সেকেন্ডে শেষ হয়, তখন যখন তা গুরুত্বপূর্ণ, সেই প্রত্যাশা সেট করুন।
  • লিক হওয়ার থেকে অনুপস্থিতি বেছে নিন। নতুনভাবে অনুমোদিত রেকর্ড একটু দেরিতে দেখা গেলে নিরাপদ, কিন্তু নতুনভাবে প্রত্যাহারকৃত রেকর্ড দেখানো চলবে না।

ইনডেক্স স্টেল থাকলে একটি নিরাপদ ব্যাকফল কনফিগার করুন

সার্চ আবিষ্কারের জন্য; কিন্তু ডিটেইল দেখা থেকেই লিক হয়। রেজাল্টে দেখানোর আগে ডিটেইল রিড টাইমে দ্বিতীয়বার পারমিশন চেক করুন। যদি ইনডেক্স স্টেল হয়ে কোনো রেজাল্ট ফিসলে যায়, ডিটেইল পেজ তখনও অ্যাক্সেস ব্লক করা উচিত।

ভাল প্যাটার্ন: সার্চে ন্যূনতম স্নিপেট দেখান, তারপর ব্যবহারকারী রেকর্ড খুললে (বা প্রিভিউ বাড়ালে) পারমিশন পুনরায় চেক করুন। যদি চেক ব্যর্থ হয়, একটি স্পষ্ট মেসেজ দেখান এবং পরবর্তী রিফ্রেশে আইটেমটি রেজাল্ট সেট থেকে সরান।

ডেটা লিক ঘটায় এমন সাধারণ ভুলগুলো

আপনার "রেকর্ড খোলার" পেজ লকডাউন থাকলেও সার্চ ডেটা ফাঁস করতে পারে। ব্যবহারকারী হয়ত রেজাল্টে ক্লিকও না করবে কিন্তু নাম, কাস্টমার আইডি বা লুকানো প্রজেক্টের আকার জানতে পারে। অনুমতি-সচেতন গ্লোবাল সার্চকে একমাত্র ডকুমেন্টগুলো নয়, ডকুমেন্ট সম্পর্কিত হিন্টগুলিকেও রক্ষা করতে হবে।

অটোকমপ্লিট প্রায়ই লিকের উৎস। সাজেশনগুলো দ্রুত প্রিফিক্স লুকআপ দ্বারা চালিত হয় যা পূর্ণ পারমিশন চেক স্কিপ করে। UI ক্ষুদ্র মনে হলেও একটি টাইপ করা অক্ষর একটি কাস্টমার নাম বা কর্মীর ইমেইল প্রকাশ করতে পারে। অটোকমপ্লিটকে একই অ্যাক্সেস ফিল্টার চালাতে হবে যা ফুল সার্চ করে, অথবা প্রি-ফিল্টার করা সাজেশন সেট থেকে তৈরি করতে হবে (উদাহরণ: per-tenant এবং per-role)।

ফ্যাসেট কাউন্ট এবং "প্রায় ১,২৪৩ ফলাফল" ব্যানারও একটি নীরব লিক। কাউন্টই নিশ্চিত করে কিছু আছে এমন তথ্য, এমনকি আপনি রেকর্ড গোপন করলে। যদি আপনি একই অ্যাক্সেস নিয়মের অধীনে সেফলি কাউন্ট গণনা করতে না পারেন, তাহলে কম ডিটেইল দেখান বা কাউন্ট বাদ দিন।

ক্যাশিং আরেকটি সাধারণ কারণ। ব্যবহারকারীদের, রোলের, বা টেন্যান্টদের মধ্যে শেয়ার করা ক্যাশে "রেজাল্ট ভুত" তৈরি করতে পারে যেখানে একজন ইউজার অন্য কারও জন্য জেনারেট করা ফলাফল দেখে। এটা edge cache, অ্যাপ-লেভেল ক্যাশে, এবং সার্চ সার্ভিসের ইন-মেমরি ক্যাশেও ঘটতে পারে।

পরীক্ষা করার মতো লিক ট্র্যাপগুলো দ্রুত যাচাই করুন:

  • অটোকমপ্লিট ও রিসেন্ট সার্চগুলো ফুল সার্চের সমান নিয়ম দ্বারা ফিল্টার করা হচ্ছে কি না।
  • ফ্যাসেট কাউন্ট ও টোটালস পারমিশনের পরে হিসাব করা হচ্ছে কি না।
  • ক্যাশ কী-তে tenant ID এবং একটি permission signature (role, team, user ID) আছে কি না।
  • লগ ও অ্যানালিটিক্সrestricted ডেটার কাঁচা কিউয়ারী বা স্নিপেট সংরক্ষণ করছে না।

অবশেষে, ওভার-ব্রড ফিল্টারের দিকে চোখ রাখুন। "শুধু tenant দ্বারা ফিল্টার" হল ক্লাসিক মাল্টি-টেন্যান্ট ভুল, কিন্তু একই tenant-ভিত্তিক পরিবেশে এটাও ঘটে: "department দিয়ে ফিল্টার" যখন অ্যাক্সেস রেকর্ড-বাই-রেকর্ড। উদাহরণ: একটি সাপোর্ট এজেন্ট "refund" সার্চ করলে টেন্যান্টের সব গ্রাহকের ওপর ফলাফল পেতে পারে, যার মধ্যে VIP অ্যাকাউন্ট আছে যা কেবল ছোট একটি টিম দেখতে পারার কথা। সমাধান সহজ: প্রতিটি কোয়েরি পাথে (সার্চ, অটোকমপ্লিট, ফ্যাসেট, এক্সপোর্ট) সারি-স্তরের নিয়ম কঠোরভাবে প্রয়োগ করুন, কেবল রেকর্ড ভিউ-তে নয়।

মানুষ ভুলে যাওয়া প্রাইভেসি ও সিকিউরিটি বিস্তারিত

প্রতিটি স্থানে একটি অনুমতি চেক
একটি একক সার্চ ফ্লো তৈরি করুন যা ফলাফল, সাজেশন এবং এক্সপোর্টগুলো নিরাপদভাবে চালায়।
এখন তৈরি করুন

অনেক ডিজাইন "কে কী দেখতে পারে"-এ নজর দেয়, কিন্তু লিক এজেইসও ঘটে এজেসে: খালি স্টেট, টাইমিং, এবং UI-র ছোট ইঙ্গিতগুলোর মাধ্যমে। অনুমতি-সচেতন সার্চ এমনভাবে নিরাপদ হতে হবে যে সেটা কিছুই ফেরত না দিলেও নিরাপদ থাকে।

সহজ একটি লিক হলো অনুপস্থিতি দ্বারা নিশ্চিতকরণ। যদি একজন অননুমোদিত ব্যবহারকারী কোনো নির্দিষ্ট কাস্টমার নাম, টিকিট ID, বা ইমেইল সার্চ করে এবং বিশেষ বার্তা পায় যেমন "No access" বা "You don't have permission," তাহলে আপনি রেকর্ডটির অস্তিত্ব নিশ্চিত করে দিয়েছেন। "নো রেজাল্ট"-কে ডিফল্ট আউটকাম হিসেবে বিবেচনা করুন—ইহা একইভাবে "অস্তিত্ব নেই" এবং "আছে কিন্তু অনুমোদন নেই" উভয়ের জন্য। রেসপন্স টাইম ও ওয়ার্ডিং ধারাবাহিক রাখুন যাতে কেউ স্পীড দেখে অনুমান করতে না পারে।

সংবেদনশীল আংশিক ম্যাচ

অটোকমপ্লিট এবং টাইপ করলেই সার্চ এখানে প্রাইভেসি ফাঁস করে। ইমেইল, ফোন নম্বর, এবং সরকারি বা কাস্টমার আইডির ওপর আংশিক ম্যাচ বেশি প্রভাব ফেলতে পারে। এগুলো কিভাবে আচরণ করবে তা আগে থেকেই সিদ্ধান্ত নিন।

একটি বাস্তবসম্মত নীতি:

  • উচ্চ-ঝুঁকির ফিল্ড (ইমেইল, ফোন, আইডি) এর জন্য এক্সাক্ট ম্যাচ বাধ্য রাখুন।
  • এমন হাইলাইটেড স্নিপেট এড়িয়ে চলুন যা লুকানো টেক্সট প্রকাশ করে।
  • সংবেদনশীল ফিল্ডের জন্য অটোকমপ্লিট সম্পূর্ণ নিষ্ক্রিয় করার কথা ভাবুন।

যদি এক অক্ষর দেখালেই কেউ অনুমান করে নিতে পারে, তাহলে সেটাকে সংবেদনশীল ভাবুন।

এমন অ্যাবিউজ কন্ট্রোল যেগুলো নতুন ঝুঁকি না তৈরি করে

সার্চ এন্ডপয়েন্টগুলো এনুমারেশন আক্রমণের জন্য আদর্শ: অনেক কোয়েরি পাঠিয়ে কী আছে মানচিত্র করা। রেট লিমিট এবং অ্যানোমালি ডিটেকশন যোগ করুন, কিন্তু আপনি কি লগ করছেন তাও সাবধানে ভাবুন। র কাঁচা কিউয়ারী লগগুলো দ্বিতীয় লিক হয়ে উঠতে পারে।

সরল রাখুন: ইউজার, IP, এবং টেন্যান্ট প্রতি রেট লিমিট; লগ করুন কাউন্ট, টাইমিং, এবং মোটা প্যাটার্ন (পূর্ণ কিউয়ারী টেক্সট নয়); "near-miss" কোয়েরিগুলোর উপর এলার্ট করুন (যেমন ধারাবাহিক IDs); এবং বারবার ব্যর্থ হলে ব্লক বা স্টেপ-আপ করে যাচাই করুন।

আপনার এররগুলো নিরুপায় রাখুন। "নো রেজাল্ট", "নট অলাউড", এবং "ইনভ্যালিড ফিল্টার"-এর জন্য একই মেসেজ ও স্টেট ব্যবহার করুন। UI যত কম বলবে, তত কম দুর্ঘটনাক্রমে তা ফাঁস করবে।

উদাহরণ: সাপোর্ট টিম কিভাবে কাস্টমারের টিকিট সার্চ করে

আপনার সার্চকে একটি বাস্তব API বানান
একটি ব্যাকএন্ড তৈরি করুন যা সার্চ এবং রেকর্ড ভিউয়ের জন্য একই অ্যাকসেস নিয়ম প্রয়োগ করে।
ব্যাকএন্ড জেনারেট করুন

একজন সাপোর্ট এজেন্ট, Maya, তিনটি কাস্টমার অ্যাকাউন্ট দেখভাল করে এমন একটি টিমে কাজ করে। তার কাছে অ্যাপ হেডারে এক সার্চ বক্স আছে। প্রডাক্টে টিকিট, কন্টাক্ট, কোম্পানি সবকিছুর ওপর একটি গ্লোবাল ইনডেক্স আছে, কিন্তু প্রতিটি রেজাল্টকে অ্যাক্সেস নিয়ম মেনে চালানো উচিত।

Maya টাইপ করে "Alic" কারণ কলারে বলা হয়েছে নাম Alice। অটোকমপ্লিট কয়েকটি সাজেস্টশন দেখায়। সে ক্লিক করে "Alice Nguyen - Ticket: Password reset." কিছু খুলার আগে অ্যাপ রেকর্ডটির অ্যাক্সেস পুনরায় চেক করে। যদি টিকিট এখনও তার টিমে অ্যাসাইন করা থাকে এবং তার রোল এটিকে দেখতে দেয়, সে টিকিট পায়।

Maya প্রতিটি ধাপে যা দেখে:

  • সার্চ বক্স: দ্রুত সাজেশন আসে, কিন্তু কেবল সেই রেকর্ডগুলোর জন্য যা সে এখনই অ্যাক্সেস করতে পারে।
  • রেজাল্ট তালিকা: টিকিট সাবজেক্ট, কাস্টমার নাম, সর্বশেষ আপডেট সময়। কোনো "আপনি অ্যাক্সেস পাচ্ছেন না" প্লেসহোল্ডার নেই।
  • টিকিটের বিস্তারিত: ফুল ভিউ লোড হয় কেবল সার্ভার-সাইডে দ্বিতীয়বার পারমিশন চেকের পরে। যদি অ্যাক্সেস বদলে যায়, অ্যাপ দেখায় "Ticket not found" (না করে "forbidden").

এবার Leo-কে তুলনা করুন, যিনি প্রশিক্ষণে নতুন এজেন্ট। তার রোল কেবল "Public to Support" চিহ্নিত টিকিট এবং এক কাস্টমারের জন্য ভিউ দেয়। Leo একই কোয়েরি "Alic" টাইপ করে। সে কম সাজেশন পায়, এবং কোনও মিসিং আইটেমের ইঙ্গিত পায় না। কোনো "৫ ফলাফল" কাউন্ট নেই যা অন্য মিলগুলি আছে নিশ্চিত করে। UI কেবল যা সে খুলতে পারে তাই দেখায়।

পরবর্তীতে যদি একজন ম্যানেজার "Alice Nguyen - Password reset" Maya-এর টিম থেকে বিশেষ এসক্যালেশন টিমে রিসাইন করে, একটি ছোট উইন্ডো (সেকেন্ড থেকে কয়েক মিনিট, আপনার সিঙ্ক পদ্ধতির উপর নির্ভর করে) পরে Maya-এর সার্চ আর ঐ টিকিট ফিরিয়ে দেবে না। যদি সে বিস্তারিত পেজ খুলে রেখেই রিফ্রেশ করে, অ্যাপ পারমিশন পুনরায় চেক করে এবং টিকিটটি অদৃশ্য হয়ে যায়।

আপনি যা চান এমন আচরণ এটি: দ্রুত টাইপিং ও দ্রুত রেজাল্ট, কোনো কাউন্ট, স্নিপেট বা স্টেল্ড ইনডেক্স এন্ট্রির মাধ্যমে ডেটার গন্ধ না ফাঁস করে।

চেকলিস্ট ও পরবর্তী ধাপ নিরাপদভাবে ইমপ্লিমেন্ট করতে

অনুমতি-সচেতন গ্লোবাল সার্চ তখনই "সম্পন্ন" যখন বিরক্তিকর এজগুলো সুরক্ষিত। অনেক লিক সেই জায়গাগুলোতে ঘটে যা ক্ষুদ্র মনে হয়: অটোকমপ্লিট, রেজাল্ট কাউন্ট, এবং এক্সপোর্ট।

দ্রুত নিরাপত্তা চেকগুলি

রিলিজ করার আগে এই চেকগুলো বাস্তব ডেটা দিয়ে চালান, নমুনা ডেটা নয়:

  • অটোকমপ্লিট: ব্যবহারকারী যা খুলতে পারবে না এমন কোনো শিরোনাম, নাম বা ID সাজেস্ট করবেন না।
  • কাউন্ট ও ফ্যাসেট: যদি আপনি টোটাল বা গ্রুপ কাউন্ট দেখান, সেগুলো পারমিশনের পরে গণনা করুন (অথবা কাউন্ট বাদ দিন)।
  • এক্সপোর্ট ও বাল্ক অ্যাকশন: "ক্যারেন্ট সার্চ" এক্সপোর্ট করার সময় প্রতিটি সারিতে একেক করে অ্যাক্সেস পুনরায় চেক করুন।
  • সর্টিং ও হাইলাইটিং: এমন ফিল্ড ব্যবহার করে না সাজান বা হাইলাইট করুন যা ব্যবহারকারী দেখতে পারবে না।
  • "Not found" বনাম "forbidden": সংবেদনশীল entity-র জন্য একই রেসপন্স আকার বিবেচনা করুন যাতে ব্যবহারকারীরা অস্তিত্ব কনফার্ম না করতে পারে।

একটি টেস্ট পরিকল্পনা যা আপনি চালাতে পারেন

একটি ছোট রোল ম্যাট্রিক্স তৈরি করুন (roles x entities) এবং একটি ডেটাসেট বানান যেখানে ইচ্ছাকৃতভাবে জটিল কেস আছে: শেয়ারড রেকর্ড, সম্প্রতি প্রত্যাহৃত অ্যাক্সেস, এবং ক্রস-টেন্যান্ট দেখতে পারা মিল আছে।

এটি তিনটি ধাপে পরীক্ষা করুন: (1) রোল ম্যাট্রিক্স টেস্ট—অস্বীকৃত রেকর্ড কখনো রেজাল্ট, সাজেশন, কাউন্ট বা এক্সপোর্টে না আসে তা যাচাই করুন; (2) "ভাঙানোর চেষ্টা করুন"—IDs পেস্ট করা, ইমেইল বা ফোন দিয়ে সার্চ করা, এবং আংশিক ম্যাচ করা যা কিছুই ফিরিয়ে না দেওয়া উচিত তা পরীক্ষা করুন; (3) টাইমিং ও ক্যাশ টেস্ট—পারমিশন বদলে ফলাফল দ্রুত আপডেট হয় কিনা ভেরিফাই করুন।

অপারেশনালি, এমন দিনটির জন্য পরিকল্পনা রাখুন যখন সার্চ রেজাল্ট "ভুল লাগবে"। কিউয়ারীর প্রসঙ্গ (ব্যবহারকারী, রোল, টেন্যান্ট) এবং প্রয়োগ করা পারমিশন ফিল্টারগুলো লগ করুন, কিন্তু কাঁচা সংবেদনশীল কিউয়ারী স্ট্রিং বা স্নিপেট সংরক্ষণ এড়িয়ে চলুন। নিরাপদ ডিবাগিংয়ের জন্য একটি অ্যাডমিন-অনলি টুল বানান যা বুঝিয়ে বলতে পারে কেন একটি রেকর্ড মিলেছে এবং কেন তা অনুমোদনপ্রাপ্ত।

যদি আপনি AppMaster (appmaster.io)-এর ওপর নির্মাণ করছেন, একটি ব্যবহারিক পন্থা হলো সার্চকে সার্ভার-সাইড ফ্লো হিসেবে রাখা: Data Designer-এ entities এবং relations মডেল করুন, Business Processes-এ অ্যাক্সেস নিয়ম প্রয়োগ করুন, এবং অটোকমপ্লিট, রেজাল্ট তালিকা, ও এক্সপোর্টের জন্য একই পারমিশন চেক পুনরায় ব্যবহার করুন—তাতে কেবল এক জায়গায় এটি ঠিক রাখতে হবে।

শুরু করা সহজ
কিছু আশ্চর্যজনকতৈরি করুন

বিনামূল্যের পরিকল্পনা সহ অ্যাপমাস্টারের সাথে পরীক্ষা করুন।
আপনি যখন প্রস্তুত হবেন তখন আপনি সঠিক সদস্যতা বেছে নিতে পারেন৷

এবার শুরু করা যাক