Skip to content

feat: Phase 5 admin features - deployment management UI#23

Merged
LahkLeKey merged 8 commits into
mainfrom
feature/phase5-admin-features
Jul 19, 2026
Merged

feat: Phase 5 admin features - deployment management UI#23
LahkLeKey merged 8 commits into
mainfrom
feature/phase5-admin-features

Conversation

@LahkLeKey

Copy link
Copy Markdown
Owner

Summary

Adds comprehensive deployment management features to the Kloak admin UI.

Features

Delete Deployment

  • Confirmation dialog prevents accidental deletion
  • Redirects to deployments list after deletion
  • Error handling with user-visible messages

Deployment Creation Wizard

  • 3-step form: Basic Information → Cloud Provider Settings → Review & Confirm
  • Supports AWS, Google Cloud, and Microsoft Azure
  • Field validation at each step before progression
  • Progress indicator, back/next navigation, loading states
  • Route: /deployments/new

Deployment Status Transitions

  • Finite state machine enforcing valid lifecycle transitions:
    draft → provisioning → healthy → drifted → repairing → failed → decommissioned
  • Invalid transitions rejected at the API layer with descriptive error messages
  • decommissioned is a terminal state (no further transitions)
  • Context-aware dropdown showing only valid next states
  • Confirmation dialogs before applying transitions
  • Error banner with dismiss button for failed transitions

Tests

51 tests, 0 failures:

  • 10 status transition tests (valid paths, invalid transitions, terminal state, timestamp updates)
  • 4 deployment CRUD tests
  • All prior tests preserved without regression

Files

New:

  • src/core/deployments.test.ts — CRUD + status transition tests
  • src/core/auth.test.ts — User auth tests
  • src/web/src/utils/statusTransitions.ts — State machine utilities
  • src/web/src/pages/DeploymentCreationPage.tsx + CSS
  • Various page files (LoginPage, SignupPage, AccountPage, DocsPage)

Modified:

  • src/core/index.ts — State machine + markDeploymentStatus validation
  • src/web/src/api.ts — New API methods
  • src/web/src/pages/DeploymentDetailPage.tsx — Status transition UI, error banner
  • src/web/src/pages/DeploymentDetailPage.module.css — Dark-theme dropdown styling
  • src/web/src/pages/DeploymentsPage.tsx — Create Deployment button

- Biome 2.5.3: TypeScript/JavaScript linting and formatting
- biome.json: Configure Biome with recommended rules, single quotes, 100 char lines
- npm scripts: lint, lint:check, format, format:check commands
- package.json: Fixed all linting errors (import sorting, unused imports, literal keys)
- Dockerfile: Add development stage with node --watch for live reload
- docker-compose.yml: Use development target with source volume mounts
- docker-compose.prod.yml: Production override with health checks
- All 18 tests passing
- All linting issues resolved (16 warnings only)
Use environment variables from docker-compose or shell instead of npm script
- README.md: Development quick start and commands
- docs/DEVELOPMENT.md: Detailed development guide with:
  - Prerequisites and quick start
  - Docker setup and management
  - Biome linting workflow
  - TypeScript configuration and imports
  - Database development guide
  - Testing instructions
  - Architecture overview
  - Common tasks
  - Troubleshooting
- Update package.json scripts to use bun (bun test, bun run dev, etc.)
- Update Dockerfile to use bun instead of node
- Update docker-compose.yml comments (already uses correct targets)
- Update README.md and DEVELOPMENT.md with bun commands
- Fix remaining `as any` type casts in keycloak/index.test.ts
- Add DeploymentId import to keycloak/index.test.ts
- Auto-fix formatting issues with biome

All 18 tests pass with bun
All linting checks pass
Dev server starts successfully with `bun run dev`
…, Playwright e2e

Domain model:
- ExternalApp: registers a domain/SaaS app, provisions a Keycloak client
- AuthFlow: maps a domain to an app with configurable OAuth flow type
- Status lifecycle: pending -> active -> suspended / revoked
- Both added to shared/models.ts, core interfaces, InMemoryDeploymentRepository

