Commit Graph

594 Commits

Author SHA1 Message Date
hsiegeln
292adeea4c docs: update documentation for passkey MFA feature
All checks were successful
CI / build (push) Successful in 2m23s
CI / docker (push) Successful in 2m19s
- 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>
2026-04-27 11:51:12 +02:00
hsiegeln
43a1058f33 fix: code review findings — auth-settings HTTP method, authorization, redirect
- Change auth-settings endpoint from PUT to PATCH (matches partial update semantics and frontend hook)
- Add @PreAuthorize("SCOPE_tenant:manage") to updateAuthSettings endpoint
- Consolidate MFA/passkey 403 redirect handling in API client

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-27 09:01:23 +02:00
hsiegeln
60a800f757 feat: add passkey offer step to onboarding wizard
After tenant creation, checks vendor auth policy and conditionally
shows a passkey enrollment offer screen before redirecting. User
can skip and set up later.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 08:55:24 +02:00
hsiegeln
76a62135ab feat: add WebAuthn and method picker modes to sign-in UI
Adds mfaWebauthn and mfaMethodPicker modes with smart routing based on
stored preference (localStorage). Auto-triggers passkey prompt on mode
entry. Adds "Use passkey instead" link in TOTP mode. Saves method
preference on successful verification.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 08:55:16 +02:00
hsiegeln
17ba02c30d feat: add WebAuthn Experience API functions to sign-in UI
Adds startWebAuthnAuth and verifyWebAuthnAuth functions that call
the Logto Experience API WebAuthn endpoints for passkey MFA verification.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 08:55:10 +02:00
hsiegeln
9b898924ab feat: add passkey management and auth policy sections to tenant settings
Adds PasskeySection (list/rename/delete passkeys), AuthPolicySection
(MFA mode + passkey enable/mode controls), and PasskeyNudgeBanner
(dismissable nudge for users without a passkey enrolled).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 08:55:04 +02:00
hsiegeln
8de16019b7 feat: add vendor authentication policy management page
Adds /vendor/auth-policy route with MFA mode (off/optional/required) and passkey (enabled/disabled, optional/preferred/required mode) controls, including a confirmation guard before enforcing required MFA.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 08:51:45 +02:00
hsiegeln
ad2b16f26d feat: add passkey and auth policy React Query hooks
Adds hooks for listing/renaming/deleting passkeys, MFA method preference,
tenant auth settings, and vendor auth policy (using the new putJson method).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 08:48:44 +02:00
hsiegeln
2007a4b2da feat: add passkey types and APP_PASSKEY_REQUIRED handling
Extends MfaStatus with passkeyEnrolled/passkeyCount fields, adds
PasskeyCredential and AuthPolicy types, expands TenantSettings with
passkey fields, handles APP_PASSKEY_REQUIRED 403 redirect, and adds
putJson method to the api client for JSON PUT requests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 08:48:39 +02:00
hsiegeln
9057479da7 feat: expose vendor auth policy in public config endpoint
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 08:48:13 +02:00
hsiegeln
89c83ec7b8 feat: expand MfaEnforcementFilter for vendor policy and passkey checks
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 08:48:09 +02:00
hsiegeln
b3104dc410 feat: add passkey and auth settings endpoints to TenantPortalController 2026-04-27 08:45:52 +02:00
hsiegeln
5bf94c6d4e feat: add passkey management and auth settings to TenantPortalService 2026-04-27 08:45:49 +02:00
hsiegeln
40daca36a0 feat: add WebAuthn credential and custom data methods to LogtoManagementClient 2026-04-27 08:45:45 +02:00
hsiegeln
8c9edfdb55 feat: add passkey_enrolled and mfa_method_preference to Custom JWT claims
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 08:44:42 +02:00
hsiegeln
25f4afcddc feat: add vendor auth policy REST endpoints
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 08:42:59 +02:00
hsiegeln
02be1d9264 feat: add VendorAuthPolicy entity and repository
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 08:42:55 +02:00
hsiegeln
cc7c87a520 feat: add vendor_auth_policy table for passkey MFA support
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 08:42:51 +02:00
hsiegeln
ca19faf4f0 docs: add passkey MFA implementation plan
18-task plan covering database migration, backend policy/endpoints,
sign-in UI WebAuthn modes, and platform UI management pages.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-27 08:39:44 +02:00
hsiegeln
b86cc812b7 docs: add passkey MFA design spec
Logto-native WebAuthn approach with independent vendor/tenant policy
domains, three registration entry points, and smart MFA method defaults.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-27 08:26:09 +02:00
hsiegeln
f0dda0d2ee fix(ui): clean up tenant pages and add license inspection
All checks were successful
CI / build (push) Successful in 2m6s
CI / docker (push) Successful in 1m28s
- Remove tier badge from tenant license page header
- Remove tier badge and Tier KPI card from tenant dashboard
- Add "Inspect License" toggle on vendor tenant detail to view all limits

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-27 07:51:29 +02:00
hsiegeln
3cd6bd5585 chore: update GitNexus index stats in documentation
Some checks failed
CI / build (push) Successful in 2m16s
CI / docker (push) Successful in 1m38s
SonarQube Analysis / sonarqube (push) Failing after 2m36s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 22:14:42 +02:00
hsiegeln
25d66af45e fix(ui): hide redundant SSO button in empty state, fix dashboard navigation
Some checks failed
CI / docker (push) Has been cancelled
CI / build (push) Has been cancelled
- Hide top-right "Add SSO Connection" when no connectors exist (empty
  state already has its own button)
