Make Cobble a local install: setup flow, bots-first admin, settings

Local, password-only auth:
- No public pages; everything outside /admin and /auth redirects in
- First run (no users) sends every page to /auth/signup, which creates
  the super admin (user #1) once and then locks
- Login is email/username + password; removed the emailed-code flow,
  /auth/sso and email password reset
- Google login kept for existing accounts only, never creates them
- seed-super-admin now requires SEED_SUPER_ADMIN_PASSWORD

Bots-first admin:
- /admin and closed sections (people, logs, backups) redirect to
  /admin/bots; only bots and settings are live (AdminSections)
- Removed the old admin layout; every /admin page uses the bots rail
- Coordinator bot created at signup/seed and by /admin/bots
  (ensureCoordinatorBot), which redirects to its chat
- bots.system_prompt (markdown) with a default coordinator prompt
- seed-bots reuses the existing coordinator

Settings:
- Sub pages general (default), profile, change-password, listed in the
  rail with a back link; unknown settings paths redirect to general
- Redesigned settings UI: pane header, grouped rows, sticky save bar
- General: System/Light/Dark theme, saved per device

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-18 17:49:25 +01:00
co-authored by Claude Opus 5.5
parent 3286b80029
commit 694c83346f
159 changed files with 1891 additions and 2964 deletions
-44
View File
@@ -70,7 +70,6 @@ export type PagePropsType = {
has_password?: boolean;
backups?: DbBackup[] | null;
envs?: {
AUTH_LOGIN_METHOD?: LoginMethod;
GOOGLE_CLIENT_ID?: string;
R2_PUBLIC_DOMAIN?: string;
PAYSTACK_PUBLIC_KEY?: string;
@@ -264,21 +263,6 @@ export type LoginFormObject = {
password?: string;
};
/**
* Site-wide login method, set by `AUTH_LOGIN_METHOD`.
*/
export type LoginMethod = "password" | "code";
/**
* What an emailed code is for: completing a login, or a password reset.
*/
export type SSOMethod = LoginMethod | "reset";
export type SSOPendingLogin = {
identifier: string;
method: SSOMethod;
};
export type SignupFormObject = {
first_name?: string;
last_name?: string;
@@ -294,16 +278,6 @@ export type PasswordFormObject = {
confirm_password?: string;
};
export type PasswordResetFormObject = {
code?: string;
new_password?: string;
confirm_password?: string;
};
export type SSOFormObject = {
code?: string;
};
export type ContactFormObject = {
name?: string;
email?: string;
@@ -332,8 +306,6 @@ export type ApiReqParams<
};
new_password?: string;
google_token?: string;
google_signup?: boolean;
sso_code?: string;
contact?: {
name?: string;
email?: string;
@@ -404,22 +376,6 @@ export type GoogleWindow = globalThis.Window & {
};
};
export type SSOAuth = {
user_id: number;
sso_code: string | number;
email?: string | null;
/**
* What issued this code. Login only accepts codes whose method matches
* the site-wide login method; reset codes only work for resets.
*/
method?: SSOMethod;
/**
* When the first step passed. Resends are refused after
* `SSOPendingLoginMaxMinutes`.
*/
first_step_at?: number;
};
export type UserAuthReturn = {
success: boolean;
msg?: string;