API (9 new endpoints):
- POST/GET /deployments/:id/apps
- GET/PUT /apps/:appId, PUT /apps/:appId/status
- POST/GET /deployments/:id/flows
- GET /flows/:flowId

Unit tests (16 new, 34 total passing):
- src/core/external-apps.test.ts - domain logic (8 tests)
- src/admin-ui/external-apps.handler.test.ts - HTTP handler (8 tests)

React frontend (src/web/):
- Vite + React 18 + react-router-dom + CSS Modules
- DeploymentsPage, DeploymentDetailPage, RegisterAppPage
- Components: AppCard, StatusBadge, AuthFlowRow, RegisterAppForm
- API client (src/web/src/api.ts) with proxy to backend

Storybook:
- AppCard.stories.tsx - 5 stories (active/pending/suspended/revoked/multi-redirect)
- StatusBadge.stories.tsx - all 11 statuses + AllStatuses composite
- RegisterAppForm.stories.tsx - 5 states (empty/prefilled/loading/error/multi-env)
- AuthFlowRow.stories.tsx - 5 stories including panel composite

Playwright e2e (e2e/):
- deployments-list.spec.ts - list view and navigation
- register-app.spec.ts - full register app workflow
- app-lifecycle.spec.ts - activate/suspend/revoke transitions
- auth-flows.spec.ts - flow display and multi-flow scenarios

Scripts: bun run web, bun run storybook, bun run test:e2e
- Add deployment deletion with confirmation dialog and redirect
- Add 3-step deployment creation wizard (Basic Info → Cloud Provider → Review)
- Add deployment status transitions with state machine validation
  - States: draft → provisioning → healthy → drifted → repairing → failed → decommissioned
  - Enforces valid transitions at API layer with descriptive errors
  - Change-status dropdown shows only context-appropriate transitions
  - Confirmation dialogs, loading states, and dismissable error banners
- Add frontend utilities: getAvailableTransitions(), canTransitionTo(), getStatusLabel()
- Add API client methods: createDeployment(), deleteDeployment(), updateDeploymentStatus()
- Add comprehensive test coverage (51 tests total, 0 failures)
  - 10 status transition tests covering all state paths and error cases
  - CRUD tests for deployment lifecycle
- Fix status dropdown dark theme styling (dark surface background with light text)
Copilot AI review requested due to automatic review settings July 14, 2026 06:31

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a React/Vite-based admin UI for managing Kloak deployments (create/delete, status transitions, and external app + auth-flow management), and expands the backend HTTP API + core domain model to support those workflows, along with new tooling (Bun/Biome) and Playwright e2e tests.

Changes:

  • Introduces a new src/web frontend (Vite + React Router) with pages/components for deployments, deployment creation, deployment detail, and external app registration.
  • Expands backend API routes and core model to support external apps/auth flows and user auth/account linking, plus adds tests.
  • Adds Playwright e2e coverage and updates repo tooling/scripts (Bun, Biome, Docker adjustments).

Reviewed changes

