v2 foundation: shared contracts, app profile schema, wiring stubs

- projects: app profile columns + one app per org; project_external_git,
  deploy_targets, org_model_grants tables (migration a0f0e1d2c3b4)
- ports + fakes: RepoWorkspace, DeliveryHooks, DeployTarget, Memory,
  ModelGrants, WorkforceBootstrap; AppProfile + AppProfileRepository
- per-workstream wiring (container_org/engine/delivery), config blocks,
  empty routers, delivery worker, MCP/delivery service shells, web stubs
- admin nav derives from ADMIN_ITEMS; plan docs updated for ext4 worktrees

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
mjalmoudy94
2026-10-13 23:21:17 +03:30
co-authored by Claude Sonnet 5.5
parent 3a68b0fa07
commit 0cd9194b64
58 changed files with 1576 additions and 26 deletions
@@ -0,0 +1,17 @@
"use client";
import { PlaceholderPage } from "@/components/PlaceholderPage";
export default function AdminDomainsPage() {
return (
<PlaceholderPage
title="دامنه‌ها"
description="مسیرهای Caddy و دامنه‌های اپلیکیشن‌ها."
planned={[
"فهرست مسیرها",
"افزودن و حذف دامنه",
"همگام‌سازی Caddy",
]}
/>
);
}
+2 -11
View File
@@ -4,6 +4,7 @@ import Link from "next/link";
import { usePathname } from "next/navigation";
import * as React from "react";
import { EmptyState, LoadingState } from "@agy/ui";
import { ADMIN_ITEMS } from "@/lib/nav";
import { useSession } from "@/lib/session";
/**
@@ -14,17 +15,7 @@ import { useSession } from "@/lib/session";
* never the security boundary.
*/
const SECTIONS = [
{ href: "/admin", label: "نمای کلی" },
{ href: "/admin/users", label: "کاربران و مدیران" },
{ href: "/admin/agy-accounts", label: "اکانت‌های agy" },
{ href: "/admin/models", label: "مدل‌ها" },
{ href: "/admin/routing", label: "مسیریابی" },
{ href: "/admin/rate-cards", label: "تعرفه‌ها" },
{ href: "/admin/usage", label: "مصرف سراسری" },
{ href: "/admin/organizations", label: "سازمان‌ها" },
{ href: "/admin/errors", label: "کنسول خطا" },
] as const;
const SECTIONS = ADMIN_ITEMS;
export default function AdminLayout({ children }: { children: React.ReactNode }) {
const { user, ready } = useSession();
+16
View File
@@ -0,0 +1,16 @@
"use client";
import { PlaceholderPage } from "@/components/PlaceholderPage";
export default function AdminMcpPage() {
return (
<PlaceholderPage
title="MCP"
description="کنترل دسترسی عامل‌های بیرونی به سازمان‌ها."
planned={[
"کلید سراسری",
"توکن‌های هر سازمان",
]}
/>
);
}
@@ -0,0 +1,17 @@
"use client";
import { PlaceholderPage } from "@/components/PlaceholderPage";
export default function AdminModelGrantsPage() {
return (
<PlaceholderPage
title="مدل‌های سازمان‌ها"
description="تخصیص مدل‌ها به هر سازمان و سیاست‌های سازمان."
planned={[
"ماتریس تخصیص مدل",
"سقف اعتبار روزانه",
"مجموعهٔ پیش‌فرض سازمان‌های جدید",
]}
/>
);
}
@@ -0,0 +1,17 @@
"use client";
import { PlaceholderPage } from "@/components/PlaceholderPage";
export default function AdminSandboxPage() {
return (
<PlaceholderPage
title="سندباکس‌ها"
description="کانتینرهای در حال اجرا و محدودیت‌های منابع."
planned={[
"کانتینرهای هر سازمان",
"محدودیت CPU و حافظه",
"توقف و راه‌اندازی مجدد",
]}
/>
);
}
+18
View File
@@ -0,0 +1,18 @@
"use client";
import { PlaceholderPage } from "@/components/PlaceholderPage";
export default function AppPage() {
return (
<PlaceholderPage
title="اپلیکیشن"
description="دمو زنده، استقرار روی production و وضعیت Git اپلیکیشن سازمان."
planned={[
"نمای کلی اپلیکیشن و آدرس دمو",
"اجراهای CI/CD با لاگ زنده",
"نسخه‌ها و بازگشت دمو",
"استقرار روی production با تأیید",
]}
/>
);
}
+18
View File
@@ -0,0 +1,18 @@
"use client";
import { PlaceholderPage } from "@/components/PlaceholderPage";
export default function MemoryPage() {
return (
<PlaceholderPage
title="حافظهٔ سازمان"
description="آنچه سازمان دربارهٔ شیوهٔ مدیریت و کد اپلیکیشن یاد گرفته است."
planned={[
"قوانین و ترجیحات",
"درس‌های آموخته",
"نقشهٔ کد",
"منابع دانش",
]}
/>
);
}
+10
View File
@@ -0,0 +1,10 @@
/**
* Typed client functions for the delivery workstream (docs/plan/PLAN-v2.md §6).
*
* Add functions to this object only; ``lib/api.ts`` is locked. Use ``apiRequest`` for transport.
*/
import { apiRequest } from "./api";
export const deliveryApi = {
// example: list: (orgId: string) => apiRequest<Foo[]>(`/api/organizations/${orgId}/foo`),
} satisfies Record<string, (...args: never[]) => ReturnType<typeof apiRequest>>;
+10
View File
@@ -0,0 +1,10 @@
/**
* Typed client functions for the AI-workforce workstream (docs/plan/PLAN-v2.md §6).
*
* Add functions to this object only; ``lib/api.ts`` is locked. Use ``apiRequest`` for transport.
*/
import { apiRequest } from "./api";
export const engineApi = {
// example: list: (orgId: string) => apiRequest<Foo[]>(`/api/organizations/${orgId}/foo`),
} satisfies Record<string, (...args: never[]) => ReturnType<typeof apiRequest>>;
+10
View File
@@ -0,0 +1,10 @@
/**
* Typed client functions for the org-platform workstream (docs/plan/PLAN-v2.md §6).
*
* Add functions to this object only; ``lib/api.ts`` is locked. Use ``apiRequest`` for transport.
*/
import { apiRequest } from "./api";
export const orgApi = {
// example: list: (orgId: string) => apiRequest<Foo[]>(`/api/organizations/${orgId}/foo`),
} satisfies Record<string, (...args: never[]) => ReturnType<typeof apiRequest>>;
+6 -2
View File
@@ -16,10 +16,10 @@ export const NAV_ITEMS: NavItem[] = [
{ href: "/dashboard", label: "داشبورد", hint: "نمای کلی سازمان" },
{ href: "/manager", label: "مدیر AI", hint: "گفتگو با مدیر" },
{ href: "/workforce", label: "نیروی کار AI", hint: "کارمندها" },
{ href: "/projects", label: "پروژه‌ها", hint: "Git و محیط اجرا" },
{ href: "/app", label: "اپلیکیشن", hint: "دمو، استقرار، Git" },
{ href: "/tasks", label: "وظایف", hint: "وضعیت کارها" },
{ href: "/traces", label: "ردیابی", hint: "اجراها و رویدادها" },
{ href: "/knowledge", label: "دانش سازمانی", hint: "منابع و اسناد" },
{ href: "/memory", label: "حافظهٔ سازمان", hint: "قوانین، درس‌ها و دانش" },
{ href: "/billing", label: "مصرف و پرداخت", hint: "اعتبار و فاکتور" },
{ href: "/settings", label: "تنظیمات", hint: "سازمان و اعضا" },
];
@@ -39,5 +39,9 @@ export const ADMIN_ITEMS: NavItem[] = [
{ href: "/admin/rate-cards", label: "تعرفه‌ها", hint: "قیمت واحدها" },
{ href: "/admin/usage", label: "مصرف سراسری", hint: "گزارش مصرف مستأجرها" },
{ href: "/admin/organizations", label: "سازمان‌ها", hint: "مستأجرها" },
{ href: "/admin/model-grants", label: "مدل‌های سازمان‌ها", hint: "تخصیص مدل به هر سازمان" },
{ href: "/admin/domains", label: "دامنه‌ها", hint: "مسیریابی Caddy" },
{ href: "/admin/sandbox", label: "سندباکس‌ها", hint: "کانتینرها و محدودیت‌ها" },
{ href: "/admin/mcp", label: "MCP", hint: "دسترسی عامل‌های بیرونی" },
{ href: "/admin/errors", label: "کنسول خطا", hint: "ردیابی خطاها" },
];
+2 -2
View File
@@ -45,10 +45,10 @@ describe("command palette", () => {
openWithShortcut();
fireEvent.change(screen.getByLabelText("جست‌وجوی بخش‌ها"), {
target: { value: "پروژه" },
target: { value: "اپلیکیشن" },
});
expect(screen.getByRole("button", { name: /پروژه/ })).toBeInTheDocument();
expect(screen.getByRole("button", { name: /اپلیکیشن/ })).toBeInTheDocument();
expect(screen.queryByRole("button", { name: /داشبورد/ })).not.toBeInTheDocument();
});