Commit Graph

35 Commits

Author SHA1 Message Date
keyhan 8d1855b89c Detect and validate app runtime from uploaded archives.
Reject zip uploads when the selected runtime does not match archive contents, and re-validate before Kaniko builds to fail fast instead of producing the wrong Dockerfile.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-30 00:27:03 +03:30
keyhan 837f0fa63f Harden platform security, reliability, and CI after full audit.
Close deployment IDOR and gate stub payment endpoints, add production
secret validation, health probes, Redis-backed build progress, GitHub
Actions CI, expanded tests, billing/k8s refactors, and ops runbooks.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 20:59:49 +03:30
keyhan bd14eb2daa feat(blog): real bilingual blog with covers, list & article pages
- Add blog content module (posts.ts): 4 platform-focused articles (deploy,
  managed databases, custom domain + SSL, replicas & cost) in fa/en with
  tag, date, reading time, excerpt and structured body.
- Self-contained gradient cover art (BlogCover) — no external images, themed
  per topic with the brand cloud motif.
- Landing blog section now shows the 3 latest posts with covers, linking to
  article pages; "view all" links to /blog.
- Dedicated /blog list page and /blog/[slug] article page over the shared
  cloud-sky shell (BlogShell), with a not-found state.
- Remove the now-redundant "Learn" header nav item (blog covers getting
  started) and drop its orphan section anchor.
- i18n: blog minRead/notFound/backToBlog strings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 13:35:02 +03:30
keyhan f89c3de826 feat(landing): glass header nav with side drawer + blog section
- Header: full glassmorphism navigation (services, pricing, estimator, learn,
  blog). Desktop shows an inline glass pill; mobile opens a side drawer that
  slides in from the inline-start edge (right in RTL, left in LTR) over a
  blurred backdrop.
- Nav links smooth-scroll via the shared Lenis instance (exposed through
  scroll-store: setLenis/scrollToId), with an 80px offset under the header.
- "Learn" links to the existing how-it-works steps (id="learn"); add a
  lightweight Blog teaser section (id="blog", "coming soon" cards).
- i18n: fa/en strings for nav and blog.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 11:36:27 +03:30
keyhan f7974dd382 feat(landing,billing): public pricing, global discount, services bar & estimator
Backend
- Add platform-wide global discount (platform_settings: global_discount_percent),
  applied centrally in PricingCatalogService.computeTotalsFromDb so it reaches
  every real charge (previews, deploys, renewals, upgrades, invoices). Admin
  GET/PATCH /billing/settings/global-discount.
- Add unauthenticated PublicPricingController (catalog + calculate) for the
  public landing page, returning gross/net and the discount percentage.
- Bill application replicas by the user-selected footprint: app CPU/RAM/storage
  now all scale by replica count; the single-replica database stays unscaled.

Frontend
- Landing: Services bar (PaaS active, DBaaS, KaaS/LaaS "coming soon" with
  expandable runtime/database menus), transparent Pricing section (per-resource
  rate cards with cycle toggle + discount strikethrough), and a cost Estimator
  ("estimate your package").
- Optional services and the database are priced like runtimes: the estimator
  lets users pick their CPU/RAM/storage (and DB type) so the cost scales by need.
- Admin billing: global-discount editor.
- i18n: fa/en strings for services, pricing, estimator and global discount.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 23:44:30 +03:30
keyhan 49726f1dfd feat(billing): add percentage discount coupons
Admins can create coupon codes that discount specific services (app
runtimes, optional services, managed products, custom-domain addon, or
all) and restrict them to specific users or make them public, with total
and per-user usage caps and an active date window.

Coupons apply in deploy, renewal, and upgrade flows: cost-breakdown lines
are tagged with a service key, the eligible portion is discounted and
capped to the payable amount, the invoice records discountAmount/
discountCode, and the redemption is recorded once when the invoice is
fully paid (covering wallet, gateway, and mixed payments).

- Discount + DiscountRedemption entities; invoice discount columns
- DiscountService (CRUD, validation, redemption) + admin/validate API
- Idempotent schema bootstrap on init so production (synchronize off)
  provisions the tables/columns without a migration runner
- Admin discounts UI, coupon entry in deploy/renewal, invoice discount line
- fa/en strings; discount.service unit spec

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 11:48:45 +03:30
keyhan 7438b44120 feat(invoices): show customer name/phone, align meta column, totals left, JPEG
- Invoice PDF now shows the customer's full name and a phone row (sourced from
  the auth store for the user page, invoice.user for admin) instead of just email.
