diff --git a/docker/logto-bootstrap.sh b/docker/logto-bootstrap.sh
index 21f6aca..f7e10d5 100644
--- a/docker/logto-bootstrap.sh
+++ b/docker/logto-bootstrap.sh
@@ -565,111 +565,16 @@ api_patch "/api/sign-in-exp" "{
log "Sign-in branding configured."
# ============================================================
-# PHASE 8b: Configure SMTP email connector
+# PHASE 8c: Configure sign-in experience (sign-in only)
# ============================================================
-# Required for email verification during registration and password reset.
-# Skipped if SMTP_HOST is not set (registration will not work without email delivery).
+# Registration is disabled by default. The vendor admin enables it
+# via the Email Connector UI after configuring SMTP delivery.
-if [ -n "${SMTP_HOST:-}" ] && [ -n "${SMTP_USER:-}" ]; then
- log "Configuring SMTP email connector..."
-
- # Discover available email connector factories
- FACTORIES=$(api_get "/api/connector-factories")
- # Prefer a factory with "smtp" in the ID
- SMTP_FACTORY_ID=$(echo "$FACTORIES" | jq -r '[.[] | select(.type == "Email" and (.id | test("smtp"; "i")))] | .[0].id // empty')
- if [ -z "$SMTP_FACTORY_ID" ]; then
- # Fall back to any non-demo Email factory
- SMTP_FACTORY_ID=$(echo "$FACTORIES" | jq -r '[.[] | select(.type == "Email" and .isDemo != true)] | .[0].id // empty')
- fi
-
- if [ -n "$SMTP_FACTORY_ID" ]; then
- # Build SMTP config JSON
- SMTP_CONFIG=$(jq -n \
- --arg host "$SMTP_HOST" \
- --arg port "${SMTP_PORT:-587}" \
- --arg user "$SMTP_USER" \
- --arg pass "${SMTP_PASS:-}" \
- --arg from "${SMTP_FROM_EMAIL:-noreply@cameleer.io}" \
- '{
- host: $host,
- port: ($port | tonumber),
- auth: { user: $user, pass: $pass },
- fromEmail: $from,
- templates: [
- {
- usageType: "Register",
- contentType: "text/html",
- subject: "Verify your email for Cameleer",
- content: "
Cameleer
Enter this code to verify your email and create your account:
{{code}}
This code expires in 10 minutes. If you did not request this, you can safely ignore this email.
"
- },
- {
- usageType: "SignIn",
- contentType: "text/html",
- subject: "Your Cameleer sign-in code",
- content: "Cameleer
Your sign-in verification code:
{{code}}
This code expires in 10 minutes.
"
- },
- {
- usageType: "ForgotPassword",
- contentType: "text/html",
- subject: "Reset your Cameleer password",
- content: "Cameleer
Enter this code to reset your password:
{{code}}
This code expires in 10 minutes. If you did not request a password reset, you can safely ignore this email.
"
- },
- {
- usageType: "Generic",
- contentType: "text/html",
- subject: "Your Cameleer verification code",
- content: "Cameleer
Your verification code:
{{code}}
This code expires in 10 minutes.
"
- }
- ]
- }')
-
- # Check if an email connector already exists
- EXISTING_CONNECTORS=$(api_get "/api/connectors")
- EMAIL_CONNECTOR_ID=$(echo "$EXISTING_CONNECTORS" | jq -r '[.[] | select(.type == "Email")] | .[0].id // empty')
-
- if [ -n "$EMAIL_CONNECTOR_ID" ]; then
- api_patch "/api/connectors/$EMAIL_CONNECTOR_ID" "{\"config\": $SMTP_CONFIG}" >/dev/null 2>&1
- log "Updated existing email connector: $EMAIL_CONNECTOR_ID"
- else
- CONNECTOR_RESPONSE=$(api_post "/api/connectors" "{\"connectorId\": \"$SMTP_FACTORY_ID\", \"config\": $SMTP_CONFIG}")
- CREATED_ID=$(echo "$CONNECTOR_RESPONSE" | jq -r '.id // empty')
- if [ -n "$CREATED_ID" ]; then
- log "Created SMTP email connector: $CREATED_ID (factory: $SMTP_FACTORY_ID)"
- else
- log "WARNING: Failed to create SMTP connector. Response: $(echo "$CONNECTOR_RESPONSE" | head -c 300)"
- fi
- fi
- else
- log "WARNING: No email connector factory found — email delivery will not work."
- log "Available factories: $(echo "$FACTORIES" | jq -c '[.[] | select(.type == "Email") | .id]')"
- fi
-else
- log "SMTP not configured (SMTP_HOST/SMTP_USER not set) — email delivery disabled."
- log "Set SMTP_HOST, SMTP_USER, SMTP_PASS, SMTP_FROM_EMAIL env vars to enable."
-fi
-
-# ============================================================
-# PHASE 8c: Enable registration (email + password)
-# ============================================================
-# Configures sign-in experience to allow self-service registration with email verification.
-# This runs AFTER the SMTP connector so email delivery is ready before registration opens.
-
-log "Configuring sign-in experience for registration..."
+log "Configuring sign-in experience (sign-in only, no registration)..."
api_patch "/api/sign-in-exp" '{
- "signInMode": "SignInAndRegister",
- "signUp": {
- "identifiers": ["email"],
- "password": true,
- "verify": true
- },
+ "signInMode": "SignIn",
"signIn": {
"methods": [
- {
- "identifier": "email",
- "password": true,
- "verificationCode": false,
- "isPasswordPrimary": true
- },
{
"identifier": "username",
"password": true,
@@ -679,7 +584,7 @@ api_patch "/api/sign-in-exp" '{
]
}
}' >/dev/null 2>&1
-log "Sign-in experience configured: SignInAndRegister (email + password)."
+log "Sign-in experience configured: SignIn only (registration disabled until email is configured)."
# ============================================================
# PHASE 9: Cleanup seeded apps