Skip to main content
পর্দার আড়ালে

আমাদের নিজেদের পেমেন্ট সিস্টেমের অডিটে যা বেরিয়ে এল

দুটি গুরুতর ফলাফল, আর কোনোটাই আমরা যেখানে খুঁজতাম সেখানে নয়। এমন ভুল নিয়ে একটা খোলা রিপোর্ট যা এরই মধ্যে ঠিক করা হয়েছে।

প্রকাশিত লিখেছেন AlphaCloud4 মিনিটে পড়া

2026 সালের আগস্টে আমরা আমাদের পেমেন্ট সিস্টেম গোড়া থেকে পর্যালোচনা করি। কিছু ঘটেছিল বলে নয়, বরং কিছুদিন আগেই এটা চালু হয়েছিল আর আমরা জানতে চেয়েছিলাম কী বাদ পড়ে গেছে।

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

যে মডেলিং ভুল থেকে দুটি গুরুতর ফলাফল এসেছে

কেউ আমাদের কাছ থেকে Premium কিনলে আমাদের পেমেন্ট প্রদানকারীর কাছে একটা গ্রাহক রেকর্ড তৈরি হয়। আমরা সেই রেকর্ড সার্ভার ID-এর অধীনে রাখতাম, কারণ Premium তো শেষ পর্যন্ত একটা সার্ভারেই যায়।

ঠিক এটাই ভুল মডেল, আর দুটি সবচেয়ে গুরুতর ফলাফলের মূলে এটাই ছিল।

একটা গ্রাহক রেকর্ড একজন ক্রেতার। এতে থাকে তাঁর পেমেন্ট পদ্ধতি, ইনভয়েসের ইতিহাস, আর কেউ দুটি সার্ভারের জন্য পেমেন্ট করার সাথে সাথেই কয়েকটি সাবস্ক্রিপশন। সার্ভার ID দিয়ে এটাকে চিহ্নিত করা মানে কয়েকজন মানুষ একই সারির দিকে নির্দেশ করছেন।

ফলাফল 1: অন্যের গ্রাহক ডেটা, পেমেন্ট ছাড়াই বদলানো যেত

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

বাস্তবে এর মানে ছিল: এমন একটা সার্ভারে একটা ক্লিকই যথেষ্ট ছিল যেখানে কেউ কোনো এক সময় কিনেছিলেন। তারপর সেই মূল ক্রেতার প্রতিটি সাবস্ক্রিপশনের ইনভয়েস অপরিচিত ব্যক্তির ইমেইল ঠিকানায় যেত। কোনো পেমেন্ট নয়, কোনো নিশ্চিতকরণ নয়।

ঠিক করা হয়েছে প্রতিবার পুনরায় ব্যবহারের আগে যাচাই করে যে রেকর্ডটা সত্যিই এই অ্যাকাউন্টের কি না। মিল না থাকলে আলাদা একটা তৈরি হয় আর অন্যটা অক্ষত থাকে।

ফলাফল 2: বিলিং পোর্টাল অন্যের সাবস্ক্রিপশন দেখাত

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

ফলে যে কেউ একটা সার্ভারে বৈধভাবে কিনলে, একই রেকর্ড অন্য সার্ভারগুলোর জন্য যে সাবস্ক্রিপশন বহন করত সেগুলো দেখতে ও পরিচালনা করতে পারতেন।

ঠিক করা হয়েছে সার্ভারের সারি থেকে নয়, নির্দিষ্ট ক্রয় থেকে গ্রাহক রেকর্ড নির্ধারণ করে।

দুটি ফলাফল যেখানে কোড আমাদের নিজেদের শর্তের বিরোধিতা করেছে

এই বিভাগটাই আমাদের সবচেয়ে বেশি ভাবিয়েছে, কারণ এটা প্রযুক্তিগত নয়।

