Commit Graph

51 Commits

Author SHA1 Message Date
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
d52084a081 feat: add Reset MFA action for team members
Adds a Reset MFA button in the Actions column and an inline confirmation
card (with warning Alert) that calls useResetTeamMemberMfa on confirm.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 14:06:20 +02:00
hsiegeln
7e7407b137 feat: add MFA enrollment and enforcement toggle to Settings page
Adds two new sections to the tenant Settings page:
- MfaSection: TOTP authenticator setup with QR code, 6-digit verification,
  backup code display (2-column grid with copy/download), and MFA removal
- MfaEnforcementToggle: tenant admin control to require MFA for all members,
  with confirmation dialog before enabling

Installs qrcode.react for QR code rendering. Uses existing MFA hooks from
tenant-hooks.ts and design-system components.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 14:04:28 +02:00
hsiegeln
d720c0500f fix: force fresh OIDC sign-in after onboarding to pick up new org membership
All checks were successful
CI / build (push) Successful in 1m55s
CI / docker (push) Successful in 1m22s
After creating a tenant, the existing Logto tokens don't include the new
org membership/scopes. A hard page reload reused stale tokens, causing
the SDK to either lose auth state (redirect loop to login) or fail to
resolve org scopes (falling through to server UI instead of tenant UI).

Replace window.location.href with signIn() to trigger a fresh OIDC flow.
The existing Logto session cookie means auto-approval — no login form.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 12:06:39 +02:00
hsiegeln
06d114b46b feat: validate slug uniqueness during onboarding
All checks were successful
CI / build (push) Successful in 1m50s
CI / docker (push) Successful in 1m22s
Add GET /api/onboarding/slug-available endpoint to check if a slug is
already taken. Frontend checks availability with 400ms debounce as the
user types and shows inline feedback. Submit button disabled when slug
is taken. POST /api/onboarding/tenant now returns 409 instead of 500
for duplicate slugs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 09:40:17 +02:00
hsiegeln
171ed1a6ab fix: provisioning race condition and noisy ClickHouse logs
Some checks failed
CI / build (push) Successful in 2m3s
CI / docker (push) Successful in 1m30s
SonarQube Analysis / sonarqube (push) Failing after 2m22s
Defer provisionAsync() until after the transaction commits using
TransactionSynchronization.afterCommit(). Previously the @Async thread
raced the @Transactional commit — findById returned null because the
tenant INSERT wasn't visible yet.

Downgrade ClickHouse UNKNOWN_TABLE errors to DEBUG level in
InfrastructureService. These are expected on fresh installs before any
cameleer-server has created the tables.

Make the onboarding slug field read-only (derived from org name).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-25 22:05:48 +02:00
hsiegeln
dee1f39554 fix: align button icons and polish vendor sidebar
All checks were successful
CI / build (push) Successful in 2m8s
CI / docker (push) Successful in 1m41s
Fix vertical alignment of Lucide icons inside Button children across
all pages by adding verticalAlign offsets (-3px for 16px icons, -2px
for 14px icons). The design system Button wraps children in an inline
span, so SVG icons defaulted to baseline alignment.

Hide the redundant top-right "Create Tenant" button on VendorTenantsPage
when no tenants exist — the EmptyState already provides that action.

Add icons to all vendor sidebar sub-items for consistency (previously
only Email Connector had one).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-25 21:30:37 +02:00
hsiegeln
9aa535ace8 feat: add EmailConfigPage with SMTP form, registration toggle, and test email 2026-04-25 18:02:30 +02:00
hsiegeln
b5068250f9 fix(ui): improve onboarding page styling to match sign-in page
All checks were successful
CI / build (push) Successful in 1m51s
CI / docker (push) Successful in 1m16s
Add 32px card padding and reduce max-width to 420px for consistency
with the sign-in page. Add noValidate to prevent browser-native
required validation outlines on inputs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-25 12:43:11 +02:00
hsiegeln
9ed2cedc98 feat: self-service sign-up with email verification and onboarding
All checks were successful
CI / build (push) Successful in 1m14s
CI / docker (push) Successful in 1m15s
Complete sign-up pipeline: email registration via Logto Experience API,
SMTP email verification, and self-service trial tenant creation.

Layer 1 — Logto config:
- Bootstrap Phase 8b: SMTP email connector with branded HTML templates
- Bootstrap Phase 8c: enable SignInAndRegister (email+password sign-up)
- Dockerfile installs official Logto connectors (ensures SMTP available)
- SMTP env vars in docker-compose, installer templates, .env.example

