Zenex CMS: هدلس، چندزبانه و آمادهٔ MCP
خلاصهٔ کاملتر
طبق مستندات پروژه، Zenex CMS یه CMS هدلس (یعنی فقط بکاند محتوا رو میده و ظاهر سایت رو خودت میسازی) با Next.js 16، React 19، Prisma 6، PostgreSQL و Editor.js ـه. چند تا بلاگ، همکاری owner و member، نویسنده و دسته و تگ، پیشنویس و انتشار، فیلدهای SEO و ترجمههای لینکشده رو پوشش میده. ترجمهٔ خودکار با OpenAI و ذخیرهٔ تصویر روی Cloudflare R2 هم اختیاریه.
نکتهٔ اصلی معماریش اینه که دو تا API جدا داره. مسیرهای عمومی زیر /api/blogs/{blogId}/ بدون احراز هویت جواب میدن و همیشه فقط محتوای منتشرشده رو برمیگردونن؛ اگه status=draft بخوای خطای 400 میگیری. لیستها صفحهبندی دارن (هر صفحه ۱ تا ۱۰۰ آیتم) و با includeContent=false میتونی لیست سبک بگیری. API خصوصی زیر /api/v1/blogs/{blogId}/ با هدر Bearer کار میکنه، پیشنویسها رو هم میده و بهجای slug با شناسهٔ رکورد کار میکنه.
همین عملیات خصوصی از راه MCP هم در دسترسه، با ترنسپورت Streamable HTTP روی /api/mcp و یه پل stdio محلی برای کلاینتهایی که فقط لوکال کار میکنن. کلاینتهای کانکتوری مثل ChatGPT و Claude میتونن بهجای پیست کردن کلید، از فلو OAuth رد بشن: سرور اندپوینتهای کشف RFC 9728 و RFC 8414 و ثبتنام داینامیک RFC 7591 رو میده و هر مجوز دقیقاً به یه بلاگ و به اسکوپهای درخواستی محدود میشه.
بخش امنیتش سفتوسخت بسته شده. کلیدهای API ۲۵۶ بیت تصادفی دارن، فقط هش SHA-256شون ذخیره میشه، بین ۱ تا ۳۶۵ روز (پیشفرض ۹۰ روز) منقضی میشن و هر بلاگ حداکثر ۲۵ کلید فعال میتونه داشته باشه. فقط owner اجازهٔ ساخت و باطل کردن کلید رو داره، پس member نمیتونه از این راه دسترسیش رو بالا ببره. یه شمارندهٔ اتمیک توی PostgreSQL هم سقف ۱۲۰ درخواست در دقیقه بهازای هر کلید رو روی همهٔ اینستنسها اعمال میکنه.
تو همون مستندات چند تا هشدار عملیاتی هم اومده. وضعیت published بلافاصله محتوا رو عمومی میکنه و publishedAt فقط متادیتاست نه زمانبند، برای همین توصیه شده ایجنتها پیشفرض پیشنویس بسازن و قبل از انتشار یا حذف تأیید بگیرن. مدیای آپلودشده عمومیه و حذف پست فایل تصویرش رو پاک نمیکنه. آخرش هم تأکید شده متنهای ویرایشی رو، حتی وقتی ایجنت میخونتشون، دادهٔ غیرقابلاعتماد حساب کنی.
نکات کلیدی:
- دو API جدا: عمومی فقط منتشرشده، خصوصی با Bearer و شامل پیشنویسها؛ اسکیمای OpenAPI 3.1 روی /api/v1/openapi بدون نیاز به کلید در دسترسه
- اسکوپها: content:read، content:write، content:publish، content:delete، blog:write و media:write؛ ویرایش پست منتشرشده هم به publish نیاز داره
- محدودیتها: بدنهٔ JSON تا ۱ مگابایت، تصویر base64 تا ۷۰۰ کیلوبایت، آپلود مولتیپارت داشبورد تا ۱۰ مگابایت
- خطای 429 هدر Retry-After: 60 میفرسته؛ محدودکنندهٔ کلید جایگزین محافظت DDoS نیست و باید روی ریورسپروکسی هم لیمیت بذاری
- فقط stdio و Streamable HTTP بدون حالت پشتیبانی میشن، SSE قدیمی نه؛ ریدایرکتها هم برای جلوگیری از لو رفتن کلید رد میشن
- مایگریشن کلیدهای API باید قبل از بالا آوردن نسخهٔ جدید اجرا بشه و توی پروداکشن سراغ migrate dev یا db push نری




