204 Commits

Author SHA1 Message Date
keyhan 5ab7a6081e feat(logging): add ElasticsearchService for cluster deployment
Deploy and manage central Elasticsearch + Kibana via K8s API, with
health checks, credentials, and per-user log query helpers.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-14 12:41:56 +03:30
keyhan e7b5284dfc feat(logging): add Elasticsearch K8s stack manifest
Add namespace, secrets, Elasticsearch StatefulSet, Kibana deployment,
and Fluent Bit RBAC for the central logging stack.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-14 12:41:54 +03:30
keyhan 583c4c4c90 feat(deploy): add DNS verification with modal before proceeding to next step
Add standalone DNS check endpoint and verify DNS on Next click in the
deploy wizard (step 2). Show error modal with CNAME instructions when
DNS is not configured instead of disabling the Next button. Also make
the custom domain clickable in the app detail header.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-14 01:20:57 +03:30
keyhan e8be7fbf03 fix(deploy): move custom domain toggle from Review to Optional Services step
The custom domain option now lives in Step 2 alongside Redis, RabbitMQ,
and Elasticsearch, styled consistently as a toggle card. The Review step
remains a read-only summary.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-14 00:53:04 +03:30
keyhan 30ccfa4ee2 fix: update cost estimate on domain toggle, switch to English, fix toggle overflow
- Cost calculation now reads custom domain price from PlatformSetting
  as fallback when no CUSTOM_DOMAIN_ADDON pricing rule exists
- Convert all custom domain UI text from Persian to English
- Fix toggle switch overflow by adding shrink-0, min-w-0, and proper
  absolute positioning

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-14 00:49:20 +03:30
keyhan 435cf92817 feat: add custom domain support with SSL, DNS verification, and billing
Users can assign a custom domain to their app with automatic SSL via
cert-manager. Includes DNS verification flow (CNAME check), Persian
instructions, admin-configurable pricing via PlatformSetting, and
integration into the deploy wizard cost calculation.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-14 00:36:29 +03:30
keyhan d87b50c6a4 fix(build): use kubectl cp for reliable source upload and fix Python/Django CMD
- Replace k8s.Exec WebSocket with kubectl cp for binary file transfer to PVC
- Fix Python Dockerfile CMD: switch from JSON exec form to shell form to avoid
  invalid JSON escape sequences (\|) causing shell parse errors
- Fix Django Dockerfile CMD with same shell form approach
- Add retry logic for ECONNRESET during build job polling
- Update seed.ts default admin email to match actual database

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-14 00:10:04 +03:30
keyhan 9937ee457d fix: resolve critical deployment issues across Helm charts, Dockerfile, and K8s fallback
- Add helm/kubectl binaries and chart directory to backend Dockerfile
- Extend Helm templates for MongoDB/MariaDB database support (env vars, probes, ports)
- Add Redis and RabbitMQ Helm templates (deployment, service, secret, PVC)
- Add generic app-storage PVC and Fluent Bit sidecar with ES authentication
- Fix imagePullSecrets in K8s API fallback, prevent secret regeneration on redeploy
- Clean up Redis/RabbitMQ/FluentBit resources on app deletion without removing shared secrets
- Fix HelmService chartPath resolution for production Docker builds

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-13 19:16:07 +03:30
keyhan 38748b0827 add optinal apps 2026-04-23 15:26:49 +03:30
keyhan f481a57d8f fix(snapshots): add sleep after dump/archive for exec retrieval
- Job containers now sleep 120s after completing dump/archive
- This allows exec to retrieve files before container exits
- Wait for DUMP_DONE/ARCHIVE_DONE marker before attempting exec
- Cleanup job immediately after retrieval
- Fix Helm registry-pull-secret ownership conflict with lookup
2026-04-22 18:49:03 +03:30
keyhan b8355f1fc1 fix(helm): skip registry-pull-secret if already exists in namespace
- Use Helm lookup to check if secret exists before creating
- Add helm.sh/resource-policy: keep to prevent deletion
- Use pre-install hook to avoid ownership conflicts between releases
2026-04-22 18:17:31 +03:30
keyhan 0ba0ee3586 fix(k8s): restore direct K8s API deploy as fallback when Helm unavailable
- deployApplication now tries Helm first, falls back to direct K8s API
- Restored all private methods: ensureNamespace, applySecret, applyDeployment,
  applyService, applyIngress, applyWordPressPvc, deployDatabase, createDbSecret, createPVC
- Added ManifestContext interface
- Added DATABASE_URL env var, PGDATA, health probes for DB, ingressClassName
2026-04-22 17:59:59 +03:30
keyhan 5f77c07183 docs: rewrite ARCHITECTURE.md, README.md; add CHANGELOG and CONTRIBUTING
- ARCHITECTURE.md: all modules, Helm charts, billing/lifecycle flow, WordPress
- README.md: updated features, API endpoints, configuration, project structure
- CHANGELOG.md: full changelog for all unreleased changes
- CONTRIBUTING.md: commit conventions, documentation requirements, PR checklist
2026-04-22 16:45:30 +03:30
keyhan e10f9c5235 feat(frontend): lifecycle status, wallet balance, admin billing UI
- Wallet balance display in dashboard header
- Lifecycle status badges (color-coded) in apps list
- Plan expiry countdown column
- Admin apps: suspended/pending-deletion summary cards
- Admin billing: lifecycle settings management
- Updated TypeScript types for lifecycle and billing
2026-04-22 16:44:58 +03:30
keyhan 5f6eccc483 fix(apps): always attempt K8s cleanup on delete, cluster service fixes
- Delete endpoint no longer requires clusterId && latestImageTag
- Clusters: getDefault fallback logic, reassign apps on delete
- Unit tests for cluster default/delete logic
2026-04-22 16:44:43 +03:30
keyhan 8ca787d46e feat(lifecycle): add billing lifecycle with auto-suspend/delete
- New AppLifecycleService with cron-based scanner (60s interval)
- State machine: ACTIVE → SUSPENDED → PENDING_DELETION → DELETED
- Auto-renew hourly plans from wallet
- Admin-configurable grace periods via PlatformSettings table
- New LifecycleController (GET/PATCH /lifecycle/settings)
- PlatformSetting entity for runtime admin config
- BillingService: calculateCostForApp, deductWallet
- Application entity: planId, billingCycle, lifecycleStatus, planExpiresAt
- New enums: AppLifecycleStatus, BillingCycle
2026-04-22 16:44:20 +03:30
keyhan 0e408d1baa fix(build): runtime detection, WordPress support, Laravel inline configs
- detectRuntime reads parent directory not zip file itself
- Full WordPress Dockerfile with custom entrypoint for wp-content merging
- Laravel: inline nginx.conf and supervisord.conf generation
- composer.lock made optional
- ConfigMap cleanup in finally block
- Unit tests for WordPress build flow
2026-04-22 16:43:59 +03:30
keyhan c42557a86b feat(k8s): add HelmService and rewrite deleteApplication
- New HelmService wrapping Helm CLI (install/upgrade, rollback, uninstall, history, status)
- deleteApplication: helm uninstall + explicit cleanup of kept PVCs, secrets, TLS certs
- buildHelmValues: include registry.url for pull secret
- Add scaleDeployment for lifecycle suspend/resume
- Unit tests for buildHelmValues and HelmService
2026-04-22 16:43:45 +03:30
keyhan 1a0b04feec feat(helm): add cloudhost-app Helm chart for all runtimes
- deployment.yaml with imagePullSecrets, health probes, WordPress volumes
- db-deployment.yaml for PostgreSQL/MySQL with readiness/liveness probes
- ingress.yaml with cert-manager TLS
- registry-pull-secret.yaml for insecure registries
- PVCs and secrets with helm.sh/resource-policy: keep
- _helpers.tpl with shared template functions
- values.yaml with comprehensive defaults
2026-04-22 16:43:29 +03:30
keyhan 2dd882bf34 fix: move useQuery before early returns in DashboardLayout
The useQuery hook for unanswered ticket counts was called after
two conditional early returns (isLoading and not isAuthenticated),
violating React rules of hooks. Moved it before the returns
and added isAuthenticated to the enabled condition.
2026-04-08 13:13:20 +03:30
keyhan cb9320ee15 refactor: add useDebounce hook and replace manual debounce in admin search
- Create reusable useDebounce<T> hook in frontend/src/hooks/useDebounce.ts
- Replace manual setTimeout/clearTimeout + extra state in AdminAppsPage
  with clean useDebounce(search, 400) pattern
- Removes timer state and handleSearch wrapper function
2026-04-08 12:40:25 +03:30
keyhan ecedf9119e fix: resolve circular import errors in TypeORM entities
- Use string-based @OneToMany relations in parent entities (wallet, ticket, service-plan)
  to break circular import chains that confused VS Code TS language server
- Add .vscode/settings.json to suppress Tailwind CSS @tailwindcss unknownAtRules warnings
- Reorder imports in child entities for consistency
2026-04-08 12:30:15 +03:30
keyhan d01a0a5e8c feat: use Kubernetes revision-based rollback for instant app rollback
- Add revisionHistoryLimit: 10 and change-cause annotation to K8s deployments
- Add getDeploymentRevisions() to list ReplicaSet revision history
- Add rollbackDeploymentRevision() using K8s API (instant, no rebuild)
- Refactor snapshot rollback: use K8s revision for app, keep file-based DB/wp-content restore
- Add GET /snapshots/applications/:appId/revisions endpoint
- Add POST /snapshots/applications/:appId/revisions/:rev/rollback endpoint
- Add K8sRevision and K8sRevisionData types to frontend
- Redesign UI with two tabs: K8s Revisions (instant) + File Snapshots (full backup)
- K8s Revisions tab shows deployment history with one-click instant rollback
- File Snapshots tab retains download, DB restore, and wp-content restore
2026-04-08 02:26:51 +03:30
keyhan d3a5240528 feat: add snapshot/rollback system with download capability
- Add AppSnapshot entity with type (pre_deploy/manual), status tracking, and file paths
- Add SnapshotsService with create, capture, rollback, prune (max 10), and download logic
- Add SnapshotsController with REST endpoints for CRUD, rollback, and file downloads
- Add K8s methods: exportDatabaseDump, archiveWpContent, restoreWpContent
- Auto-create pre-deploy snapshots before each deployment for rollback safety
- Support downloading current live state (source, wp-content, database) without snapshots
- Add snapshot management UI in app detail page with create, rollback, download, delete
- Wire circular dependencies with forwardRef between Deployments and Snapshots modules
2026-04-08 01:55:00 +03:30
keyhan ac5278d73b feat: replace native confirm() dialogs with custom modal component
- Add ModalProvider context and useConfirm hook (confirm-modal.tsx)
- Support danger/warning/info variants with icons and colors
- Animated backdrop and dialog with CSS keyframes
- Accessible: aria-modal, role=dialog, ESC to close, auto-focus
- Replace all 6 native confirm() calls across dashboard pages
- Integrate ModalProvider in app providers
2026-04-07 23:38:55 +03:30
keyhan 5979b48a61 feat: WordPress migration support — upload existing site files
- Add two deployment modes for WordPress: Fresh Install vs Migrate Existing Site
- Fresh Install: vanilla WordPress from official image (existing behavior)
- Migrate: upload ZIP with wp-content/ (themes, plugins, uploads), wp-config.php, .htaccess
- Custom entrypoint merges staged wp-content into PVC on first container run
- Add init container for fresh WordPress builds (empty source context for Kaniko)
- Increase upload limit to 200MB for WordPress sites
- Add PHP upload limits (64MB) and memory config in WordPress Dockerfile
- Update deploy page review step to show WordPress mode info
- All UI in English
2026-04-07 23:12:25 +03:30
keyhan c2c6a32ae8 feat: billing v2 — runtime-based plans, English UI, payment flow
- ServicePlan now has 'runtime' field (nodejs/laravel/wordpress)
- Admin billing page: Application Type dropdown, English UI, Toman prices
- calculateCost filters active plans by matching runtime
- Wallet page: English UI, payment gateway integration (Pay Now button)
- Deploy page Review step: billing cycle selector (hourly/monthly/yearly),
  payment method choice (wallet or payment gateway), Pay & Deploy button
- Payment gateway endpoints: POST /billing/gateway/initiate + /verify
  (simulated — ready for Zarinpal/IDPay integration)
- Deploy requires payment: wallet deduction or gateway charge before deploy
2026-04-07 02:05:58 +03:30
keyhan 4974f88e8c feat: billing system — service plans, wallet, cost calculation
- Backend: billing module with ServicePlan, PricingRule, Wallet, WalletTransaction entities
- Admin can CRUD service plans with hourly/monthly/yearly billing cycles
- Each plan has flexible pricing rules (base_fee, cpu, memory, storage, db addon)
- Wallet system: auto-created per user, charge, deduct, refund, transaction history
- Cost calculation endpoint: cross-cycle conversion (hourly*720=monthly, monthly*12=yearly)
- Frontend: admin billing management page (/dashboard/admin/billing)
- Frontend: user wallet page with balance, quick-charge, transaction history
- Deploy page: cost breakdown shown in Review step (hourly/monthly/yearly)
- Navigation: Wallet link for users, Billing Plans link for admins
2026-04-07 01:45:45 +03:30
keyhan ac489c88d8 feat: dynamic database storage size with PVC expansion
- Add dbStorageSize column to Application entity (default: 1Gi)
- Add dbStorageSize to CreateApplicationDto, frontend types
- Use dynamic storage size in K8s deployDatabase instead of hardcoded 5Gi
- Deploy page: storage size selector with +/- buttons (min 1GB, max 100GB)
- Auto-suggest storage based on DB dump file size (3x dump size, min 1GB)
- Show DB storage in Review step
- App detail: Database Storage section with expand button
- GET /applications/:id/db-storage — read current PVC size from K8s
- PATCH /applications/:id/db-storage — expand PVC (only increase, no shrink)
- PVC resize uses JSON patch on K8s API
2026-04-07 01:28:01 +03:30
keyhan e775b57421 feat: move runtime selection to Step 0, hide source code for WordPress
- Move Application Type (Node.js/Laravel/WordPress) cards from Step 1 to Step 0 (Basic Info)
- Hide source code upload/git section when WordPress is selected
- Show WordPress info box explaining official Docker image usage
- Rename Step 1 heading to 'Versions & Database'
- Update Review step to show 'WordPress (Official Image)' as source
- Hide git branch/token review lines for WordPress
2026-04-07 00:47:42 +03:30
keyhan 762657f9ed feat: version selection for runtimes and databases
Backend:
- Add runtimeVersion, phpVersion, dbVersion columns to Application entity
- Add version fields to CreateApplicationDto with validation
- Node.js Dockerfile: use selected version (22/20/18/16) instead of hardcoded 20
- Laravel Dockerfile: use selected PHP version (8.4/8.3/8.2/8.1) instead of 8.3
- WordPress Dockerfile: use selected WP version (6.7/6.6/6.5/6.4) + PHP version
- K8s deployDatabase(): use selected DB version instead of hardcoded postgres:16/mysql:8.0
- K8s restoreDatabaseDump(): match DB image version for restore jobs
- Add dbVersion to ManifestContext interface

Frontend:
- Add runtimeVersion, phpVersion, dbVersion to Application and CreateApplicationDto
- Deploy page: Node.js version dropdown (22/20/18/16)
- Deploy page: Laravel PHP version dropdown (8.4/8.3/8.2/8.1)
- Deploy page: WordPress version + PHP version dropdowns
- Deploy page: PostgreSQL version dropdown (17/16/15/14)
- Deploy page: MySQL version dropdown (9.0/8.4/8.0/5.7)
- Deploy page: auto-set default versions on runtime/DB selection
- Review step: show selected versions
- App detail page: display runtime + DB versions in config and header
2026-04-06 23:38:23 +03:30
keyhan c411c5873e feat: add WordPress as runtime — Dockerfile, K8s env vars, wp-content PVC, frontend UI
Backend:
- Add WORDPRESS to AppRuntime enum
- Add wordpressDockerfile() using wordpress:6-php8.3-apache base image
  with custom theme/plugin/wp-content merge support
- Add WordPress-specific K8s env vars (WORDPRESS_DB_HOST, WORDPRESS_DB_USER,
  WORDPRESS_DB_PASSWORD, WORDPRESS_DB_NAME, WORDPRESS_TABLE_PREFIX)
- Create wp-content PersistentVolumeClaim (2Gi) for WordPress deployments
- Mount wp-content PVC in deployment container at /var/www/html/wp-content

Frontend:
- Add 'wordpress' to runtime type unions (Application, CreateApplicationDto)
- Add WordPress runtime card in deploy page (port 80, blue icon)
- Auto-select MySQL database when WordPress is chosen, disable other DB options
- Show Persian hint 'وردپرس به MySQL نیاز دارد' when WordPress selected
- Update all runtime icon colors across dashboard, apps, admin/apps pages
  to show blue-600 for WordPress
2026-04-06 23:13:39 +03:30
keyhan ea86acf2ab feat(ui): allow uploading DB dump at app creation — deploy page accepts optional SQL dump and uploads it after app creation 2026-04-06 22:53:47 +03:30
keyhan 9e3347cb71 feat: database management — custom credentials, dump upload/restore
Backend:
- Add dbUsername/dbPassword columns to Application entity
- Add optional DB credential fields to CreateApplicationDto
- Auto-generate dbPassword (crypto.randomBytes) and default dbUsername='appuser'
  when databaseType != 'none' on app creation
- Store both username and password in K8s DB secret (was password-only)
- Read DB_USER/POSTGRES_USER/MYSQL_USER from secretKeyRef instead of hardcoded
- New restoreDatabaseDump() in KubernetesService: creates K8s Job with
  psql/mysql client to restore uploaded SQL dump, waits for completion,
  returns logs
- New POST /applications/:id/db-upload endpoint with 500MB file limit

Frontend:
- Add dbUsername/dbPassword to Application and CreateApplicationDto types
- Deploy page: show username/password fields when database is selected,
  with generate-random-password button and show/hide toggle
- App detail page: new Database section with connection info (host, port,
  db name, username, password with copy-to-clipboard), SQL dump upload
  area with drag-and-drop, and restore output logs display

Security:
- Database remains ClusterIP only (no external exposure)
- Credentials stored in K8s Secrets (base64-encoded)
- Dump file uploaded as temporary K8s Secret, auto-cleaned after restore
2026-04-06 22:47:41 +03:30
keyhan 3c3e0e48fa refactor: migrate from react-hot-toast to react-toastify and replace all emoji icons with Lucide React
- Replaced react-hot-toast with react-toastify (ToastContainer in providers.tsx)
- Removed @heroicons/react dependency
- Added lucide-react for consistent SVG icon system
- Migrated all 18 frontend pages from emoji icons to Lucide components
- Updated sidebar navigation, login/register, dashboard, apps, deploy,
  tickets, admin users/clusters/pools pages
- All emoji indicators (status, runtime, actions) now use proper SVG icons
- Build passes with zero TypeScript errors
2026-04-06 17:20:56 +03:30
keyhan 5d281b85d6 feat: add status summary cards to All Applications page
- Show running, deploying, pending, stopped, failed counts as color-coded cards
- Cards displayed at top of All Applications page for quick status overview
- Skeleton loading state includes card placeholders
2026-04-06 14:44:57 +03:30
keyhan 8243ac7df2 feat: technical role can view all applications with search, separate /all route
- Add GET /applications/all endpoint for admin/technical with search by user name/email/ID
- GET /applications now always returns only the current user's apps (fix for technical seeing all apps)
- Technical role can view/edit/delete any application (same as admin)
- Add 'All Applications' page with search bar, user info columns, status badges
- Add 'All Applications' link to admin and technical sidebar navigation
- Add user relation to Application TypeScript interface
2026-04-06 14:43:46 +03:30
keyhan a64f8407b9 feat: unanswered ticket badges, dashboard counts, cross-department ticket creation
- Add /tickets/unanswered-counts API endpoint for staff/admin
- Show red badge with unanswered count on sidebar nav (staff tickets, admin tickets)
- Add summary cards (unanswered/answered/total) to staff tickets page
- Highlight unanswered count in admin tickets stats cards
- Staff can create tickets to OTHER departments only (not their own)
- Frontend hides own department from ticket creation dropdown
- Sidebar badges auto-refresh every 30 seconds
2026-04-06 13:55:15 +03:30
keyhan a1dbd0a85f fix: resolve TypeORM cascade bug in ticket reply/close/updateStatus
- Replace ticketsRepo.save(ticket) with ticketsRepo.update() to avoid
  cascade orphaning existing messages (SET ticketId=null violates NOT NULL)
- Fix reply(), close() in tickets.service.ts
- Fix updateStatus() in tickets.controller.ts using new updateTicketFields() method
- Add updateTicketFields() helper to TicketsService for safe partial updates
2026-04-06 13:34:48 +03:30
keyhan 3ab647be2e feat: ticketing system with technical/sales roles and department routing
Backend:
- Added TECHNICAL and SALES roles to UserRole enum
- Added TicketDepartment, TicketStatus, TicketPriority enums
- Created Ticket and TicketMessage entities with relationships
- Created TicketsModule with full CRUD service and controller
- Ticket routing: users create tickets to technical/sales departments
- Staff reply updates status (answered), user reply sets waiting
- Role-based access: technical staff sees technical tickets, sales sees sales tickets
- Admin sees all tickets with stats (total, open, avg response time)
- Updated access control: technical role has admin-level access (except role change)
- Sales role can view users and handle sales tickets
- Clusters controller: technical role can manage clusters/pools
- Users controller: technical/sales can view users, only admin changes roles

Frontend:
- New user ticket pages: list (with create form) + detail (chat-style messages)
- Staff ticket panel: filtered by department with status filters
- Admin all-tickets page with statistics dashboard and department/status filters
- Updated sidebar: role-based nav items (admin/technical/sales sections)
- Role badges in header for technical (blue) and sales (green)
- Admin users page: new roles in dropdowns, role change restricted to admin only
- Deploy page: technical role gets cluster selection access like admin
2026-04-06 12:36:41 +03:30
keyhan 4fd102468e security: restrict cluster/pool selection to admin users only
Backend:
- ApplicationsService.create() now accepts userRole parameter
- Non-admin users have clusterId/poolId stripped automatically
- Logs warning when non-admin attempts manual cluster selection

Frontend:
- Deploy wizard hides cluster assignment mode selector for non-admin users
- Non-admin users see a simple 'Default Cluster' info box instead
- Cluster/pool API queries only execute for admin users (enabled: isAdmin)
- Review step shows 'Default Cluster' for non-admin regardless of form state
2026-04-06 11:36:58 +03:30
keyhan 4853fe3020 perf: add timing logs and faster polling for build jobs
Added detailed timing logs for build pipeline stages (secret creation,
job submission, job completion). Reduced polling interval from 5s to 3s.
2026-04-06 11:29:19 +03:30
keyhan e646ac3689 fix: switch health probes from HTTP /health to TCP socket check
Most user apps (e.g. Next.js) don't have a /health endpoint, causing
liveness/readiness probes to fail with 404 and crash-loop the pods.
TCP socket probes just check if the port is open, which works universally.
2026-04-06 01:36:42 +03:30
keyhan dfdffca7ef fix: use npm install instead of npm ci for more resilient builds
npm ci fails when package-lock.json is out of sync with package.json,
which is common with GitHub-downloaded ZIPs. Switched to npm install
with --legacy-peer-deps flag for maximum compatibility.
2026-04-06 01:00:25 +03:30
keyhan 2be3c50455 fix: auto-flatten single subfolder in uploaded ZIP files for build context
GitHub-downloaded ZIPs contain files inside a subfolder (e.g., repo-main/).
The build init container now detects this pattern and flattens the contents
to the workspace root so Kaniko can find package.json and other files.
2026-04-06 00:50:20 +03:30
keyhan c8e66f6771 feat: comprehensive UI polish with responsive design, animations, and modern styling
- Rewrite globals.css with professional utility classes (btn-primary/secondary/danger/ghost, input-field, card/card-hover, badge system, stat-card, skeleton, page-header, animations)
- Responsive dashboard layout with mobile hamburger menu, slide-out sidebar, backdrop overlay
- Polish login/register pages with gradient backgrounds, slide-up animations, loading spinners
- Dashboard home with stat cards grid (2-col mobile, 4-col desktop), skeleton loading, empty states
- Apps list with desktop table + mobile card views, proper badges
- Deploy wizard with responsive step indicator (checkmarks, progress line), mobile-friendly forms
- App detail page with responsive header/action buttons, improved logs tabs, resource scaling
- Admin users page with desktop table + mobile cards, skeleton loading
- Admin clusters page with responsive layout, animated resource panel
- Admin pools page with responsive form grids, improved pool cards
- Consistent rounded-2xl cards, rounded-xl buttons/inputs, active:scale feedback throughout
2026-04-05 18:34:27 +03:30
keyhan e7d70f87cd feat: show build logs alongside pod logs in app detail page 2026-04-05 17:56:48 +03:30
keyhan e97af36740 feat: admin user management (create/search/role) and cluster resource monitoring
- Add POST /users endpoint for admin to create users with hashed passwords
- Add GET /users?search= with ILike search on email/firstName/lastName
- Add PATCH /users/:id/role for role assignment (user/admin)
- Return appCount per user in the users list
- Add GET /clusters/:id/resources for node, CPU, memory, pod monitoring
- Parse K8s node capacity/allocatable with CPU millicores and memory MiB helpers
- Frontend: admin users page with search bar, create form, role dropdown, app count
- Frontend: cluster resource panel with nodes table, CPU/memory bars, summary cards
2026-04-05 17:48:15 +03:30
keyhan 2621dc0cc6 feat: multi-cluster management with pool-based load balancing
- Add ClusterPool entity for grouping clusters into named pools
- Support 3 deployment modes: manual cluster, pool load-balanced, default fallback
- Pool strategies: least-apps (fewest deployed apps) and round-robin
- Add pool CRUD API endpoints (admin) and public pool listing
- Frontend deploy page: 3-mode cluster selector (Default/Manual/Pool)
- Frontend app detail: shows assigned cluster and pool info
- Admin pools management page with cluster selection and strategy picker
- Application entity extended with poolId field
2026-04-05 17:37:05 +03:30
keyhan 1b1ccfc18f feat: support private git repositories with token auth
- Entity: added gitToken and gitBranch columns to Application
- DTO: added gitToken and gitBranch fields to Create/Update DTOs
- Build pipeline: git-clone init container now injects token into
  HTTPS URL for private repo authentication (GitHub PAT, GitLab token, etc.)
- Build pipeline: supports cloning specific branch (default: main)
- Frontend deploy page: added Access Token (password field) and Branch
  inputs when Git Repository source is selected
- Frontend deploy page: Review step shows branch and token status
- Frontend app detail: shows branch badge and 🔑 Private indicator
  when git credentials are configured
- Works with: GitHub, GitLab, Bitbucket, any HTTPS-based git host
2026-04-05 16:48:35 +03:30