Skip to content

feat(provision): seed default admin during SLM deployment; eliminate single_user mode + #6838 bypass (#10193) #10199

Closed

Description

@mrveiss

Capture the admin password in the SLM setup wizard/provisioning; seed it as the default admin in autobot_users (Postgres now mandatory). Remove AUTOBOT_USER_MODE=single_user branching and the AUTOBOT_DEV_AUTH_BYPASS synthetic-admin path (#6838). Add a login-time unsafe-password warning (soft complaint). Part of #10193.

Activity

  1. mrveiss commented on Jun 15, 2026

    @mrveiss
    OwnerAuthor

    Scope note — the password-collection mechanism already exists; reuse it

    install.sh already handles the admin password with no shipped default (verified):

    • user-set via --admin-pass= / AUTOBOT_SLM_ADMIN_PASSWORD / the setup wizard (the documented source of truth), else a randomly generated strong fallback (install.sh:565-566);
    • persisted as SLM_ADMIN_PASSWORD, preserved on reinstall, displayed at the end, passed to ansible (slm_admin_password=).

    So this issue is NOT "build password collection" — it's:

    1. Seed the CANONICAL autobot_users admin from that already-collected install/wizard password (instead of seeding slm_users).
    2. Remove single_user mode + the AUTOBOT_DEV_AUTH_BYPASS (security(auth): /api/auth/login accepts ANY password for admin user #6838) synthetic-admin path.
    3. Add the login-time unsafe-password warning (only bites when a user provides a weak password; the random fallback is already strong).

    Reduces scope materially — the "no default password / user sets own" requirement is already met by install.sh; the work is re-pointing it at the canonical store + killing single_user.

  2. mrveiss commented on Jun 16, 2026

    @mrveiss
    OwnerAuthor

    Scope analysis — this is larger/riskier than a typical child; proposed sub-staging

    single_user/AUTOBOT_USER_MODE/DeploymentMode.SINGLE_USER/AUTOBOT_DEV_AUTH_BYPASS is referenced across ~34 backend/shared files (agents, api/auth.py, auth_middleware, auth_rbac, LLC deps/api/scheduler, lifespan, user_management/{config,database,base_service}, ssot_config, settings, onboarding, live_events, security_layer, service_registry, …). Most use it to gate Postgres-optional behavior. Eliminating the mode also makes Postgres mandatory on every install and requires seeding a default admin at provision — a deployment/provisioning change, highest blast radius in the epic.

    Proposed sub-stages (each its own PR) instead of one 34-file sweep:

    1. Seed default admin in autobot_users at SLM deploy (reuse the install/wizard-collected password) — provisioning + a one-time seed. Makes a real admin exist.
    2. Remove the security(auth): /api/auth/login accepts ANY password for admin user #6838 synthetic-admin bypass in api/auth.py so the user app authenticates against the real seeded admin (depends on 1 + Postgres present). Add the login-time unsafe-password warning.
    3. Make Postgres mandatory in provisioning/startup (install.sh/ansible always stand up autobot_users; lifespan no longer degrades to no-DB).
    4. Dead-branch cleanup (overlaps chore(cleanup): remove dead single_user 503-gates after single_user elimination (#10193) #10202): remove the now-unreachable single_user branches across the ~30 remaining files — no behavior change once Postgres is always present.

    Stages 1-3 are the behavioral change; 4 is mechanical cleanup. This also wants coordination with #10200 (migrate slm_users → autobot_users) so the seeded/migrated admins land in one place.

    Recommend: confirm this staging before building (highest-risk change in #10193). Also: the live deploy currently runs single_user + the bypass — these stages change that, so a redeploy/reinstall is needed to realize them.

  3. mrveiss commented on Jun 16, 2026

    @mrveiss
    OwnerAuthor

    Stage 1 DONE — merged via PR #10230 (f9ea2c235)

    Default admin seeded into autobot_users at startup (idempotent, Postgres-gated, no shipped default password; reads AUTOBOT_ADMIN_PASSWORD/AUTOBOT_ADMIN_USERNAME). Purely additive — login/single_user/#6838 untouched. Next: stage 2 (remove #6838 synthetic-admin bypass + unsafe-password login warning).

  4. mrveiss commented on Jun 16, 2026

    @mrveiss
    OwnerAuthor

    Stage 2a OPEN — PR #10243 (enabling step before bypass removal)

    Investigating stage 2 surfaced a hard coupling: single_user mode is "Postgres-off" (postgres_enabled = mode != SINGLE_USER), so deleting the #6838 bypass in isolation would 500 (engine raises). Also, nothing in provisioning ever set AUTOBOT_ADMIN_PASSWORD — the stage-1 seed would always skip, so removing the bypass without this would leave installs with no admin and no login.

    Chosen path (safest): split stage 2 into 2a (enable) + 2b (remove).

    • 2a (PR feat(auth): default to single_company + seed unified admin from SLM creds (#10199) #10243): default mode → single_company (Postgres-backed real auth); wire wizard-set SLM_ADMIN_PASSWORD → backend AUTOBOT_ADMIN_PASSWORD so the seed creates the single canonical admin ("same creds as SLM"). Bypass untouched but now unreachable on the default path.
    • 2b (next): delete the synthetic-admin bypass + add the login-time unsafe-password warning, off clean Dev_new_gui after 2a merges.

    single_user code + 503 gates untouched (stages 3/4).

  5. mrveiss commented on Jun 21, 2026

    @mrveiss
    OwnerAuthor

    Live cutover runbook — 172.16.168.20 (single_user → single_company / full auth)

    Decision (2026-06-21): upgrade the live box to full auth. Code side is done (#10243 merged: default single_company + seed_default_admin from AUTOBOT_ADMIN_PASSWORD, idempotent, Postgres-gated). The live box still has AUTOBOT_USER_MODE=single_user in its backend .env (rsync-excluded, so the deploy didn't change it).

    Prerequisites (verified on box)

    • PostgreSQL active; user DBs present; seed_default_admin wired in lifespan.py Phase 2 (@requires_postgres).
    • Auth flow: single_company /login → real Postgres credential check (UserService.authenticate), no synthetic bypass (api/auth.py:213).

    ⚠️ #1 lockout risk

    If AUTOBOT_ADMIN_PASSWORD is not set before restart, no admin is seeded and /login rejects all creds → locked out. So set it FIRST.

    Safe ordered steps (backend /opt/autobot/autobot-backend/.env)

    1. AUTOBOT_ADMIN_PASSWORD=<strong> (+ optional AUTOBOT_ADMIN_USERNAME=admin) — before restart.
    2. Confirm AUTOBOT_POSTGRES_{HOST,PORT,DB,USER,PASSWORD} set + reachable + migrations applied (autobot_users table exists).
    3. AUTOBOT_USER_MODE=single_company.
    4. Remove/false AUTOBOT_DEV_AUTH_BYPASS.
    5. systemctl restart autobot-backend → Phase 2 seeds admin (idempotent).
    6. Log in: admin / AUTOBOT_ADMIN_PASSWORD. Verify LLC 503s clear (company-mode features enable).

    Rollback

    AUTOBOT_USER_MODE=single_user + AUTOBOT_DEV_AUTH_BYPASS=true, restart.

    Follow-ups

  6. mrveiss commented on Jul 6, 2026

    @mrveiss
    OwnerAuthor

    Final AC (login-time weak-password soft-warning) merged to Dev_new_gui via #10979 (daa33d0). All 5 ACs now complete: seed-admin (#10230/#10243), single_company default, single_user removal (#10861/#10713), AUTOBOT_DEV_AUTH_BYPASS removal, and now the non-blocking login weak-password warning (checks seeded-default/length/common-list; plaintext never logged; 14/14 tests). All required CI checks passed. Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions