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:
co-authored by
Claude Sonnet 5.5
parent
3a68b0fa07
commit
0cd9194b64
@@ -0,0 +1,17 @@
|
||||
"use client";
|
||||
|
||||
import { PlaceholderPage } from "@/components/PlaceholderPage";
|
||||
|
||||
export default function AdminDomainsPage() {
|
||||
return (
|
||||
<PlaceholderPage
|
||||
title="دامنهها"
|
||||
description="مسیرهای Caddy و دامنههای اپلیکیشنها."
|
||||
planned={[
|
||||
"فهرست مسیرها",
|
||||
"افزودن و حذف دامنه",
|
||||
"همگامسازی Caddy",
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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 و حافظه",
|
||||
"توقف و راهاندازی مجدد",
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -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 با تأیید",
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
"use client";
|
||||
|
||||
import { PlaceholderPage } from "@/components/PlaceholderPage";
|
||||
|
||||
export default function MemoryPage() {
|
||||
return (
|
||||
<PlaceholderPage
|
||||
title="حافظهٔ سازمان"
|
||||
description="آنچه سازمان دربارهٔ شیوهٔ مدیریت و کد اپلیکیشن یاد گرفته است."
|
||||
planned={[
|
||||
"قوانین و ترجیحات",
|
||||
"درسهای آموخته",
|
||||
"نقشهٔ کد",
|
||||
"منابع دانش",
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -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>>;
|
||||
@@ -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>>;
|
||||
@@ -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>>;
|
||||
@@ -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: "ردیابی خطاها" },
|
||||
];
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user