Layer 2 — Experience API (ui/sign-in/experience-api.ts):
- Registration flow: initRegistration → sendVerificationCode → verifyCode
  → addProfile (password) → identifyUser → submit
- Sign-in auto-detects email vs username identifier

Layer 3 — Custom sign-in UI (ui/sign-in/SignInPage.tsx):
- Three-mode state machine: signIn / register / verifyCode
- Reads first_screen=register from URL query params
- Toggle links between sign-in and register views

Layer 4 — Post-registration onboarding:
- OnboardingService: reuses VendorTenantService.createAndProvision(),
  adds calling user to Logto org as owner, enforces one trial per user
- OnboardingController: POST /api/onboarding/tenant (authenticated only)
- OnboardingPage.tsx: org name + auto-slug form
- LandingRedirect: detects zero orgs → redirects to /onboarding
- RegisterPage.tsx: /platform/register initiates OIDC with firstScreen

Installers (install.sh + install.ps1):
- Both prompt for SMTP config in SaaS mode
- CLI args, env var capture, cameleer.conf persistence

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-25 00:21:07 +02:00
hsiegeln
1fbafbb16d feat: add vendor tenant metrics dashboard
All checks were successful
CI / build (push) Successful in 1m24s
CI / docker (push) Successful in 1m0s
Fleet overview page at /vendor/metrics showing per-tenant operational
metrics (agents, CPU, heap, HTTP requests, ingestion drops, uptime).
Queries each tenant's server via the new POST /api/v1/admin/server-metrics/query
REST API instead of direct ClickHouse access, supporting future per-tenant
CH instances.

Backend: TenantMetricsService fires 11 metric queries per tenant
concurrently over a 5-minute window, assembles into a summary snapshot.
ServerApiClient.queryServerMetrics() handles the M2M authenticated POST.

Frontend: VendorMetricsPage with KPI strip (fleet totals) and per-tenant
table with color-coded badges and heap usage bars. Auto-refreshes every 60s.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-24 14:02:57 +02:00
hsiegeln
91e93696ed fix: improve Infrastructure page readability
All checks were successful
CI / build (push) Successful in 1m11s
CI / docker (push) Successful in 54s
Use Card and KpiStrip design system components, add database icons to
section headers, right-align numeric columns, replace text toggles with
chevron icons, and constrain max width to prevent ultra-wide stretching.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 23:26:43 +02:00
hsiegeln
92503a1061 feat: add vendor infrastructure page with PG/CH per-tenant view
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:18:59 +02:00
hsiegeln
e2e5c794a2 feat: add server upgrade action — force-pull latest images and re-provision
All checks were successful
CI / build (push) Successful in 1m19s
CI / docker (push) Successful in 48s
Restart only stops/starts existing containers with the same image. The new
upgrade action removes server + UI containers, force-pulls the latest
Docker images, then re-provisions (preserving app containers, volumes, and
networks). Available to both vendor (tenant detail) and tenant admin
(dashboard).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 10:45:45 +02:00
hsiegeln
d5eead888d feat: server admin password reset via tenant portal
All checks were successful
CI / build (push) Successful in 2m23s
CI / docker (push) Successful in 1m8s
- POST /api/tenant/server/admin-password — resets server's built-in
  admin password via M2M API call to the tenant's server
- Settings page: "Server Admin Password" card
- ServerApiClient.resetServerAdminPassword() calls server's password
  reset endpoint with M2M token

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 09:46:30 +02:00
hsiegeln
4121bd64b2 feat: password management for tenant portal
All checks were successful
CI / build (push) Successful in 1m15s
CI / docker (push) Successful in 47s
- POST /api/tenant/password — change own Logto password
- POST /api/tenant/team/{userId}/password — reset team member password
- Settings page: "Change Password" card with confirm field
- Team page: "Reset Password" button per member with inline form
- LogtoManagementClient.updateUserPassword() via Logto Management API

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 09:19:48 +02:00
hsiegeln
875b07fb3a feat: use FileInput DS component for file uploads, fix certs volume perms
All checks were successful
CI / build (push) Successful in 1m24s
CI / docker (push) Successful in 1m12s
- Replace inline FileField and native <input type="file"> with
  FileInput from @cameleer/design-system (drag-and-drop, icons, clear)