- Left-align all meta values into a single clean column (unicode-bidi:plaintext
  so Persian names stay RTL while phone/dates read LTR).
- Move the totals box to the left side of the page.
- Rasterize as JPEG (q0.9) instead of PNG to keep the file small (~130KB).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 00:41:17 +03:30
keyhan 4d64fda227 feat(invoices): Persian line items + elegant client-side PDF download
- Translate persisted English invoice line labels/descriptions/reasons to
  Persian at display time (new lib/invoice-labels.ts), covering both new and
  historical invoices without a data migration.
- Generate a styled, RTL Persian invoice PDF on the client (lib/invoice-pdf.ts)
  with the Abrban logo, line-item table and totals, via html2canvas + jsPDF.
- Wire both the user and admin invoice pages to the translator and new download.
- Add invoices.pdf dictionary keys (fa/en).
- Remove the now-dead ASCII-only backend PDF endpoints and generateInvoicePdf.
- Add frontend/.npmrc (npmmirror registry + high timeouts) for Iran-network installs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 19:59:22 +03:30
keyhan 78ed95b29b feat(landing): restructure footer with enamad seal, contact info, and logo
- Remove login/register/dashboard nav links from the footer
- Add Enamad trust seal on the left
- Center the contact block (title, phone, email) in the middle
- Move the logo to the right side
- Place the copyright line at the bottom, centered
- Update copyright text and add contact strings (fa/en)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 19:55:37 +03:30
keyhan 04b2f040e0 feat(frontend): show active app domain with click-to-copy
Surface the domain the app is actually reachable on right now (verified
custom domain, else the platform subdomain) as a single "Application
Domain" field. Clicking it copies the address to the clipboard and shows
a "Copied" toast. Centralizes the active-domain logic so the page header
and the verified-custom-domain block stay in sync, and always loads
domain-info so the platform host is correct even without a custom domain.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 14:31:45 +03:30
keyhan fd38f5659f feat(admin): login-as-user impersonation with audit log
Let super admins act as a user from the user detail dashboard for
support/debugging ("full with guardrails", audit-only).

Backend: AuthService.impersonate issues a short-lived token for the
target carrying an `act` claim (acting admin); refresh preserves it and
JwtStrategy surfaces `impersonatedBy`. Guardrails: cannot impersonate an
admin or a deactivated account; new ImpersonationGuard blocks sensitive
self-service (change own password/phone) while impersonating. New
AuditLog entity records impersonation start/stop (admin, target, ip,
time); admin endpoints POST users/:id/impersonate + .../impersonation/
stop and GET users/:id/audit.

Frontend: lib/impersonation swaps admin/impersonation tokens in
localStorage; persistent banner with exit; "Login as user" button and an
"Admin access log" tab on the detail page; logout clears impersonation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 00:49:02 +03:30
keyhan 7958d2fa72 feat(admin): super-admin user detail dashboard
Add a read-only User Detail dashboard for super admins, reachable by
clicking a user name in the admin users list.

Backend: new `admin` module aggregating existing domain services
(no new entities). ADMIN-only endpoints under /api/v1/admin:
overview (profile, account status, wallet balance, revenue, summary
counts), wallet transactions, applications (incl. deleted/docked with
restore eligibility), build/deploy errors, tickets with conversation,
and a composite activity timeline. Adds BillingService.getRevenueSummary
and guards against a wallet get-or-create race in the overview reads.

Frontend: tabbed detail page (overview/applications/activity/errors/
tickets) with lazy per-tab queries; user names in the admin list link to
it (admin only); fa/en i18n keys and response types.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 23:52:21 +03:30
keyhan a3b7e9055c feat(admin): create users by mobile number instead of email
Admin user management now creates accounts with a required mobile
number and an optional contact email, matching mobile-only auth.
Admin-created accounts are pre-verified (phoneVerified) so the user
can sign in by password immediately. The user list and search now
include phone.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 12:34:43 +03:30
keyhan 37c103fa20 feat(auth): mobile-only register/login with OTP verification
- Register and login by mobile number; email is now an optional
  contact field only (never used to authenticate)
