نوشتهها
مطالعهٔ موردی Vellum: ساخت فضای کاری متنباز تیمی با Next.js و PostgreSQL
Vellum فضای کاری متنباز من برای تیمها، پروژهها، بردهای کانبان و کارهاست. در این مطالعهٔ موردی از مدل رابطهای داده، دسترسی مبتنی بر نقش، TypeScript در Next.js و Drizzle و اثری میگویم که عمومی بودن کد روی طراحی میگذارد.
اصلاً چرا یک فضای کاری دیگر؟
Vellum از یک خواستهٔ عمداً فروتنانه شروع شد: گردش کار تیم و پروژه در یک فضای سرراست جمع شود. برد کانبان دارد، پیگیری کار، سازماندهی تیم، مسئول و اولویت و دسترسی مبتنی بر نقش. هیچکدام از این واژهها عجیب نیستند؛ مسئلهٔ مهندسی این است که به هم وصلشان کنی، بیآنکه محصول شبیه سیستم اداریای شود که گاهی اجازه میدهد آدمها کار هم بکنند.
برای همین Vellum مطالعهٔ موردی خوبی است؛ سختیاش همان سختی معمول نرمافزار کسبوکار است. برد فقط چند ستون روی صفحه نیست؛ ادعای مشترکی است دربارهٔ اینکه هر کار در چه وضعی است. تسک فقط عنوان نیست؛ جایی تعلق دارد، برای کسی معنا دارد و دست به دست میشود. اگر این رابطهها غلط چیده شوند، هر قابلیت بعدی تبدیل میشود به دور زدنِ مدل، در لباس یک صفحهٔ تازه.
دامنهٔ مسئله بیشتر «رابطه» است
تیم آدم دارد، پروژه کار دارد و هر تسک همزمان در یک بافت سازمانی و یک بافت گردش کاری نشسته است. برای همین PostgreSQL مرکز طبیعی Vellum است، نه یک میانبُر سندمحور. محصول مدام سؤال رابطهای میپرسد: این کار مال کدام تیم است؟ مسئولش کیست؟ در چه وضعی است؟ و چه کسی حق تغییرش را دارد؟ اگر پاسخ اینها در مدل داده سخت باشد، همه جا سخت خواهد بود.
Drizzle مدل را نزدیک SQL نگه میدارد و همزمان اسکیما را وارد کدبیس TypeScript میکند. این همان ترجیحی است که در نوشتهٔ پلتفرمهای SvelteKit گفتم: کوئری شبیه همان کاری باشد که انجام میدهد و دیتابیس پشت جادو قایم نشود. فرانتاند Vellum متفاوت است، اما فلسفهٔ دیتابیسش عمداً آشناست؛ زیر داده «کسلکننده» بودن تعریف است، نه ایراد.
PostgreSQL روی Neon از نظر عملیاتی این انتخاب را کامل میکند: برنامه یک دیتابیس رابطهای واقعی دارد، بدون اینکه نگهداری دیتابیس سرگرمی اصلی پروژه شود. البته این یعنی انضباط عملکرد دیتابیس لازم نیست؛ برعکس. نمای برد، فهرست پروژه و فیلتر مسئول همان کوئریهای روزمرهایاند که باید دور شیوهٔ نگاه آدمها به کارشان شکل بگیرند. اگر مدل برای جواب دادن به «روی این برد چیست، مال کیست و چه چیزی عوض شده؟» مجبور به آکروبات شود، رابط دیر یا زود هزینهاش را با کندی یا استثناهای عجیب میدهد. اسکیمای آرام یعنی سؤالهای معمول محصول را بشود بارها و ارزان پرسید.
دسترسی مبتنی بر نقش، مرز خود محصول است
دسترسی مبتنی بر نقش تا وقتی تیم واقعی از محصول استفاده نکرده، شبیه یک جدول تنظیمات است. بعدش روشن میشود نقشها تعیین میکنند کار چه کسی دیده شود، چه کسی پروژه را مرتب کند و اصلاً کدام عمل برای کدام آدم معنا دارد. پس مجوزدهی تزئین امنیتیِ آخر کار نیست؛ بخشی از شکل محصول است و باید در صفحه و عمل و دسترسی به داده با خودش یکی باشد، وگرنه رابط قولهایی میدهد که سیستم هرگز نباید اجازهشان را بدهد.
اینجا همان عادت امنیتمحور من به کار ابزار متنباز میآید. برای توجیه مرز روشن لازم نیست قصهٔ تهدید دراماتیک بسازم؛ درستی معمولی کافی است: هر کس فقط به کاری برسد که نقشش دلیل رسیدن به آن را میدهد و نگهدار بعدی هم بتواند قاعده را توضیح بدهد. منطق دسترسیای که هیچکس نتواند شرحش بدهد، پیش از رسیدن مهاجم هم نیمهخراب است.
Next.js و React و یک گفتوگوی TypeScript
برنامه را با Next.js و React ساختم و TypeScript و Tailwind CSS در سراسرش حضور دارند. ارزش عملیاش این نیست که یک فریمورک جادویی مرز فرانتاند و بکاند را حذف کند؛ این است که مفاهیم محصول — تسک، پروژه، مسئول، اولویت — از دیتابیس تا منطق سرور و رابط، شکل قابل شناختنشان را حفظ میکنند و خطاهای ترجمه در دستبهدست شدن کمتر میشود.
برای همین Vellum کنار بقیهٔ کار وب من طبیعی مینشیند، هرچند بیشتر پلتفرمهای مشتریام SvelteKit هستند. انتخاب فریمورک سینتکس و شکل استقرار را عوض میکند، وظیفههای زیرین را نه: دامنه را تمیز مدل کن، مجوزها را یکدست نگه دار، رابط را مستقیم بساز و بگذار تایپها ناهماهنگیهای کسلکننده را پیش از کاربر بگیرند. این عادتها مسافرند.
متنباز بودن، خوانندهٔ کد را عوض میکند
کد Vellum با مجوز MIT عمومی است و همین مشخص میکند کد برای چه کسی نوشته میشود. ابزار داخلی خصوصی مدتی با دانش شفاهی تیم سر میکند؛ مخزن عمومی باید برای کسی که در اتاق نبوده هم معنا داشته باشد و همین نامگذاری و مرز و مسیر راهاندازی را به سمت صداقت هل میدهد. نتیجه را میشود در مخزن عمومی پروژه دید، نه اینکه فقط پاراگراف نمونهکار را باور کنی.
این فشار یکی از دلیلهای ارزش کار متنباز در مسیر مستقل توسعه و تدریسم است؛ تصمیمهایی را علنی میکند که کار مشتری معمولاً نمیتواند منتشرشان کند. دربارهٔ PromptForge هم همینطور است، هرچند مسئلهاش کاملاً فرق دارد. کنار هم، وجه ابزارسازی برای توسعهدهندگان در کار من را نشان میدهند: نرمافزاری که قرار است خوانده شود، استفاده شود و بشود با ساختارش بحث کرد.
Vellum هنوز چه چیزی یادم میدهد؟
درس اصلی این است که «فضای کاری ساده» نتیجه است، نه نقطهٔ شروع. مدل رابطهای میخواهد که به مالکیت احترام بگذارد، تایپهایی که در سفرشان در پشته سالم بمانند و قواعد دسترسیای که خوانا بمانند. بیشتر پیچیدگی محصول با یک قابلیت عظیم وارد نمیشود؛ از استثناهای کوچک نشت میکند تا روزی که دیگر کسی نمیداند چرا یک تسک اینجا یک جور رفتار میکند و آنجا جور دیگر. دفاعش همان یکدستی کسلکننده است. همین یکدستی برای نقشهٔ راه هم انضباط میسازد: نمای تازه باید از همان حقیقت واحدِ تسک استفاده کند، نقش تازه همان مدل دسترسی قبلی را گسترش بدهد و گردش کار تازه یواشکی برای وضعیت و مالکیت و اولویت معنای دومی اختراع نکند.
اگر فضای کاری داخلی، ابزار پروژه یا اپلیکیشن چندکاربرهٔ کسبوکاری میسازی، من از همین مرزها شروع میکنم، پیش از بحث برد و داشبورد. در صفحهٔ پروژهٔ Vellum پشته و لینک کد هست، نوشتهٔ لاراول نیمهٔ عملکرد دیتابیس در سابقهٔ بکاند من را پوشش میدهد و رزومهام کوتاهترین مسیر به بقیهٔ کارهاست.
