feat(auth): capture Steward URL during first-run admin setup (OOBE)
CI / lint (push) Successful in 3s
CI / unit (push) Successful in 7s
CI / integration (push) Successful in 2m17s
CI / publish (push) Successful in 56s

A fresh install had no prompt for general.public_base_url, so first-run agent
installs/share links silently used the request Host header. Add a "Steward URL"
field to the first-run /setup page (create-admin), pre-filled with the current
address, with help text. setup_post saves general.public_base_url and applies
it to app.config immediately (no restart). Editable later in Settings → General.

Scribe #896.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-17 10:15:28 -04:00
parent 7e6e63521b
commit f80f6c87e8
2 changed files with 22 additions and 1 deletions
+11 -1
View File
@@ -184,7 +184,10 @@ async def setup():
from quart import current_app
if await get_user_count(current_app) > 0:
return redirect(url_for("auth.login"))
return await render_template("auth/setup.html")
# Pre-fill the public URL with however the operator reached this page — the
# common case is correct, and it's what agent installs / share links use.
return await render_template(
"auth/setup.html", default_url=request.host_url.rstrip("/"))
@auth_bp.post("/setup")
@@ -201,9 +204,16 @@ async def setup_post():
return await render_template("auth/setup.html", error="All fields required"), 400
pw_hash = bcrypt.hashpw(password, bcrypt.gensalt()).decode()
user = User(username=username, email=email, password_hash=pw_hash, role=UserRole.admin)
steward_url = (form.get("public_base_url", "") or "").strip().rstrip("/")
async with current_app.db_sessionmaker() as db:
async with db.begin():
db.add(user)
if steward_url:
from steward.core.settings import set_setting
await set_setting(db, "general.public_base_url", steward_url)
if steward_url:
# Apply immediately so agent installs / share links use it without a restart.
current_app.config["PUBLIC_BASE_URL"] = steward_url
login_user(user)
await log_audit(current_app, user.id, user.username, "auth.setup",
detail={"username": username})
+11
View File
@@ -18,6 +18,17 @@
<label>Password</label>
<input type="password" name="password" required>
</div>
<div class="form-group">
<label>Steward URL
<span style="color:var(--text-muted);font-weight:normal;font-size:0.78rem;">(how hosts & browsers reach this server)</span>
</label>
<input type="text" name="public_base_url" value="{{ default_url or '' }}"
placeholder="https://steward.example.com">
<span style="color:var(--text-muted);font-size:0.78rem;">
Used for agent installs, share links, and alert links. Pre-filled from your current
address — change it if hosts reach Steward by a different name. Editable later in Settings → General.
</span>
</div>
<button type="submit" class="btn">Create Admin Account</button>
</form>
</div>