docs: update documentation for passkey MFA feature
- Add V002/V003 migrations and VendorAuthPolicy classes to CLAUDE.md - Document MFA & passkey enforcement model in config CLAUDE.md - Mark passkey MFA design spec as Implemented Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -27,7 +27,7 @@ Agent-server protocol is defined in `cameleer/cameleer-common/PROTOCOL.md`. The
|
||||
|---------|---------|-------------|
|
||||
| `config/` | Security, tenant isolation, web config | `SecurityConfig`, `TenantIsolationInterceptor`, `TenantContext`, `PublicConfigController`, `MeController` |
|
||||
| `tenant/` | Tenant data model | `TenantEntity` (JPA: id, name, slug, tier, status, logto_org_id, db_password) |
|
||||
| `vendor/` | Vendor console (platform:admin) | `VendorTenantService`, `VendorTenantController`, `InfrastructureService`, `EmailConnectorService`, `EmailConnectorController` |
|
||||
| `vendor/` | Vendor console (platform:admin) | `VendorTenantService`, `VendorTenantController`, `InfrastructureService`, `EmailConnectorService`, `EmailConnectorController`, `VendorAuthPolicyController`, `VendorAuthPolicyEntity` |
|
||||
| `onboarding/` | Self-service sign-up onboarding | `OnboardingController`, `OnboardingService` |
|
||||
| `portal/` | Tenant admin portal (org-scoped) | `TenantPortalService`, `TenantPortalController` |
|
||||
| `provisioning/` | Pluggable tenant provisioning | `DockerTenantProvisioner`, `TenantDatabaseService`, `TenantDataCleanupService` |
|
||||
@@ -56,6 +56,8 @@ For detailed architecture docs, see the directory-scoped CLAUDE.md files (loaded
|
||||
|
||||
PostgreSQL (Flyway): `src/main/resources/db/migration/`
|
||||
- V001 — consolidated baseline: tenants (with db_password, server_endpoint, provision_error, ca_applied_at), licenses, audit_log, certificates, tenant_ca_certs
|
||||
- V002 — license minter: signing_keys table, tier renames, license label + grace period
|
||||
- V003 — passkey MFA: vendor_auth_policy single-row config table (mfa_mode, passkey_enabled, passkey_mode)
|
||||
|
||||
## Related Conventions
|
||||
|
||||
@@ -79,7 +81,7 @@ PostgreSQL (Flyway): `src/main/resources/db/migration/`
|
||||
<!-- gitnexus:start -->
|
||||
# GitNexus — Code Intelligence
|
||||
|
||||
This project is indexed by GitNexus as **cameleer-saas** (3336 symbols, 7094 relationships, 281 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
|
||||
This project is indexed by GitNexus as **cameleer-saas** (3330 symbols, 7090 relationships, 281 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
|
||||
|
||||
> If any GitNexus tool warns the index is stale, run `npx gitnexus analyze` in terminal first.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Passkey MFA Design
|
||||
|
||||
**Date:** 2026-04-27
|
||||
**Status:** Draft
|
||||
**Status:** Implemented
|
||||
**Goal:** Add passkeys (WebAuthn) as an MFA factor alongside existing TOTP, with a long-term path toward passwordless sign-in.
|
||||
|
||||
## Motivation
|
||||
|
||||
@@ -13,7 +13,24 @@
|
||||
- Org roles: `owner` -> `server:admin` + `tenant:manage`, `operator` -> `server:operator`, `viewer` -> `server:viewer`
|
||||
- `saas-vendor` global role created by bootstrap Phase 12 and always assigned to the admin user — has `platform:admin` + all tenant scopes
|
||||
- Custom `JwtDecoder` in `SecurityConfig.java` — ES384 algorithm, `at+jwt` token type, split issuer-uri (string validation) / jwk-set-uri (Docker-internal fetch), audience validation (`https://api.cameleer.local`)
|
||||
- Logto Custom JWT (Phase 7b in bootstrap) injects a `roles` claim into access tokens based on org roles and global roles — this makes role data available to the server without Logto-specific code
|
||||
- Logto Custom JWT (Phase 7b in bootstrap) injects claims into access tokens: `roles` (org role mapping), `mfa_enrolled` (true if TOTP or WebAuthn factor), `passkey_enrolled` (true if WebAuthn factor), `mfa_method_preference` (from user custom data)
|
||||
|
||||
## MFA & Passkey enforcement
|
||||
|
||||
Two independent policy domains — **no inheritance**, vendor and tenant policies are separate scopes:
|
||||
|
||||
| Policy | Scope | Who it affects | Stored in |
|
||||
|--------|-------|---------------|-----------|
|
||||
| **Vendor auth policy** | Platform logins (`/api/vendor/**`, `/api/portal/**`) | Tenant admins | `vendor_auth_policy` table (single-row) |
|
||||
| **Tenant auth policy** | Org user logins (`/api/tenant/**`) | Org members | `tenants.settings` JSONB (`mfaMode`, `passkeyEnabled`, `passkeyMode`) |
|
||||
|
||||
- `MfaEnforcementFilter` (after `BearerTokenAuthenticationFilter`) checks JWT claims `mfa_enrolled` and `passkey_enrolled` against effective policy
|
||||
- Error codes: `APP_MFA_REQUIRED`, `APP_PASSKEY_REQUIRED` (returned via `X-Cameleer-Error` header)
|
||||
- Exempt routes: `/api/tenant/mfa/`, `/api/config`, `/api/me`, `/api/onboarding`, `/api/vendor/auth-policy`, `/api/tenant/auth-settings`
|
||||
- Backward-compatible: legacy `mfaRequired: true` in settings treated as `mfaMode: "required"`
|
||||
- Policy settings: `mfa_mode` (off/optional/required), `passkey_enabled` (bool), `passkey_mode` (optional/preferred/required)
|
||||
- Passkey registration only via Logto Experience API during sign-in (Approach A: Logto-native WebAuthn)
|
||||
- Passkey management (list/rename/delete) via Logto Management API through SaaS backend endpoints
|
||||
|
||||
## Auth routing by persona
|
||||
|
||||
|
||||
Reference in New Issue
Block a user