feat: enforce email as primary user identity in SaaS mode
All checks were successful
CI / build (push) Successful in 2m23s
CI / docker (push) Successful in 53s

All users in SaaS mode must have an email address. The bootstrap creates
the admin user with primaryEmail set to SAAS_ADMIN_EMAIL (defaults to
<SAAS_ADMIN_USER>@<PUBLIC_HOST>). This prevents the admin from being
locked out when self-service registration (which requires email) is
enabled via the Email Connector UI.

Documentation updated across all CLAUDE.md files, .env.example,
user-manual.md, and installer submodule (README, .env.example, compose).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-25 20:23:30 +02:00
parent f0aa2b7d3a
commit 3ab6408258
7 changed files with 22 additions and 9 deletions

View File

@@ -25,8 +25,11 @@ POSTGRES_DB=cameleer_saas
CLICKHOUSE_PASSWORD=change_me_in_production CLICKHOUSE_PASSWORD=change_me_in_production
# Admin user (created by bootstrap) # Admin user (created by bootstrap)
# Email is the primary user identity in SaaS mode. The admin email defaults
# to <SAAS_ADMIN_USER>@<PUBLIC_HOST> if not set explicitly.
SAAS_ADMIN_USER=admin SAAS_ADMIN_USER=admin
SAAS_ADMIN_PASS=change_me_in_production SAAS_ADMIN_PASS=change_me_in_production
# SAAS_ADMIN_EMAIL=admin@example.com
# SMTP / email connector configuration is managed at runtime via the vendor # SMTP / email connector configuration is managed at runtime via the vendor
# admin UI (Email Connector page at /vendor/email). No SMTP env vars needed. # admin UI (Email Connector page at /vendor/email). No SMTP env vars needed.

View File

@@ -6,6 +6,8 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
Cameleer SaaS — **vendor management plane** for the Cameleer observability stack. Three personas: **vendor** (platform:admin) manages the platform and provisions tenants; **tenant admin** (tenant:manage) manages their observability instance; **new user** (authenticated, no scopes) goes through self-service onboarding. Tenants can be created by the vendor OR via self-service sign-up (email registration + onboarding wizard). Each tenant gets per-tenant cameleer-server + UI instances via Docker API. Cameleer SaaS — **vendor management plane** for the Cameleer observability stack. Three personas: **vendor** (platform:admin) manages the platform and provisions tenants; **tenant admin** (tenant:manage) manages their observability instance; **new user** (authenticated, no scopes) goes through self-service onboarding. Tenants can be created by the vendor OR via self-service sign-up (email registration + onboarding wizard). Each tenant gets per-tenant cameleer-server + UI instances via Docker API.
**Email is the primary user identity** in SaaS mode. All users — including the admin — must have an email address. The admin email defaults to `<SAAS_ADMIN_USER>@<PUBLIC_HOST>` if not set explicitly via `SAAS_ADMIN_EMAIL`. Self-service registration (email + password + verification code) is disabled by default and enabled via the vendor UI after configuring an email connector.
## Ecosystem ## Ecosystem
This repo is the SaaS layer on top of two proven components: This repo is the SaaS layer on top of two proven components:

View File

@@ -80,7 +80,7 @@ Idempotent script run inside the Logto container entrypoint. **Clean slate** —
3. Create Logto apps (SPA, Traditional Web App with `skipConsent`, M2M with Management API role + server API role) 3. Create Logto apps (SPA, Traditional Web App with `skipConsent`, M2M with Management API role + server API role)
3b. Create API resource scopes (1 platform + 9 tenant + 3 server scopes) 3b. Create API resource scopes (1 platform + 9 tenant + 3 server scopes)
4. Create org roles (owner, operator, viewer with API resource scope assignments) + M2M server role (`cameleer-m2m-server` with `server:admin` scope) 4. Create org roles (owner, operator, viewer with API resource scope assignments) + M2M server role (`cameleer-m2m-server` with `server:admin` scope)
5. Create admin user (SaaS admin with Logto console access) 5. Create admin user (SaaS admin with Logto console access). Email is the primary user identity in SaaS mode — admin email defaults to `<SAAS_ADMIN_USER>@<PUBLIC_HOST>` if `SAAS_ADMIN_EMAIL` is not set.
7b. Configure Logto Custom JWT for access tokens (maps org roles -> `roles` claim: owner->server:admin, operator->server:operator, viewer->server:viewer; saas-vendor global role -> server:admin) 7b. Configure Logto Custom JWT for access tokens (maps org roles -> `roles` claim: owner->server:admin, operator->server:operator, viewer->server:viewer; saas-vendor global role -> server:admin)
8. Configure Logto sign-in branding (Cameleer colors `#C6820E`/`#D4941E`, logo from `/platform/logo.svg`) 8. Configure Logto sign-in branding (Cameleer colors `#C6820E`/`#D4941E`, logo from `/platform/logo.svg`)
8c. Configure sign-in experience (sign-in only) — sets `signInMode: "SignIn"` with username+password method. Registration is disabled by default; the vendor admin enables it via the Email Connector UI after configuring SMTP delivery. 8c. Configure sign-in experience (sign-in only) — sets `signInMode: "SignIn"` with username+password method. Registration is disabled by default; the vendor admin enables it via the Email Connector UI after configuring SMTP delivery.