- Fix broken relative navigations on tenant dashboard: ../license and
  ../oidc resolved to wrong paths; now use absolute /tenant/license and
  /tenant/sso

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 22:13:41 +02:00
hsiegeln
d783040030 feat(ui): add license usage visualization with progress bars
Split license limits into metered "Resource Usage" (with color-coded
progress bars) and static "Plan Limits" cards. Updated UsageIndicator
with 8px bars, green/amber/red thresholds, and tabular-nums formatting.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 22:12:33 +02:00
hsiegeln
6afc337b16 feat: add usage data to license and vendor detail endpoints
Add getAppCount() to ServerApiClient, include usage counts (agents,
environments, apps, users) in tenant license and vendor detail responses
so the frontend can render progress bars against license limits.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 22:08:47 +02:00
hsiegeln
e881e302b6 fix(ui): check ApiError.status instead of message string for 404 detection
All checks were successful
CI / build (push) Successful in 2m3s
CI / docker (push) Successful in 1m27s
The ApiError class (088bc34) extracts messages from response bodies, so
a 404 with no body produces "Request failed" — not "404". The email
connector hook's string check failed, treating "not configured" as an
error and showing "Failed to load config" on fresh installs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 21:28:53 +02:00
hsiegeln
d7ef2c488b fix: use valid STARTER tier in onboarding tenant creation
All checks were successful
CI / build (push) Successful in 2m17s
CI / docker (push) Successful in 1m16s
OnboardingService passed "LOW" as the tier, but the Tier enum only has
STARTER/TEAM/BUSINESS/ENTERPRISE. Tier.valueOf("LOW") threw
IllegalArgumentException, which the controller caught as a blanket 409
Conflict — masking the real cause. Also catch IllegalStateException
(user already has a tenant) to return 409 instead of 500.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 21:17:23 +02:00
hsiegeln
088bc34e67 fix(ui): extract meaningful error messages from API responses
All checks were successful
CI / build (push) Successful in 2m9s
CI / docker (push) Successful in 1m28s
Introduces ApiError class in client.ts that parses Spring Boot error
bodies to extract human-readable messages (message, error, detail fields).
Adds errorMessage() helper used by all toast descriptions instead of
raw String(err) which dumped JSON blobs to the user.

