From fb66614e385dbbd1e7fd6947a2baf7356e9ac55d Mon Sep 17 00:00:00 2001 From: ChickenPige0n <2336983354@qq.com> Date: Wed, 15 Jul 2026 17:39:22 +0800 Subject: [PATCH] fix(admin-web): break /admin/login returnTo redirect loop in dev vite dev only proxied /api and /auth, so /admin/login hit the SPA root layout, re-ran loadSession, got 401, and redirected back to /admin/login with an ever-nesting returnTo. Proxy /admin/login to the backend (which owns it before the SPA fallback) and guard redirectToLogin against re-entering /admin/login. Replace the only emoji-as-icon (the back-arrow on project detail) with the Icon component (new arrow-left glyph). Add scripts/dev-bootstrap.ts for seeding a local Silo (stub probes) so npm run dev can start on a fresh dev DB. --- hub/admin-web/src/lib/components/Icon.svelte | 19 +++++-- hub/admin-web/src/lib/session.ts | 1 + .../[slug]/projects/[projectId]/+page.svelte | 4 +- hub/admin-web/vite.config.ts | 4 ++ hub/scripts/dev-bootstrap.ts | 52 +++++++++++++++++++ 5 files changed, 74 insertions(+), 6 deletions(-) create mode 100644 hub/scripts/dev-bootstrap.ts diff --git a/hub/admin-web/src/lib/components/Icon.svelte b/hub/admin-web/src/lib/components/Icon.svelte index f51370c..7f6ca06 100644 --- a/hub/admin-web/src/lib/components/Icon.svelte +++ b/hub/admin-web/src/lib/components/Icon.svelte @@ -11,11 +11,12 @@ | 'projects' | 'provider' | 'feishu' - | 'menu' - | 'logout' - | 'org' - | 'chevron' - | 'folder' + | 'menu' + | 'logout' + | 'org' + | 'chevron' + | 'arrow-left' + | 'folder' | 'file' | 'check'; class?: string; @@ -100,6 +101,14 @@ +{:else if name === 'arrow-left'} + + + {:else if name === 'folder'} - ← 返回项目列表 + + 返回项目列表 diff --git a/hub/admin-web/vite.config.ts b/hub/admin-web/vite.config.ts index 6134e79..90d4bb4 100644 --- a/hub/admin-web/vite.config.ts +++ b/hub/admin-web/vite.config.ts @@ -8,6 +8,10 @@ export default defineConfig({ proxy: { '/api': 'http://127.0.0.1:8788', '/auth': 'http://127.0.0.1:8788', + // Backend owns /admin/login (registered before the SPA fallback in + // src/admin/static.ts). Proxy it in dev so the SPA doesn't re-render + // its layout on that path and 401-redirect into a returnTo loop. + '/admin/login': 'http://127.0.0.1:8788', }, }, }); diff --git a/hub/scripts/dev-bootstrap.ts b/hub/scripts/dev-bootstrap.ts new file mode 100644 index 0000000..58a21d9 --- /dev/null +++ b/hub/scripts/dev-bootstrap.ts @@ -0,0 +1,52 @@ +import { config } from "dotenv"; +config(); + +import { PrismaClient } from "@prisma/client"; +import { bootstrapAlphaSilo } from "../src/deployment/bootstrap-silo.js"; +import { loadLocalSecretKeyring, LocalSecretEnvelope } from "../src/security/secretEnvelope.js"; + +async function main(): Promise { + const keyringFile = process.env["HUB_SECRET_KEYRING_FILE"]; + if (!keyringFile) throw new Error("HUB_SECRET_KEYRING_FILE is required"); + const secrets = new LocalSecretEnvelope(await loadLocalSecretKeyring()); + const prisma = new PrismaClient(); + try { + const result = await bootstrapAlphaSilo( + prisma, + secrets, + { + organization: { + id: "org_default", + slug: "default", + name: "Default Organization", + }, + owner: { + openId: process.env["FEISHU_BOT_OPEN_ID"] ?? "dev-owner", + displayName: "Dev Owner", + }, + feishu: { + appId: process.env["FEISHU_APP_ID"] ?? "dev-app", + appSecret: process.env["FEISHU_APP_SECRET"] ?? "dev-secret", + botOpenId: process.env["FEISHU_BOT_OPEN_ID"] ?? "dev-bot", + }, + provider: { + providerId: "openrouter", + baseUrl: process.env["ANTHROPIC_BASE_URL"] ?? "https://openrouter.ai/api", + authToken: process.env["ANTHROPIC_AUTH_TOKEN"] ?? "dev-token", + }, + }, + { + feishu: async () => undefined, + provider: async () => undefined, + }, + ); + console.log("bootstrap ok:", JSON.stringify(result, null, 2)); + } finally { + await prisma.$disconnect(); + } +} + +main().catch((error: unknown) => { + console.error("[dev-bootstrap] failed:", error instanceof Error ? error.message : String(error)); + process.exitCode = 1; +});