- After registration, the phone is verified via a 6-digit SMS code
- Login supports both password and one-time-code (OTP) methods
- Phone OTP delivered via Kavenegar (verify/lookup); API key in env
- Account page: edit name/optional email, change password, and
  change mobile number with OTP re-verification
- Codes are hashed, expire in 5m, capped at 5 attempts, rate-limited
- Seed gives the admin a verified phone so mobile login still works

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 16:40:08 +03:30
keyhan ce6813db99 fix(logs): stop build-log polling once build finishes
The build-logs tab kept polling every 5s and showing the auto-refresh
indicator even after the build reached a terminal state. Gate both on
the build still being in progress, and label a completed build as
"done" instead of the misleading "running" status.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 02:23:01 +03:30
keyhan 643e8c5c61 Merge branch 'feat/live-build-logs-modal' 2026-06-16 02:08:03 +03:30
keyhan 6022739b80 feat(deploy): stream live build logs in build progress modal
Show real-time kaniko/init-container build output inside the build
progress modal during the building/deploying phases, alongside the
existing percentage. The build-logs endpoint now returns live pod logs
while a build is in progress (falling back to the persisted log once
finished), and the modal polls it every 2s with auto-scroll. Minimize
behaviour is unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 01:50:14 +03:30
keyhan 901a20eb01 feat(deploy): configurable CPU/RAM/disk for app databases
Let users size the database workload from the deploy wizard the same way
Redis/RabbitMQ are configured: a resource card (CPU request/limit, memory
request/limit, storage) on the Resources step, stored in
optionalServiceResources.database.

- entity/DTO: add `database` to optionalServiceResources
- k8s: resolveDatabaseResources() applies user-selected resources on both
  the Helm and K8s-API deploy paths (was hardcoded 100m/256Mi→500m/512Mi)
- billing: bill database CPU/RAM as a separate line on top of the app's
  resources; merge it through the upgrade path too
- wizard: db resource card on the Resources step, disk moved into the card,
  cost preview + review summary include the database resources

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 01:20:33 +03:30
keyhan 91a66d5645 Restyle toasts and centralize friendly error handling.
Replace the default react-toastify look with project-styled toast cards
(icon chip, rounded shell, RTL-aware container, type-colored progress
bar) via a new notify helper and globals.css overrides.

Add a central error layer (src/lib/errors.ts): classify any caught error
by HTTP status / network condition, log the full technical detail
(including the raw backend message) to the console only, and surface a
friendly, localized message to the user. Raw backend messages are no
longer shown. All ~190 toast call sites across 22 files move to notify,
routing backend errors through notify.error(err, fallback); dead
apiErrorMessage/formatApiError helpers removed. Adds an `errors` section
to the fa/en dictionaries.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 11:45:26 +03:30
keyhan d31d93f6b8 Localize the admin all-applications page.
Move the final dashboard page (admin all-apps) onto a
dashboard.adminApps dictionary: status-count cards, search, table/cards,
lifecycle & migration statuses, plan/expiry, and the migrate modal —
completing full fa-IR/en-US coverage across the entire app.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 01:06:33 +03:30
keyhan e43274e9a2 Localize the deploy wizard.
Move the multi-step deploy wizard (app type/runtime, source, versions &
database, optional services, resources & cluster assignment, custom
domain + DNS, env vars, cost/payment, review and the provisioning
overlay) onto a dashboard.deployWizard dictionary, with localized runtime
descriptions, billing cycles, stage labels and RTL-aware controls.