Affected: all 10 page components that display error toasts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 21:10:28 +02:00
hsiegeln
73e41e5607 fix(ci): force SNAPSHOT updates in build job Maven command
All checks were successful
CI / build (push) Successful in 2m15s
CI / docker (push) Successful in 1m31s
The actions/cache restored a stale ~/.m2/repository with the old
cameleer-license-minter SNAPSHOT (pre-license-api extraction).
Adding -U forces re-resolution of SNAPSHOT dependencies.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 20:58:06 +02:00
hsiegeln
f5b68c212b fix: force SNAPSHOT updates in Docker build to resolve stale cache
Some checks failed
CI / build (push) Failing after 1m2s
CI / docker (push) Has been skipped
The BuildKit cache mount for ~/.m2/repository persists the old
cameleer-license-minter SNAPSHOT (which depended on server-core).
Adding -U forces Maven to re-resolve SNAPSHOTs from the Gitea
registry, picking up the updated minter that depends on license-api.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 20:55:41 +02:00
hsiegeln
7c82ba93b0 refactor: update imports for cameleer-license-api package extraction
Some checks failed
CI / build (push) Successful in 3m6s
CI / docker (push) Failing after 30s
Server team extracted license types into cameleer-license-api (#156).
Package moved from com.cameleer.server.core.license to com.cameleer.license.
Dependency tree is now: cameleer-saas → minter → license-api (no server-core).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 20:50:18 +02:00
hsiegeln
1066101e8a fix: add Gitea Maven repository for cameleer-license-minter resolution
All checks were successful
CI / build (push) Successful in 2m31s
CI / docker (push) Successful in 1m25s
CI needs to resolve com.cameleer:cameleer-license-minter from the
Gitea package registry. Without this repository declaration, the
dependency only resolved from the local Maven cache.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 19:31:27 +02:00
hsiegeln
ffb7ef0839 feat(ui): add license minting form, verify tool, and update all pages
Some checks failed
CI / build (push) Successful in 2m42s
CI / docker (push) Failing after 51s
Vendor UI:
- TenantDetailPage: full minting form with tier presets, 13 configurable
  limits, expiry/grace period, label. Mint & Push or Mint & Copy actions.
  License bundle display with all three env vars for standalone deployment.
- LicenseVerifyPage: paste token to decode + validate signature, shows
  envelope details and state badge. Public key viewer with copy button.
- Layout: added "License Tools" nav item under Vendor section.
- vendor-hooks: useMintLicense, useLicensePresets, useVerifyLicense, usePublicKey

Tenant UI:
- TenantLicensePage: replaced features card with full 13-key limits display,
  added grace period and label fields
- TenantDashboardPage: fixed limit keys (agents→max_agents, environments→max_environments)

Common:
- Updated types (dropped features, added label/gracePeriodDays/bundle types)
- Updated tier colors for STARTER/TEAM/BUSINESS/ENTERPRISE
- Updated CreateTenantPage tier dropdown

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 17:41:40 +02:00
hsiegeln
4dea1c6764 feat: push Ed25519 public key to tenant server containers
DockerTenantProvisioner now injects CAMELEER_SERVER_LICENSE_PUBLICKEY
env var on provisioned server containers, enabling cryptographic
license validation. SigningKeyService passed through auto-config.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 17:36:06 +02:00
hsiegeln
6c3f21d4db test: update all tests for Ed25519 license minting and tier rename
- LicenseServiceTest: mock SigningKeyService, assert signed token format
- VendorTenantServiceTest: add SigningKeyService mock, update mintLicense stubs
- All tests: LOW→STARTER, MID→TEAM, HIGH→BUSINESS, BUSINESS→ENTERPRISE
- Remove all features-related test assertions
- 80/80 tests passing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 17:33:10 +02:00
hsiegeln
7a8960ca46 feat: add vendor license minting, presets, and verify endpoints
- POST /vendor/tenants/{id}/license now accepts MintLicenseRequest body
  with custom limits, expiresAt, gracePeriodDays, label, pushToServer
- Returns LicenseBundleResponse with token + public key + tenant slug
- GET /vendor/license-presets returns tier preset limits
- POST /vendor/license/verify decodes and validates signed tokens
- GET /vendor/signing-key/public returns the Ed25519 public key
- VendorTenantService.mintLicense() supports configurable minting
- Updated portal DTOs to drop features, add label + gracePeriodDays

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 17:24:23 +02:00
hsiegeln
fdc7187424 feat: rewrite LicenseService to mint Ed25519-signed tokens
Replaces UUID token generation with LicenseMinter.mint() from
cameleer-license-minter. Adds full-control generateLicense() overload
accepting custom limits, expiry, grace period, and label.
Adds verifyToken() and verifyTokenSignature() using LicenseValidator.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 17:22:05 +02:00
hsiegeln
2fd14165bc feat: add SigningKeyService for Ed25519 keypair management
Entity, repository, and service for generating and storing Ed25519
signing keys. Lazy-initializes on first call — generates keypair
and persists to signing_keys table.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 17:21:16 +02:00
hsiegeln
13bd03997a refactor: rename tiers and rewrite LicenseDefaults to 13-key cap matrix
- Tier enum: LOW→STARTER, MID→TEAM, HIGH→BUSINESS, BUSINESS→ENTERPRISE
- LicenseDefaults: 13-key limits per tier matching server handoff cap matrix
- Drop features concept from LicenseEntity, LicenseResponse, portal DTOs
- Add label and gracePeriodDays to LicenseEntity
- Fix agent limit key from 'agents' to 'max_agents' in VendorTenantController

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 17:20:22 +02:00
hsiegeln
e64bf4f0d1 feat: add cameleer-license-minter dependency and V002 migration
Adds Ed25519 license minting library, signing_keys table,
renames tiers (LOW→STARTER, MID→TEAM, HIGH→BUSINESS, BUSINESS→ENTERPRISE),
adds label + grace_period_days to licenses, drops features column.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 17:17:44 +02:00
hsiegeln
883e10ba7c feat: test SMTP connection on save and retain password on edit
All checks were successful
CI / build (push) Successful in 2m20s
CI / docker (push) Successful in 1m36s
Adds testSmtpConnection() that performs EHLO + auth via JavaMailSender
before persisting to Logto — saves fail fast with a clear error if
SMTP credentials are wrong. Password is now optional when editing:
if left blank the backend fetches the existing password from Logto's
connector config, so users can update host/port/fromEmail without
re-entering the password every time.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 16:23:42 +02:00
hsiegeln
0413a5b882 fix: remove HTML document wrapper from email templates for GMX compat
All checks were successful
CI / build (push) Successful in 2m12s
CI / docker (push) Successful in 1m5s
GMX webmail broke after adding <!DOCTYPE html><html><head><body>
wrappers — the Logto SMTP connector sets these as nodemailer's html
field, and GMX's sanitizer chokes on a full document inside its own
page shell. Reverts to bare HTML fragments (the format that worked
before 12:17 commit 484a388) while keeping the extra text paragraphs
added for mail checker text-to-HTML ratio compliance.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 16:08:04 +02:00
hsiegeln
c6b6bafc0f fix: revert email templates to inline styles for GMX webmail compat
All checks were successful
CI / build (push) Successful in 1m59s
CI / docker (push) Successful in 1m52s
GMX webmail strips <head> content including <style> blocks, rendering
emails as unstyled plain text. Reverts to inline styles (the only
reliable approach for email HTML) while keeping the proper HTML document
structure and extra text content added for mail checker compliance.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 15:56:10 +02:00
hsiegeln
988035b952 fix: handle MFA binding skip during registration submit
The registration flow hit a 422 on /api/experience/submit when MFA
policy is UserControlled. Adds the same trySubmit + skipMfaBinding
pattern already used in the sign-in flow — Logto confirms mfa-skipped
works for both SignIn and Register interaction events.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 15:52:46 +02:00
hsiegeln
c55427c22b fix: restore watermark image in email templates
All checks were successful
CI / build (push) Successful in 2m18s
CI / docker (push) Successful in 1m10s
The previous commit incorrectly removed the watermark — only the
style extraction into <style> blocks was requested. Restores the
watermark <img>, {{watermarkUrl}} placeholder resolution in both
EmailConnectorService and PasswordResetNotificationService, and
the corresponding test assertions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 15:14:35 +02:00
hsiegeln
f681784e7e fix: move email styles to <style> block and remove watermark image
Some checks failed
CI / build (push) Successful in 1m59s
CI / docker (push) Has been cancelled
Extracts repeated inline styles into <head> <style> to improve the
text-to-HTML ratio flagged by mail checkers. Removes the decorative
watermark <img> (opacity 0.07, barely visible) which was the only
image element and triggered the "too many images" classification.
Cleans up the now-unused ProvisioningProperties dependency from
EmailConnectorService and PasswordResetNotificationService.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 15:11:53 +02:00
hsiegeln
7b57ee8246 fix: add proper HTML document structure and more text to email templates
All checks were successful
CI / build (push) Successful in 2m35s
CI / docker (push) Successful in 1m6s
Mail checkers flagged missing <html> tag and insufficient text content.
Wraps all 5 templates in DOCTYPE/html/head/body, adds Outlook conditional
comments, and includes a descriptive paragraph to improve text-to-image ratio.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 14:57:47 +02:00
hsiegeln
6e6e4218c9 fix: skip MFA binding prompt for UserControlled policy during sign-in
All checks were successful
CI / build (push) Successful in 2m1s
CI / docker (push) Successful in 59s
Logto returns 422 with an MFA recommendation when policy is
UserControlled. Call POST /profile/mfa/mfa-skipped to skip the
binding prompt, then re-submit. Users who already have MFA enrolled
still get the TOTP verification flow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 14:43:55 +02:00
hsiegeln
469b36613b fix: resolve CI type errors in TeamPage and install qrcode.react
All checks were successful
CI / build (push) Successful in 2m52s
CI / docker (push) Successful in 2m16s
- Change Button size="small" to size="sm" (design system API)
- Remove unsupported style prop from Card component
- Ensure qrcode.react is properly installed

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 14:29:59 +02:00
hsiegeln
bcb8a040f4 docs: add MFA handoff document for cameleer-server team
Some checks failed
CI / build (push) Failing after 38s
CI / docker (push) Has been skipped
Covers JWT mfa_enrolled claim, enforcement model (APP_MFA_REQUIRED),
Logto Management API contract for TOTP enrollment and backup codes,
UX requirements, and error states.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 14:07:27 +02:00