- Update CertificatesPage and SsoPage to use FileInput + FormField
- Fix /certs volume permissions (chmod 775) so cameleer user can write

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 08:04:47 +02:00
hsiegeln
8eef7e170b feat: show agent/env counts in vendor tenant list
All checks were successful
CI / build (push) Successful in 1m20s
CI / docker (push) Successful in 48s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 22:02:46 +02:00
hsiegeln
a5445e332e fix: fetch actual agent/environment counts from server for tenant dashboard
All checks were successful
CI / build (push) Successful in 1m8s
CI / docker (push) Successful in 43s
The dashboard was showing hardcoded zeroes for agent and environment usage.
Now fetches real counts via M2M API from the tenant's server.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 20:35:24 +02:00
hsiegeln
3ae8fa18cd feat: support password-protected private keys
All checks were successful
CI / build (push) Successful in 1m8s
CI / docker (push) Successful in 42s
Encrypted PKCS#8 private keys are decrypted during staging using the
provided password. The decrypted key is stored for Traefik (which needs
cleartext PEM). Unencrypted keys continue to work without a password.

- CertificateManager.stage() accepts optional keyPassword
- DockerCertificateManager handles EncryptedPrivateKeyInfo decryption
- UI: password field in upload form (vendor CertificatesPage)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 19:44:09 +02:00
hsiegeln
dd30ee77d4 feat: tenant CA certificate management with staging
Some checks failed
CI / build (push) Successful in 1m7s
CI / docker (push) Has been cancelled
Tenants can upload multiple CA certificates for enterprise SSO providers
that use private certificate authorities.

- New tenant_ca_certs table (V013) with PEM storage in DB
- Stage/activate/delete lifecycle per CA cert
- Aggregated ca.pem rebuild on activate/delete (atomic .wip swap)
- REST API: GET/POST/DELETE on /api/tenant/ca
- UI: CA Certificates section on SSO page with upload, activate, remove

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 19:35:04 +02:00
hsiegeln
22752ffcb1 fix: polish CertificatesPage layout
All checks were successful
CI / build (push) Successful in 1m7s
CI / docker (push) Successful in 44s
- Truncate fingerprint with hover tooltip
- Remove duplicate warning icon in stale banner
- Style file inputs to match design system
- Bump grid min-width for better card spacing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 19:04:16 +02:00
hsiegeln
45bcc954ac feat: certificate management with stage/activate/restore lifecycle
All checks were successful
CI / build (push) Successful in 1m8s
CI / docker (push) Successful in 45s
Provider-based architecture (Docker now, K8s later):
- CertificateManager interface + DockerCertificateManager (file-based)
- Atomic swap via .wip files for safe cert replacement
- Stage -> Activate -> Archive lifecycle with one-deep rollback
- Bootstrap supports user-supplied certs via CERT_FILE/KEY_FILE/CA_FILE
- CA bundle aggregates platform + tenant CAs, distributed to containers
- Vendor UI: Certificates page with upload, activate, restore, discard
- Stale tenant tracking (ca_applied_at) with restart banner
- Conditional TLS skip removal when CA bundle exists

Includes design spec, migration V012, service + controller tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 18:29:02 +02:00
hsiegeln
7e7a07470b feat: add restart server action for vendor and tenant
Some checks failed
CI / build (push) Failing after 36s
CI / docker (push) Has been skipped
Vendor: POST /api/vendor/tenants/{id}/restart (platform:admin scope)
Tenant: POST /api/tenant/server/restart (tenant:manage scope)

Both call TenantProvisioner.stop() then start() on the server + UI
containers. Restart button on vendor TenantDetailPage (Actions card)
and tenant TenantDashboardPage (Server card). Allowed in any status
including PROVISIONING.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 17:21:14 +02:00
hsiegeln
252c18bcff feat: async tenant provisioning with polling UX
Some checks failed
CI / build (push) Failing after 39s
CI / docker (push) Has been skipped
Backend: extract Docker provisioning into @Async method so the API
returns immediately with status=PROVISIONING. The tenant record, Logto
org, admin user, and license are created synchronously; container
provisioning, health check, license push, and OIDC config happen in a
background thread.

Frontend: navigate to tenant detail page immediately after creation.
Detail page polls every 3s while status=PROVISIONING and shows a
spinner indicator. Toast notification when provisioning completes.
Fixes #52.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 17:14:26 +02:00
hsiegeln
e559267f1e feat: replace tenant OIDC page with Enterprise SSO connector management
All checks were successful
CI / build (push) Successful in 1m3s
CI / docker (push) Successful in 46s
- Add LogtoManagementClient methods for SSO connector CRUD + org JIT
- Add TenantSsoService with tenant isolation (validates connector-org link)
- Add TenantSsoController at /api/tenant/sso with test endpoint
- Create SsoPage with provider selection, dynamic config form, test button
- Remove old OIDC config endpoints from tenant portal (server OIDC is
  now platform-managed, set during provisioning)