This completes full fa-IR/en-US localization of the dashboard.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 00:48:45 +03:30
keyhan aca69fc5e6 Localize the application detail page.
Move the largest dashboard page (app detail) onto a dashboard.appDetail
dictionary: header actions, status/lifecycle banners, configuration,
deployment history, source upload, custom-domain + DNS guide, resources
& scaling, storage, rollback/snapshots, DB restore, service credentials,
renewal and upgrade modals — with localized statuses, locale-aware dates
and RTL-aware layout.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 23:45:16 +03:30
keyhan 8d423f8224 Localize the managed-service detail page.
Move the service detail view (header actions, renewal banner, config,
deployment history, DB/Redis/RabbitMQ connection panels, renew modal)
onto a dashboard.serviceDetail dictionary with localized product-type and
deploy-status labels, locale-aware dates and RTL-aware layout.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 22:48:47 +03:30
keyhan deef498f65 Localize the managed-service resources panel.
Add components.serviceResources and move the resources/scaling panel
(metrics, storage usage/expansion, CPU/memory adjust, dump restore,
upgrade toasts) onto it; route through the locale-aware router.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 21:02:57 +03:30
keyhan 96d24b50a1 Localize database-config, snapshots panel and new-service wizard.
Add components.dbConfig / components.snapshots and dashboard.servicesNew
dictionaries; move the managed-database config (engine, credentials, dump
upload, storage), the snapshots panel and the three-step new-service
wizard onto them. validateDbDumpStorage now takes a localized template.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 19:22:37 +03:30
keyhan 63e368f464 Localize workload-logs and external-access panels.
Add components.workloadLogs, components.deployStatus and
components.externalAccess dictionaries; move the workload logs panel and
the service external-access panel onto them (tabs, live-refresh hints,
access modes, countdown units, toasts) with RTL-aware spacing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 18:25:45 +03:30
keyhan f64d341c80 Localize shared resource-field components.
Add a components.res resource-label set and move the database workload
resources and optional-service resource-field components onto it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 17:37:26 +03:30
keyhan fcba1ed93c Localize admin cluster and billing-plan pages.
Move the cluster management page (resource panel, tools install/uninstall
flow, statuses/health) and the billing-plans page (pricing matrices,
deploy defaults, add-ons, data-retention settings) onto the dictionaries
with locale-aware dates and RTL-aware tables.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 17:05:43 +03:30
keyhan 6c1133f534 Localize shared modals/overlays, logs, users and cluster-pool pages.
Add a components dictionary (delete/deleting overlays, confirm-modal
defaults, build-progress phases, deployment bar, resource-upgrade modal)
and move the logs, admin users, and admin cluster-pools pages onto the
dictionaries — filters, tables, forms, statuses, toasts and confirm
dialogs — with locale-aware dates and RTL-aware layout.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 15:36:30 +03:30
keyhan e99ab789ba Localize shared modal, overlay and deployment-progress components.
Localize the confirm modal, delete button, deleting overlays/modal, the
build-progress modal, deployment progress bar/manager and the resource
upgrade modal via a shared components dictionary. Build-phase labels now
resolve from the dictionary; deleting overlays take name/kind and build
their own localized message (callers updated).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 13:23:44 +03:30
keyhan f8ee1ca168 Localize user and admin invoice pages.
Move both invoice views onto a shared invoices dictionary — statuses,
filters, payment/line-item/transaction labels, manual status controls and
toasts — with locale-aware Link, dates and RTL-aware table/search layout.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 13:00:15 +03:30
keyhan e99dccaff1 Localize wallet and ticket pages.
Move the wallet page and all four ticket views (user list, ticket detail,
staff queue, admin overview) onto the i18n dictionaries — statuses,
priorities, departments, forms, stats, toasts and empty states — using
locale-aware Link/router and locale-aware date formatting.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 12:54:19 +03:30
keyhan 2bc86c03b8 Localize applications and services list pages.
Move the apps and managed-services list pages onto the i18n dictionaries
(titles, table headers, lifecycle/expiry labels, delete confirmations,
toast messages) and the locale-aware Link, reusing the shared status and
lifecycle/expiry copy. Add RTL-aware table alignment and icon spacing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 12:28:59 +03:30
keyhan e0964e6528 Localize dashboard shell and home page.
Convert the dashboard layout (sidebar nav, header, role badges, wallet,
sign-out, language switcher) and the dashboard home page to the i18n
dictionaries, including a shared deployment-status label map. Switch their
links/router to the locale-aware helpers and add RTL-aware spacing.

Remaining dashboard page bodies and shared components still render English
copy and will be localized in follow-up commits.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 12:15:21 +03:30
keyhan 34993d417f Add i18n foundation (fa-IR/en-US) and localize landing + auth.
Introduce path-prefixed locale routing under app/[lang] with a middleware
that detects locale from cookie/Accept-Language (default fa-IR) and
redirects. Add fa-IR (source of truth) and en-US dictionaries, a server
getDictionary, a client I18nProvider/useT, locale-aware Link + router
helpers, and a language switcher. The root [lang] layout sets html
lang/dir and the per-locale font (Peyda for fa, Inter for en).

Landing sections and the login/register/auth shell now read all copy from
the dictionaries; dashboard localization follows in a later commit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 12:05:03 +03:30