Copilot reviewed 80 out of 84 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
src/web/vite.config.ts Adds Vite dev server + /api proxy configuration.
src/web/tsconfig.tsbuildinfo Adds TS build info artifact (should not be committed).
src/web/tsconfig.json Adds TypeScript config for the web package.
src/web/src/utils/statusTransitions.ts Adds deployment status transition helpers for UI.
src/web/src/stories/StatusBadge.stories.tsx Storybook stories for StatusBadge.
src/web/src/stories/RegisterAppForm.stories.tsx Storybook stories for RegisterAppForm.
src/web/src/stories/AuthFlowRow.stories.tsx Storybook stories for AuthFlowRow.
src/web/src/stories/AppCard.stories.tsx Storybook stories for AppCard.
src/web/src/pages/SignupPage.tsx Adds signup UI flow (currently mismatched with backend contract).
src/web/src/pages/SignupPage.module.css Styles for signup page.
src/web/src/pages/RegisterAppPage.tsx Adds “register external app” page wired to API.
src/web/src/pages/RegisterAppPage.module.css Styles for register app page.
src/web/src/pages/LoginPage.tsx Adds login UI flow (currently mismatched with backend/proxy expectations).
src/web/src/pages/LoginPage.module.css Styles for login page.
src/web/src/pages/DocsPage.module.css Styles for docs page.
src/web/src/pages/DeploymentsPage.tsx Adds deployments list UI + “Create Deployment” CTA.
src/web/src/pages/DeploymentsPage.module.css Styles for deployments list.
src/web/src/pages/DeploymentDetailPage.tsx Adds deployment detail UI incl. delete + status transitions + apps/flows panels.
src/web/src/pages/DeploymentDetailPage.module.css Styles for deployment detail page incl. status dropdown and error banner.
src/web/src/pages/DeploymentCreationPage.tsx Adds 3-step deployment creation wizard.
src/web/src/pages/DeploymentCreationPage.module.css Styles for deployment creation wizard.
src/web/src/pages/AccountPage.tsx Adds account linking UI (GitHub/Gmail) + linked account management.
src/web/src/pages/AccountPage.module.css Styles for account page.
src/web/src/main.tsx Frontend bootstrap w/ React Router.
src/web/src/index.css Adds global dark theme tokens and base styles.
src/web/src/components/StatusBadge.tsx Adds shared status badge component for app/deployment statuses.
src/web/src/components/StatusBadge.module.css Styles for status badge variants.
src/web/src/components/RegisterAppForm.tsx Adds register-app form component + parsing helper.
src/web/src/components/RegisterAppForm.module.css Styles for register-app form.
src/web/src/components/Layout.tsx Adds app layout shell (header/nav + main).
src/web/src/components/Layout.module.css Styles for layout shell.
src/web/src/components/AuthFlowRow.tsx Adds auth flow row UI component.
src/web/src/components/AuthFlowRow.module.css Styles for auth flow row.
src/web/src/components/AppCard.tsx Adds external app card UI w/ status actions + copy client id.
src/web/src/components/AppCard.module.css Styles for app card.
src/web/src/App.tsx Defines web routes for the new UI.
src/web/src/api.ts Adds web API client + shared types (currently has TS syntax + 204 handling issues).
src/web/package.json Adds web workspace scripts/deps (vite, storybook, vitest).
src/web/index.html Adds Vite HTML entrypoint.
src/web/.storybook/preview.ts Storybook preview globals (dark backgrounds).
src/web/.storybook/main.ts Storybook config for Vite/React.
src/sync/index.ts Formatting/refactor updates.
src/sync/index.test.ts Formatting updates for sync tests.
src/sync/fakes.ts Formatting updates for sync fakes.
src/shared/models.ts Extends domain model for external apps/auth flows/users (currently has TS union syntax errors).
src/orchestrator/index.ts Formatting/refactor updates.
src/keycloak/keycloak.ts Export ordering tweak.
src/keycloak/index.ts Formatting/refactor updates.
src/keycloak/index.test.ts Refactor test typing/formatting updates.
src/infrastructure/index.ts Formatting updates.
src/infrastructure/index.test.ts Formatting updates.
src/infrastructure/in-memory.ts Formatting updates.
src/index.ts Reorders exports.
src/database/sql-repository.ts Import cleanup/formatting.
src/database/migrate.ts Formatting updates.
src/database/index.ts Export ordering tweak.
src/core/external-apps.test.ts Adds core tests for external apps + auth flows.
src/core/auth.test.ts Adds core auth tests (currently has broken import paths/extensions).
src/core/deployments.test.ts Adds deployments CRUD/status tests (imports missing explicit .ts extensions).
src/aws/index.ts AWS provisioner code formatting/cleanup.
src/aws/index.test.ts Test refactor/cleanup.
src/aws/aws.ts Export ordering tweak.
src/admin-ui/server.ts Adds route pattern matching for new endpoints (currently missing auth/user/oauth patterns).
src/admin-ui/handler.ts Adds handlers for apps/flows/auth/users/oauth endpoints.
src/admin-ui/handler.test.ts Updates handler tests for new behavior/formatting.
src/admin-ui/external-apps.handler.test.ts Adds handler tests for apps/flows endpoints.
src/admin-ui/cli.ts Formatting updates.
README.md Adds development/docs sections and commands.
playwright.config.ts Adds Playwright e2e config with webServer setup.
package.json Switches scripts/tooling to Bun/Biome/Playwright; adds deps.
e2e/register-app.spec.ts Adds e2e tests for registering external apps.
e2e/helpers.ts Adds shared e2e helpers that call the API server.
e2e/deployments-list.spec.ts Adds e2e tests for deployments list navigation.
e2e/auth-flows.spec.ts Adds e2e tests for auth flows display.
e2e/app-lifecycle.spec.ts Adds e2e tests for app status transitions.
docs/DEVELOPMENT.md Adds detailed development guide (includes import-extension convention).
Dockerfile Moves to Bun-based images; adds dev/prod stages and Bun healthcheck.
docker-compose.yml Uses development target + mounts src for live reload.
docker-compose.prod.yml Adds production override compose (healthcheck currently uses node).
biome.json Adds Biome config for formatting/linting.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/web/src/api.ts Outdated
Comment on lines +11 to +12
status:|'draft'|'provisioning'|'healthy'|'drifted'|'repairing'|'failed'|
'decommissioned';
Comment thread src/shared/models.ts Outdated
Comment thread src/shared/models.ts Outdated
Comment thread src/web/src/api.ts
Comment on lines +71 to +76
if (!res.ok) {
const err = await res.json().catch(() => ({error: res.statusText}));
throw new Error((err as {error: string}).error ?? res.statusText);
}
return res.json() as Promise<T>;
}
Comment thread src/admin-ui/server.ts
Comment on lines +33 to 44
function findRoutePattern(path: string): string | null {
const patterns = [
'/deployments/:id/versions',
'/deployments/:id/status',
'/deployments/:id/apps',
'/deployments/:id/flows',
'/deployments/:id',
'/deployments',
'/apps/:appId/status',
'/apps/:appId',
'/flows/:flowId',
];
Comment thread src/core/deployments.test.ts Outdated
Comment on lines +3 to +6
import type {CreateDeploymentInput, DeploymentId, DeploymentRepository} from '../shared';

import {CoreService, InMemoryDeploymentRepository} from './index';

Comment thread src/web/src/pages/SignupPage.tsx Outdated
Comment on lines +46 to +64
const response = await fetch('/auth/signup', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: form.email,
password: form.password,
displayName: form.displayName || undefined,
}),
});

