Split back-office into standalone memind_adm service
Carve the platform super-admin API (/admin-api) and plaza operations console API (/api/ops/v1) out of the public server.mjs into their own process, so the user-facing fleet can no longer be taken down or scaled by back-office traffic. Architecture (split-ready, single process for now): - admin-routes.mjs: createAdminApi / createOpsApi route factories (DI, single source of truth; the route logic moved verbatim out of server.mjs). - admin-bootstrap.mjs: lean service container (user-auth, LLM providers, minimal plaza graph) with no user-facing daemons. - admin-server.mjs: standalone entry with a console registry. ADMIN_CONSOLES selects which consoles a process mounts (default both), so splitting into two processes later is a config change, not a code change. - admin-guard.mjs (+ tests): per-console host / IP-CIDR allowlists, letting the super-admin surface be locked down harder than moderation. server.mjs no longer serves or mounts either surface. user-auth.mjs gains pagination on listUsers/listUsageRecords/listBillingLedger to back the admin dashboards. dev.mjs launches memind_adm; the ops SPA proxies /api to it while /auth stays on the portal. Sessions are read from the shared cookie (H5_COOKIE_DOMAIN=.tkmind.cn); login stays on the main domain. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+14
-1
@@ -13,7 +13,9 @@ const portalPort = Number(process.env.H5_PORT ?? 8081);
|
||||
const vitePort = Number(process.env.VITE_PORT ?? 5173);
|
||||
const plazaPort = Number(process.env.PLAZA_PORT ?? 3001);
|
||||
const opsPort = Number(process.env.OPS_PORT ?? 3002);
|
||||
const adminPort = Number(process.env.ADMIN_PORT ?? 8082);
|
||||
const portalUrl = `http://127.0.0.1:${portalPort}`;
|
||||
const adminUrl = `http://127.0.0.1:${adminPort}`;
|
||||
const plazaHost = process.env.PLAZA_LOCAL_HOST ?? 'plaza.tkmind.cn';
|
||||
const plazaPublicPort = Number(process.env.PLAZA_PUBLIC_PORT ?? 443);
|
||||
const plazaPublicScheme = String(process.env.PLAZA_PUBLIC_BASE ?? 'https://plaza.tkmind.cn').startsWith('http://')
|
||||
@@ -69,6 +71,7 @@ function spawnChild(command, args, label, cwd = root, extraEnv = {}) {
|
||||
}
|
||||
|
||||
let server;
|
||||
let admin;
|
||||
let plaza;
|
||||
let plazaProxy;
|
||||
let ops;
|
||||
@@ -79,6 +82,7 @@ function shutdown(code = 0) {
|
||||
if (stopping) return;
|
||||
stopping = true;
|
||||
server?.kill('SIGTERM');
|
||||
admin?.kill('SIGTERM');
|
||||
plaza?.kill('SIGTERM');
|
||||
plazaProxy?.kill('SIGTERM');
|
||||
ops?.kill('SIGTERM');
|
||||
@@ -121,7 +125,9 @@ const viteEnv = {
|
||||
};
|
||||
|
||||
const opsEnv = {
|
||||
// /auth (login/session) stays on the public portal; /api (ops console) hits memind_adm.
|
||||
OPS_API_PROXY: portalUrl,
|
||||
OPS_ADMIN_PROXY: adminUrl,
|
||||
VITE_PLAZA_BASE: plazaPublicBase,
|
||||
VITE_MINDSPACE_BASE: mindSpacePublicBase,
|
||||
};
|
||||
@@ -210,8 +216,9 @@ function plazaHostConfigured(host) {
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`==> 清理端口 ${portalPort} / ${vitePort} / ${plazaPort} / ${opsPort}...`);
|
||||
console.log(`==> 清理端口 ${portalPort} / ${adminPort} / ${vitePort} / ${plazaPort} / ${opsPort}...`);
|
||||
freePort(portalPort);
|
||||
freePort(adminPort);
|
||||
freePort(vitePort);
|
||||
freePort(plazaPort);
|
||||
freePort(opsPort);
|
||||
@@ -233,6 +240,11 @@ try {
|
||||
await waitFor(portalUrl, async (url) => (await fetch(`${url}/auth/status`)).ok, 'Portal');
|
||||
console.log(`==> Portal 就绪: ${portalUrl}`);
|
||||
|
||||
console.log('==> 启动 memind_adm (admin-server.mjs)...');
|
||||
admin = spawnChild('node', ['admin-server.mjs'], 'admin');
|
||||
await waitFor(adminUrl, async (url) => (await fetch(`${url}/healthz`)).ok, 'Admin');
|
||||
console.log(`==> memind_adm 就绪: ${adminUrl}`);
|
||||
|
||||
console.log(`==> 启动 Plaza Next.js @ ${plazaPublicBase} (bind ${plazaHost})`);
|
||||
plaza = spawnChild(
|
||||
'npm',
|
||||
@@ -288,6 +300,7 @@ try {
|
||||
console.log(` (setup) sudo pnpm setup:plaza-local && sudo pnpm dev:plaza-proxy`);
|
||||
console.log(` Ops 审核后台 http://localhost:${opsPort}/ops/`);
|
||||
console.log(` API / Portal ${portalUrl}`);
|
||||
console.log(` memind_adm ${adminUrl} (gadm.tkmind.cn)`);
|
||||
console.log('');
|
||||
console.log('首次使用 Ops:先登录 MindSpace,再执行 node scripts/grant-ops-role.mjs admin ops_admin');
|
||||
} catch (err) {
|
||||
|
||||
Reference in New Issue
Block a user