Use the seeded kaniko v1.27.6-debug image, retry npm ci, and push via harbor-core without HTTP_PROXY so Harbor UI metadata and blob uploads keep working.
Co-authored-by: Cursor <cursoragent@cursor.com>
Add REGISTRY_PUSH_URL config, route CI Kaniko to harbor-core, and document dual-host kaniko auth for core push plus registry base-image pull.
Co-authored-by: Cursor <cursoragent@cursor.com>
Route k3s registry mirrors through harbor-core ClusterIP with hostname-only auth keys, use HTTP EXT_ENDPOINT so OAuth tokens work on port 80, extend deploy readiness timeout, and harden Kaniko build/dockerfile fallbacks.
Co-authored-by: Cursor <cursoragent@cursor.com>
Mount docker config as config.json (Kaniko requirement), push via
harbor-registry internal URL, and wire harbor_registry_user credentials
in Helm/GitOps values.
Co-authored-by: Cursor <cursoragent@cursor.com>
Use seeded abrban/ images instead of flaky proxy-gcr pulls, fix Kaniko dockerfile path for v1.27, correct docker auth host keys, route /v2/abrban/ through harbor-core, and prefer abrban/ for base images.
Co-authored-by: Cursor <cursoragent@cursor.com>
v1.27.6-debug does not exist on gcr.io; proxy-gcr pulls are flaky on kubelet. Seed and reference abrban/kaniko-executor:v1.23.2 instead.
Co-authored-by: Cursor <cursoragent@cursor.com>
Inject registry-egress-proxy into Kaniko and network init containers so npm/apk/composer/pip/git clone work on restricted egress clusters.
Co-authored-by: Cursor <cursoragent@cursor.com>
Enable backend.sms in the chart so MizbanSMS credentials from the platform
Secret are injected into the backend deployment for production OTP delivery.
Co-authored-by: Cursor <cursoragent@cursor.com>
Hardcoded Basic auth in probes broke after password rotation; exec probes
read the live secret so Elasticsearch stays healthy when credentials change.
Co-authored-by: Cursor <cursoragent@cursor.com>
Backend validate-production-config requires a non-default ELASTIC_PASSWORD;
read it from abrban-platform-secrets.elastic-password like other credentials.
Co-authored-by: Cursor <cursoragent@cursor.com>
User-app builds no longer pull gcr.io/docker.io directly when build.images
is configured in values.yaml, fixing ImagePullBackOff on clusters without
upstream registry access.
Co-authored-by: Cursor <cursoragent@cursor.com>
Harden preview/deploy flows, OTP generation, zip extraction, and multi-replica billing races; document full remediation status in AUDIT-STATUS.fa.md.
Co-authored-by: Cursor <cursoragent@cursor.com>
Document server-side rollout (values, Sealed Secrets, logging, greenfield
reset) with environment variables so any cluster can follow the same steps.
Co-authored-by: Cursor <cursoragent@cursor.com>
Close billing, tenancy, migration, build, and CI/CD gaps identified in the
audit: wallet/gateway guards, full-UUID namespaces, idempotent migrations with
base schema, stateful service stability, safer Dockerfiles/git builds, and
platform chart hardening (Redis auth, RollingUpdate, backups, Swagger off).
Co-authored-by: Cursor <cursoragent@cursor.com>
Kaniko builds failed with context deadline exceeded pulling node:24-alpine
from index.docker.io through the egress proxy. Seed node:24-alpine into
abrban/ and pass BASE_IMAGE build-arg so builds use the internal registry.
Co-authored-by: Cursor <cursoragent@cursor.com>
Backend now fails production validation without CLUSTER_KUBECONFIG_KEY.
Add cluster-kubeconfig-key to the chart secret and env, plus
secrets.existingSecret so GitOps deployments can use a pre-created
(sealed) Secret instead of the lookup/randAlphaNum template that churns
under Argo CD's helm template rendering.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Workflow now pushes image tags to the separate cloud-host-gitops repo
(no more CI loop risk) and authenticates via CI_TOKEN secret
- Fix undefined ${REGISTRY} in Kaniko jobs, add concurrency group,
targeted tag update, and mounted kaniko-harbor-auth docker config
- Argo CD Application is now multi-source (chart from cloud-host,
values from cloud-host-gitops)
- Remove plaintext runner token and proxy credentials from manifests;
secrets are now SealedSecrets in the gitops repo
Co-authored-by: Cursor <cursoragent@cursor.com>
Harbor proxy-cache works from core API but containerd can't use it directly,
so all runner images are seeded to abrban/ project.
Co-authored-by: Cursor <cursoragent@cursor.com>
Harbor in-cluster builds via Kaniko, ArgoCD auto-sync, and production Helm values for abrban.com domains.
Co-authored-by: Cursor <cursoragent@cursor.com>
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>
Update both docs to match the code after reverting the build-pipeline revamp:
Kaniko with per-runtime generated Dockerfiles, disk/PVC + git source, no
Nixpacks/MinIO/Trivy/registry-GC/build-queue. Also refreshes the stack
(Next.js 16, NestJS 11), mobile-OTP auth, the three Helm charts, project
structure, and local + cluster deploy steps.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- 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>
- 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>
The closing sky drew two suns: the 3D sun mesh (corona + GodRays) at a
fixed world point, and a disc/halo painted by the sky shader aimed at a
fixed direction. As the camera flew forward, parallax split them apart —
the mesh rode high while the painted halo stayed low.
Aim the sky shader's uSunDir at the real camera→sun direction each frame
so the halo locks onto the mesh (one sun), and lower SUN_POS.y 34→13 so
that single sun sits at the lower, near-horizon spot.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
Give the login/register card a proper glassmorphism look (new .auth-glass:
more transparent so the clouds blur through, bright glassy edge, soft layered
shadow) while keeping a slate tint so the white form text stays legible.
Make the "no account? register" CTA stand out over the bright sky: a dark
frosted glass pill with an arrow, and dark slate prompt text with a soft white
halo instead of the washed-out white.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace AuthShell's deep-blue grid backdrop with AuthSky — the same bright
pale-blue gradient (weather stop 0) and the same vendored cloud puff
(/cloud.png) as the landing, as lightweight drifting CSS sprites so no
three.js lands on the auth routes. The form keeps the shared frosted-glass
panel, so login/register now read as one world with the public landing.
Cloud drift respects prefers-reduced-motion.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rework the application build/deploy pipeline for scalability, reproducibility,
and security:
- Build queue: deploys run through a bounded-concurrency Bull queue
(BUILD_CONCURRENCY, default 3) so concurrent user deploys can't flood the
cluster with Kaniko jobs. Build state (progress / cancel / session) moves from
in-memory Maps to Redis, so cancel + live logs work across backend replicas.
- Nixpacks + BYO Dockerfile: code runtimes build via Nixpacks (or the user's own
Dockerfile when present); the hand-written per-runtime Dockerfile generators
and runtime auto-detection are removed. WordPress keeps its templated path.
Build-time mirror env (NIXPACKS_BUILD_ENV) supports the Iran network.
- Source upload to MinIO: archives stream to in-cluster MinIO; build pods pull
via a presigned URL. Removes the PVC + helper pod + kubectl cp upload path.
- Report-only Trivy scan after build; per-severity summary stored on the
deployment and shown as a badge in the dashboard. Never gates a deploy.
- Registry GC: a Redis-locked daily job keeps the newest N image tags per app
(REGISTRY_KEEP_VERSIONS, default 3) and reclaims disk via garbage-collect.
- Hardening: git tokens are delivered via a per-build Secret + git credential
store instead of being embedded in the clone URL / Job manifest; build timeout
is configurable.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
The payment method was rendered as the raw enum ("wallet") in the PDF and in the
invoice detail/list views. Map it through the existing methodWallet/methodGateway/
methodMixed dictionary keys everywhere.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- 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>
Render the prepaid resource credit "remaining" and "expires" text in
Persian with Jalali calendar when locale is fa: localized digits and
day/hour/minute units for time left, and weekday + Jalali date + time
for the expiry. Parts are assembled explicitly so order is stable
regardless of the runtime's ICU pattern data.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
html2canvas re-implements text layout and mangled Persian RTL output (joined
words, broken spacing, reordered emails). Switch the rasterizer to html-to-image,
which renders through an SVG foreignObject using the browser's native text
engine, so Persian shaping/spacing/bidi and oklch() colors all come out right.
Peyda is embedded as base64 @font-face via fontEmbedCSS so html-to-image skips
its slow document-wide font scan. Drop the now-unused html2canvas dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
html2canvas 1.x cannot parse Tailwind v4's oklch() colors, so generating the
invoice PDF from the live document threw and the download silently failed.
Render the invoice template inside a sandboxed iframe that loads only the Peyda
@font-face and no app stylesheets, so the captured tree is free of oklch.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- 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>
- 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>
Drop the admin-only "cluster assignment" UI from the resources &
config step of the deploy wizard and the related backend override.
App placement is now always decided automatically by the allocator.
- frontend: remove cluster/pool selection block, review-step cluster
row, clusterMode state, public cluster/pool queries, and clusterId/
poolId from CreateApplicationDto
- backend: drop clusterId/poolId override from the create DTO and
simplify ApplicationsService.create to always auto-allocate; widen
selectClusterForApplication param to keep the fallback path working
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>