واژگان مشترک حرکت در globals.css: شش @keyframes و شش کلاس .anim-* بههمراه .anim-stagger برای ورود آبشاری. همهٔ مدتزمانها پشت custom property هستند تا یک override کل اپ را تنظیم کند. - packages/ui: Button، Card، Stat، Loading/Empty/ErrorState، UsageBar، Timeline، Modal، Drawer، Table، ToastStack و ArtifactViewer - ریشهٔ هر صفحهٔ (app) با .anim-stagger وارد میشود - AppShell: محتوا fade، منوی کنار stagger، منوهای کشویی slide-up - prefers-reduced-motion مدتزمانها را به ۰.۰۱ms میرساند تا وضعیت پایانی حفظ شود - قرارداد motion در src/test/motion.test.tsx تست میشود تا بازنویسی بعدی آن را بیصدا حذف نکند - تستهای فرانتاند: ۳۵ ← ۴۵
1450 lines
44 KiB
Markdown
1450 lines
44 KiB
Markdown
# TODO اجرای کامل نسخه وب مستقل Smart Organization
|
|
|
|
> **وضعیت (بهروزرسانی نهایی):** پیادهسازی کامل شده است.
|
|
>
|
|
> - بکاند: **۲۱۶ تست سبز**، `ruff check` تمیز، `mypy` روی **۹۰ فایل** بدون خطا.
|
|
> - فرانتاند: **۴۵ تست سبز**، `next lint` بدون هشدار، `tsc --noEmit` تمیز.
|
|
> - دو migration در `apps/api/alembic/versions/` ساخته و با `alembic check`
|
|
> تأیید شد که هیچ drift ندارد. مسیر upgrade و downgrade هر دو تست شدهاند.
|
|
> - workerها (`billing-worker`, `ai-runtime`, `sandbox-gateway`) واقعی و تستشدهاند.
|
|
> - مستندات: `docs/architecture/overview.md` و `docs/security-checklist.md` نوشته شدند.
|
|
>
|
|
> **افزودهٔ بعد از بستن مراحل (درخواست کاربر):** ثبت کامل خطا در دیتابیس.
|
|
> هر خطایی — در HTTP، در worker، در راهاندازی — با جزئیات کامل
|
|
> (ردِّ خطا، `request_id`، سازمان، کاربر، مسیر، اثر انگشت) در جدول
|
|
> `error_events` ذخیره میشود و در `/admin/errors` قابل مشاهده و رسیدگی است.
|
|
> هیچ خطایی بدون پاکسازی secret ذخیره نمیشود (`app/core/redact.py`).
|
|
>
|
|
> **افزودهٔ بعد از بستن مراحل (درخواست کاربر):** پالت فرمان (`⌘K`) و صفحهٔ
|
|
> `/admin/usage`.
|
|
>
|
|
> **افزودهٔ بعد از بستن مراحل (درخواست کاربر):** Motion system. یک واژگان
|
|
> مشترک در `apps/web/src/app/globals.css` — شش `@keyframes` و شش کلاس
|
|
> `.anim-*` بههمراه `.anim-stagger` برای ورود آبشاری — و همهٔ مدتزمانها
|
|
> پشت custom property. در `packages/ui/src/index.tsx` روی Button، Card،
|
|
> Stat، Loading/Empty/ErrorState، UsageBar، Timeline، Modal، Drawer، Table،
|
|
> ToastStack و ArtifactViewer اعمال شده و ریشهٔ هر صفحهٔ `(app)` با
|
|
> `.anim-stagger` وارد میشود. `prefers-reduced-motion` مدتزمانها را به
|
|
> ۰.۰۱ms میرساند تا وضعیت پایانی حفظ شود. قرارداد motion در
|
|
> `src/test/motion.test.tsx` Tests میشود تا بازنویسی بعدی آن را بیصدا
|
|
> حذف نکند.
|
|
>
|
|
> **چیزهایی که عمداً باز ماندهاند:** در `docs/security-checklist.md` دو مورد
|
|
> «⚠️ بدون تست اختصاصی» علامت خوردهاند (نبود secret در frontend، و مقدار پیشفرض
|
|
> `NetworkPolicy.DENY_ALL`). هر دو کنترل در کد درست کار میکنند، فقط تست مستقل
|
|
> ندارند. هیچکدام شکاف امنیتی فعال نیست.
|
|
>
|
|
> **نکتهٔ صداقت:** چکباکسهای زیر **معیارهای پذیرش**، **§۲۲**، **§۲۳** و **§۰.۲**
|
|
> علامت خوردهاند چون مستقیماً تأیید شدهاند. بندهای ریزتر داخل بدنهٔ هر مرحله
|
|
> (۵۰۰ بند توصیفی) بهعنوان شرح کار باقی ماندهاند و علامت نخوردهاند؛ ادعای
|
|
> تأیید تکتک آنها بدون شاهد، خودش یک نقض صداقت مستندسازی میبود.
|
|
|
|
این فایل برای اجرای مرحلهبهمرحله توسط یک عامل کدنویس سبک مثل **DeepSeek v4.1 Flash** نوشته شده است.
|
|
هدف: ساخت نسخه وب مستقل و کامل محصول، بدون وابستگی runtime به ربات تلگرام فعلی.
|
|
|
|
> فایل مرجع محصول و معماری: `web/PLAN.md`
|
|
> محل مجاز توسعه: فقط داخل پوشه `web/` مگر در مواردی که صراحتاً گفته شده است.
|
|
> زبان رابط کاربری: فارسی، راستبهچپ، حرفهای، سریع و ساده.
|
|
> نکته مهم: سیستم فعلی already کدهایی برای **route دامنههای تست** و **Git/Gitea** دارد. در نسخه وب جدید همه سازمانها/کاربران باید بتوانند از این امکانات از طریق وب استفاده کنند، اما کد جدید نباید به تلگرام وابسته شود.
|
|
|
|
---
|
|
|
|
## 0. قوانین قطعی قبل از شروع
|
|
|
|
### 0.1 محدودیتهای اصلی
|
|
|
|
- [ ] هیچ قابلیت جدیدی را داخل فایلهای قدیمی ریشه پروژه مثل `bot.py`، `web_panel.py`، `bot_menus.py`، `bot_messages.py` پیادهسازی نکن.
|
|
- [ ] نسخه جدید باید داخل `web/` ساخته شود.
|
|
- [ ] هیچ منطق جدیدی نباید به `telegram`, `chat_id`, `callback_data`, `InlineKeyboardMarkup`, `MessageHandler`, `CallbackQueryHandler` وابسته باشد.
|
|
- [ ] اگر لازم است از منطق فعلی Git یا domain routing استفاده شود، فقط آن را به عنوان reference بخوان و در `web/` یک abstraction تمیز و مستقل بساز.
|
|
- [ ] هیچ API key، token، secret، credential یا password را در frontend یا لاگها چاپ نکن.
|
|
- [ ] اجرای کد کاربر یا agent روی host اصلی ممنوع است؛ همه چیز باید از مسیر Sandbox Gateway عبور کند.
|
|
- [ ] برای هر عملیات destructive مثل حذف سازمان، حذف repo، حذف دامنه، حذف sandbox یا پاککردن artifact باید confirmation و audit log وجود داشته باشد.
|
|
- [ ] هر endpoint چندسازمانی باید `organization_id` را enforce کند؛ هیچ کاربر نباید داده سازمان دیگر را ببیند.
|
|
|
|
### 0.2 تعریف Done برای کل پروژه
|
|
|
|
پروژه زمانی کامل است که:
|
|
|
|
- [x] کاربر بدون تلگرام ثبتنام و ورود کند.
|
|
- [x] کاربر بتواند سازمان بسازد و عضو دعوت کند.
|
|
- [x] مدیر سامانه بتواند provider/model/routing/price را پنهانی مدیریت کند.
|
|
- [x] کاربر عادی مدل خام نبیند؛ فقط مدیر و کارمندان AI را ببیند.
|
|
- [x] سازمان بتواند پروژه بسازد.
|
|
- [x] هر پروژه بتواند repo خصوصی Git داشته باشد.
|
|
- [x] هر پروژه بتواند یک دامنه تست/preview بگیرد.
|
|
- [x] هر پروژه بتواند یک محیط اجرای ایزوله بگیرد.
|
|
- [x] کاربر بتواند با Manager Chat صحبت کند و task بسازد.
|
|
- [x] یک task واقعی توسط AI worker اجرا شود.
|
|
- [x] usage event برای model call، sandbox runtime، storage/artifact و tool call ثبت شود.
|
|
- [x] داشبورد مصرف، run history، audit log و billing قابل مشاهده باشد.
|
|
- [x] build، lint، typecheck و تستهای اصلی بدون خطا اجرا شوند.
|
|
|
|
---
|
|
|
|
## 1. شناخت کد فعلی فقط برای reference
|
|
|
|
کد فعلی نباید runtime پایه نسخه جدید باشد، اما این فایلها را برای فهم زیرساخت بخوان:
|
|
|
|
- [ ] `caddy_manager.py`
|
|
- کار فعلی: مدیریت Caddy reverse proxy و ساخت route برای subdomain.
|
|
- نکات مهم:
|
|
- دامنه wildcard فعلی: `msa.artacloud.ir`
|
|
- فقط hostهای تکlabel زیر این دامنه مجاز هستند.
|
|
- target فقط باید `localhost:<port>` یا `127.0.0.1:<port>` باشد.
|
|
- قبل از reload، Caddyfile validate میشود.
|
|
- [ ] `port_registry.py`
|
|
- کار فعلی: تخصیص port و ledger مالکیت subdomain.
|
|
- نکات مهم:
|
|
- port range فعلی: `8080-8999`
|
|
- protected ports شامل `3000`, `35555`, `35556`, `35557`, `80`, `443`, `5432`, `6379` و موارد سیستمی است.
|
|
- جدول مفهومی `subdomain_registry` برای جلوگیری از hijack دامنه وجود دارد.
|
|
- هر پروژه حداکثر چند subdomain میگیرد؛ مقدار فعلی `MAX_SUBDOMAINS_PER_PROJECT = 5` است.
|
|
- [ ] `git_manager.py`
|
|
- کار فعلی: ساخت repo خصوصی Gitea، credential پروژه، git sync/commit/push، lock repo.
|
|
- نکات مهم:
|
|
- Gitea URL از config خوانده میشود.
|
|
- repo باید private باشد.
|
|
- credential پروژه باید per owner/project پایدار و collision-free باشد.
|
|
- [ ] `gitea_api.py`
|
|
- کار فعلی: API سبک برای PR، issue، comment و merge.
|
|
- نکات مهم:
|
|
- token نباید در خروجی یا prompt دیده شود.
|
|
- PR workflow و issue ingestion قابل استفاده برای نسخه جدید است.
|
|
|
|
### خروجی این مرحله
|
|
|
|
- [ ] در `web/docs/current-infra-notes.md` خلاصهای 1 تا 2 صفحهای از domain routing و Git فعلی بنویس.
|
|
- [ ] صراحتاً بنویس که نسخه جدید این کدها را مستقیماً import نمیکند، بلکه adapter مستقل خودش را میسازد.
|
|
|
|
---
|
|
|
|
## 2. ساختار پروژه داخل web
|
|
|
|
### 2.1 ساخت پوشهها
|
|
|
|
داخل `web/` این ساختار را بساز:
|
|
|
|
```text
|
|
web/
|
|
TODO.md
|
|
PLAN.md
|
|
README.md
|
|
package.json
|
|
pnpm-workspace.yaml
|
|
apps/
|
|
web/
|
|
api/
|
|
services/
|
|
ai-runtime/
|
|
sandbox-gateway/
|
|
billing-worker/
|
|
packages/
|
|
contracts/
|
|
ui/
|
|
infra/
|
|
docker/
|
|
migrations/
|
|
docs/
|
|
architecture/
|
|
product/
|
|
current-infra-notes.md
|
|
```
|
|
|
|
### 2.2 README اولیه
|
|
|
|
- [ ] در `web/README.md` بنویس:
|
|
- محصول چیست.
|
|
- چطور dev server اجرا میشود.
|
|
- چطور test/lint/typecheck اجرا میشود.
|
|
- معماری کلی چیست.
|
|
- کجا باید کد frontend/backend/worker نوشته شود.
|
|
|
|
### 2.3 package manager
|
|
|
|
- [ ] از `pnpm` استفاده کن.
|
|
- [ ] root `package.json` باید scriptهای زیر داشته باشد:
|
|
- `dev`
|
|
- `build`
|
|
- `lint`
|
|
- `typecheck`
|
|
- `test`
|
|
- `format`
|
|
- `db:migrate`
|
|
- `db:seed`
|
|
|
|
### پذیرش مرحله 2
|
|
|
|
- [x] اجرای `pnpm install` بدون خطا.
|
|
- [x] اجرای `pnpm lint` حداقل بدون خطای ساختاری.
|
|
- [x] همه پوشهها و README ساخته شده باشند.
|
|
|
|
---
|
|
|
|
## 3. انتخاب stack و bootstrapping
|
|
|
|
### 3.1 Frontend
|
|
|
|
در `web/apps/web` بساز:
|
|
|
|
- [ ] Next.js + TypeScript
|
|
- [ ] App Router
|
|
- [ ] Tailwind CSS
|
|
- [ ] ESLint
|
|
- [ ] Prettier
|
|
- [ ] RTL support
|
|
- [ ] Dark-first design
|
|
- [ ] Component پایه داخل `packages/ui`
|
|
|
|
صفحات اولیه:
|
|
|
|
- [ ] `/login`
|
|
- [ ] `/signup`
|
|
- [ ] `/onboarding`
|
|
- [ ] `/dashboard`
|
|
- [ ] `/workforce`
|
|
- [ ] `/manager`
|
|
- [ ] `/tasks`
|
|
- [ ] `/projects`
|
|
- [ ] `/knowledge`
|
|
- [ ] `/billing`
|
|
- [ ] `/settings`
|
|
- [ ] `/admin`
|
|
|
|
### 3.2 Backend API
|
|
|
|
در `web/apps/api` بساز:
|
|
|
|
- [ ] Python FastAPI
|
|
- [ ] SQLAlchemy 2.x
|
|
- [ ] Alembic
|
|
- [ ] Pydantic v2
|
|
- [ ] JWT/session auth
|
|
- [ ] pytest
|
|
- [ ] ruff
|
|
- [ ] mypy یا pyright اگر ساده بود
|
|
|
|
ساختار backend:
|
|
|
|
```text
|
|
apps/api/app/
|
|
main.py
|
|
core/
|
|
config.py
|
|
security.py
|
|
database.py
|
|
errors.py
|
|
domain/
|
|
identity/
|
|
billing/
|
|
ai_control/
|
|
workforce/
|
|
sandbox/
|
|
knowledge/
|
|
audit/
|
|
projects/
|
|
platform/
|
|
application/
|
|
infrastructure/
|
|
interfaces/
|
|
http/
|
|
```
|
|
|
|
### 3.3 دیتابیس و Redis
|
|
|
|
- [ ] در `infra/docker/docker-compose.yml` سرویسهای زیر را بساز:
|
|
- postgres
|
|
- redis
|
|
- api
|
|
- web
|
|
- [ ] env نمونه بساز: `web/.env.example`
|
|
- [ ] secret واقعی داخل repo نگذار.
|
|
|
|
### پذیرش مرحله 3
|
|
|
|
- [x] `docker compose` از داخل `web/infra/docker` بالا بیاید.
|
|
- [x] API health endpoint داشته باشد: `GET /health`.
|
|
- [x] frontend صفحه dashboard خالی اما قابل مشاهده داشته باشد.
|
|
|
|
---
|
|
|
|
## 4. معماری و قراردادهای مشترک
|
|
|
|
### 4.1 اصول معماری
|
|
|
|
- [ ] معماری backend باید Clean/Hexagonal باشد.
|
|
- [ ] domain layer هیچ dependency به FastAPI، SQLAlchemy، Redis، provider خارجی یا HTTP نداشته باشد.
|
|
- [ ] application layer use caseها را اجرا کند.
|
|
- [ ] infrastructure layer adapterها را پیادهسازی کند.
|
|
- [ ] interface/http فقط route و request/response schema داشته باشد.
|
|
|
|
### 4.2 Ports الزامی
|
|
|
|
این interfaceها را تعریف کن:
|
|
|
|
- [ ] `ModelProviderPort`
|
|
- [ ] `PaymentProviderPort`
|
|
- [ ] `SandboxProviderPort`
|
|
- [ ] `GitProviderPort`
|
|
- [ ] `DomainRouterPort`
|
|
- [ ] `StoragePort`
|
|
- [ ] `VectorStorePort`
|
|
- [ ] `NotificationPort`
|
|
- [ ] `AuditPort`
|
|
- [ ] `UsageLedgerPort`
|
|
|
|
### 4.3 Adapterهای اولیه
|
|
|
|
- [ ] `MockModelProviderAdapter` برای dev/test.
|
|
- [ ] `OpenAICompatibleModelAdapter` با base_url و api_key سمت سرور.
|
|
- [ ] `LocalMockPaymentAdapter`.
|
|
- [ ] `LocalMockSandboxAdapter`.
|
|
- [ ] `GiteaGitAdapter`.
|
|
- [ ] `CaddyDomainRouterAdapter` یا `ManagedDomainRouterAdapter`.
|
|
|
|
### پذیرش مرحله 4
|
|
|
|
- [x] تست واحد نشان دهد domain بدون دیتابیس و FastAPI اجرا میشود.
|
|
- [x] adapterها با mock قابل جایگزینی باشند.
|
|
|
|
---
|
|
|
|
## 5. Identity، Auth و Multi-Tenancy
|
|
|
|
### 5.1 مدلها
|
|
|
|
جدولها:
|
|
|
|
- [ ] `users`
|
|
- `id`
|
|
- `email`
|
|
- `password_hash`
|
|
- `name`
|
|
- `avatar_url`
|
|
- `is_platform_owner`
|
|
- `created_at`
|
|
- `updated_at`
|
|
- [ ] `organizations`
|
|
- `id`
|
|
- `name`
|
|
- `slug`
|
|
- `owner_user_id`
|
|
- `created_at`
|
|
- [ ] `memberships`
|
|
- `id`
|
|
- `organization_id`
|
|
- `user_id`
|
|
- `role`
|
|
- `status`
|
|
- `created_at`
|
|
- [ ] `invites`
|
|
- `id`
|
|
- `organization_id`
|
|
- `email`
|
|
- `role`
|
|
- `token_hash`
|
|
- `expires_at`
|
|
- `accepted_at`
|
|
|
|
### 5.2 APIها
|
|
|
|
- [ ] `POST /auth/signup`
|
|
- [ ] `POST /auth/login`
|
|
- [ ] `POST /auth/logout`
|
|
- [ ] `GET /auth/me`
|
|
- [ ] `POST /organizations`
|
|
- [ ] `GET /organizations`
|
|
- [ ] `GET /organizations/{org_id}`
|
|
- [ ] `POST /organizations/{org_id}/invites`
|
|
- [ ] `GET /organizations/{org_id}/members`
|
|
- [ ] `PATCH /organizations/{org_id}/members/{member_id}`
|
|
|
|
### 5.3 قوانین امنیتی
|
|
|
|
- [ ] هر request باید user فعلی را resolve کند.
|
|
- [ ] هر endpoint سازمانی باید membership را چک کند.
|
|
- [ ] roleهای اولیه:
|
|
- `owner`
|
|
- `admin`
|
|
- `manager`
|
|
- `member`
|
|
- `viewer`
|
|
- [ ] platform owner فقط برای admin console دسترسی بالاتر دارد؛ نباید خودکار وارد داده خصوصی سازمان شود مگر برای support با audit.
|
|
|
|
### 5.4 UIها
|
|
|
|
- [ ] signup/login فارسی.
|
|
- [ ] onboarding ساخت اولین سازمان.
|
|
- [ ] organization switcher.
|
|
- [ ] صفحه members و invite.
|
|
|
|
### پذیرش مرحله 5
|
|
|
|
- [x] کاربر جدید ثبتنام کند.
|
|
- [x] سازمان بسازد.
|
|
- [x] کاربر دوم را invite کند.
|
|
- [x] کاربر بدون membership نتواند داده سازمان را ببیند.
|
|
- [x] تست API برای tenant isolation نوشته شود.
|
|
|
|
---
|
|
|
|
## 6. Admin Console برای مالک سامانه
|
|
|
|
### 6.1 AI Provider Management
|
|
|
|
جدولها:
|
|
|
|
- [ ] `ai_providers`
|
|
- `id`
|
|
- `name`
|
|
- `type`
|
|
- `base_url`
|
|
- `is_active`
|
|
- `created_at`
|
|
- [ ] `ai_model_credentials`
|
|
- `id`
|
|
- `provider_id`
|
|
- `name`
|
|
- `encrypted_api_key`
|
|
- `is_active`
|
|
- `created_at`
|
|
- [ ] `ai_models`
|
|
- `id`
|
|
- `provider_id`
|
|
- `internal_name`
|
|
- `display_name_for_admin`
|
|
- `capabilities`
|
|
- `input_price_per_1m`
|
|
- `output_price_per_1m`
|
|
- `is_active`
|
|
|
|
نکته:
|
|
|
|
- [ ] کاربر عادی هیچوقت `internal_name`, `provider`, `base_url`, `api_key` یا قیمت خام provider را نبیند.
|
|
|
|
### 6.2 Routing Policy
|
|
|
|
جدول:
|
|
|
|
- [ ] `routing_policies`
|
|
- `id`
|
|
- `name`
|
|
- `description`
|
|
- `mode`: `fast`, `cheap`, `balanced`, `reasoning`, `vision`, `coding`
|
|
- `fallback_policy_json`
|
|
- `budget_limits_json`
|
|
- `is_default`
|
|
|
|
### 6.3 Rate Card
|
|
|
|
جدول:
|
|
|
|
- [ ] `rate_cards`
|
|
- `id`
|
|
- `name`
|
|
- `unit`
|
|
- `customer_price`
|
|
- `internal_cost_estimate`
|
|
- `is_active`
|
|
|
|
واحدها:
|
|
|
|
- [ ] `model_input_tokens`
|
|
- [ ] `model_output_tokens`
|
|
- [ ] `sandbox_cpu_second`
|
|
- [ ] `sandbox_memory_gb_second`
|
|
- [ ] `storage_gb_day`
|
|
- [ ] `tool_call`
|
|
- [ ] `premium_employee_run`
|
|
|
|
### 6.4 UI admin
|
|
|
|
- [ ] `/admin/providers`
|
|
- [ ] `/admin/models`
|
|
- [ ] `/admin/routing`
|
|
- [ ] `/admin/rate-cards`
|
|
- [ ] `/admin/organizations`
|
|
- [ ] `/admin/usage`
|
|
|
|
### پذیرش مرحله 6
|
|
|
|
- [x] platform owner بتواند provider بسازد.
|
|
- [x] platform owner بتواند model بسازد.
|
|
- [x] platform owner بتواند routing policy پیشفرض بسازد.
|
|
- [x] user عادی نتواند هیچ اطلاعات provider/model خام ببیند.
|
|
|
|
---
|
|
|
|
## 7. Projects، Git و Repo برای همه کاربران
|
|
|
|
این بخش بسیار مهم است چون سیستم فعلی Git دارد و در نسخه وب همه سازمانها/کاربران باید بتوانند از Git استفاده کنند.
|
|
|
|
### 7.1 مدل پروژه
|
|
|
|
جدولها:
|
|
|
|
- [ ] `projects`
|
|
- `id`
|
|
- `organization_id`
|
|
- `name`
|
|
- `slug`
|
|
- `description`
|
|
- `created_by_user_id`
|
|
- `default_branch`
|
|
- `created_at`
|
|
- [ ] `project_repositories`
|
|
- `id`
|
|
- `project_id`
|
|
- `provider`: `gitea`
|
|
- `owner`
|
|
- `repo_name`
|
|
- `clone_url`
|
|
- `web_url`
|
|
- `default_branch`
|
|
- `created_at`
|
|
- [ ] `project_git_credentials`
|
|
- `id`
|
|
- `project_id`
|
|
- `username`
|
|
- `encrypted_password`
|
|
- `created_at`
|
|
|
|
### 7.2 GitProviderPort
|
|
|
|
تعریف کن:
|
|
|
|
```python
|
|
class GitProviderPort:
|
|
async def ensure_project_repo(project) -> RepoInfo: ...
|
|
async def create_branch(project_id, branch_name, from_branch) -> BranchInfo: ...
|
|
async def commit_files(project_id, branch_name, files, message) -> CommitInfo: ...
|
|
async def open_pull_request(project_id, head, base, title, body) -> PullRequestInfo: ...
|
|
async def merge_pull_request(project_id, pr_number) -> MergeResult: ...
|
|
async def get_repo_status(project_id) -> RepoStatus: ...
|
|
```
|
|
|
|
### 7.3 Gitea adapter
|
|
|
|
- [ ] adapter جدید داخل `web/apps/api/app/infrastructure/git/gitea_adapter.py` بساز.
|
|
- [ ] از `git_manager.py` و `gitea_api.py` فقط به عنوان reference استفاده کن.
|
|
- [ ] admin token فقط سمت backend باشد.
|
|
- [ ] repoها private باشند.
|
|
- [ ] نام repo collision-free باشد: بهتر است `orgslug-projectslug-shortid`.
|
|
- [ ] credential هر پروژه encrypted ذخیره شود.
|
|
- [ ] token/password هیچوقت به frontend خام داده نشود مگر برای clone URL موقت و فقط اگر واقعاً لازم شد.
|
|
|
|
### 7.4 APIها
|
|
|
|
- [ ] `POST /organizations/{org_id}/projects`
|
|
- [ ] `GET /organizations/{org_id}/projects`
|
|
- [ ] `GET /organizations/{org_id}/projects/{project_id}`
|
|
- [ ] `POST /organizations/{org_id}/projects/{project_id}/repo/ensure`
|
|
- [ ] `GET /organizations/{org_id}/projects/{project_id}/repo`
|
|
- [ ] `POST /organizations/{org_id}/projects/{project_id}/repo/branches`
|
|
- [ ] `POST /organizations/{org_id}/projects/{project_id}/repo/pull-requests`
|
|
|
|
### 7.5 UIها
|
|
|
|
- [ ] صفحه projects.
|
|
- [ ] ساخت project.
|
|
- [ ] نمایش repo status.
|
|
- [ ] دکمه ساخت repo.
|
|
- [ ] لینک باز کردن Gitea web_url.
|
|
- [ ] نمایش branchها و PRهای باز.
|
|
|
|
### پذیرش مرحله 7
|
|
|
|
- [x] هر سازمان بتواند پروژه بسازد.
|
|
- [x] هر پروژه بتواند repo خصوصی Gitea بگیرد.
|
|
- [x] کاربر عضو سازمان A نتواند repo سازمان B را ببیند یا ایجاد کند.
|
|
- [x] platform owner بتواند همه repoها را در admin view ببیند.
|
|
- [x] هیچ token در response خام برنگردد.
|
|
|
|
---
|
|
|
|
## 8. Domain Routing و Preview Domain برای همه پروژهها
|
|
|
|
این بخش هم حیاتی است چون سیستم فعلی route دامنه تست دارد و نسخه وب باید آن را عمومی، امن و ساده کند.
|
|
|
|
### 8.1 مدلها
|
|
|
|
جدولها:
|
|
|
|
- [ ] `preview_ports`
|
|
- `id`
|
|
- `organization_id`
|
|
- `project_id`
|
|
- `service_name`
|
|
- `port`
|
|
- `status`
|
|
- `created_at`
|
|
- [ ] `preview_domains`
|
|
- `id`
|
|
- `organization_id`
|
|
- `project_id`
|
|
- `host`
|
|
- `port`
|
|
- `status`: `active`, `disabled`, `failed`
|
|
- `protected`
|
|
- `created_by_user_id`
|
|
- `created_at`
|
|
|
|
### 8.2 DomainRouterPort
|
|
|
|
تعریف کن:
|
|
|
|
```python
|
|
class DomainRouterPort:
|
|
async def allocate_port(org_id, project_id, service_name) -> int: ...
|
|
async def claim_preview_domain(org_id, project_id, requested_subdomain, port) -> PreviewDomain: ...
|
|
async def configure_reverse_proxy(host, port) -> ReverseProxyResult: ...
|
|
async def remove_preview_domain(domain_id) -> None: ...
|
|
async def list_project_domains(project_id) -> list[PreviewDomain]: ...
|
|
```
|
|
|
|
### 8.3 قوانین امنیتی دامنه
|
|
|
|
- [ ] فقط subdomainهای تکlabel زیر `msa.artacloud.ir` مجاز باشند مگر بعداً custom domain رسمی اضافه شود.
|
|
- [ ] label فقط شامل `a-z`, `0-9`, `-` باشد.
|
|
- [ ] label بین 3 تا 40 کاراکتر باشد.
|
|
- [ ] host collision ممنوع است.
|
|
- [ ] هر host دقیقاً یک owner داشته باشد.
|
|
- [ ] هیچ سازمانی نتواند دامنه سازمان دیگر را حذف یا hijack کند.
|
|
- [ ] port فقط از range امن داده شود.
|
|
- [ ] target reverse proxy فقط localhost/127.0.0.1 باشد.
|
|
- [ ] قبل از reload، Caddy config validate شود.
|
|
- [ ] protected domains فقط توسط platform owner قابل تغییر باشند.
|
|
|
|
### 8.4 Port allocation
|
|
|
|
از منطق فعلی reference بگیر:
|
|
|
|
- [ ] range پیشفرض: `8080-8999`
|
|
- [ ] protected ports را رزرو کن.
|
|
- [ ] اگر snapshot listening ports ممکن نبود، port allocate نکن.
|
|
- [ ] در concurrent allocation، retry داشته باش.
|
|
|
|
### 8.5 APIها
|
|
|
|
- [ ] `POST /organizations/{org_id}/projects/{project_id}/preview/ports`
|
|
- [ ] `POST /organizations/{org_id}/projects/{project_id}/preview/domains`
|
|
- [ ] `GET /organizations/{org_id}/projects/{project_id}/preview/domains`
|
|
- [ ] `DELETE /organizations/{org_id}/projects/{project_id}/preview/domains/{domain_id}`
|
|
|
|
### 8.6 UIها
|
|
|
|
- [ ] در صفحه project یک tab به نام `پیشنمایش و دامنه تست` بساز.
|
|
- [ ] دکمه `ساخت دامنه تست`.
|
|
- [ ] input برای subdomain پیشنهادی.
|
|
- [ ] نمایش URL نهایی مثل `https://my-app.msa.artacloud.ir`.
|
|
- [ ] وضعیت active/failed.
|
|
- [ ] دکمه حذف با confirmation.
|
|
|
|
### پذیرش مرحله 8
|
|
|
|
- [x] کاربر عضو سازمان بتواند برای project خودش دامنه تست بسازد.
|
|
- [x] دامنه روی Caddy route شود.
|
|
- [x] دامنه تکراری خطای واضح بدهد.
|
|
- [x] کاربر نتواند دامنه پروژه دیگر را حذف کند.
|
|
- [x] route به protected port ممنوع باشد.
|
|
- [x] همه عملیات audit شوند.
|
|
|
|
---
|
|
|
|
## 9. Sandbox Gateway و محیط ایزوله
|
|
|
|
### 9.1 اصل مهم
|
|
|
|
- [ ] هیچ کدی از کاربر یا AI worker روی host اصلی اجرا نشود.
|
|
- [ ] Sandbox Gateway تنها مسیر اجرای command، build، test، preview و app runtime باشد.
|
|
|
|
### 9.2 مدلها
|
|
|
|
- [ ] `sandbox_templates`
|
|
- [ ] `workspaces`
|
|
- [ ] `sandbox_sessions`
|
|
- [ ] `command_runs`
|
|
- [ ] `snapshots`
|
|
- [ ] `preview_urls`
|
|
- [ ] `sandbox_resource_limits`
|
|
|
|
فیلدهای مهم `workspaces`:
|
|
|
|
- `id`
|
|
- `organization_id`
|
|
- `project_id`
|
|
- `template_id`
|
|
- `provider`
|
|
- `external_workspace_id`
|
|
- `status`
|
|
- `created_at`
|
|
|
|
فیلدهای مهم `sandbox_sessions`:
|
|
|
|
- `id`
|
|
- `workspace_id`
|
|
- `external_session_id`
|
|
- `status`
|
|
- `started_at`
|
|
- `stopped_at`
|
|
- `last_active_at`
|
|
|
|
### 9.3 SandboxProviderPort
|
|
|
|
```python
|
|
class SandboxProviderPort:
|
|
async def create_workspace(project_id, template_id) -> WorkspaceInfo: ...
|
|
async def start_session(workspace_id) -> SessionInfo: ...
|
|
async def run_command(session_id, command, timeout_seconds, env=None) -> CommandResult: ...
|
|
async def read_file(session_id, path) -> str: ...
|
|
async def write_file(session_id, path, content) -> None: ...
|
|
async def snapshot(session_id, name) -> SnapshotInfo: ...
|
|
async def pause(session_id) -> None: ...
|
|
async def resume(session_id) -> SessionInfo: ...
|
|
async def destroy(session_id) -> None: ...
|
|
async def get_preview_url(session_id, port) -> str: ...
|
|
```
|
|
|
|
### 9.4 MVP adapter
|
|
|
|
- [ ] اول `LocalMockSandboxAdapter` بساز که command واقعی اجرا نکند، فقط fake result بدهد.
|
|
- [ ] سپس adapter واقعی برای Daytona یا E2B بساز؛ اگر credential نداریم، adapter را feature-flag کن.
|
|
- [ ] انتخاب provider از env باشد:
|
|
- `SANDBOX_PROVIDER=mock|daytona|e2b`
|
|
|
|
### 9.5 محدودیتها
|
|
|
|
- [ ] timeout برای هر command الزامی.
|
|
- [ ] max output size الزامی.
|
|
- [ ] max CPU/RAM/DISK در policy ذخیره شود.
|
|
- [ ] egress network در طراحی deny-by-default باشد، حتی اگر در MVP mock است.
|
|
- [ ] secretها فقط از Secret Broker تزریق شوند.
|
|
|
|
### 9.6 اتصال به preview domain
|
|
|
|
- [ ] وقتی sandbox app روی port داخلی اجرا شد، backend بتواند از DomainRouterPort دامنه تست بگیرد.
|
|
- [ ] mapping باید به session/project وصل باشد.
|
|
- [ ] اگر sandbox stop شد، UI باید هشدار بدهد که preview ممکن است offline باشد.
|
|
|
|
### پذیرش مرحله 9
|
|
|
|
- [x] project بتواند workspace sandbox بسازد.
|
|
- [x] command mock یا واقعی اجرا شود.
|
|
- [x] command result در UI دیده شود.
|
|
- [x] usage event برای sandbox runtime/command ثبت شود.
|
|
- [x] هیچ مسیر API برای اجرای مستقیم shell host وجود نداشته باشد.
|
|
|
|
---
|
|
|
|
## 10. AI Workforce و کارمندان هوش مصنوعی
|
|
|
|
### 10.1 مدلها
|
|
|
|
- [ ] `agent_templates`
|
|
- `id`
|
|
- `name`
|
|
- `role_key`
|
|
- `description`
|
|
- `default_prompt`
|
|
- `default_tools_json`
|
|
- `default_routing_policy_id`
|
|
- `is_system`
|
|
- [ ] `employees`
|
|
- `id`
|
|
- `organization_id`
|
|
- `project_id` nullable
|
|
- `template_id`
|
|
- `name`
|
|
- `role_key`
|
|
- `status`
|
|
- `routing_policy_id`
|
|
- `budget_limit_json`
|
|
- `created_at`
|
|
- [ ] `prompt_versions`
|
|
- `id`
|
|
- `employee_id`
|
|
- `version`
|
|
- `content`
|
|
- `created_by_user_id`
|
|
- `created_at`
|
|
- [ ] `employee_tool_permissions`
|
|
- `employee_id`
|
|
- `tool_key`
|
|
- `allowed`
|
|
- `policy_json`
|
|
|
|
### 10.2 templateهای اولیه
|
|
|
|
بساز:
|
|
|
|
- [ ] مدیر سازمان / Manager
|
|
- [ ] تحلیلگر و معمار / Planner
|
|
- [ ] برنامهنویس / Developer
|
|
- [ ] بازبین کد / Reviewer
|
|
- [ ] تستر / Tester
|
|
- [ ] محقق / Researcher
|
|
- [ ] تولیدکننده محتوا / Content Creator
|
|
- [ ] پشتیبان مشتری / Support Agent
|
|
|
|
### 10.3 APIها
|
|
|
|
- [ ] `GET /organizations/{org_id}/agent-templates`
|
|
- [ ] `POST /organizations/{org_id}/employees`
|
|
- [ ] `GET /organizations/{org_id}/employees`
|
|
- [ ] `GET /organizations/{org_id}/employees/{employee_id}`
|
|
- [ ] `PATCH /organizations/{org_id}/employees/{employee_id}`
|
|
- [ ] `POST /organizations/{org_id}/employees/{employee_id}/prompt-versions`
|
|
|
|
### 10.4 UIها
|
|
|
|
- [ ] صفحه `AI Workforce`.
|
|
- [ ] کارت هر کارمند:
|
|
- نام
|
|
- نقش
|
|
- وضعیت
|
|
- taskهای فعال
|
|
- مصرف امروز
|
|
- دکمه تنظیمات
|
|
- [ ] wizard ساخت کارمند از template.
|
|
- [ ] صفحه جزئیات کارمند.
|
|
|
|
### پذیرش مرحله 10
|
|
|
|
- [x] سازمان بتواند کارمند AI بسازد.
|
|
- [x] کارمند به routing policy وصل باشد اما user مدل خام نبیند.
|
|
- [x] prompt version ثبت شود.
|
|
- [x] فقط admin/manager بتواند کارمند را تغییر دهد.
|
|
|
|
---
|
|
|
|
## 11. Manager Chat، Thread، Task و Run Engine
|
|
|
|
### 11.1 مدلها
|
|
|
|
- [ ] `threads`
|
|
- [ ] `messages`
|
|
- [ ] `tasks`
|
|
- [ ] `runs`
|
|
- [ ] `run_steps`
|
|
- [ ] `tool_calls`
|
|
- [ ] `artifacts`
|
|
|
|
وضعیتهای task:
|
|
|
|
- `new`
|
|
- `triaged`
|
|
- `waiting_approval`
|
|
- `running`
|
|
- `done`
|
|
- `failed`
|
|
- `cancelled`
|
|
|
|
وضعیتهای run:
|
|
|
|
- `queued`
|
|
- `planning`
|
|
- `waiting_approval`
|
|
- `running`
|
|
- `tool_calling`
|
|
- `sandbox_running`
|
|
- `completed`
|
|
- `failed`
|
|
- `cancelled`
|
|
- `timed_out`
|
|
|
|
### 11.2 APIها
|
|
|
|
- [ ] `POST /organizations/{org_id}/threads`
|
|
- [ ] `GET /organizations/{org_id}/threads`
|
|
- [ ] `GET /organizations/{org_id}/threads/{thread_id}`
|
|
- [ ] `POST /organizations/{org_id}/threads/{thread_id}/messages`
|
|
- [ ] `POST /organizations/{org_id}/tasks`
|
|
- [ ] `GET /organizations/{org_id}/tasks`
|
|
- [ ] `GET /organizations/{org_id}/tasks/{task_id}`
|
|
- [ ] `POST /organizations/{org_id}/tasks/{task_id}/runs`
|
|
- [ ] `GET /organizations/{org_id}/runs/{run_id}`
|
|
- [ ] `POST /organizations/{org_id}/runs/{run_id}/cancel`
|
|
|
|
### 11.3 اجرای AI
|
|
|
|
- [ ] برای MVP، Manager Chat با `MockModelProviderAdapter` پاسخ قابل پیشبینی بدهد.
|
|
- [ ] سپس `OpenAICompatibleModelAdapter` وصل شود.
|
|
- [ ] model routing فقط سمت backend انجام شود.
|
|
- [ ] هر model call باید usage event بسازد.
|
|
- [ ] tool callها در `tool_calls` ثبت شوند.
|
|
- [ ] run_steps timeline بسازد.
|
|
|
|
### 11.4 UI Manager
|
|
|
|
- [ ] صفحه `/manager` split-view داشته باشد:
|
|
- ستون chat
|
|
- ستون task/artifacts
|
|
- ستون کوچک run timeline یا logs
|
|
- [ ] پیامها realtime یا polling سبک داشته باشند.
|
|
- [ ] اگر task ساخته شد، card task نشان بده.
|
|
- [ ] اگر run در حال اجراست، status واضح نشان بده.
|
|
|
|
### پذیرش مرحله 11
|
|
|
|
- [x] کاربر با Manager Chat پیام بفرستد.
|
|
- [x] Manager بتواند task بسازد یا پیشنهاد task بدهد.
|
|
- [x] task run شود.
|
|
- [x] run_steps و usage_events ثبت شود.
|
|
- [x] UI خروجی و artifact را نشان دهد.
|
|
|
|
---
|
|
|
|
## 12. Tools و دسترسی کارمندها
|
|
|
|
### 12.1 tool registry
|
|
|
|
Toolهای اولیه:
|
|
|
|
- [ ] `git.ensure_repo`
|
|
- [ ] `git.create_branch`
|
|
- [ ] `git.open_pr`
|
|
- [ ] `domain.create_preview`
|
|
- [ ] `sandbox.run_command`
|
|
- [ ] `sandbox.read_file`
|
|
- [ ] `sandbox.write_file`
|
|
- [ ] `knowledge.search`
|
|
- [ ] `artifact.create`
|
|
|
|
### 12.2 قوانین toolها
|
|
|
|
- [ ] هر tool باید permission check داشته باشد.
|
|
- [ ] هر tool call باید audit و trace شود.
|
|
- [ ] toolهای خطرناک approval بخواهند:
|
|
- حذف repo
|
|
- حذف دامنه
|
|
- merge PR
|
|
- اجرای command با دسترسی بالا
|
|
- حذف فایل
|
|
- destroy sandbox
|
|
|
|
### 12.3 UI approvals
|
|
|
|
- [ ] صفحه task باید actionهای منتظر approval را نشان دهد.
|
|
- [ ] approve/reject با توضیح ثبت شود.
|
|
|
|
### پذیرش مرحله 12
|
|
|
|
- [x] کارمند بدون permission نتواند tool را اجرا کند.
|
|
- [x] approval flow برای tool خطرناک کار کند.
|
|
- [x] audit log کامل ثبت شود.
|
|
|
|
---
|
|
|
|
## 13. Billing و Usage Ledger
|
|
|
|
### 13.1 مدلها
|
|
|
|
- [ ] `plans`
|
|
- [ ] `subscriptions`
|
|
- [ ] `credit_wallets`
|
|
- [ ] `usage_events`
|
|
- [ ] `invoices`
|
|
- [ ] `payments`
|
|
|
|
فیلدهای `usage_events`:
|
|
|
|
- `id`
|
|
- `organization_id`
|
|
- `project_id` nullable
|
|
- `user_id` nullable
|
|
- `employee_id` nullable
|
|
- `run_id` nullable
|
|
- `unit`
|
|
- `quantity`
|
|
- `unit_price`
|
|
- `internal_cost_estimate`
|
|
- `total_price`
|
|
- `metadata_json`
|
|
- `created_at`
|
|
|
|
### 13.2 قوانین billing
|
|
|
|
- [ ] هر مصرف باید اول در ledger داخلی ثبت شود.
|
|
- [ ] Stripe یا payment provider فقط adapter است؛ منبع حقیقت usage ledger داخلی است.
|
|
- [ ] اگر wallet اعتبار کافی نداشت، run جدید متوقف یا نیازمند پرداخت شود.
|
|
- [ ] platform owner بتواند credit دستی اضافه کند.
|
|
|
|
### 13.3 APIها
|
|
|
|
- [ ] `GET /organizations/{org_id}/billing/summary`
|
|
- [ ] `GET /organizations/{org_id}/billing/usage-events`
|
|
- [ ] `GET /organizations/{org_id}/billing/invoices`
|
|
- [ ] `POST /organizations/{org_id}/billing/add-credit` فقط admin/platform owner طبق policy
|
|
- [ ] `POST /organizations/{org_id}/billing/checkout` در صورت اتصال payment واقعی
|
|
|
|
### 13.4 UI Billing
|
|
|
|
- [ ] موجودی اعتبار.
|
|
- [ ] مصرف امروز/ماه.
|
|
- [ ] breakdown بر اساس employee/project/unit.
|
|
- [ ] invoice list.
|
|
- [ ] هشدار اعتبار کم.
|
|
|
|
### پذیرش مرحله 13
|
|
|
|
- [x] هر model call usage بسازد.
|
|
- [x] هر sandbox command usage بسازد.
|
|
- [x] billing summary درست جمع بزند.
|
|
- [x] کاربر عادی فقط billing سازمان خودش را ببیند.
|
|
|
|
---
|
|
|
|
## 14. Knowledge Base
|
|
|
|
### 14.1 مدلها
|
|
|
|
- [ ] `knowledge_sources`
|
|
- [ ] `documents`
|
|
- [ ] `document_chunks`
|
|
- [ ] `embedding_jobs`
|
|
- [ ] `retrieval_policies`
|
|
|
|
### 14.2 MVP
|
|
|
|
- [ ] upload فایل متنی/markdown/pdf اگر ساده بود.
|
|
- [ ] extract text.
|
|
- [ ] chunk.
|
|
- [ ] embedding با adapter قابل mock.
|
|
- [ ] search ساده keyword در MVP اگر vector آماده نبود.
|
|
|
|
### 14.3 permissions
|
|
|
|
- [ ] هر knowledge source به organization وصل باشد.
|
|
- [ ] optionally به project وصل باشد.
|
|
- [ ] employee فقط knowledge مجاز خودش را ببیند.
|
|
|
|
### پذیرش مرحله 14
|
|
|
|
- [x] کاربر فایل knowledge اضافه کند.
|
|
- [x] Manager در پاسخ بتواند از knowledge استفاده کند.
|
|
- [x] سازمان دیگر به این knowledge دسترسی نداشته باشد.
|
|
|
|
---
|
|
|
|
## 15. Observability، Audit و Trace
|
|
|
|
### 15.1 مدلها
|
|
|
|
- [ ] `audit_events`
|
|
- [ ] `traces`
|
|
- [ ] `spans`
|
|
- [ ] `error_events`
|
|
- [ ] `quality_metrics`
|
|
|
|
### 15.2 audit الزامی برای
|
|
|
|
- [ ] login/logout
|
|
- [ ] ساخت/حذف سازمان
|
|
- [ ] invite و تغییر role
|
|
- [ ] ساخت/تغییر employee
|
|
- [ ] ساخت/حذف repo
|
|
- [ ] ساخت/حذف preview domain
|
|
- [ ] sandbox command
|
|
- [ ] approval/rejection
|
|
- [ ] billing credit/payment
|
|
- [ ] تغییر provider/model/routing
|
|
|
|
### 15.3 UI
|
|
|
|
- [ ] صفحه audit در settings سازمان.
|
|
- [ ] صفحه traces در admin یا task detail.
|
|
- [ ] timeline run در task detail.
|
|
|
|
### پذیرش مرحله 15
|
|
|
|
- [x] هر عملیات حساس audit شود.
|
|
- [x] trace یک run از ابتدا تا انتها قابل مشاهده باشد.
|
|
|
|
---
|
|
|
|
## 16. UI/UX کامل
|
|
|
|
### 16.1 Design System
|
|
|
|
- [ ] رنگبندی dark حرفهای.
|
|
- [ ] RTL کامل.
|
|
- [ ] فونت مناسب فارسی.
|
|
- [ ] componentها:
|
|
- Button
|
|
- Card
|
|
- Badge
|
|
- Modal
|
|
- Drawer
|
|
- Table
|
|
- Tabs
|
|
- Toast
|
|
- EmptyState
|
|
- LoadingState
|
|
- ErrorState
|
|
- ConfirmDialog
|
|
- Timeline
|
|
- UsageBar
|
|
- EmployeeCard
|
|
- TaskCard
|
|
- ArtifactViewer
|
|
|
|
### 16.2 Layout اصلی
|
|
|
|
- [ ] sidebar:
|
|
- داشبورد
|
|
- مدیر AI
|
|
- نیروی کار AI
|
|
- پروژهها
|
|
- وظایف
|
|
- دانش سازمانی
|
|
- مصرف و پرداخت
|
|
- تنظیمات
|
|
- [ ] topbar:
|
|
- organization switcher
|
|
- command/search
|
|
- user menu
|
|
- credit badge
|
|
|
|
### 16.3 صفحات
|
|
|
|
- [ ] Dashboard
|
|
- خلاصه مصرف
|
|
- taskهای فعال
|
|
- کارمندهای فعال
|
|
- خطاهای اخیر
|
|
- preview domains
|
|
- [ ] Workforce
|
|
- [ ] Manager Chat
|
|
- [ ] Tasks
|
|
- [ ] Project detail
|
|
- Overview
|
|
- Git
|
|
- Sandbox
|
|
- Preview Domain
|
|
- Artifacts
|
|
- [ ] Billing
|
|
- [ ] Knowledge
|
|
- [ ] Settings
|
|
- [ ] Admin Console
|
|
|
|
### پذیرش مرحله 16
|
|
|
|
- [x] UI در desktop خوب باشد.
|
|
- [x] RTL کامل باشد.
|
|
- [x] stateهای empty/loading/error وجود داشته باشد.
|
|
- [x] user عادی هیچ عبارت provider/model خام نبیند.
|
|
|
|
---
|
|
|
|
## 17. Seed Data و Dev Experience
|
|
|
|
### 17.1 seed
|
|
|
|
- [ ] یک platform owner بساز.
|
|
- [ ] یک user عادی بساز.
|
|
- [ ] یک organization نمونه بساز.
|
|
- [ ] چند employee template بساز.
|
|
- [ ] routing policyهای نمونه بساز.
|
|
- [ ] rate card نمونه بساز.
|
|
- [ ] provider mock بساز.
|
|
|
|
### 17.2 dev commands
|
|
|
|
- [ ] `pnpm dev` frontend و backend را بالا بیاورد یا حداقل راهنمای واضح بدهد.
|
|
- [ ] `pnpm test` تستها را اجرا کند.
|
|
- [ ] `pnpm db:migrate` migrationها را اجرا کند.
|
|
- [ ] `pnpm db:seed` داده seed بسازد.
|
|
|
|
### پذیرش مرحله 17
|
|
|
|
- [x] توسعهدهنده جدید با README بتواند پروژه را بالا بیاورد.
|
|
- [x] seed loginها در README نوشته شده باشند، بدون secret واقعی production.
|
|
|
|
---
|
|
|
|
## 18. تستها
|
|
|
|
### 18.1 Backend tests
|
|
|
|
- [ ] auth signup/login.
|
|
- [ ] organization isolation.
|
|
- [ ] role permission.
|
|
- [ ] provider hidden from user.
|
|
- [ ] project creation.
|
|
- [ ] Gitea adapter mock.
|
|
- [ ] domain allocation collision.
|
|
- [ ] protected port/domain rejection.
|
|
- [ ] sandbox command mock.
|
|
- [ ] usage ledger aggregation.
|
|
- [ ] audit event creation.
|
|
- [ ] task/run lifecycle.
|
|
|
|
### 18.2 Frontend tests
|
|
|
|
- [ ] صفحات اصلی render شوند.
|
|
- [ ] organization switcher کار کند.
|
|
- [ ] dashboard empty state داشته باشد.
|
|
- [ ] manager chat message ارسال کند.
|
|
- [ ] project preview domain form validation داشته باشد.
|
|
|
|
### 18.3 E2E حداقلی
|
|
|
|
سناریو:
|
|
|
|
- [ ] signup
|
|
- [ ] create organization
|
|
- [ ] create project
|
|
- [ ] ensure repo
|
|
- [ ] create preview domain
|
|
- [ ] create employee
|
|
- [ ] send manager message
|
|
- [ ] create task
|
|
- [ ] run task
|
|
- [ ] see usage summary
|
|
|
|
### پذیرش مرحله 18
|
|
|
|
- [x] تستها در CI/local با یک دستور اجرا شوند.
|
|
- [x] تست multi-tenancy حتماً وجود داشته باشد.
|
|
|
|
---
|
|
|
|
## 19. امنیت
|
|
|
|
### 19.1 Secret Management
|
|
|
|
- [ ] API keys encrypted at rest.
|
|
- [ ] passwordها hash با argon2 یا bcrypt.
|
|
- [ ] JWT secret از env.
|
|
- [ ] frontend هیچ secret ندارد.
|
|
|
|
### 19.2 Access Control
|
|
|
|
- [ ] middleware مرکزی برای auth.
|
|
- [ ] dependency مرکزی برای org membership.
|
|
- [ ] policy object برای role/permission.
|
|
- [ ] تست منفی برای unauthorized/forbidden.
|
|
|
|
### 19.3 Sandbox Security
|
|
|
|
- [ ] host shell مستقیم ممنوع.
|
|
- [ ] command timeout.
|
|
- [ ] output limit.
|
|
- [ ] egress policy طراحی شود.
|
|
- [ ] audit برای command.
|
|
|
|
### 19.4 Domain/Git Security
|
|
|
|
- [ ] host injection ممنوع.
|
|
- [ ] Caddy target SSRF ممنوع.
|
|
- [ ] protected ports ممنوع.
|
|
- [ ] repo private.
|
|
- [ ] token never returned.
|
|
|
|
### پذیرش مرحله 19
|
|
|
|
- [x] security checklist داخل `web/docs/security-checklist.md` کامل شود.
|
|
- [x] تستهای امنیتی اصلی سبز باشند.
|
|
|
|
---
|
|
|
|
## 20. Performance
|
|
|
|
### 20.1 Frontend
|
|
|
|
- [ ] loading skeleton.
|
|
- [ ] pagination برای tables.
|
|
- [ ] caching با TanStack Query یا روش مشابه.
|
|
- [ ] bundle بیدلیل سنگین نشود.
|
|
|
|
### 20.2 Backend
|
|
|
|
- [ ] pagination در list endpoints.
|
|
- [ ] index روی `organization_id`, `project_id`, `created_at`.
|
|
- [ ] queryهای dashboard aggregate باشند.
|
|
- [ ] long-running taskها background worker بروند.
|
|
|
|
### 20.3 AI/Sandbox
|
|
|
|
- [ ] runها async باشند.
|
|
- [ ] timeout و retry کنترلشده.
|
|
- [ ] cancellation ممکن باشد.
|
|
|
|
### پذیرش مرحله 20
|
|
|
|
- [x] dashboard با seed data معمولی سریع load شود.
|
|
- [x] API listها pagination داشته باشند.
|
|
|
|
---
|
|
|
|
## 21. Migration از ذهنیت فعلی به نسخه وب
|
|
|
|
این migration دیتای production فعلی نیست؛ منظور تبدیل مفاهیم است.
|
|
|
|
### 21.1 Mapping مفاهیم
|
|
|
|
- Telegram user/chat_id → User
|
|
- allowed/admin user ids → platform owner و memberships
|
|
- project workspace → Project + Workspace + Repo
|
|
- bot inline menu → Web pages/components
|
|
- USER_INPUT_STATES → DB-backed wizard/form state
|
|
- AGY/OpenCode model selection → hidden AI Control Plane routing
|
|
- org manager/current organization → Organization + AI Manager Employee
|
|
- Caddy subdomain → PreviewDomain service
|
|
- Gitea repo → ProjectRepository service
|
|
|
|
### 21.2 ممنوعیتها
|
|
|
|
- [ ] `chat_id` در schema جدید استفاده نشود.
|
|
- [ ] Telegram auth در نسخه جدید استفاده نشود.
|
|
- [ ] callback_data در workflow جدید استفاده نشود.
|
|
|
|
---
|
|
|
|
## 22. ترتیب اجرای پیشنهادی برای DeepSeek
|
|
|
|
اگر عامل کدنویس نمیداند از کجا شروع کند، دقیقاً این ترتیب را اجرا کند:
|
|
|
|
1. [x] ساخت ساختار پوشه و README.
|
|
2. [x] bootstrap frontend و backend.
|
|
3. [x] docker compose برای postgres/redis.
|
|
4. [x] health endpoint و صفحه dashboard خالی.
|
|
5. [x] auth و organization.
|
|
6. [x] membership و RBAC.
|
|
7. [x] admin provider/model/routing/rate-card با mock.
|
|
8. [x] projects.
|
|
9. [x] GitProviderPort و Gitea adapter mock/real.
|
|
10. [x] DomainRouterPort و preview domain mock/real.
|
|
11. [x] Sandbox Gateway mock.
|
|
12. [x] AI Workforce templates و employees.
|
|
13. [x] Manager Chat mock.
|
|
14. [x] Task/Run engine.
|
|
15. [x] Usage ledger.
|
|
16. [x] Billing UI.
|
|
17. [x] Audit/Trace.
|
|
18. [x] Sandbox real adapter اگر credential موجود بود.
|
|
19. [x] UI polish.
|
|
20. [x] تست E2E.
|
|
|
|
---
|
|
|
|
## 23. Definition of Done نهایی
|
|
|
|
قبل از تحویل نهایی، این چکلیست باید کامل باشد:
|
|
|
|
- [x] `web/README.md` کامل است.
|
|
- [x] `web/docs/architecture/overview.md` کامل است.
|
|
- [x] `web/docs/security-checklist.md` کامل است.
|
|
- [x] frontend بالا میآید.
|
|
- [x] backend بالا میآید.
|
|
- [x] database migration اجرا میشود.
|
|
- [x] seed اجرا میشود.
|
|
- [x] کاربر ثبتنام میکند.
|
|
- [x] سازمان ساخته میشود.
|
|
- [x] عضویت و role کار میکند.
|
|
- [x] admin console provider/model/routing/rate-card دارد.
|
|
- [x] user مدل/provider خام نمیبیند.
|
|
- [x] پروژه ساخته میشود.
|
|
- [x] repo ساخته یا mock میشود.
|
|
- [x] preview domain ساخته یا mock میشود.
|
|
- [x] sandbox workspace ساخته یا mock میشود.
|
|
- [x] کارمند AI ساخته میشود.
|
|
- [x] Manager Chat کار میکند.
|
|
- [x] task ساخته و run میشود.
|
|
- [x] usage event ثبت میشود.
|
|
- [x] billing summary نشان داده میشود.
|
|
- [x] audit log نشان داده میشود.
|
|
- [x] تست multi-tenancy وجود دارد و سبز است.
|
|
- [x] تست domain security وجود دارد و سبز است.
|
|
- [x] تست git provider وجود دارد و سبز است.
|
|
- [x] تست usage ledger وجود دارد و سبز است.
|
|
- [x] `pnpm lint` موفق است.
|
|
- [x] `pnpm test` موفق است.
|
|
- [x] `pnpm build` موفق است.
|
|
|
|
---
|
|
|
|
## 24. یادداشت مهم درباره «کامل انجام بده»
|
|
|
|
اگر در زمان اجرا credential واقعی برای Gitea، Caddy، Daytona، E2B یا payment provider وجود نداشت:
|
|
|
|
- [ ] feature را حذف نکن.
|
|
- [ ] interface و UI و مدل دیتابیس را کامل بساز.
|
|
- [ ] adapter mock قابل تست بساز.
|
|
- [ ] adapter واقعی را پشت env flag آماده کن.
|
|
- [ ] در README دقیق بنویس برای فعالسازی واقعی چه envهایی لازم است.
|
|
|
|
یعنی خروجی باید از نظر محصول و معماری کامل باشد، حتی اگر بعضی providerهای خارجی در محیط dev با mock اجرا شوند.
|
|
|
|
---
|
|
|
|
## 25. envهای پیشنهادی
|
|
|
|
در `web/.env.example` این موارد را قرار بده:
|
|
|
|
```env
|
|
APP_ENV=development
|
|
APP_URL=http://localhost:3000
|
|
API_URL=http://localhost:8000
|
|
|
|
DATABASE_URL=postgresql+psycopg://agy:agy@localhost:5432/agy_web
|
|
REDIS_URL=redis://localhost:6379/0
|
|
|
|
JWT_SECRET=change-me
|
|
ENCRYPTION_KEY=change-me-32-bytes
|
|
|
|
AI_DEFAULT_PROVIDER=mock
|
|
OPENAI_COMPATIBLE_BASE_URL=
|
|
OPENAI_COMPATIBLE_API_KEY=
|
|
|
|
GIT_PROVIDER=mock
|
|
GITEA_URL=
|
|
GITEA_INTERNAL_URL=
|
|
GITEA_ADMIN_TOKEN=
|
|
|
|
DOMAIN_ROUTER=mock
|
|
PREVIEW_ROOT_DOMAIN=msa.artacloud.ir
|
|
PREVIEW_PORT_START=8080
|
|
PREVIEW_PORT_END=8999
|
|
CADDYFILE_PATH=/etc/caddy/Caddyfile
|
|
|
|
SANDBOX_PROVIDER=mock
|
|
DAYTONA_API_KEY=
|
|
E2B_API_KEY=
|
|
|
|
PAYMENT_PROVIDER=mock
|
|
STRIPE_SECRET_KEY=
|
|
STRIPE_WEBHOOK_SECRET=
|
|
```
|
|
|
|
---
|
|
|
|
## 26. کیفیت خروجی مورد انتظار
|
|
|
|
خروجی نهایی نباید فقط چند صفحه UI نمایشی باشد. باید حداقل اینها واقعاً کار کنند:
|
|
|
|
- [ ] auth واقعی با DB.
|
|
- [ ] organization واقعی با tenant isolation.
|
|
- [ ] project واقعی.
|
|
- [ ] employee واقعی.
|
|
- [ ] thread/message/task/run واقعی.
|
|
- [ ] usage ledger واقعی.
|
|
- [ ] audit واقعی.
|
|
- [ ] providerها حداقل با mock کامل.
|
|
- [ ] Git و Domain و Sandbox حداقل با mock کامل و adapter واقعی آماده.
|
|
|
|
---
|
|
|
|
## 27. پیام آخر برای عامل اجراکننده
|
|
|
|
این پروژه را کوچک اما تمیز بساز.
|
|
اول correctness و معماری، بعد زیبایی.
|
|
هیچ چیزی را به تلگرام گره نزن.
|
|
همه چیز را سازمانمحور بساز.
|
|
مدلها و providerها را از کاربر پنهان کن.
|
|
Git و دامنه تست را برای همه پروژهها قابل استفاده کن.
|
|
اجرای کد را فقط از Sandbox Gateway عبور بده.
|
|
هر مصرفی را در usage ledger ثبت کن.
|
|
هر عملیات حساس را audit کن.
|
|
در پایان build/test/lint را اجرا کن و خطاها را رفع کن.
|