درخواستی که اکثر ابزارها را خراب می‌کند

مشتری می‌خواهد پروژه‌اش را ببیند. راه ساده این است: «برایش یک حساب معمولی بساز» — و حالا او می‌تواند لیست تیم را مرور کند، هر پروژه‌ی مشتری دیگری را در نوار کناری ببیند، و اگر کسی یادش نرفته باشد قفلش کند، تب مالی را هم باز کند. اکثر سیستم‌های مجوز برای آدم‌های داخل شرکت ساخته شده‌اند، پس اولین حساب بیرونی همان چیزی را برملا می‌کند که کسی صراحتاً پنهانش نکرده بود.

«مهمان» در WKFGo واقعاً یعنی چه

مهمان یک ردیف واقعی User است — همان جدول، همان ورود — با یک فیلد تنظیم‌شده: IsGuest = true. این پرچم دو کار مستقل انجام می‌دهد، و فهمیدن اینکه چرا دوتاست اهمیت دارد.

اول، هنگام دعوت، مهمان همان مجوزهای دسترسی‌ویژگیِ هر همکار دیگری را در همان پروژه می‌گیرد — DASHBOARD_VIEW، TASK_VIEW، KNOWLEDGE_VIEW_OTHERS، DOCUMENTS_VIEW، DESCRIPTION_VIEW برای دسترسی نمایشی، به‌علاوه TASK_ADD و KNOWLEDGE_ADD اگر به‌عنوان ویرایشگر دعوت شده باشد. این همان سیستم مجوز معمولی است — چیز خاصی نیست، فقط محدود به یک projectId.

دوم — و این بخشی است که واقعاً برای امنیت اهمیت دارد — یک میان‌افزار محافظ روی هر درخواست اجرا می‌شود و isGuest را از زمینه‌ی احراز هویت چک می‌کند. اگر true بود، درخواست را برای فهرستی از پیشوندهای سطح‌سازمان کاملاً مسدود می‌کند، بدون توجه به اینکه جدول دسترسی‌ویژگی چه می‌گوید:

var guestDenyPrefixes = []string{
    "/api/teams", "/api/finances", "/api/saas", "/api/audit", "/api/usage",
    "/api/reports", "/api/project-roles", "/api/feature-accesses", "/api/organization",
    "/api/insight", "/api/portfolio", "/api/git", "/api/email", "/api/packages",
    "/api/goals", "/api/workload", "/api/roles", "/api/digest", "/api/ai/config",
    "/api/ai/usage", "/api/sprints", "/api/scrum",
}

چرا دو لایه به‌جای یکی

سؤال بدیهی این است: اگر مجوزهای دسترسی‌ویژگی از قبل محدودند، این فهرست مسدودی دوم برای چیست؟ چون دسترسی‌ویژگی یک سیستم مجوز مثبت است — چیزی را می‌دهد که صراحتاً پیکربندی کرده‌اید، و درستی‌اش وابسته به این است که هر مسیر به کلید ویژگیِ درست وصل باشد. اگر یک نقطه‌پایانی جدید بدون کلید ویژگیِ درست منتشر شود، یا ادمینی مجوزی که برای همکاران بوده را اشتباهی به کسی بدهد، هیچ‌چیز دیگری جلوی یک کاربر معمولی را نمی‌گیرد. مهمان، چون بیرونی است، به یک پشتیبان نیاز دارد که وابسته به درست‌پیکربندی‌بودن هر مسیر نباشد — فهرست مسدودی که فقط بر اساس «آیا این یک سطح سازمانی است» فعال می‌شود، مستقل از چیزی که جدول مجوزها می‌گوید.

این الگوی دفاع‌درعمق است: یک لایه می‌گوید مهمان به چه چیزی می‌تواند برسد، دیگری می‌گوید مهمان هرگز به چه چیزی نمی‌رسد، و دومی حتی اگر اولی اشتباه پیکربندی شده باشد برنده می‌شود.

تنها استثنای عمدی

