Skip to content

feat(auth): seed default admin into autobot_users at startup (idempotent, Postgres-gated) — #10199 stage 1 - #10230

Merged
mrveiss merged 2 commits into
Dev_new_guifrom
issue-10199-seed
Jun 16, 2026
Merged

mrveiss merged 2 commits into
Dev_new_guifrom
issue-10199-seed

Conversation

@mrveiss

@mrveiss mrveiss commented Jun 16, 2026

Copy link
Copy Markdown
Owner

Thinking Path

Phase 3 / #10199 stage 1 of 4 (epic #10193). Eliminating single_user requires a real admin to exist in the canonical autobot_users store. This stage seeds one at startup from the operator-configured password — purely additive; login behavior, single_user, and the #6838 bypass are untouched (stages 2-4).

What Changed

  • user_management/services/seed.py (new): seed_default_admin(session) — resolves admin username/password from config; skips (warns) if no password configured (no shipped default); idempotent (skips if any is_platform_admin user or the username exists — never overwrites an existing admin's password, mirroring install.sh preserving the wizard-set password); else creates via UserService.create_user(is_platform_admin=True, role_ids=[admin]).
  • initialization/lifespan.py: _seed_default_admin() wired into Phase-2 startup, decorated @requires_postgres so single_user/no-DB deploys skip cleanly (non-fatal, like the other seeds).
  • ssot_config.py: AUTOBOT_ADMIN_USERNAME (default admin) + AUTOBOT_ADMIN_PASSWORD (default empty → seeding disabled) on AuthConfig. No hardcoded password.

Verification

  • 7 tests pass: seeds when absent; idempotent (existing admin/username → skip, no overwrite); no-password → skip (no crash); Postgres-unavailable → skip; is_platform_admin=True + admin role; DuplicateUserError race swallowed.
  • black --check clean (26.3.1); bandit -c .bandit 0 issues; py_compile clean.

Out of scope (later stages)

Stage 2: remove #6838 synthetic-admin bypass + unsafe-password login warning. Stage 3: Postgres mandatory in provisioning. Stage 4: dead single_user branch cleanup. Coordinates with #10200 (slm_users migration). Provisioning must set AUTOBOT_ADMIN_PASSWORD (reuse the install/wizard password) for the seed to run.

Model Used

Opus 4.8 (1M) — implemented via subagent, verified (tests/black/bandit independently).

Advances #10199 (stage 1, part of #10193).

…ent, Postgres-gated) (#10199)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 16, 2026 •

Copy link
Copy Markdown
Contributor

✅ SSOT Configuration Compliance: Passing

🎉 No hardcoded values detected that have SSOT config equivalents!

@mrveiss
mrveiss merged commit f9ea2c2 into Dev_new_gui Jun 16, 2026
28 checks passed
@mrveiss
mrveiss deleted the issue-10199-seed branch June 16, 2026 19:04
mrveiss added a commit that referenced this pull request Jun 17, 2026
…reds (#10199) (#10243)

Stage 2a of #10199 (unified userbase). Flips the default deployment mode from
single_user (no-auth/no-Postgres) to single_company (Postgres-backed real auth)
and wires the wizard-set SLM admin password into the backend so the startup
seed (PR #10230) creates a single canonical admin in autobot_users — a single
user then logs in with the same credentials as the SLM.

This is the enabling step before removing the #6838 synthetic-admin bypass
(stage 2b): once the default path is real-auth + a seeded admin, the bypass is
no longer reachable on any default deployment.

- user_management/config.py: unset/invalid AUTOBOT_USER_MODE now defaults to
  single_company (was single_user). single_user remains valid but legacy.
- ansible backend role: backend_user_mode default single_company; new
  backend_admin_username/backend_admin_password sourced from slm_admin_*;
  backend.env.j2 + config.yaml.j2 + group_vars flipped; emits AUTOBOT_ADMIN_*.
- .env.example: documents single_company default + admin seed vars.

Flipping backend_user_mode activates the existing 'Configure PostgreSQL for
user management' provisioning step, so single_company installs create the
autobot_users DB + autobot_app role automatically. single_user code paths and
the 503/@requires_postgres gates are untouched (removed in later stages).

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant