diff --git a/artifacts/sandbox-ai/src/App.tsx b/artifacts/sandbox-ai/src/App.tsx index 3feaa26..dd2dc8c 100644 --- a/artifacts/sandbox-ai/src/App.tsx +++ b/artifacts/sandbox-ai/src/App.tsx @@ -28,6 +28,34 @@ const queryClient = new QueryClient(); const clerkPubKey = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY; const clerkProxyUrl = import.meta.env.VITE_CLERK_PROXY_URL; const basePath = import.meta.env.BASE_URL.replace(/\/$/, ""); +const requestedAuthMode = (import.meta.env.VITE_AUTH_MODE ?? "clerk").toLowerCase(); +const authMode = requestedAuthMode === "public" ? "public" : "clerk"; +const isClerkConfigured = Boolean(clerkPubKey); +const isAuthEnabled = authMode === "clerk" && isClerkConfigured; + +const envChecklist = [ + { + key: "VITE_AUTH_MODE", + value: import.meta.env.VITE_AUTH_MODE, + required: false, + status: "info" as const, + hint: "Optional. Use 'clerk' (default) or 'public'.", + }, + { + key: "VITE_CLERK_PUBLISHABLE_KEY", + value: clerkPubKey, + required: authMode === "clerk", + status: isClerkConfigured ? ("ok" as const) : ("missing" as const), + hint: "Required when VITE_AUTH_MODE=clerk.", + }, + { + key: "VITE_CLERK_PROXY_URL", + value: clerkProxyUrl, + required: false, + status: "info" as const, + hint: "Optional proxy URL for Clerk.", + }, +]; function stripBase(path: string): string { return basePath && path.startsWith(basePath) @@ -198,6 +226,33 @@ function ClerkAuthTokenSetter() { return null; } + +function HealthConfigPage() { + return ( +
+

Health Config

+

+ Runtime auth mode: {authMode}. Auth enabled: {String(isAuthEnabled)}. +

+
+ {envChecklist.map((item) => ( +
+
+ {item.key} + + {item.status === "ok" ? "✅ configured" : item.status === "missing" ? "❌ missing" : "ℹ️ optional"} + +
+
required: {String(item.required)}
+
value: {item.value ? "set" : "empty"}
+
{item.hint}
+
+ ))} +
+
+ ); +} + function Router() { return ( @@ -207,6 +262,7 @@ function Router() { + @@ -258,14 +314,54 @@ function ClerkProviderWithRoutes() { ); } + +function PublicOnlyRouter() { + return ( + + + + + + + + + + + + + + + + + + + + + + ); +} + +function PublicAppWithoutAuth() { + return ( + + +
+ Auth is running in public mode. Open /health-config to inspect environment readiness. +
+ + +
+
+ ); +} function App() { const [showSplash, setShowSplash] = useState(true); - if (!clerkPubKey) { + if (!isAuthEnabled) { return ( -
- Missing VITE_CLERK_PUBLISHABLE_KEY — please check environment variables. -
+ + + ); } diff --git a/docs_self_healing_process.md b/docs_self_healing_process.md new file mode 100644 index 0000000..0403d9f --- /dev/null +++ b/docs_self_healing_process.md @@ -0,0 +1,27 @@ +# Self-healing reminder workflow (OpenClaw/Eios style) + +## Goal +Automatically remind maintainers when deployment-critical configuration or code artifacts are missing. + +## 1) Detect +- On every deploy, open `/health-config` and validate required env keys. +- On CI, run `pnpm --filter @workspace/sandbox-ai run build` and fail on errors. + +## 2) Classify +- **Config missing** (e.g. `VITE_CLERK_PUBLISHABLE_KEY` when `VITE_AUTH_MODE=clerk`). +- **Artifact missing** (route/page/module referenced but not found). +- **Type/build breakage** (TypeScript/build errors). + +## 3) Notify owner +- Config missing -> notify DevOps/release owner. +- Artifact missing -> notify feature owner/repo maintainer. +- Build/type breakage -> notify author of latest PR and reviewer. + +## 4) Auto-remediation checklist +- If auth env missing in non-production: set `VITE_AUTH_MODE=public` as temporary fallback. +- If auth env missing in production: block release and require secret injection. +- If artifact missing: create placeholder file + TODO with owner and deadline. + +## 5) Prevent regressions +- Add a PR checklist item: “Did you verify `/health-config` and auth mode behavior?” +- Keep a short runbook for required variables per environment.