if (!response.ok) {
const body = await response.text();
throw new Error(body || 'Signup failed');
}

const { user, token } = (await response.json()) as {
user: { id: string; email: string; deploymentId: string };
token: string;
};
Comment thread src/web/src/pages/LoginPage.tsx Outdated
Comment on lines +28 to +42
const response = await fetch('/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(form),
});

if (!response.ok) {
const body = await response.text();
throw new Error(body || 'Login failed');
}

const { user, token } = (await response.json()) as {
user: { id: string; email: string; deploymentId: string };
token: string;
};
Comment thread docker-compose.prod.yml Outdated
Comment thread src/web/tsconfig.tsbuildinfo Outdated
@@ -0,0 +1 @@
{"root":["./src/app.tsx","./src/api.ts","./src/main.tsx","./src/components/appcard.tsx","./src/components/authflowrow.tsx","./src/components/layout.tsx","./src/components/registerappform.tsx","./src/components/statusbadge.tsx","./src/pages/accountpage.tsx","./src/pages/deploymentcreationpage.tsx","./src/pages/deploymentdetailpage.tsx","./src/pages/deploymentspage.tsx","./src/pages/docspage.tsx","./src/pages/loginpage.tsx","./src/pages/registerapppage.tsx","./src/pages/signuppage.tsx","./src/stories/appcard.stories.tsx","./src/stories/authflowrow.stories.tsx","./src/stories/registerappform.stories.tsx","./src/stories/statusbadge.stories.tsx","./src/utils/statustransitions.ts"],"errors":true,"version":"5.9.3"} No newline at end of file
- Auto-fix Biome formatting across all modified files
- Remove redeclared local DeploymentStatus type (conflicts with shared import)
- Remove unused oauthProviders private field from InMemoryDeploymentRepository
- Replace non-null assertion with safe null-check in OAuth callback handler
- Fix 204 No Content handling in api.ts (avoid calling res.json() on empty body)
- Add missing auth/user/oauth route patterns to server.ts findRoutePattern()
- Add explicit .ts extensions to imports in deployments.test.ts and auth.test.ts
- Fix broken import path in auth.test.ts (../../../shared -> ../shared/index.ts)
- Update CI workflow to use Bun instead of npm (setup-bun, bun install, bun test)
- Add lint check step to CI (biome check)
- Fix docker-compose.prod.yml healthcheck to use bun instead of node
- Add *.tsbuildinfo to .gitignore
- Fix LoginPage and SignupPage fetch paths to use /api prefix for Vite proxy
Copilot AI review requested due to automatic review settings July 14, 2026 06:41

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 81 out of 86 changed files in this pull request and generated no new comments.