View File

@@ -27,6 +27,9 @@ API_RESOURCE_NAME="Cameleer SaaS API"
# Users (configurable via env vars) # Users (configurable via env vars)
SAAS_ADMIN_USER="${SAAS_ADMIN_USER:-admin}" SAAS_ADMIN_USER="${SAAS_ADMIN_USER:-admin}"
SAAS_ADMIN_PASS="${SAAS_ADMIN_PASS:-admin}" SAAS_ADMIN_PASS="${SAAS_ADMIN_PASS:-admin}"
# Admin email: use provided value, or derive from username@host.
# SaaS enforces email as the user identity — admin must have one.
SAAS_ADMIN_EMAIL="${SAAS_ADMIN_EMAIL:-${SAAS_ADMIN_USER}@${PUBLIC_HOST:-localhost}}"
# No server config — servers are provisioned dynamically by the admin console # No server config — servers are provisioned dynamically by the admin console
@@ -394,11 +397,12 @@ ADMIN_USER_ID=$(api_get "/api/users?search=$SAAS_ADMIN_USER" | jq -r ".[] | sele
if [ -n "$ADMIN_USER_ID" ]; then if [ -n "$ADMIN_USER_ID" ]; then
log "Platform owner exists: $ADMIN_USER_ID" log "Platform owner exists: $ADMIN_USER_ID"
else else
log "Creating platform owner '$SAAS_ADMIN_USER'..." log "Creating platform owner '$SAAS_ADMIN_USER' (email: $SAAS_ADMIN_EMAIL)..."
ADMIN_RESPONSE=$(api_post "/api/users" "{ ADMIN_RESPONSE=$(api_post "/api/users" "{
\"username\": \"$SAAS_ADMIN_USER\", \"username\": \"$SAAS_ADMIN_USER\",
\"password\": \"$SAAS_ADMIN_PASS\", \"password\": \"$SAAS_ADMIN_PASS\",
\"name\": \"Platform Owner\" \"name\": \"Platform Owner\",
\"primaryEmail\": \"$SAAS_ADMIN_EMAIL\"
}") }")
ADMIN_USER_ID=$(echo "$ADMIN_RESPONSE" | jq -r '.id') ADMIN_USER_ID=$(echo "$ADMIN_RESPONSE" | jq -r '.id')
log "Created platform owner: $ADMIN_USER_ID" log "Created platform owner: $ADMIN_USER_ID"

View File

@@ -26,13 +26,12 @@ Both audiences share the same UI and workflows. The self-hosted setup section at
### Logging In ### Logging In
Cameleer SaaS uses Logto for single sign-on (SSO). To log in: Cameleer SaaS uses Logto for single sign-on (SSO). Email is the primary user identity — all users must have an email address. To log in:
1. Navigate to the Cameleer SaaS URL in your browser. 1. Navigate to the Cameleer SaaS URL in your browser.
2. You will see the login screen with the title "Cameleer SaaS" and a subtitle "Managed Apache Camel Runtime." 2. You will be redirected to the Cameleer sign-in page.
3. Click **Sign in with Logto**. 3. Enter your email or username and password.
4. Authenticate with your Logto credentials (username/password or any configured social login). 4. After successful authentication, you are redirected to the dashboard.
5. After successful authentication, you are redirected back to the dashboard.
![Login page](screenshots/login-page.png) ![Login page](screenshots/login-page.png)
@@ -444,6 +443,7 @@ Copy `.env.example` to `.env` and configure as needed:
| `PUBLIC_PROTOCOL` | Public protocol (`http` or `https`) | `https` | | `PUBLIC_PROTOCOL` | Public protocol (`http` or `https`) | `https` |
| `SAAS_ADMIN_USER` | Platform admin username | `admin` | | `SAAS_ADMIN_USER` | Platform admin username | `admin` |
| `SAAS_ADMIN_PASS` | Platform admin password | `admin` | | `SAAS_ADMIN_PASS` | Platform admin password | `admin` |
| `SAAS_ADMIN_EMAIL` | Platform admin email (primary identity) | `<SAAS_ADMIN_USER>@<PUBLIC_HOST>` |
| `TENANT_ADMIN_USER` | Tenant admin username | `camel` | | `TENANT_ADMIN_USER` | Tenant admin username | `camel` |
| `TENANT_ADMIN_PASS` | Tenant admin password | `camel` | | `TENANT_ADMIN_PASS` | Tenant admin password | `camel` |

View File

@@ -1,5 +1,9 @@
# Auth & Security Config # Auth & Security Config
## User identity
**Email is the primary user identity** in SaaS mode. All users must have an email address — Logto enforces this via `signUp.identifiers: ["email"]` when registration is enabled. The bootstrap creates the admin user with `primaryEmail` set to `SAAS_ADMIN_EMAIL` (defaults to `<SAAS_ADMIN_USER>@<PUBLIC_HOST>`). Self-service registration requires email verification via a configured email connector (vendor UI at `/vendor/email`).
## Auth enforcement ## Auth enforcement
- All API endpoints enforce OAuth2 scopes via `@PreAuthorize("hasAuthority('SCOPE_xxx')")` annotations - All API endpoints enforce OAuth2 scopes via `@PreAuthorize("hasAuthority('SCOPE_xxx')")` annotations