অধ্যায় 2 · ন্যায্যতা ও ডেটা
ডেটা গভর্ন্যান্স: উদ্দেশ্য, সম্মতি, ন্যূনতম ডেটা, মান ও পুনঃশনাক্তকরণ
- পৃষ্ঠা 7 / 22
- 18 মিনিট পড়া
বিগিনার পাতা গোপনীয়তা, সম্মতি ও ডেটা ব্যবহার: AI টুলে আপনি কী শেয়ার করেন এবং ডেটা অধিকার, সংরক্ষণ ও গোপনীয়তার অনুশীলন: মানুষকে রক্ষা করার অভ্যাস আপনাকে একজন মানুষের একটা টুল ব্যবহারের অভ্যাস দিয়েছিল। একটা টিমের দরকার রেকর্ড: কোন ডেটাসেট আছে, কার মালিকানায়, প্রতিটা ফিল্ড কীসের জন্য, আর প্রতিটা এরপর কোন কাজে লাগানো যাবে। এই পাতা শুরু হয় চলমান উদাহরণ, অর্থাৎ এক নম্বর পাতার স্ক্রিনিং ফিচার দিয়ে, আর সেই রেকর্ড বানায় এমন Python দিয়ে যা ফাঁক অনুমান না করে জানিয়ে দেয়।
আপনার দরকার Python 3.12, শুধু স্ট্যান্ডার্ড লাইব্রেরি। ব্লকগুলো ক্রমে একটা সেশনে লিখুন; এগুলো ভেরিয়েবল ভাগ করে নেয়, আর প্রতিটা ব্লকের নিচের লেখাটা তার আসল আউটপুট।
সততার নিয়ম। প্রতিটা ডেটাসেট, কোম্পানি, ভূমিকা ও সংখ্যা কাল্পনিক এবং
Toy data:লেবেল দেওয়া। ফলাফল শুধু দেখায় একটা হিসাব কীভাবে কাজ করে। এগুলো কোনো বাস্তব সিস্টেমের প্রমাণ নয়, আর এখানে কিছুই আইনি পরামর্শ নয়। নৈতিক উদ্বেগ, আইনি বাধ্যবাধকতা আর কোম্পানির পলিসি আলাদা জিনিস; এই পাতা দেখায় কোনটা কোনটা।
যা শিখবেন
- ডেটার উৎস ও মালিকের তালিকা কীভাবে বানাবেন, প্রতিটা ফিল্ডের উদ্দেশ্য কীভাবে লিখবেন, আর একটা প্রোগ্রামকে দিয়ে কীভাবে অনুপস্থিত এন্ট্রি জানাবেন।
- ডেটা সংগ্রহের কর্তৃত্ব আর পুনর্ব্যবহারের অনুমতির পার্থক্য কীভাবে করবেন, এবং অনুমতি অনুপস্থিত বা অস্পষ্ট হলে কী করবেন।
- প্রোভেন্যান্স ও রূপান্তর কীভাবে নথিভুক্ত করবেন, আর ডি-আইডেন্টিফাইড টেবিলে পুনঃশনাক্তকরণের ঝুঁকি কীভাবে গুনবেন।
- সম্মতির মান ও ক্ষমতার ভারসাম্যহীনতা কীভাবে বিচার করবেন, সংরক্ষণ ও মুছে ফেলার নিয়ম কীভাবে লিখবেন, এবং ডেটায় প্রবেশাধিকার কীভাবে কাজের দায়িত্বের সঙ্গে মেলাবেন।
- সংস্থার সীমানা পেরিয়ে ডেটা স্থানান্তরের তালিকা কীভাবে বানাবেন।
ইনভেন্টরি: উৎস, মালিক ও অনুমতি
ডেটার উৎস ও তাদের মালিকের ইনভেন্টরি বানান। ডেটা ইনভেন্টরি প্রতিটা ডেটাসেট তালিকাভুক্ত করে এবং প্রতিবার একই প্রশ্নের উত্তর দেয়: কোথা থেকে এসেছে, কে দায়ী (একজন নামধারী ভূমিকা, "টিম" নয়), কেন রাখা হয়েছে, কোন অনুমতির অধীনে সংগ্রহ হয়েছে, নতুন ফিচারের জন্য পুনর্ব্যবহার চলবে কি না, কোথা দিয়ে গেছে, আর কত দিন রাখা হবে। প্রোগ্রামের নিয়ম: ফাঁকা উত্তর MISSING হিসেবে জানানো হয়, আর অস্পষ্ট উত্তর ("not stated", "unknown") UNCLEAR হিসেবে। সে কখনো ফাঁক পূরণ করে না।
টয় ডেটা: ShortlistHelper-এর জন্য Harbourline Staffing-এর হাতে থাকা চারটা কাল্পনিক ডেটাসেট।
NEED = ["source", "owner", "purpose", "collected_under", "reuse_ok", "provenance", "retention"]
UNCLEAR = {"", "not stated", "unknown", "tbc"}
INVENTORY = {
"D1 applicant CVs": {"source": "applicants upload", "owner": "Head of recruitment",
"purpose": "assess applicants for one job", "collected_under": "application notice v3",
"reuse_ok": "not stated", "provenance": "upload, then text extracted by vendor tool",
"retention": "12 months after the job closes"},
"D2 past hiring outcomes": {"source": "agency records", "owner": "Head of recruitment",
"purpose": "label for scoring tests", "collected_under": "employment records",
"provenance": "exported 2026-02"},
"D3 job requirements": {"source": "hiring managers", "owner": "Head of recruitment",
"purpose": "tell the feature what a job needs", "collected_under": "internal work product",
"reuse_ok": "yes, internal", "provenance": "typed by hiring manager", "retention": "3 years"},
"D4 public profiles": {"source": "public web", "purpose": "extra signals",
"collected_under": "public web", "reuse_ok": "unknown"},
}
def review(inventory):
for name, rec in inventory.items():
missing = [f for f in NEED if f not in rec]
unclear = [f for f in NEED if f in rec and rec[f] in UNCLEAR]
print(f"{name:<25} MISSING: {', '.join(missing) or '-'} | UNCLEAR: {', '.join(unclear) or '-'}")
review(INVENTORY)D1 applicant CVs MISSING: - | UNCLEAR: reuse_ok
D2 past hiring outcomes MISSING: reuse_ok, retention | UNCLEAR: -
D3 job requirements MISSING: - | UNCLEAR: -
D4 public profiles MISSING: owner, provenance, retention | UNCLEAR: reuse_okশুধু D3 সম্পূর্ণ। D1-এর মালিক ও উদ্দেশ্য আছে, কিন্তু তার সিভিগুলো স্কোরিং ফিচার পরীক্ষায় পুনর্ব্যবহার করা যাবে কি না তা কেউ লিখে রাখেননি। D2-তে পুনর্ব্যবহারের উত্তর আর সংরক্ষণের নিয়ম নেই। D4-এর মালিক, প্রোভেন্যান্স ও সংরক্ষণ নেই, আর অনুমতি "unknown": প্রকাশ্য হওয়া মানে প্রবেশাধিকারের তথ্য, অনুমতির উত্তর নয় (গোপনীয়তা ও ডেটা ব্যবহারের বিগিনার পাতা কথায় এই কথাটাই বলেছিল)।
প্রতিটা ডেটা ফিল্ডের উদ্দেশ্য লিখে রাখুন। একই ধারণা এক স্তর নিচেও খাটে। কোনো ফিল্ড কীসের জন্য তা কেউ বলতে না পারলে সবচেয়ে নিরাপদ প্রশ্ন হলো, তাকে রাখা আদৌ উচিত কি না।
FIELDS = {"name": "contact the applicant after shortlisting", "email": "contact the applicant after shortlisting",
"cv_text": "the fit score for one job", "postcode": "estimate the commute",
"date_of_birth": "", "photo": ""}
for field, purpose in FIELDS.items():
print(f"{field:<14}", purpose or "MISSING: remove it, or write the purpose and who approved it")name contact the applicant after shortlisting
email contact the applicant after shortlisting
cv_text the fit score for one job
postcode estimate the commute
date_of_birth MISSING: remove it, or write the purpose and who approved it
photo MISSING: remove it, or write the purpose and who approved itদুটো ফিল্ডের কোনো উদ্দেশ্য নেই। তৃতীয়টা, postcode-এর উদ্দেশ্য আছে, কিন্তু পাঁচ নম্বর পাতা দেখিয়েছে সাধারণ চেহারার একটা ইনপুট কীভাবে সুরক্ষিত বৈশিষ্ট্যের প্রক্সি হতে পারে, তাই উদ্দেশ্য থাকলেই রিভিউ শেষ হয় না। লিখে রাখলেই রিভিউটা করা যায়।
সংগ্রহের কর্তৃত্ব ও পুনর্ব্যবহারের অনুমতি
সংগ্রহের কর্তৃত্ব আর পুনর্ব্যবহারের অনুমতির পার্থক্য করুন। সংগ্রহের কর্তৃত্ব হলো সেই অনুমতি বা যুক্তি, যার অধীনে ডেটা প্রথমে সংগ্রহ হয়েছিল, মানুষকে যে উদ্দেশ্য বলা হয়েছিল তার জন্য। পুনর্ব্যবহারের অনুমতি আলাদা প্রশ্ন: সেই অনুমতি এই নতুন ব্যবহারকে ঢাকে কি না? ডেটা হাতে থাকা কোনো উত্তর নয়।
কাল্পনিক পরিস্থিতি:
Situation: Harbourline wants to test ShortlistHelper on last year's CVs (D1).
Collected: under "application notice v3": "we use your CV to assess your application".
New use: scoring tests for a tool. The notice does not mention tools or testing.
Question: does the original permission cover the new use? Nobody has decided.
Options: A use D1 anyway; B ask applicants for a separate, optional permission;
C use only CVs collected after a new notice; D test on synthetic CVs, not D1.
Unknowns: how the privacy owner reads the notice; what applicants would reasonably expect.যুক্তিসঙ্গত মানুষ এটা আলাদাভাবে ওজন করেন। A সবচেয়ে দ্রুত, আর নোটিশ ব্যাপক হলে এবং গোপনীয়তা দায়িত্বপ্রাপ্ত একমত হলে তা সমর্থনযোগ্য হতে পারে; কিন্তু আবেদনকারীরা এটা আশা করেননি, আর ভুল হলে অনেক মানুষ প্রভাবিত হন। B পছন্দের সম্মান করে, কিন্তু ছোট ও স্বনির্বাচিত স্যাম্পল দেয়, যা পরীক্ষাকে বাঁকা করতে পারে। C পরিষ্কার কিন্তু ধীর। D বাস্তবতা কমায়। সিদ্ধান্তের প্যাটার্ন বলে বেছে নিন, শর্ত ও একজন জবাবদিহিকারী ঠিক করুন: যেমন "এখন D, ছয় মাসের মধ্যে C, আর A কখনো গ্রহণযোগ্য হবে কি না তা গোপনীয়তা দায়িত্বপ্রাপ্ত ঠিক করবেন"। নোটিশের আইনি ব্যাখ্যা আপনার গোপনীয়তা বা আইনি দায়িত্বপ্রাপ্তের কাজ; ইনভেন্টরির কাজ প্রশ্নটাকে দৃশ্যমান করা।
প্রোভেন্যান্স ও রূপান্তর
ডেটার প্রোভেন্যান্স ও রূপান্তর নথিভুক্ত করুন। প্রোভেন্যান্স (provenance) হলো একটা ডেটাসেটের ইতিহাস: কোথায় শুরু, আর তার ওপর কী করা হয়েছে। রূপান্তর মানে যেকোনো পরিবর্তন: টেক্সট বের করা, নাম সরানো, মেলানো, ছাঁকা, লেবেল দেওয়া। প্রতিটা ধাপ তথ্য হারাতে, ভুল যোগ করতে বা গোপনীয়তার অবস্থা বদলাতে পারে, তাই প্রতিটা ধাপ তারিখ এবং একজন মানুষ বা টুলের নামসহ লেখা হয়।
টেমপ্লেট:
Provenance record: D1 applicant CVs
step date who or what action effect to note
1 2026-03-01 applicants uploaded CV files original, with names
2 2026-03-02 vendor text tool extracted plain text tables and layout lost
3 2026-03-05 recruitment analyst replaced names with codes pseudonymised; key held by
Head of recruitment
4 2026-03-06 analyst dropped CVs under 50 words sample now skews to long CVs
Unknown: how the vendor tool treats non-Latin scripts. Owner of this record: analytics lead.৪ নম্বর ধাপটা ভুলে যাওয়া সহজ, অথচ পরে তা গুরুত্বপূর্ণ: একটা ফিল্টার ঠিক করে ডেটায় কারা থাকবেন, আর তাই (ছয় নম্বর পাতার) কোনো ন্যায্যতা টেবিল কী বলতে পারে। ৩ নম্বর ধাপ সিউডোনিমাইজেশন (pseudonymisation), যা নিচে আলোচিত: চাবি (key) থাকা পর্যন্ত কোডগুলোও ব্যক্তিগত ডেটা।
অনুপস্থিত বা অস্পষ্ট অনুমতি
অনুপস্থিত বা অস্পষ্ট ডেটা-অনুমতি চিহ্নিত করুন। ইনভেন্টরির আউটপুট ইতিমধ্যে ঘটনাগুলো দেখিয়েছে। সবচেয়ে সতর্ক থেকে কম সতর্ক পর্যন্ত একটা কাজের উপায়:
| পর্যবেক্ষণ | সাধারণ প্রতিক্রিয়া | কে ঠিক করেন |
|---|---|---|
মালিক MISSING (D4) | নামধারী মালিক না থাকা পর্যন্ত ব্যবহার বন্ধ | বিভাগীয় প্রধান |
পুনর্ব্যবহার UNCLEAR (D1) | থামুন; গোপনীয়তা দায়িত্বপ্রাপ্তকে জিজ্ঞেস করুন; ততক্ষণ কম ঝুঁকির বিকল্প ব্যবহার করুন | গোপনীয়তা দায়িত্বপ্রাপ্ত |
সংরক্ষণ MISSING (D2) | নিয়ম ঠিক করার তারিখসহ সময়সীমা দিয়ে স্বল্প সময় চালানো যায় | ডেটার মালিক |
| প্রকাশ্য, অনুমতি অজানা (D4) | উৎসের শর্ত ও প্রযোজ্য নিয়ম যাচাই না হওয়া পর্যন্ত সীমাবদ্ধ হিসেবে ধরুন | গোপনীয়তা বা আইনি দায়িত্বপ্রাপ্ত |
ডি-আইডেন্টিফাইড ডেটায় পুনঃশনাক্তকরণ
ডি-আইডেন্টিফাইড ডেটায় পুনঃশনাক্তকরণের ঝুঁকি মূল্যায়ন করুন। নাম সরালেই একটা টেবিল বেনামি হয় না। কোয়াসি-আইডেন্টিফায়ার হলো সাধারণ বৈশিষ্ট্য (এলাকা, জন্মসাল, পেশা) যা একা অনন্য নয়, কিন্তু একসঙ্গে একজন মানুষকে আলাদা করে দিতে পারে, বিশেষ করে যখন অন্য কারও কাছে নামসহ একই বৈশিষ্ট্যের আরেকটা তালিকা থাকে। একটা সহজ যাচাইয়ে প্রতিটা সংমিশ্রণে কতগুলো রেকর্ড আছে তা গোনা হয়। k-anonymity-ধাঁচের গণনা জিজ্ঞেস করে: ক্ষুদ্রতম গ্রুপের আকার k কত, আর কতগুলো রেকর্ড নিজের গ্রুপে একা (k = 1)?
টয় ডেটা: ৪০ জন কাল্পনিক মানুষ, নির্দিষ্ট সিড দিয়ে বানানো, জেলা, জন্মসাল, পেশা ও একটা ব্যক্তিগত ফলাফলসহ।
import random
from collections import Counter
rng = random.Random(42)
RECORDS = [{"district": rng.choice(["D1", "D2", "D3", "D4", "D5"]), "birth_year": rng.randint(1980, 1999),
"role": rng.choice(["analyst", "nurse", "driver", "teacher"]),
"outcome": rng.choice(["yes", "no"])} for _ in range(40)]
REGION = {"D1": "R1", "D2": "R1", "D3": "R2", "D4": "R2", "D5": "R2"}
LEVELS = {"exact": lambda r: (r["district"], r["birth_year"], r["role"]),
"coarse": lambda r: (REGION[r["district"]], r["birth_year"] // 10 * 10, r["role"]),
"coarser": lambda r: (REGION[r["district"]], r["role"])}
for name, key in LEVELS.items():
sizes = Counter(key(r) for r in RECORDS)
alone = sum(1 for v in sizes.values() if v == 1)
print(f"{name:<8} groups {len(sizes):>2} | records alone {alone:>2} | smallest group k = {min(sizes.values())}")exact groups 40 | records alone 40 | smallest group k = 1
coarse groups 15 | records alone 4 | smallest group k = 1
coarser groups 8 | records alone 1 | smallest group k = 1এক্স্যাক্ট টেবিলে ৪০ জনই নিজের গ্রুপে একা। সাধারণীকরণ করলে (জেলা থেকে অঞ্চল, জন্মসাল থেকে দশক) একা থাকে ৪ জন; আরও সাধারণীকরণে ১ জন। এবার একটা লিংকেজ পরীক্ষা: অন্য কোনো উৎস থেকে নামসহ একটা দ্বিতীয় তালিকা (এটাও কাল্পনিক)। প্রতিটা স্তরে কতজনকে আলাদা করা যায়, আর ব্যক্তিগত ফলাফল কী প্রকাশ করবে?
PUBLIC = [("Ana", RECORDS[3]), ("Bo", RECORDS[8]), ("Cy", RECORDS[15]), ("Di", RECORDS[22]),
("Eli", RECORDS[30]), ("Fay", {"district": "D2", "birth_year": 1990, "role": "nurse"})] # Fay is not in the table
for name, key in LEVELS.items():
learned = []
for person, attrs in PUBLIC:
match = [r for r in RECORDS if key(r) == key(attrs)]
if len(match) == 1:
learned.append(f"{person}={match[0]['outcome']}")
print(f"{name:<8} singled out {len(learned)} of {len(PUBLIC)}:", ", ".join(learned) or "none")exact singled out 5 of 6: Ana=yes, Bo=no, Cy=no, Di=no, Eli=no
coarse singled out 1 of 6: Fay=yes
coarser singled out 0 of 6: noneএক্স্যাক্ট স্তরে নামধারী ছয়জনের পাঁচজনকে আলাদা করা যায় এবং তাঁদের ব্যক্তিগত ফলাফল পড়ে ফেলা যায়। মোটা (coarse) স্তরে একজন মেলে, আর সেই মিল ভুল: Fay টেবিলে আদৌ নেই। মোটা ডেটায় একটা অনন্য মিল অন্য কোনো মানুষের হতে পারে, আর সাধারণীকরণ এভাবেও মানুষকে রক্ষা করে। এই যাচাইয়ের সীমা গুরুত্বপূর্ণ। এটা শুধু আপনার বাছা বৈশিষ্ট্য ব্যবহার করে; বাইরের কেউ আরও জানতে পারেন। সংবেদনশীল কলাম নিয়ে এটা কিছু বলে না: কোনো গ্রুপের সবার ফলাফল এক হলে k = 5 হলেও ফলাফল ফাঁস হয়। এটা একটা স্ক্রিনিং গণনা, গ্যারান্টি নয়, আইনি পরীক্ষাও নয়।
নথিভুক্ত ঘটনা:
Year: 2008 (IEEE Symposium on Security and Privacy; arXiv cs/0610105).
Established: Narayanan and Shmatikov studied the Netflix Prize dataset, about 500,000
subscribers, from which names had been removed. With limited background
knowledge about a subscriber, the authors could locate that person's record.
Using the public IMDb site as background knowledge, they matched known
users to records and uncovered apparent political preferences.
Lesson: removing names is not enough when a record is unique or nearly unique.আইনি নোট (২০২৬-১০-১২ অনুযায়ী; আইনি পরামর্শ নয়): GDPR-এর অধীনে, একটা অনানুষ্ঠানিক পাঠ-সাইট থেকে সহজ ভাষায় (সরকারি পাঠ EUR-Lex-এ): Recital 26 বলে, সিউডোনিমাইজড ডেটা এখনও ব্যক্তিগত ডেটা। কোনো মানুষ শনাক্তযোগ্য কি না তা ঠিক করতে খরচ, সময় ও প্রযুক্তিসহ যেসব উপায় ব্যবহার হওয়ার যুক্তিসঙ্গত সম্ভাবনা আছে তার সবই বিবেচনায় নিতে হয়। সত্যিকারের বেনামি ডেটা এই রেগুলেশনের বাইরে। একটা নির্দিষ্ট টেবিল বেনামি বলে গণ্য হবে কি না তা একটা আইনি ও প্রযুক্তিগত বিচার, k-এর গণনা তা ঠিক করে না। উৎসের ধরন: Recital-এর পাঠ। আপনার দেশ ও খাতের বর্তমান সরকারি পাঠ দেখে নিন।
সম্মতির মান ও ক্ষমতার ভারসাম্যহীনতা
সম্মতির মান ও ক্ষমতার ভারসাম্যহীনতা মূল্যায়ন করুন। বাক্সে টিক মানে একটা ক্লিকের রেকর্ড। সেটা ভালো সম্মতি কি না তা নির্ভর করে চারপাশের শর্তের ওপর। নিচের প্রশ্নগুলো ভালো অনুশীলনের বিবরণ; সম্মতি আইনত বৈধ কি না তা আলাদা প্রশ্ন, যা আপনার গোপনীয়তা দায়িত্বপ্রাপ্তের।
| প্রশ্ন | দুর্বল উদাহরণ (Harbourline, কাল্পনিক) | শক্তিশালী উদাহরণ |
|---|---|---|
| অবহিত: কীসের জন্য তা জানতেন কি না? | "আমরা আমাদের সেবা উন্নত করতে আপনার ডেটা ব্যবহার করতে পারি।" | "আমরা একটা স্কোরিং টুল পরীক্ষা করতে আপনার সিভি ব্যবহার করি। শর্টলিস্টেড প্রতিটা সিভি এখনও একজন রিক্রুটার পড়েন।" |
| নির্দিষ্ট: প্রতিটা পছন্দে একটা উদ্দেশ্য? | একটা টিক মূল্যায়ন, মার্কেটিং ও টুল পরীক্ষা সবকিছু ঢাকে | আলাদা আলাদা পছন্দ |
| স্বাধীন: না বললে কোনো শাস্তি আছে? | বাক্সটা আগে থেকে টিক দেওয়া, আর তা ছাড়া ফর্ম পাঠানো যায় না | ঐচ্ছিক; না বললে আবেদনে কিছু বদলায় না |
| প্রত্যাহারযোগ্য: তাঁরা তুলে নিতে পারেন কি না? | চাওয়ার কোনো উপায় নেই, চাওয়ার মতো কেউ নেই | একজন নামধারী যোগাযোগকারী, একটা নির্দিষ্ট সময়সীমা, প্রত্যাহারের রেকর্ড |
ক্ষমতার ভারসাম্যহীনতা থাকে যখন একপক্ষ এমন কিছু নিয়ন্ত্রণ করে যা অন্যপক্ষের দরকার: আবেদনকারীর চাকরি দরকার, কর্মীর বেতন, শিক্ষার্থীর গ্রেড, রোগীর চিকিৎসা। ভারসাম্যহীনতা বড় হলে ফর্মে যা-ই থাকুক, "হ্যাঁ" দেওয়া হতে পারে কারণ না বলা ব্যয়বহুল মনে হয়। এর ফল কী হওয়া উচিত তা নিয়ে যুক্তিসঙ্গত মানুষ একমত নন। কেউ মনে করেন এমন পরিবেশে সম্মতি খুব কমই ভিত্তি হওয়া উচিত এবং নোটিশ ও প্রয়োজনীয়তার ওপর ভর করা উচিত; কেউ মনে করেন ভালোভাবে সাজানো ঐচ্ছিক পছন্দ মানুষকে সম্মান করে। যেটাই হোক, ব্যবহারিক প্রশ্ন একই: এই মানুষটা ক্ষতি ছাড়া না বলতে পারতেন কি না, আর বললে আমরা তা টের পেতাম কি না।
সংরক্ষণ ও মুছে ফেলার নিয়ম
সংরক্ষণ ও মুছে ফেলার নিয়ম ঠিক করুন। সংরক্ষণ একটা ডিজাইন নীতি: ঘোষিত উদ্দেশ্যের যতটুকু দরকার ততটুকুই রাখুন, নির্দিষ্ট সময়ের জন্য, মুছে ফেলার একটা পথসহ। আপনার আইন বা খাতও সীমা ঠিক করে দিতে পারে; জিজ্ঞেস করুন। একটা নিয়ম শুধু মূল ডেটাসেটকে নয়, আরও অনেক কিছুকে ঢাকে।
| বিষয় | কত দিন রাখা হবে (কাল্পনিক) | ট্রিগার | মুছে ফেলার পথ ও যাচাই |
|---|---|---|---|
| সিভি ফাইল (D1) | ১২ মাস | চাকরির বিজ্ঞপ্তি বন্ধ হওয়া | রিক্রুটমেন্ট মোছে; অ্যানালিটিক্স লিড সংখ্যা মিলিয়ে নিশ্চিত করেন |
| ফিট স্কোর | সিভি যত দিন | সিভি মুছে ফেলা হয় | একই কাজে মোছা হয় |
| পরীক্ষার কপি, এক্সপোর্ট, ব্যাকআপ | উৎসের চেয়ে বেশি নয় | উৎসের মেয়াদ শেষ | ইনভেন্টরিতে তালিকাভুক্ত থাকে, নইলে ভুলে যাওয়া হয় |
| রিকোয়েস্ট লগ | ৯০ দিন | বয়স | স্বয়ংক্রিয়; প্রতি ত্রৈমাসিকে যাচাই |
| যা কিছু হোল্ডের অধীনে (বিরোধ, অডিট) | মুক্তি না পাওয়া পর্যন্ত | গোপনীয়তা দায়িত্বপ্রাপ্তের লিখিত হোল্ড | প্রতি মাসে পর্যালোচনা |
দুর্বল রূপটা হলো "ডেটা যত দিন কাজে লাগে তত দিন রাখি": কার কাজে লাগে, আর কে যাচাই করে? আট নম্বর পাতা Python-এ একটা সংরক্ষণ-সূচি বানায়।
ডেটায় প্রবেশাধিকারকে কাজের দায়িত্বের সঙ্গে মেলানো
ডেটায় প্রবেশাধিকারকে কাজের দায়িত্বের সঙ্গে মেলান। মানুষ পৌঁছাবেন সেই ফিল্ডে যা তাঁর কাজের জন্য দরকার, তার বেশি নয়। আগে প্রয়োজন লিখুন, তারপর বাস্তবে যা দেওয়া আছে তার সঙ্গে মেলান।
টয় ডেটা: কাল্পনিক এজেন্সির পাঁচটা ভূমিকা।
NEEDED = {"recruiter": {"name", "email", "cv_text", "score"}, "hiring manager": {"cv_text", "score"},
"analyst": {"score", "outcome_label"}, "vendor support": set(), "IT admin": set()}
GRANTED = {"recruiter": {"name", "email", "cv_text", "score", "date_of_birth"},
"hiring manager": {"name", "email", "cv_text", "score"},
"analyst": {"score", "outcome_label", "name", "cv_text"}, "vendor support": {"cv_text"},
"IT admin": {"name", "email", "cv_text", "score", "date_of_birth", "outcome_label"}}
for role in NEEDED:
extra, lacking = sorted(GRANTED[role] - NEEDED[role]), sorted(NEEDED[role] - GRANTED[role])
print(f"{role:<15} no stated need: {', '.join(extra) or '-'} | needed but not granted: {', '.join(lacking) or '-'}")recruiter no stated need: date_of_birth | needed but not granted: -
hiring manager no stated need: email, name | needed but not granted: -
analyst no stated need: cv_text, name | needed but not granted: -
vendor support no stated need: cv_text | needed but not granted: -
IT admin no stated need: cv_text, date_of_birth, email, name, outcome_label, score | needed but not granted: -ফলাফল একটা প্রশ্নের তালিকা, রায় নয়। রিক্রুটারের জন্মতারিখের কোনো ঘোষিত প্রয়োজন নেই। কাজে শুধু স্কোর আর লেবেল লাগলেও অ্যানালিস্ট নাম দেখতে পান। ভেন্ডর সাপোর্ট ও IT অ্যাডমিনের প্রয়োজন ফাঁকা, তাই তাঁরা যে ফিল্ডেই পৌঁছান তা একটা প্রশ্ন: সিস্টেম চালাতে একজন অ্যাডমিনের বিস্তৃত প্রবেশাধিকার সত্যিই লাগতে পারে, কিন্তু তখন প্রয়োজনটা হলো "রক্ষণাবেক্ষণ, লগসহ, সময়সীমিত", আর সেটা লেখা থাকে ও পর্যালোচনা হয়।
সংস্থার সীমানা পেরিয়ে ডেটা স্থানান্তর
সংস্থার সীমানা পেরোনো ডেটা স্থানান্তর চিহ্নিত করুন। ডেটা যতবার তার ধারক সংস্থা ছেড়ে যায়, একটা নতুন পক্ষ তা দেখতে, রাখতে বা পুনর্ব্যবহার করতে পারে। প্রতিটা প্রবাহ তালিকাভুক্ত করুন: কী যাচ্ছে, কেন, কোন লিখিত চুক্তির অধীনে, আর পরে ডেটার কী হবে।
FLOWS = [("applicants", "Harbourline", "CV, contact details", "application notice v3", "12 months"),
("Harbourline", "ScoreVendor (invented)", "CV text for scoring", "MISSING", "MISSING"),
("Harbourline", "client employer", "shortlist of 5 CVs", "client contract clause 7", "client deletes after hire")]
for src, dst, what, agreement, afterwards in FLOWS:
flag = " <-- ask before continuing" if "MISSING" in (agreement, afterwards) else ""
print(f"{src} -> {dst}: {what} | agreement: {agreement} | afterwards: {afterwards}{flag}")applicants -> Harbourline: CV, contact details | agreement: application notice v3 | afterwards: 12 months
Harbourline -> ScoreVendor (invented): CV text for scoring | agreement: MISSING | afterwards: MISSING <-- ask before continuing
Harbourline -> client employer: shortlist of 5 CVs | agreement: client contract clause 7 | afterwards: client deletes after hireভেন্ডরের প্রবাহে কোনো চুক্তি আর ব্যবহার-শেষের নিয়ম লেখা নেই। হয়তো সেগুলো আছে কিন্তু ফাইল করা হয়নি; রেজিস্টারের কাজ সেটা খুঁজে বের করা। আট নম্বর পাতায় দেখা যাবে ভেন্ডর নিজে ডেটা কোথায় পাঠায়।
কাজের জায়গায় এটা কোথায় দেখা যায়
পাইলটের আগে গোপনীয়তা বা গভর্ন্যান্স রিভিউয়ার ইনভেন্টরি, প্রোভেন্যান্স রেকর্ড ও প্রবেশাধিকারের তালিকা চান। যে টিম এগুলো মিনিটের মধ্যে, ফাঁক সৎভাবে জানিয়ে, দিতে পারে, সে সাধারণত স্মৃতি থেকে উত্তর দেওয়া টিমের চেয়ে দ্রুত ও নির্দিষ্ট সিদ্ধান্ত পায়।
সাধারণ ভুল
- "ডেটা তো আমাদের কাছেই আছে।" ডেটা হাতে থাকা মানে নতুন উদ্দেশ্যে ব্যবহারের অনুমতি নয়। সংগ্রহের কর্তৃত্ব আর পুনর্ব্যবহার আলাদা করে লিখুন।
- প্রকাশ্য ডেটাকে অবাধে ব্যবহারযোগ্য ভাবা। প্রকাশ্য মানে প্রবেশাধিকার। মালিক, শর্ত ও অনুমতি যাচাই করে লিখে রাখুন।
- নাম নেই বলে টেবিলকে বেনামি বলা। অনন্য সংমিশ্রণ গুনুন আর লিংকেজ পরীক্ষা করুন।
- সম্মতির বাক্সকেই পুরো গল্প ভাবা। অবহিত, নির্দিষ্ট, স্বাধীন ও প্রত্যাহারযোগ্য কি না দেখুন, আর ক্ষমতা নিয়ে প্রশ্ন করুন।
- ফাঁকা জায়গা অনুমান দিয়ে ভরা।
MISSINGলেখা রেকর্ড কাজের; একটা বানানো মালিক বসানো রেকর্ড সমস্যা লুকায়।
নিজে চেষ্টা করুন
এই পাতার নেমস্পেস ব্যবহার করুন। অনুশীলনগুলো চলমান উদাহরণ আর পাঁচ নম্বর পাতার প্রক্সির ধারণা আবার ব্যবহার করে।
- সহজ। ইনভেন্টরির আউটপুট থেকে বলুন কাল ShortlistHelper-এর জন্য কোন ডেটাসেটগুলো আপনি ব্যবহার করবেন না, আর প্রতিটাকে ছাড়পত্র দিতে পারে এমন একটা প্রশ্ন কী।
- মাঝারি। একটা পঞ্চম ডেটাসেট,
"D5 interview notes", যোগ করুন, যাতে উৎস, মালিক, উদ্দেশ্য ও সংরক্ষণ আছে কিন্তুcollected_underনেই আরreuse_ok"tbc"।reviewচালান। সে কী জানায়, আর প্রথম পদক্ষেপ কী? - কঠিন। একজন ভেন্ডর-সাপোর্ট কর্মী একটা ব্যর্থ আপলোড ডিবাগ করতে
cv_text-এ রিড অ্যাক্সেস চান। সিদ্ধান্তের প্যাটার্ন দিয়ে প্রবেশাধিকারের সিদ্ধান্ত লিখুন: প্রয়োজন, বিকল্প (প্রবেশাধিকার না দেওয়াসহ), শর্ত, মালিক ও পর্যালোচনার তারিখ।
উত্তর
সহজ। D4 (মালিক, প্রোভেন্যান্স ও সংরক্ষণ নেই; অনুমতি অজানা): "এর মালিক কে, আর উৎসের শর্ত এই ব্যবহার অনুমোদন করে কি না?" D1 (পুনর্ব্যবহার উল্লেখ নেই): "নোটিশ v3 স্কোরিং পরীক্ষাকে ঢাকে বলে গোপনীয়তা দায়িত্বপ্রাপ্ত পড়েন কি না?" D2 (পুনর্ব্যবহারের উত্তর ও সংরক্ষণ নেই): "ফলাফলের রেকর্ড লেবেল হিসেবে ব্যবহার করা যাবে কি না, আর কত দিন?" D3 ব্যবহার করা যায়। পাস চেকলিস্ট: D3-ই একমাত্র ছাড়পত্র-পাওয়া ডেটাসেট; আটকে থাকা প্রতিটার একটা নির্দিষ্ট প্রশ্ন ও জিজ্ঞেস করার একজন মালিক আছে; উত্তরে ধরে নেওয়া হয়নি যে প্রকাশ্য বা অভ্যন্তরীণ ডেটায় অনুমতি লাগে না। দুর্বল উত্তর D1-কে ছাড়পত্র দেয় "আমরা নিজেরাই তো সংগ্রহ করেছি" বলে।
মাঝারি।
INVENTORY["D5 interview notes"] = {"source": "recruiters", "owner": "Head of recruitment",
"purpose": "record interview impressions", "reuse_ok": "tbc", "provenance": "typed after interviews",
"retention": "6 months"}
review({"D5 interview notes": INVENTORY["D5 interview notes"]})D5 interview notes MISSING: collected_under | UNCLEAR: reuse_okসে collected_under MISSING এবং reuse_ok UNCLEAR জানায়। প্রথম পদক্ষেপ মালিককে জিজ্ঞেস করা, নোটগুলো কোন নোটিশের অধীনে লেখা হয় আর সাক্ষাৎকারদাতারা জানেন কি না যে নোটগুলো আছে; দুটো ফিল্ডের উত্তর না পাওয়া পর্যন্ত নোট ফিচারে ব্যবহার করবেন না। পাস চেকলিস্ট: দুটো ফাঁকই নাম ধরে বলা হয়েছে; পদক্ষেপ একজন মানুষকে জিজ্ঞেস করে, মান বানায় না। দুর্বল উত্তর একটা সম্ভাব্য ভিত্তি বসিয়ে দেয়।
কঠিন। একটা আদর্শ সিদ্ধান্ত:
Need: debug one failed upload for one applicant; the text of that CV may be needed.
Options: A no access, ask the recruiter to send the file; B read access to all CVs;
C access to one named CV, with the recruiter's approval, for 24 hours.
Decision: C. A is safest but slows a fix; B is far more than the need.
Conditions: access is logged; the person sees no names or contact fields; the CV text is
not copied outside the support tool; the vendor flow's agreement is on file
before any access (it is MISSING today, so until then: option A).
Owner: Head of recruitment approves; privacy owner reviews the log monthly.
Review: 2027-01-15, or after any access request that is refused or abused.পাস চেকলিস্ট: অনুমতির আগে প্রয়োজন বলা হয়েছে; "প্রবেশাধিকার না দেওয়া" একটা বিকল্প; সিদ্ধান্ত সংকীর্ণ, সময়সীমিত ও লগ-করা; এটা ভেন্ডরের অনুপস্থিত চুক্তি লক্ষ করেছে; একজন মালিক ও একটা পর্যালোচনার তারিখ আছে। দুর্বল উত্তর "নিরাপদ থাকতে" ব্যাপক রিড অ্যাক্সেস দেয়।
সারসংক্ষেপ
- উৎস, মালিক, উদ্দেশ্য ও অনুমতির ইনভেন্টরি বানান; প্রোগ্রাম
MISSINGওUNCLEARজানাক, কখনো ফাঁক ভরাক না। - সংগ্রহের কর্তৃত্ব মানে পুনর্ব্যবহারের অনুমতি নয়; অনুপস্থিত বা অস্পষ্ট অনুমতিতে জিজ্ঞেস করুন, সংকীর্ণ করুন বা বিকল্প নিন, অনুমান করবেন না।
- প্রোভেন্যান্স ও প্রতিটা রূপান্তর লিখুন; একটা ফিল্টার পরের টেবিল কী বলতে পারে তা বদলে দেয়।
- নাম সরানো মানে বেনামি করা নয়; অনন্য সংমিশ্রণ গুনুন ও লিংকেজ পরীক্ষা করুন, ফলকে স্ক্রিন হিসেবে দেখুন।
- সম্মতির মান ও ক্ষমতা যাচাই করুন, কপি ও লগের জন্যও সংরক্ষণ ঠিক করুন, আর প্রতিটা ভূমিকাকে শুধু সেই ফিল্ড দিন যা তার কাজের জন্য দরকার।
এরপর: ডেটা অধিকার, স্থানান্তর ও রেকর্ড: অনুরোধ, সংরক্ষণ ও অডিট ট্রেইল পাতায় আছে সীমান্ত পেরোনো স্থানান্তর, ভেন্ডর ও তাদের সাব-কন্ট্রাক্টর, শিশুদের ডেটা, কপিরাইটের প্রশ্ন, আর Python-এ বানানো একটা সংরক্ষণ-সূচি।