docs: update architecture docs for single-domain /platform routing
Reflects current state: path-based routing, SaaS at /platform, Logto catch-all, TLS init container, server integration env vars, custom JwtDecoder for ES384, skip consent for SSO. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
32
CLAUDE.md
32
CLAUDE.md
@@ -26,10 +26,38 @@ The existing cameleer3-server already has single-tenant auth (JWT, RBAC, bootstr
|
||||
- Proxy or federate access to tenant-specific cameleer3-server instances
|
||||
- Enforce usage quotas and metered billing
|
||||
|
||||
Auth enforcement (current state):
|
||||
### Routing (single-domain, path-based via Traefik)
|
||||
|
||||
All services on one hostname. Two env vars control everything: `PUBLIC_HOST` + `PUBLIC_PROTOCOL`.
|
||||
|
||||
| Path | Target | Notes |
|
||||
|------|--------|-------|
|
||||
| `/platform/*` | cameleer-saas:8080 | SPA + API (`server.servlet.context-path: /platform`) |
|
||||
| `/server/*` | cameleer3-server-ui:80 | Server dashboard (strip-prefix + `BASE_PATH=/server`) |
|
||||
| `/` | redirect → `/platform/` | Via `docker/traefik-dynamic.yml` |
|
||||
| `/*` (catch-all) | logto:3001 (priority=1) | Sign-in, OIDC, interaction, assets |
|
||||
|
||||
- SPA assets at `/_app/` (Vite `assetsDir: '_app'`) to avoid conflict with Logto's `/assets/`
|
||||
- Logto `ENDPOINT` = `${PUBLIC_PROTOCOL}://${PUBLIC_HOST}` (same domain, same origin)
|
||||
- TLS: self-signed cert init container (`traefik-certs`) for dev, ACME for production
|
||||
- Root `/` → `/platform/` redirect via Traefik file provider (`docker/traefik-dynamic.yml`)
|
||||
|
||||
### Auth enforcement
|
||||
|
||||
- All API endpoints enforce OAuth2 scopes via `@PreAuthorize("hasAuthority('SCOPE_xxx')")` annotations
|
||||
- Tenant isolation enforced by `TenantIsolationInterceptor` (a single `HandlerInterceptor` on `/api/**` that resolves JWT org_id to TenantContext and validates `{tenantId}`, `{environmentId}`, `{appId}` path variables; fail-closed, platform admins bypass)
|
||||
- 10 OAuth2 scopes defined on the Logto API resource (`https://api.cameleer.local`), served to the frontend from `GET /api/config`
|
||||
- 10 OAuth2 scopes defined on the Logto API resource (`https://api.cameleer.local`), served to the frontend from `GET /platform/api/config`
|
||||
- Custom `JwtDecoder` in `SecurityConfig.java` — ES384 algorithm, `at+jwt` token type, split issuer-uri (string validation) / jwk-set-uri (Docker-internal fetch)
|
||||
|
||||
### Server integration (cameleer3-server env vars)
|
||||
|
||||
| Env var | Value | Purpose |
|
||||
|---------|-------|---------|
|
||||
| `CAMELEER_OIDC_ISSUER_URI` | `${PUBLIC_PROTOCOL}://${PUBLIC_HOST}/oidc` | Token issuer claim validation |
|
||||
| `CAMELEER_OIDC_JWK_SET_URI` | `http://logto:3001/oidc/jwks` | Docker-internal JWK fetch |
|
||||
| `CAMELEER_OIDC_TLS_SKIP_VERIFY` | `true` | Skip cert verify for OIDC discovery (dev) |
|
||||
| `CAMELEER_CORS_ALLOWED_ORIGINS` | `${PUBLIC_PROTOCOL}://${PUBLIC_HOST}` | Allow browser requests through Traefik |
|
||||
| `BASE_PATH` (server-ui) | `/server` | React Router basename + `<base>` tag |
|
||||
|
||||
## Related Conventions
|
||||
|
||||
|
||||
Reference in New Issue
Block a user