ব্ল্যাকলিস্ট পেমেন্ট করা সময় কেড়ে নিত। আমাদের শর্তাবলি বলে একটা সাবস্ক্রিপশন চলতি মেয়াদ শেষে শেষ হয়। কিন্তু একটা সার্ভার ব্লক করার সময় কোড তাৎক্ষণিক বাতিলের ডাক দিত: কোনো ফেরত নয়, আর ইতিমধ্যে পেমেন্ট করা মেয়াদের জন্য সেই মুহূর্ত থেকে কোনো সেবা নয়। আমরা লিখিতভাবে যা প্রতিশ্রুতি দিয়েছিলাম কোড তার থেকে আলাদা কিছু করত। এখন পেমেন্ট করা মেয়াদ শেষ পর্যন্ত চলে।

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

দ্বিতীয় দফা প্রথমটার চেয়ে খারাপ ছিল

প্রথম 21টি ফলাফলের পর কয়েক সপ্তাহ পরে আমরা আবার দেখলাম। সিদ্ধান্তটা সঠিক ছিল, কারণ একক সবচেয়ে গুরুতর ফলাফলটা তখনই বেরিয়ে এল।

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

নির্ধারণ এখন চারটি সুনির্দিষ্ট ধাপে চলে, আর যা দ্ব্যর্থহীনভাবে নির্ধারণ করা যায় না তা অনুমান না করে রিপোর্ট করা হয়।

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

ডেটা সংরক্ষণ পেমেন্ট করা সার্ভার মুছে দিত। বট কোনো সার্ভার ছাড়লে 30 দিন পর তার ডেটা সরিয়ে ফেলা হয়। সেই পরিষ্কার করার প্রক্রিয়া কখনো জিজ্ঞেস করত না যে কোনো চলমান সাবস্ক্রিপশন যুক্ত ছিল কি না।

আমরা কী শিখলাম

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

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

"আমাদের শর্তে তাই বলা আছে" একটা যাচাইযোগ্য বাক্য। দুটি ফলাফল ছিল আমরা লিখিতভাবে যা প্রতিশ্রুতি দিয়েছিলাম আর কোড যা করত তার মধ্যে পার্থক্য। এটা পড়ে দেখা যায়, আর কেউ তা করে না, কারণ এটা প্রকৌশলের বদলে আইনের মতো দেখায়।

ক্রয়ের সম্পূর্ণ শর্তাবলি আমাদের পরিষেবার শর্তাবলিতে, প্রত্যাহারের অধিকার প্রত্যাহার-এ আছে।

আরও নিবন্ধ

পর্দার আড়ালে

আমাদের কোডের ভেতরের আইন

একটা বাতিল বাটন যা লগইন ছাড়াই কাজ করতে হবে। একটা ফর্ম যা কখনো আপনাকে প্রত্যাখ্যান করতে পারবে না। আমাদের কাছে আইনি দায়িত্ব কেন বাঁধা গৎ নয়, বরং স্থাপত্য।

পর্দার আড়ালে

কেন AlphaCloud-এর প্রায় সবকিছু বিনামূল্যে থাকে

বেশিরভাগ Discord বট তাদের সবচেয়ে কাজের ফিচারগুলো একটা সাবস্ক্রিপশনের পেছনে আটকে রাখে। আমরা ইচ্ছে করেই তা করি না, আর এর সাথে উদারতার সম্পর্ক যতটা শোনায় তার চেয়ে কম।

পর্দার আড়ালে

4,000টি Discord সার্ভারের ওপর নজর: Grafana, PostHog আর এরা আমাদের যা দেখাল

একটা লুপ যা চুপচাপ আমাদের অর্ধেক ট্রাফিক তৈরি করত, দিনে তিন মিলিয়ন অর্থহীন অনুরোধ আর একটা আক্রমণ যা এক মিনিটে শেষ হয়ে গেল। আমাদের মনিটরিং কী দেখে, আর কী ইচ্ছে করেই দেখে না।