- Sidebar: OIDC -> SSO with Shield icon

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 15:48:51 +02:00
hsiegeln
8b94937d38 feat: add audit log viewing for vendor and tenant personas
All checks were successful
CI / build (push) Successful in 52s
CI / docker (push) Successful in 40s
Vendor sees all audit events with tenant filter at /vendor/audit.
Tenant admin sees only their own events at /tenant/audit.
Both support pagination, action/result filters, and text search.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 13:07:18 +02:00
hsiegeln
3b345881c6 fix: strip non-alphanumeric chars from admin username input
All checks were successful
CI / build (push) Successful in 53s
CI / docker (push) Successful in 41s
Logto usernames must match alphanumeric regex. The form now strips
invalid characters on input and shows a hint about the constraint.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 07:44:59 +02:00
hsiegeln
2dc75c4361 feat: create initial admin user + add vendor to new tenant orgs
All checks were successful
CI / build (push) Successful in 50s
CI / docker (push) Successful in 41s
When creating a tenant, the vendor can specify adminUsername +
adminPassword. The backend creates the user in Logto and assigns them
the owner org role. The vendor user is also auto-added to every new
org for support access.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 07:35:17 +02:00
hsiegeln
e6f2f17fa1 fix: use correct tier enum values (LOW/MID/HIGH/BUSINESS) in create form
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 22:39:23 +02:00
hsiegeln
9ecaf22f09 feat: tenant portal — all 5 pages (dashboard, license, OIDC, team, settings)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 22:30:06 +02:00
hsiegeln
d2f6b02a5f feat: vendor console — tenant list, create wizard, detail page
Implements Task 9: shared components (ServerStatusBadge, UsageIndicator,
platform.module.css, tierColor utility) and full vendor console pages
(VendorTenantsPage, CreateTenantPage, TenantDetailPage). Build passes cleanly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 22:30:06 +02:00
hsiegeln
bf3aa57274 feat: restructure frontend routes — vendor/tenant persona split
Splits the flat 3-page UI into /vendor/* (platform:admin) and /tenant/*
(all authenticated users) route trees, with stub pages, new API hooks,
updated Layout with persona-aware sidebar, and SpaController forwarding.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 22:29:59 +02:00
hsiegeln
af7abc3eac fix: add confirmation dialog before tenant context switch
All checks were successful
CI / build (push) Successful in 1m18s
CI / build (pull_request) Successful in 1m19s
CI / docker (pull_request) Has been skipped
CI / docker (push) Successful in 1m1s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 19:51:59 +02:00
hsiegeln
ce1655bba6 fix: add error states to OrgResolver, DashboardPage, AdminTenantsPage
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 19:51:28 +02:00
hsiegeln
798ec4850d fix: replace raw button with DS Button, add token copy-to-clipboard
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 19:51:03 +02:00
hsiegeln
7d4126ad4e fix: unify tier color mapping, fix feature badge colors
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 19:50:28 +02:00
hsiegeln
7c7d574aa7 fix: replace hardcoded text-white with DS variables, fix label/value layout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 19:49:32 +02:00
hsiegeln
5c4a84e64c fix: platform label/value spacing and neutral license badge colors
Disabled features on the license page now show 'Not included' with a
neutral (auto) badge color instead of 'Disabled' in error red, which
looked like an actionable error rather than a plan tier indicator.

Label/value spacing on DashboardPage already used flex justify-between
correctly — no change needed there.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 18:46:09 +02:00
hsiegeln
5938643632 feat: strip SaaS UI to vendor management dashboard
- Delete EnvironmentsPage, EnvironmentDetailPage, AppDetailPage
- Delete EnvironmentTree and DeploymentStatusBadge components
- Simplify DashboardPage to show tenant info, license status, server link
- Remove environment/app/deployment routes from router
- Remove environment section from sidebar, keep dashboard/license/platform
- Strip API hooks to tenant/license/me only
- Remove environment/app/deployment/observability types

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 00:03:01 +02:00
hsiegeln
8febdba533 feat: per-app resource limits, auto-slug, and polished create dialogs
Add per-app memory limit and CPU shares (stored on AppEntity, used by
DeploymentService with fallback to global defaults). JAR upload is now
optional at creation time. Both create modals show the computed slug in
the dialog title and use consistent Cancel-left/Action-right button
layout with inline styles to avoid Modal CSS conflicts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 14:53:57 +02:00
hsiegeln
c96faa4f3f fix: display username in UI, fix license limits key mismatch
All checks were successful
CI / build (push) Successful in 1m0s
CI / docker (push) Successful in 55s
- Read user profile from Logto ID token in OrgResolver, store in
  Zustand org store, display in sidebar footer and TopBar avatar
- Fix license limits showing "—" by aligning frontend LIMIT_LABELS
  keys with backend snake_case convention (max_agents, retention_days,
  max_environments)
- Bump @cameleer/design-system to v0.1.38 (font-size floor)
- Add dev volume mount for local UI hot-reload without image rebuild

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 12:20:40 +02:00
hsiegeln
e3baaeee84 fix: replace stale permission prop with scope in EnvironmentDetailPage
All checks were successful
CI / build (push) Successful in 39s
CI / docker (push) Successful in 38s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 14:13:37 +02:00
hsiegeln
9c2a1d27b7 feat: replace hardcoded permission map with direct OAuth2 scope checks
Remove role-to-permission mapping (usePermissions, RequirePermission) and replace
with direct scope reads from the Logto access token JWT. OrgResolver decodes the
scope claim after /api/me resolves and stores scopes in Zustand. RequireScope and
useScopes replace the old hooks/components across all pages.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 14:04:06 +02:00
hsiegeln
827e388349 feat: bootstrap 2 users, tenant, org-scoped tokens, platform admin UI
All checks were successful
CI / build (push) Successful in 40s
CI / docker (push) Successful in 39s
Bootstrap script now creates:
- SaaS Owner (admin/admin) with platform-admin role
- Tenant Admin (camel/camel) in Example Tenant org
- Traditional Web App for cameleer3-server OIDC
- DB records: tenant, default environment, license
- Configures cameleer3-server OIDC via its admin API
All credentials configurable via env vars.

Backend:
- Fix LogtoManagementClient resource URL (https://default.logto.app/api)
- Add getUserRoles/getUserOrganizations to LogtoManagementClient
- Add GET /api/me endpoint (user info, platform admin status, tenants)
- Add GET /api/tenants list-all for platform admins
- Remove insecure X-header forwarding from Traefik

Frontend:
- Org-scoped tokens: getAccessToken(resource, orgId) for tenant context
- OrgResolver component populates org store from /api/me
- useOrganization Zustand store (currentOrgId + currentTenantId)
- Platform admin sidebar section + AdminTenantsPage
- View Dashboard link points to cameleer3-server on port 8081

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 02:50:51 +02:00
hsiegeln
0843a33383 refactor: replace hand-rolled OIDC with @logto/react SDK
All checks were successful
CI / build (push) Successful in 38s
CI / docker (push) Successful in 48s
The hand-rolled OIDC flow (manual PKCE, token exchange, URL
construction) was fragile and accumulated multiple bugs. Replaced
with the official @logto/react SDK which handles PKCE, token
exchange, storage, and refresh automatically.

- Add @logto/react SDK dependency
- Add LogtoProvider with runtime config in main.tsx
- Add TokenSync component bridging SDK tokens to API client
- Add useAuth hook replacing Zustand auth store
- Simplify LoginPage to signIn(), CallbackPage to useHandleSignInCallback()
- Delete pkce.ts and auth-store.ts (replaced by SDK)
- Fix react-router-dom → react-router imports in page files
- All 17 React Query hooks unchanged (token provider pattern)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 01:17:47 +02:00
hsiegeln
f6d3627abc feat: add license page with tier features and limits
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 22:04:55 +02:00
hsiegeln
fe786790e1 feat: add app detail page with deploy, logs, and status
Full AppDetailPage with tabbed layout (Overview / Deployments / Logs),
current deployment status with auto-poll, action bar (deploy/stop/restart/re-upload/delete),
agent status card, routing card with edit modal, deployment history table,
and container log viewer with stream filter.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 22:03:29 +02:00
hsiegeln
5eac48ad72 feat: add environments list and environment detail pages
Implements EnvironmentsPage with DataTable, create modal, and row navigation,
and EnvironmentDetailPage with app list, inline rename, new app form with JAR
upload, and delete confirmation — all gated by RBAC permissions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 22:00:14 +02:00
hsiegeln
02019e9347 feat: add dashboard page with tenant overview and KPI stats
Replaces placeholder DashboardPage with a full implementation: tenant
name + tier badge, KPI strip (environments, total apps, running, stopped),
environment list with per-env app counts, and a recent deployments
placeholder. Uses EnvApps helper component to fetch per-environment app
data without violating hook rules.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 21:57:53 +02:00