مهمان‌ها از /api/feature-accesses — نقطه‌پایانی مدیریت — مسدودند، اما اجازه‌ی خواندن مجوزهای خودشان را از طریق /api/feature-accesses/check دارند. بدون این استثنا، رابط کاربری خود مهمان نمی‌توانست تشخیص دهد دکمه‌ی «افزودن تسک» را نشان بدهد یا نه، چون هیچ راهی برای پرسیدن «من اینجا چه می‌توانم بکنم؟» ندارد. این یک استثنای باریک، فقط-خودش، فقط-خواندنی است، نه یک سوراخ در فهرست مسدودی.

چیزی که مهمان‌ها هرگز نمی‌گیرند

هنوز جریان دعوت با لینک ایمیلی وجود ندارد — ادمین با ایمیل و پروژه دعوت می‌کند، و پاسخ شامل یک رمز عبور موقت یک‌بارمصرف است که باید مستقیماً به مهمان بدهد. این عمداً دستی است: نبود ایمیل خودکار یعنی خطر اینکه دعوتی به صندوق اشتباه برود و خودش را فعال کند وجود ندارد.

اشتباهات رایج

فرض کردن «مهمان» یعنی فقط‌خواندنی. نیست — هر دو سطح VIEWER و EDITOR سطح مهمان هستند؛ EDITOR می‌تواند تسک و ورودی دانش روی همان یک پروژه اضافه کند. فقط‌خواندنی انتخابی است که هنگام دعوت می‌کنید، نه ویژگی ذاتی پرچم مهمان.

استفاده مجدد از یک حساب مهمان روی دو پروژه‌ی مشتری. دعوت هنگام ساخت به یک projectId محدود است. دعوت همان فرد به پروژه‌ی دوم، دعوتی جدید با مجوزهای محدود خودش است — اولی را گسترده‌تر نمی‌کند.

فراموش کردن چک تداخل نام کاربری. نام کاربری مهمان ایمیلش است، و باید درون همان سازمان آزاد باشد — اگر همکاری قبلاً همان ایمیل را نام کاربری کرده باشد، دعوت به‌جای ادغام خاموش دو حساب، تمیز شکست می‌خورد.

سؤالات متداول

آیا مهمان می‌تواند مهمان‌های دیگر همان پروژه را ببیند؟

فقط چیزی که TASK_VIEW و بقیه درباره‌ی افراد مسئول تسک‌هایی که از قبل می‌تواند ببیند نشان می‌دهند — سطح جداگانه‌ای برای «فهرست همه‌ی مهمان‌ها» وجود ندارد، و فهرست /api/users برای مهمان‌ها کاملاً مسدود است (می‌توانند یک کاربر را با شناسه برای نام مسئول بگیرند، نه مرور فهرست کامل).

اگر ادمین بعداً دسترسی پروژه را لغو کند چه می‌شود؟

مجوزهای دسترسی‌ویژگی فقط ردیف‌اند — حذفشان کنید و مهمان در درخواست بعدی دیدش را از دست می‌دهد؛ میان‌افزار محافظ همچنان سطوح سازمانی را مسدود نگه می‌دارد.

آیا مهمان روی سقف صندلی‌های اشتراک حساب می‌شود؟

صفحه‌ی صورتحساب پلن خود را ببینید — صندلی‌های مهمان معمولاً همان‌طور که صندلی‌های همکار پیگیری می‌شوند شمرده می‌شوند، چون همان جدول User زیرش است.

جمع‌بندی

دسترسی بیرونی محدود یعنی «حساب بساز و امیدوار باش کسی روی لینک اشتباه کلیک نکند» نیست — دو لایه‌ی مستقل است که به هم اعتماد ندارند: مجوزهای صریح به‌ازای هر پروژه برای چیزی که مهمان باید ببیند، و یک فهرست مسدودیِ کدگذاری‌شده برای چیزی که مهمان هرگز نباید ببیند، صرف‌نظر از اینکه لایه‌ی اول چه می‌گوید.