- Fix invalid Deployment status union type syntax in web API model
- Add CSS module declaration for web TypeScript builds
- Remove tracked tsbuildinfo artifact from repository
- Align login/signup forms with backend contract by including deploymentId
- Keep signup response handling aligned with user-only response payload
- Fix optimistic revoke rollback to restore previous app status
- Expand node HTTP adapter route table to include auth/user/oauth/app/flow endpoints
- Apply biome formatting updates in touched files
Copilot AI review requested due to automatic review settings July 19, 2026 01:24
@LahkLeKey
LahkLeKey merged commit 4895829 into main Jul 19, 2026
2 checks passed
@LahkLeKey
LahkLeKey deleted the feature/phase5-admin-features branch July 19, 2026 01:25

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 80 out of 86 changed files in this pull request and generated 8 comments.

Comment thread src/admin-ui/server.ts
Comment on lines +126 to 128
const headers: Record<string, string> = { 'Content-Type': 'application/json' };
res.writeHead(httpResponse.status, headers);
res.end(JSON.stringify(httpResponse.body));
Comment on lines +41 to +43
const response = await fetch(`/users/${userId}`, {
headers: { Authorization: `Bearer ${token}` },
});
Comment on lines +66 to +71
const response = await fetch(`/users/${user.id}/link-account/${provider}`, {
method: 'DELETE',
headers: {
Authorization: `Bearer ${localStorage.getItem('authToken')}`,
},
});
Comment on lines +97 to +107
const response = await fetch(`/oauth/authorize/${provider}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${localStorage.getItem('authToken')}`,
},
body: JSON.stringify({
deploymentId,
redirectUri,
}),
});
Comment thread docs/DEVELOPMENT.md
Comment on lines +117 to +130
### Commands

```bash
# Check for issues (don't fix)
npm run lint:check

# Fix issues automatically
npm run lint

# Format code
npm run format

# Check formatting
npm run format:check
Comment thread docs/DEVELOPMENT.md
Comment on lines +143 to +145
npm run lint # Fix issues
npm test # Verify tests pass
npm run lint:check # Double-check linting
Comment thread docs/DEVELOPMENT.md
Comment on lines +150 to +153
Kloak uses TypeScript with `--experimental-transform-types`:
- Direct TypeScript execution (no build step)
- `.ts` files run natively on Node.js 25+
- Explicit file extensions required in imports (`./index.ts` not `./index`)
Comment thread src/core/index.ts
Comment on lines +344 to +349
if (!canTransitionTo(deployment.status, status)) {
throw new Error(
`Cannot transition from ${deployment.status} to ${status}. ` +
`Valid transitions: ${getAvailableTransitions(deployment.status).join(', ')}`
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants