Commit Graph

36 Commits

Author SHA1 Message Date
soroush.asadi 7fe5f8a563 feat(admin): standalone Projects page + per-project asset manager
Build backend images / build content-svc (push) Failing after 1m36s
Build backend images / build file-svc (push) Failing after 1m28s
Build backend images / build gateway (push) Failing after 2m11s
Build backend images / build identity-svc (push) Failing after 2m11s
Build backend images / build notification-svc (push) Failing after 3m46s
Build backend images / build render-svc (push) Failing after 55s
Build backend images / build studio-svc (push) Failing after 1m2s
- content-svc: GET /v1/projects (browse/search all projects across containers,
  paginated, admin) returning template name/slug + AE status; project_assets
  table (mig 23) + entity; GET/POST/DELETE /v1/projects/{id}/assets
- /admin/projects: searchable, paginated list of every renderable project with
  thumbnail, template, aspect/resolution, AE-file + publish status
- ProjectAssets component: list/upload/delete named footage/image/audio/font
  files per project (reused in the projects page; AE file upload alongside)
- nav + fa/en "Projects" label

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 00:39:33 +03:30
soroush.asadi c4839bd35f feat(admin): project (template-item) manager + After Effects file upload
Build backend images / build content-svc (push) Failing after 50s
Build backend images / build file-svc (push) Failing after 1m5s
Build backend images / build gateway (push) Failing after 3m13s
Build backend images / build identity-svc (push) Failing after 1m32s
Build backend images / build notification-svc (push) Failing after 5m7s
Build backend images / build render-svc (push) Failing after 1m2s
Build backend images / build studio-svc (push) Failing after 54s
The admin could edit a container but not manage its renderable projects or attach
AE files. Now, inside the template editor:
- add a new project/variant under the container (name, WxH, aspect, resolution,
  duration, fps, choose-mode) → POST /v1/projects (maps via container_id)
- upload the After Effects file (.aep/.zip) per project → new PATCH
  /v1/projects/{id}/aep (sets AepFileUrl/Minio/Md5/Size + RenderAepComp), with an
  "AE ✓ / بدون فایل" status badge
- set the render composition name; delete a variant
- ProjectResponse now surfaces aep_file_url / aep_file_size_bytes / render_aep_comp

Additive only — the existing aspect/resolution variant editing is unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 00:23:50 +03:30
soroush.asadi 675b60d858 feat(auth+admin): Sign in with Google (OAuth) + Integrations config panel
Build backend images / build content-svc (push) Failing after 1m2s
Build backend images / build file-svc (push) Failing after 3m11s
Build backend images / build gateway (push) Failing after 5m39s
Build backend images / build identity-svc (push) Failing after 38s
Build backend images / build notification-svc (push) Failing after 2m0s
Build backend images / build render-svc (push) Failing after 58s
Build backend images / build studio-svc (push) Failing after 58s
Backend (identity-svc):
- oauth_config table (mig 22) + OAuthConfig entity
- OAuthService: admin config CRUD + Google authorization-code flow (build consent
  URL, exchange code, fetch userinfo, find/create RegisterMode.Google user, issue
  session via AuthService.IssueOAuthSessionAsync)
- AuthController: GET /v1/auth/google/{start,callback} (public); tokens handed to
  frontend via URL fragment
- AdminController: GET/PUT /v1/admin/oauth/{provider} (admin, secret masked)

Frontend:
- "ورود با گوگل" button on /auth → identity start endpoint
- /auth/callback reads fragment tokens → /api/auth/oauth-session sets httpOnly cookies
- /admin/integrations: Google client_id/secret/redirect_uri + enable, with setup guide
- nav + fa/en labels

Client ID/Secret are configured entirely in the admin panel — no redeploy needed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 00:08:21 +03:30
soroush.asadi 88a44b1349 feat(admin): full Persian (fa) localization + RTL polish
- admin-resources: all config titles/descriptions/columns/fields → Persian
- AdminResource: generic UI strings (new/edit/delete/save/cancel/loading/empty/
  actions/confirm) → Persian; text-left/right → logical text-start/end
- TemplatesAdmin: all labels, table, modal, statuses, errors → Persian
- FileUploadField, WebsiteSettingsAdmin, FileManager → Persian
- layout: ms-auto logical prop (NodesTable/RenderQueue/AiContentStudio already
  i18n with Persian values)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 23:47:35 +03:30
soroush.asadi 0cbfcbfdf7 feat(admin): render inline SVG category icons in tables
AdminThumb detects raw <svg> markup and renders it inline (object-contain);
categories list shows an Icon column. Admin-entered, authenticated input.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 23:29:01 +03:30
soroush.asadi b47314fcab feat(admin): image thumbnails in lists + template image/demo fields
- AdminThumb: reusable thumbnail (raster + SVG via <img>, dashed fallback on
  empty/broken)
- AdminResource: ColumnDef gains type:"image" → renders thumbnails in tables
- image thumbnail columns for categories, slides, home-events, internal routes;
  categories icon field now multiline (accepts raw SVG markup)
- TemplatesAdmin: cover image / mini-demo / demo / full-demo upload fields
  (backed by existing container image/demo fields) + thumbnail column in the list

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 23:23:52 +03:30
soroush.asadi 151970accd feat(admin): plan statistics + node restart/close-ae actions
Build backend images / build content-svc (push) Failing after 1m22s
Build backend images / build file-svc (push) Failing after 3m8s
Build backend images / build gateway (push) Failing after 53s
Build backend images / build identity-svc (push) Failing after 57s
Build backend images / build notification-svc (push) Failing after 1m25s
Build backend images / build render-svc (push) Failing after 2m5s
Build backend images / build studio-svc (push) Failing after 3m59s
Final legacy-admin items:
- identity GET /v1/admin/plan-statistics (active/total users + revenue per plan
  from user_plans); surfaced as a breakdown table in /admin/stats
- NodesTable: wire Restart + Close-AE actions (backend already supported them) via
  new proxy routes; was only drain/release before

Full DivineGateWeb legacy-admin parity achieved.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 23:02:03 +03:30
soroush.asadi 3091911260 feat(admin): affiliate/personal discounts, user-videos, internal routes, authz
Build backend images / build content-svc (push) Failing after 1s
Build backend images / build file-svc (push) Failing after 1s
Build backend images / build gateway (push) Failing after 0s
Build backend images / build identity-svc (push) Failing after 0s
Build backend images / build notification-svc (push) Failing after 1s
Build backend images / build render-svc (push) Failing after 1s
Build backend images / build studio-svc (push) Failing after 1s
Closes the remaining legacy-admin gaps:
- Users «مدیریت» modal: create personal discount or affiliate code (owner_user_id +
  owner_profit_percentage on existing /v1/discounts), and view the user's saved
  projects ("videos") via new admin GET /v1/saved-projects/by-user/{id} (studio)
- Internal routes admin (/admin/routes): CRUD on content.internal_routes
  (RoutesController + CmsService + gateway /v1/routes/*)
- Security: lock identity UsersController Search + Ban to [Authorize(Roles="Admin")]

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 22:42:01 +03:30
soroush.asadi 0b538e1b1e feat(content+admin): home-events CRUD + comments moderation
Build backend images / build content-svc (push) Failing after 45s
Build backend images / build file-svc (push) Failing after 1m3s
Build backend images / build gateway (push) Failing after 0s
Build backend images / build identity-svc (push) Failing after 0s
Build backend images / build notification-svc (push) Failing after 1s
Build backend images / build render-svc (push) Failing after 1s
Build backend images / build studio-svc (push) Failing after 0s
- content-svc: home-events gains Create/Update/Delete + includeInactive list
  (POST/PUT/DELETE /v1/home-events, admin-gated; dates coerced to UTC)
- admin /admin/home-events: full CRUD for homepage hero event banners
- admin /admin/comments: list + approve/unapprove + delete (moderation)
- AdminResource: optional listQuery to fetch inactive rows for admin views

Fills the remaining legacy-admin gaps (home events, comments).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 22:24:56 +03:30
soroush.asadi 3acd366fda feat(admin): music library admin + fix CRM analytics UTC
Build backend images / build content-svc (push) Failing after 1m7s
Build backend images / build file-svc (push) Failing after 50s
Build backend images / build gateway (push) Failing after 59s
Build backend images / build identity-svc (push) Failing after 56s
Build backend images / build notification-svc (push) Failing after 1m0s
Build backend images / build render-svc (push) Failing after 1m0s
Build backend images / build studio-svc (push) Failing after 56s
- /admin/music: list / upload / delete studio audio tracks (content-svc
  GET/POST/DELETE /v1/music) — fills the legacy music-library gap
- fix: CRM analytics coerced query-bound dates to UTC (Npgsql timestamptz
  rejects Kind=Unspecified) — endpoint was returning 400

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 22:17:14 +03:30
soroush.asadi 2c961b123b feat(content+admin): content ranking + statistics dashboard
Build backend images / build content-svc (push) Failing after 16s
Build backend images / build file-svc (push) Failing after 48s
Build backend images / build gateway (push) Failing after 17s
Build backend images / build identity-svc (push) Failing after 2m12s
Build backend images / build notification-svc (push) Failing after 3m15s
Build backend images / build render-svc (push) Failing after 51s
Build backend images / build studio-svc (push) Failing after 56s
- content-svc: template list gains popularity/rating sort modes (use_count_desc,
  popular, rating_desc); new PATCH /v1/templates/{id}/sort to set manual sort
  weight (feature/pin) without a full edit
- admin /admin/ranking: templates ordered by popularity with views/uses/rating
  and inline manual-sort editor
- admin /admin/stats: overview dashboard (users, revenue, paying customers,
  conversion, templates/categories/campaigns/blogs counts) aggregated from
  existing identity + content endpoints
- nav: Dashboard + Ranking links

Completes the epic: SMS/Email/Templates → Marketing → CRM → Ranking + Stats.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 22:11:18 +03:30
soroush.asadi 62a5121ffe feat(identity+admin): CRM analytics + customer notes + user power-actions
Build backend images / build content-svc (push) Failing after 56s
Build backend images / build file-svc (push) Failing after 54s
Build backend images / build gateway (push) Failing after 1m1s
Build backend images / build identity-svc (push) Failing after 55s
Build backend images / build notification-svc (push) Failing after 54s
Build backend images / build render-svc (push) Failing after 52s
Build backend images / build studio-svc (push) Failing after 1m2s
Modeled on the legacy DivineGateWeb admin (CRM + Security/* actions):
- identity-svc AdminService + AdminController (admin-gated):
  - GET /v1/admin/crm/analytics — signups/buyers/conversion/revenue + daily series
    (from identity.users + identity.payments)
  - GET/PUT /v1/users/{id}/crm — tags / note / pipeline status (user_crm table, mig 20)
  - power-actions: POST /v1/users/{id}/{balance,password,charge,moderator,grant-plan}
- admin UI: /admin/crm dashboard (funnel cards + daily signup/revenue bars);
  per-user "مدیریت" modal in Users (balance, render charge, plan days, password,
  moderator, CRM notes)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 18:59:07 +03:30
soroush.asadi 6dbb14d146 feat(notifications+admin): marketing campaigns
Build backend images / build content-svc (push) Failing after 14s
Build backend images / build file-svc (push) Failing after 22s
Build backend images / build gateway (push) Failing after 1m21s
Build backend images / build identity-svc (push) Failing after 1m43s
Build backend images / build notification-svc (push) Failing after 1m6s
Build backend images / build render-svc (push) Failing after 53s
Build backend images / build studio-svc (push) Failing after 1m5s
- campaigns table (migration 19) + CRUD + send endpoint in notification-svc
- audience resolution reads cross-schema from identity.users (all / verified /
  with_plan); send dispatches via the SMS or Email channel and logs deliveries
- endpoints: GET/POST /v1/campaigns, POST /v1/campaigns/:id/send, DELETE
- gateway route /v1/campaigns/* → notification
- /admin/marketing: create campaign (channel, audience, template/subject/body),
  list with status + sent counts, send, delete

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 18:17:19 +03:30
soroush.asadi 507ac7e6a4 feat(notifications+admin): SMS (Kavenegar) + Email (SMTP) channels & templates
Build backend images / build content-svc (push) Failing after 56s
Build backend images / build file-svc (push) Failing after 47s
Build backend images / build gateway (push) Failing after 1m0s
Build backend images / build identity-svc (push) Failing after 56s
Build backend images / build notification-svc (push) Failing after 11s
Build backend images / build render-svc (push) Failing after 4m5s
Build backend images / build studio-svc (push) Failing after 56s
Backend (notification-svc):
- channel_config table (per-tenant Kavenegar + SMTP settings) + migration 18
- sender pkg: Kavenegar SMS client + SMTP mailer (STARTTLS / implicit TLS), stdlib only
- endpoints: GET/PUT /v1/channels[/:channel], POST /v1/sms/send, POST /v1/email/send
  (template + {{var}} rendering); deliveries logged
- seeded 3 Persian email templates: welcome / account_verification / promotion
- gateway routes /v1/{channels,sms,email}/* → notification

Admin UI:
- /admin/messaging: SMS + Email provider config cards, test-send, email template editor
- nav link + fa/en labels

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 17:32:54 +03:30
soroush.asadi 9a1d60e9d0 feat(admin): Discounts and Website Settings sections
- /admin/discounts: list + create discount codes (kind, value, max uses, expiry)
  via /v1/discounts (backend has no edit/delete API yet)
- /admin/settings: key/value site settings with upsert + secret flag. The value
  column is jsonb, so values are JSON-encoded on save / decoded for display
- nav links + fa/en labels

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 15:20:07 +03:30
soroush.asadi 163f0c9ec3 feat(admin): media library + upload component (replace URL fields)
- /admin/files Media Library: drag-drop multi-upload, thumbnails, copy-URL, delete
- FileUploadField replaces raw URL inputs; new "image" field type in AdminResource;
  wired into category image
- upload proxy /api/admin/files/upload: browser → Next → presigned PUT (server-side,
  reaches minio:9000) → confirm → returns public URL
- user-uploads bucket is public-read; public base via NEXT_PUBLIC_MINIO_URL

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 14:55:52 +03:30
soroush.asadi cf5dd4f195 feat(admin): category SEO fields, Templates admin, safe project PATCH
Build backend images / build content-svc (push) Failing after 21s
Build backend images / build file-svc (push) Failing after 3m49s
Build backend images / build gateway (push) Failing after 1m2s
Build backend images / build identity-svc (push) Failing after 1m1s
Build backend images / build notification-svc (push) Failing after 1m2s
Build backend images / build render-svc (push) Failing after 1m0s
Build backend images / build studio-svc (push) Failing after 58s
- categories/tags admin forms: add meta title/description/keywords, bot-follow,
  sort, is_active (backend already supported these)
- new Templates admin (/admin/templates): container CRUD with description,
  keywords, publishing, premium, primary mode, category/tag assignment, plus
  editable per-variant aspect & resolution
- content-svc: PATCH /v1/projects/{id} partial update so aspect/resolution edits
  never wipe render/colour data (SharedColorsSvg, RenderAepComp, Folder)
- admin resource proxy: add PATCH passthrough

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 14:26:44 +03:30
soroush.asadi 1aacf8bd5d fix(i18n): working locale switcher + RTL category sidebar
- add src/i18n/navigation.ts (next-intl createNavigation) and rewire
  LanguageSwitcher to router.replace(pathname, { locale }) — the manual
  next/navigation path-munging didn't switch locale reliably
- VideoTemplatesCategorySidebar: text-left → text-start, ml-auto → ms-auto
  so labels/badges align correctly under dir="rtl"

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 09:59:07 +03:30
soroush.asadi 3fc7bf2b97 feat: AI SEO generator, full admin panel, i18n sweep, new logo + auth/RTL fixes
Build backend images / build content-svc (push) Failing after 3m39s
Build backend images / build file-svc (push) Failing after 52s
Build backend images / build gateway (push) Failing after 58s
Build backend images / build identity-svc (push) Failing after 1m21s
Build backend images / build notification-svc (push) Failing after 1m0s
Build backend images / build render-svc (push) Failing after 58s
Build backend images / build studio-svc (push) Failing after 55s
AI SEO content generator
- content-svc: per-tenant OpenAI config (ai_settings) + /v1/ai endpoints
  (settings GET/PUT, seo-post) with SEO-expert prompt → structured article
- admin UI to configure token/base-url/model and generate + save as blog
- configurable base URL for restricted networks

Full data-driven admin panel
- generic /api/admin/resource proxy + reusable AdminResource component
- categories/tags/fonts/blogs (CRUD), users (list + ban), plans/slides
- AI content section; nav + i18n

i18n localization sweep
- localized 116 user-facing + studio/editor components to next-intl (fa+en)
  under the auto.* namespace; merge tooling in scripts/merge-i18n.js

Branding + assets
- Monoline F logo (LogoMark + favicon)
- offline SVG placeholder generator (/api/placeholder), dropped picsum.photos

Fixes
- JWT issuer mismatch on content/studio (flatrender → flatrender-identity)
- missing role claim → [Authorize(Roles="Admin")] now works (RBAC)
- Secure cookies broke HTTP sessions → gated behind AUTH_COOKIE_SECURE
- Radix RTL via DirectionProvider (right-aligned menus in fa)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 09:35:14 +03:30
soroush.asadi bcc69f0a2e feat: complete node-agent pipeline, TLS proxy, billing cancel, password reset
Node-agent — full render pipeline (items 1-3):
- render-svc: ClaimedJob now includes aep_download_url (presigned MinIO GET,
  2h TTL, path=templates/{original_project_id}/template.aep)
- render-svc: POST /v1/internal/render/jobs/:id/output-upload-url
  allocates Export row + returns presigned MinIO PUT URL + export_id
- render-svc: db.CreateExportForJob() inserts export row with 30-day retention
- render-svc: InternalHandler now owns minio client (templatesBucket + exportsBucket)
  MINIO_TEMPLATES_BUCKET env var (default flatrender-templates)
- node-agent: runner/download.go — DownloadFile() + UploadFile() (stdlib only)
- node-agent: client.GetOutputUploadURL() + ClaimedJob.AEPDownloadURL field
- node-agent: runJob() full flow: download AEP → render → get upload URL →
  PUT output to MinIO → Complete(export_id)
  All steps are non-fatal with fallback (AEP miss → mock, upload fail → no export)

TLS reverse proxy (item 15):
- Caddyfile: three virtual hosts (DOMAIN, API_DOMAIN, STORAGE_DOMAIN)
  auto-TLS via Let's Encrypt; security headers; 512MB upload limit on API
- docker-compose.v2.yml: caddy:2-alpine service, ports 80/443/443udp,
  caddy_data + caddy_config volumes; env vars DOMAIN/API_DOMAIN/STORAGE_DOMAIN/ACME_EMAIL
- .env.v2.example: new Caddy + MINIO_TEMPLATES_BUCKET entries

Billing portal (item 5):
- Identity: POST /v1/users/me/plan/cancel — sets cancelled_at, auto_renew=false
  (access continues to expiry); 404 when no active plan
- POST /api/billing/cancel — frontend proxy, validates auth
- GET /api/billing/portal — redirects to /dashboard/settings?tab=billing
- SettingsBilling: "Cancel plan" button with confirm dialog + optimistic UI,
  "Change plan" button; becomes "use client" component

Password reset UI (item 7):
- POST /api/auth/password-reset — proxies /v1/auth/password/reset/request
  (always 200, anti-enumeration)
- POST /api/auth/password-reset-confirm — proxies /v1/auth/password/reset/confirm
- AuthPageContent: "Forgot password?" link on sign-in tab opens 2-step reset flow
  (email → OTP+new-password) without leaving the auth page

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 16:41:13 +03:30
soroush.asadi 12773e125a feat: token auto-refresh, studio→render wiring, admin panel (nodes + render queue)
Token auto-refresh (middleware):
- Proactively refresh fr_access when < 120s remain — no more silent 15-min kick
- Inlines /v1/auth/refresh call in middleware, stamps new cookies on response
- /admin/* protected: is_admin JWT claim required, else redirect /dashboard
- apiFetch() (src/lib/api/fetch.ts): client-side 401 → auto-refresh → retry;
  de-duplicates concurrent refresh calls; redirects to /auth on failure

Studio → Render V2 wiring:
- scenes[] no longer sent to POST /api/render (V2 render-svc fetches project
  from Studio service via saved_project_id directly)
- renderRequestSchema.scenes is now optional
- RenderModal uses apiFetch for auto-refresh on 401 during polling

Admin panel (/admin/*):
- Admin layout: server-side is_admin guard + top nav (Nodes, Render Queue)
- /admin/nodes: lists all nodes from GET /v1/nodes with status badges,
  heartbeat age, slot usage, tags; Drain (PATCH status=Draining) + Release actions
- /admin/renders: render job table with step filter tabs; progress bars,
  error messages, Retry + Cancel per-row actions; polls GET /v1/renders
- API proxy routes: /api/admin/nodes/:id/drain|release,
  /api/admin/renders/:id/retry|cancel — all validate is_admin in JWT before proxying

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 13:42:30 +03:30
soroush.asadi d7743a6fbe feat: live render preview — node agent pushes PNG frames, frontend displays them in real time
render-svc:
- db.UpdateJobPreview(): writes base64 PNG to render_jobs.image_preview_b64
  (only on active jobs; Done/Failed/Cancelled rows ignored)
- POST /v1/internal/render/jobs/:job_id/preview — node agent endpoint
- Route registered under /v1/internal (nodeAuth)

node-agent:
- runner.PreviewFn callback type alongside ProgressFn
- runner.preview.go: GeneratePreviewB64(percent, quality, resolution)
  — pure stdlib (image/png + encoding/base64), no external deps
  — 320×180 dark frame with animated progress bar + colored indicator dots
- mock render: pushes a preview frame at every step (5→95%)
- real AE render: pushes a preview frame every 30s
- client.UpdatePreview(): POST /v1/internal/render/jobs/:job_id/preview
- main.go: onPreview callback wires client.UpdatePreview() into runner.Run()

frontend:
- render-jobs.ts: RenderJobRow.preview_b64 field; read from progress endpoint
- status/route.ts: previewB64 included in JSON response
- RenderModal: aspect-ratio preview pane during polling — shows spinner until
  first frame arrives, then live-updates with each poll (every 3s);
  step label overlaid as badge bottom-right

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 09:42:03 +03:30
soroush.asadi a076c4911f feat(frontend): migrate render jobs off Supabase to V2 render orchestrator; drop all Supabase lib files
- render-jobs.ts: replace Supabase client with V2 gateway calls
  POST /v1/renders (saved_project_id + quality + resolution + frame_rate)
  GET  /v1/renders/:id/progress for status polling
  GET  /v1/renders/:id + /v1/exports/:id/download-url for completed output URL
  triggerRenderWorker is now a no-op (V2 dispatches internally)
- render/route.ts: add getAccessToken() guard, pass token to createRenderJob
- render/[jobId]/status/route.ts: add getAccessToken() guard, pass token to getRenderJob
- Delete src/lib/supabase/, src/lib/supabase.ts — no remaining consumers

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 08:41:58 +03:30
soroush.asadi 9555044485 feat(frontend): route checkout through V2 Identity plan-purchase; drop dead Stripe webhook
/api/checkout now resolves the requested plan (pro|business × monthly|annual)
to a plan GUID via gateway /v1/plans (codes follow pro_monthly / business_annual)
and POSTs /v1/users/me/plan/purchase. The payments service owns the gateway
(ZarinPal/Stripe) and returns redirect_url, which we hand back unchanged.

Removes the orphaned Stripe→Supabase webhook + lib/stripe.ts client: profile
plan reads come from Identity now, so the Supabase profiles upsert loop is dead.
V2 payments has its own gateway callback (skip-auth, payment-callback route).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 12:46:01 +03:30
soroush.asadi 903306c7cf feat(frontend): settings page reads user from V2 Identity; drop dead OAuth callback
- dashboard/settings/page.tsx now resolves the current user via getCurrentUser()
  (Identity JWT cookie) instead of the Supabase server client; display name comes
  from Identity's full_name.
- Remove src/app/auth/callback/route.ts — the Supabase OAuth code-exchange
  callback is unreferenced now that auth runs entirely on Identity.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 06:10:21 +03:30
soroush.asadi 2adaf57f10 feat(frontend): move settings profile + password off Supabase to V2 Identity
Adds two authenticated gateway proxies and rewires the settings UI to them:
- POST /api/auth/password → Identity /v1/auth/password/change (server-side
  re-validates current password; drops the client-side re-auth round-trip)
- PATCH /api/profile → Identity PATCH /v1/users/me (full_name)

SettingsProfile and SettingsSecurity now fetch these routes instead of the
Supabase browser client.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 06:06:47 +03:30
soroush.asadi 6d2a296c38 feat(frontend): read user profile + plan from V2 Identity instead of Supabase
getUserProfile now calls the gateway /v1/users/me and /v1/users/me/plan with
the access-token cookie, mapping plan_code → PlanId. Falls back to a free-plan
profile when signed out or Identity is unreachable. Stripe ids drop to null
(V2 billing runs through the payments service). Signature unchanged so the
dashboard plan badge + settings call sites are untouched.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 06:02:17 +03:30
soroush.asadi 14cdb772b4 feat(frontend): migrate dashboard projects flow off Supabase to V2 Studio
User-saved projects now read/write through the gateway /v1/saved-projects
(studio schema) using the Identity access-token cookie, replacing the
Supabase `projects` table. Adds src/lib/api/saved-projects.ts client that
maps studio snake_case DTOs into the existing DashboardProject shape.

- DashboardProjectsContent: lists via studio service, degrades gracefully
- /api/projects GET: studio list; POST: copy-from-template create
  (studio requires original_project_id; falls back to scene_data.templateId)
- /api/projects/[projectId] GET/PATCH: proxy to studio with JWT

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 05:56:25 +03:30
soroush.asadi e8c1587695 fix: satisfy next build ESLint in admin-api (unused param)
next build runs ESLint (stricter than tsc --noEmit), which failed on the
unused `type` param in fetchCategories with no-unused-vars, breaking the
frontend production build. Reference it via `void type;` while keeping
the signature for API compatibility.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 05:45:10 +03:30
soroush.asadi fa013b2305 feat: repoint admin-api content reads to V2 gateway
src/lib/admin-api.ts now reads categories/templates/projects from the
V2 content service via the gateway (/v1/*) instead of the legacy
admin-api (:5000). Maps V2 snake_case DTOs (CategoryResponse tree,
PagedResponse<ContainerSummaryResponse>) into the existing camelCase
AdminCategory/AdminProject shapes, so call sites are unchanged and the
hardcoded fallback still applies when the gateway is unreachable.

V2 containers are video templates (primary_mode is a render mode, not a
type), so all map to type "video". Query params use camelCase
(pageSize/isPublished) since .NET binds query strings by property name,
not the snake_case used in response bodies.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 05:15:45 +03:30
soroush.asadi 90ac0b81d1 feat: V2 microservices stack — backend services, gateway, JWT auth
Add full V2 architecture: identity, content, studio (.NET 10) and file,
render, notification, gateway (Go) services with vendored deps, plus DB
migrations, event/API contracts, and an init-db script.

Wire the Next.js frontend to the gateway: server-side JWT auth routes
(login/register/refresh/logout/me), gateway fetch helper, and session/
cookie/jwt helpers under src/lib.

Containerize the stack via docker-compose.v2.yml and per-service
Dockerfiles. Base images resolve through a Nexus mirror (Docker Hub) and
MCR directly; npm/NuGet pull from Nexus groups. Self-host fonts via
next/font/local to avoid Google Fonts (geo-blocked).

Add CI workflow and ignore .env.v2, *.stackdump, and .NET bin/obj.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-29 23:29:31 +03:30
Soroush.Asadi 36e264f3e3 feat: admin API integration, LogoMark, settings page, i18n, RTL font, docs
- Wire admin API into homepage + templates page (ISR 60s, null fallback)
- Add src/lib/admin-api.ts with safeFetch helper
- Add adminProjectToTemplateItem + adminProjectToCatalogTemplate mappers
- Add LogoMark SVG component, replace Sparkles icon in Navbar/Footer/Sidebar
- Add public/favicon.svg (SVG brand mark)
- Rewrite opengraph-image.tsx with FlatRender branding
- Add RTL/Persian font cascade: unlayered [dir=rtl] block forces Vazirmatn
- Dashboard Settings page: Profile, Security, Billing, Notifications sections
- Add src/lib/supabase/client.ts browser client
- Admin API: GET /me, PATCH /profile, POST /change-password endpoints
- Admin API DTOs: AdminUserDto, UpdateProfileRequest, ChangePasswordRequest
- Admin UI Settings page with TanStack Query + mutations
- Add CLAUDE.md + README.md to both repos for new-machine onboarding
- Update PROJECT_MEMORY.md with session log
- Add appsettings.Development.json.example template
2026-05-27 09:06:51 +03:30
Soroush.Asadi 4875e468fe i18n: wire useTranslations for video-maker, image-maker, and pricing heading
- Add videoMaker + imageMaker namespace to en.json and fa.json
  (hero, features x5, use-cases x4, CTA per section)
- Pricing.tsx: replace hardcoded heading with t('pricing.heading')
- VideoMakerHero/Features/UseCases/Cta: full useTranslations wiring
- ImageMakerHero/Features/UseCases/Cta: full useTranslations wiring
- Features/UseCases arrays moved inside components; icons kept as
  module-level constants to avoid per-render allocation
2026-05-25 07:40:26 +03:30
Soroush.Asadi 39a86b93d4 fix: konva Image alt prop + useMemo dep array corrections 2026-05-25 07:29:40 +03:30
Soroush.Asadi c61f587767 feat: full studio build -- light theme, canvas thumbnails, i18n (fa/en) 2026-05-24 17:37:31 +03:30
Soroush.Asadi d962483359 Initial commit from Create Next App 2026-05-21 12:17:29 +03:30