diff --git a/.env.example b/.env.example index b5ded73..c2f89be 100644 --- a/.env.example +++ b/.env.example @@ -25,8 +25,11 @@ POSTGRES_DB=cameleer_saas CLICKHOUSE_PASSWORD=change_me_in_production # Admin user (created by bootstrap) +# Email is the primary user identity in SaaS mode. The admin email defaults +# to @ if not set explicitly. SAAS_ADMIN_USER=admin SAAS_ADMIN_PASS=change_me_in_production +# SAAS_ADMIN_EMAIL=admin@example.com # SMTP / email connector configuration is managed at runtime via the vendor # admin UI (Email Connector page at /vendor/email). No SMTP env vars needed. diff --git a/CLAUDE.md b/CLAUDE.md index 8e233f3..4d00cf6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -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. +**Email is the primary user identity** in SaaS mode. All users — including the admin — must have an email address. The admin email defaults to `@` 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 This repo is the SaaS layer on top of two proven components: diff --git a/docker/CLAUDE.md b/docker/CLAUDE.md index 11c6855..418d81e 100644 --- a/docker/CLAUDE.md +++ b/docker/CLAUDE.md @@ -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) 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) -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 `@` 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) 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. diff --git a/docker/logto-bootstrap.sh b/docker/logto-bootstrap.sh index f7e10d5..5f56d2c 100644 --- a/docker/logto-bootstrap.sh +++ b/docker/logto-bootstrap.sh @@ -27,6 +27,9 @@ API_RESOURCE_NAME="Cameleer SaaS API" # Users (configurable via env vars) SAAS_ADMIN_USER="${SAAS_ADMIN_USER:-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 @@ -394,11 +397,12 @@ ADMIN_USER_ID=$(api_get "/api/users?search=$SAAS_ADMIN_USER" | jq -r ".[] | sele if [ -n "$ADMIN_USER_ID" ]; then log "Platform owner exists: $ADMIN_USER_ID" 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" "{ \"username\": \"$SAAS_ADMIN_USER\", \"password\": \"$SAAS_ADMIN_PASS\", - \"name\": \"Platform Owner\" + \"name\": \"Platform Owner\", + \"primaryEmail\": \"$SAAS_ADMIN_EMAIL\" }") ADMIN_USER_ID=$(echo "$ADMIN_RESPONSE" | jq -r '.id') log "Created platform owner: $ADMIN_USER_ID" diff --git a/docs/user-manual.md b/docs/user-manual.md index 9c96da2..8fd0aea 100644 --- a/docs/user-manual.md +++ b/docs/user-manual.md @@ -26,13 +26,12 @@ Both audiences share the same UI and workflows. The self-hosted setup section at ### 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. -2. You will see the login screen with the title "Cameleer SaaS" and a subtitle "Managed Apache Camel Runtime." -3. Click **Sign in with Logto**. -4. Authenticate with your Logto credentials (username/password or any configured social login). -5. After successful authentication, you are redirected back to the dashboard. +2. You will be redirected to the Cameleer sign-in page. +3. Enter your email or username and password. +4. After successful authentication, you are redirected to the dashboard. ![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` | | `SAAS_ADMIN_USER` | Platform admin username | `admin` | | `SAAS_ADMIN_PASS` | Platform admin password | `admin` | +| `SAAS_ADMIN_EMAIL` | Platform admin email (primary identity) | `@` | | `TENANT_ADMIN_USER` | Tenant admin username | `camel` | | `TENANT_ADMIN_PASS` | Tenant admin password | `camel` | diff --git a/installer b/installer index 1ef0016..b225932 160000 --- a/installer +++ b/installer @@ -1 +1 @@ -Subproject commit 1ef0016965133144ef4cc92b100807b1712e89d4 +Subproject commit b2259328d392482fe2a3aa9044ebe0403ed2fc3d diff --git a/src/main/java/net/siegeln/cameleer/saas/config/CLAUDE.md b/src/main/java/net/siegeln/cameleer/saas/config/CLAUDE.md index 442a427..f23a93b 100644 --- a/src/main/java/net/siegeln/cameleer/saas/config/CLAUDE.md +++ b/src/main/java/net/siegeln/cameleer/saas/config/CLAUDE.md @@ -1,5 +1,9 @@ # 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 `@`). Self-service registration requires email verification via a configured email connector (vendor UI at `/vendor/email`). + ## Auth enforcement - All API endpoints enforce OAuth2 scopes via `@PreAuthorize("hasAuthority('SCOPE_xxx')")` annotations