1106c03feb9bc4e3d3bd180ecb48ede02e6dab6e
70 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
b34904549f |
ci(build): pull golang base image from kargadan mirror
mirror.soroushasadi.com serves only cached images (node:20 resolved, golang:1.25 was 'not found' — too new to be cached, upstream can't back-fill). Point the Go services' golang:1.25-alpine base at mirror.kargadan.ir per infra owner; alpine/ busybox/node/postgres/minio stay on soroushasadi (cached). GOPROXY already kargadan. |
||
|
|
ee2a6b9b60 |
ci(build): pull Docker Hub base images via Nexus mirror + kargadan GOPROXY
Docker Hub blocks Iran (403) on the BUILD base images too (golang/alpine/busybox/ node) once they fall out of cache. Prefix every Docker Hub FROM/COPY --from with mirror.soroushasadi.com/ (MCR dotnet images are reachable, left as-is). Go builders also set GOPROXY=mirror.kargadan.ir/repository/go-group/ + GOSUMDB=off so any module/ toolchain fetch avoids the geo-blocked proxy.golang.org. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
127f40e1c1 |
ci: Gitea CI/CD pipeline + server deploy (Nexus mirror, Caddy HTTPS)
- .gitea/workflows/ci-cd.yml: frontend tsc check → self-hosted deploy job that
builds the full compose stack and brings it up behind Caddy. Locks
COMPOSE_PROJECT_NAME=flatrender (stable volumes), backs up the DB before each
deploy, health-waits gateway+frontend, no `down -v`.
- Route all package installs through mirror.soroushasadi.com:
frontend Dockerfile npm registry → NPM_REGISTRY build arg (Nexus default);
3× NuGet.Config (content/identity/studio) → HTTPS nuget-group (were a bare IP).
- Harden host ports: ${HOST_BIND:-0.0.0.0} prefix on postgres/minio/render/gateway/
frontend so prod (HOST_BIND=127.0.0.1) keeps them off the public internet — only
Caddy 80/443 is public. Dev (unset → 0.0.0.0) unchanged.
- render-svc MINIO_USE_SSL now env-driven (MINIO_HOST_USE_SSL) for HTTPS storage domain.
- deploy/ENV_FILE.production.example (the Gitea secret template) + deploy/README.md
(one-time setup + go-live checklist).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
1f6c35eb7c |
chore(content): seed demo blog + learn posts and CMS page rows
Build backend images / build content-svc (push) Failing after 1m16s
Build backend images / build file-svc (push) Failing after 53s
Build backend images / build gateway (push) Failing after 53s
Build backend images / build identity-svc (push) Failing after 1m7s
Build backend images / build notification-svc (push) Failing after 59s
Build backend images / build render-svc (push) Failing after 47s
Build backend images / build studio-svc (push) Failing after 1m2s
Idempotent seed (services/content/migrations/002_seed_blog_learn_pages.sql): one Blog article, one Learn tutorial, and the 7 static Page rows (about/contact/careers/privacy/terms/cookies/help) so the new public sections render with real content and the admin "Pages" section has editable rows. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
c92de06c28 |
feat(content): public Blog + Learn sections and static CMS pages (full-stack)
Adds the missing public-facing content pages and their admin authoring, all powered by the existing content-svc Blog entity discriminated by `kind`. Backend (content-svc): - BlogKind enum += Learn, Page (reuses Blog CRUD/SEO/slug/publish for all three). - SQL migration services/content/migrations/001_blog_kind_learn_page.sql (ALTER TYPE content.blog_kind ADD VALUE 'Learn','Page'). Frontend (public, Next.js): - lib/content-api.ts: fetchArticles(kind) / fetchArticle(slug) / fetchPage(slug) with safe empty/null fallbacks. - components/content: article-ui (card/list/detail + RTL prose), CmsPageContent, CmsRoute (admin-authored page or localized built-in fallback copy). - Routes: /blog, /blog/[slug], /learn, /learn/[slug] and static pages /about /contact /careers /privacy /terms /cookies /help. - Navbar "tutorials" → /learn; all footer links now resolve. Admin: - AdminResource: new `fixedValues` option (injects kind on create/update). - learnConfig (kind=Learn) + pagesConfig (kind=Page) reuse the /v1/blogs endpoint; /admin/learn + /admin/pages routes + nav items. i18n: blog, learn and 7 *Page namespaces added to both fa.json and en.json (verified key parity); admin nav labels learn/pages. Frontend tsc clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
6cf8716d7e |
feat(render): node-agent AE snapshot runner (Epic C2) + colour render-binding (Epic B)
Build backend images / build content-svc (push) Failing after 13s
Build backend images / build file-svc (push) Failing after 53s
Build backend images / build gateway (push) Failing after 1m22s
Build backend images / build identity-svc (push) Failing after 19s
Build backend images / build notification-svc (push) Failing after 21s
Build backend images / build render-svc (push) Failing after 20s
Build backend images / build studio-svc (push) Failing after 1m6s
C2 — real-AE scene snapshots on the node:
- node-agent: runner/snapshot.go RunSnapshot (aerender -comp <key> -s f -e f
→ findRenderedOutput → ffmpeg -frames:v 1 PNG); client ClaimSnapshot /
GetSnapshotUploadURL / ReportSnapshotResult / ReportSnapshotFail; snapshotLoop +
pollSnapshotOnce mirroring the scan loop (reuses the AE-exclusive lock).
- render-svc: GetSnapshotJobMeta + UploadURL handler presigns a PUT to the
public-read user-uploads bucket at snapshots/{project}/{scene}.png and returns a
permanent public_url (not the time-limited export presign); MINIO_UPLOAD_BUCKET +
MINIO_PUBLIC_URL config + compose env + /snapshot/:id/upload-url route.
Epic B — bind edited colours into the render:
- render-svc GetRenderBindings UNIONs studio.saved_shared_colors +
saved_scene_colors (type 'color') so the node writes them before render.
- node-agent binder.go routes type:"color" bindings into the bind-spec colors[]
array that bind.jsx already applies to the frshare colour layers.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
8488acb115 |
feat(snapshots): AE scene-snapshot pipeline + admin trigger (Epic C, C1)
Build backend images / build content-svc (push) Failing after 31s
Build backend images / build file-svc (push) Failing after 30s
Build backend images / build gateway (push) Failing after 30s
Build backend images / build identity-svc (push) Failing after 30s
Build backend images / build notification-svc (push) Failing after 31s
Build backend images / build render-svc (push) Failing after 31s
Build backend images / build studio-svc (push) Failing after 31s
Per-scene preview thumbnails for templates. Admin clicks "ساخت پیشنمایش صحنهها" → one single-frame AE render per scene → content.scenes.snapshot_url → shown as a thumbnail in the admin scene list (and available to the studio). - migration 30_render_snapshot_jobs.sql: render.snapshot_jobs (queued|running| done|error, per scene, image_url). - render-svc: db/snapshotjobs.go (EnqueueSceneSnapshots, List, Claim, SetResult -> writes content.scenes.snapshot_url cross-schema, SetError); handlers/ snapshotjobs.go (admin POST/GET /v1/scene-snapshots/:project_id + node-facing internal claim/result/fail); main.go routes; gateway route. - devworker: RunSnapshots — fulfils snapshot jobs with a generated placeholder PNG (data: URL, scene-key-tinted) so the flow is verifiable without an AE node. Gated by RENDER_DEV_SNAPSHOTS (default off; never hijacks real render jobs). - admin UI: ProjectScenes "generate snapshots" button (enqueue + poll + reload) and a thumbnail (snapshot_url || image) per scene row. Verified e2e via the dev mock: enqueue -> jobs run -> content.scenes.snapshot_url populated -> scenes API returns it -> admin renders the thumbnail. Remaining (C2): node-agent real-AE runner — claim snapshot, aerender -s0 -e0 -> ffmpeg still -> upload to a PERMANENT URL (mirror file-svc, not the time-limited export presign) -> post result. Needs a live AE node to build + verify. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
93411da462 |
feat(presets): pre-fill the user's project from preset values (A4)
Build backend images / build content-svc (push) Failing after 30s
Build backend images / build file-svc (push) Failing after 30s
Build backend images / build gateway (push) Failing after 31s
Build backend images / build identity-svc (push) Failing after 31s
Build backend images / build notification-svc (push) Failing after 30s
Build backend images / build render-svc (push) Failing after 30s
Build backend images / build studio-svc (push) Failing after 31s
"Use this example" now actually fills the new project, not just stores a ref.
- studio-svc: CreateProjectAsync applies the chosen preset story's saved values
after the template-graph copy. ApplyPresetValuesAsync reads
content.preset_stories.scenes_spa = { values: {contentKey:value},
colors: {elementKey:hex} } and overlays them onto studio.saved_scene_contents
(by key) + saved_shared_colors/saved_scene_colors (by element_key, is_selected).
Keys are globally unique (AE convention) so key-only matching is safe.
Malformed scenes_spa is skipped (defaults kept). Runs in the create tx.
- admin UI: ProjectPresetStories raw scenes_spa textarea replaced with a
structured PresetValueEditor — loads each preset scene's content elements +
the project's shared colours and renders a type-aware input per item
(text/textarea/number, media→upload, fill/color→colour). Serializes to
scenes_spa {values,colors}; parses it back on edit.
Verified e2e: authored a preset with values+colour → used it → the new
project's saved_scene_contents + saved_shared_colors carry the preset values
(which the B2 render binder then writes into AE).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
ab568c0663 |
feat(presets): admin preset stories (premade example videos) end-to-end
Build backend images / build content-svc (push) Failing after 31s
Build backend images / build file-svc (push) Failing after 31s
Build backend images / build gateway (push) Failing after 31s
Build backend images / build identity-svc (push) Failing after 30s
Build backend images / build notification-svc (push) Failing after 30s
Build backend images / build render-svc (push) Failing after 31s
Build backend images / build studio-svc (push) Failing after 31s
Epic A — admins author premade example videos per template; users pick one on the template detail page to start a pre-filled project. Backend (content-svc): - PresetStory DTOs + PresetStoryService (admin CRUD + public published-only filter via role check + soft-delete) + PresetStoriesController (/v1/preset-stories) - DI registration; gateway route /v1/preset-stories (optionalAuth, public read) Frontend: - ProjectPresetStories admin authoring UI (name/description/demo upload/published/ sort + scene picker with order+duration + advanced scenes_spa); «ویدیوهای نمونه» button + modal in ProjectsAdmin - TemplateDetailExamples renders real published stories (image/video preview, hover → "use this example" → creates a pre-bound project), falls back to placeholders when none; selected aspect's variant id keys the fetch - public /api/preset-stories route; preset_story_id plumbed through createProjectFromTemplate + projects POST route; usePreset i18n (fa+en) Verified: full CRUD via gateway (public hides unpublished); creating a project with presetStoryId persists selected_preset_story_id on the saved project. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
23624f7db9 |
feat(admin): auto-fill new scene length from the AEP
Build backend images / build content-svc (push) Failing after 2m22s
Build backend images / build file-svc (push) Failing after 1m49s
Build backend images / build gateway (push) Failing after 1m6s
Build backend images / build identity-svc (push) Failing after 59s
Build backend images / build notification-svc (push) Failing after 50s
Build backend images / build render-svc (push) Failing after 54s
Build backend images / build studio-svc (push) Failing after 55s
When adding a scene in the admin scene editor, its duration is now pulled from the After Effects project automatically (scene key = comp name). frontend (ProjectScenes): - the new/edit scene form quick-scans the project .aep for comp names + durations and offers a "pick composition" dropdown that fills key, title and default duration in one click - the key field gains a datalist of comp names; typing a key that matches a comp auto-fills the length (only when empty, never clobbering a manual value) - an inline "AEP duration: Ns — insert" hint next to the duration field - graceful states when no .aep is uploaded / scan fails render-svc (aep.durationFromCdta): fix the composition-duration offset. The duration rational lives at cdta offset 44 (numerator) / 48 (time base) on AE 2024/2026, not 32/36 (previous guess) or 40/44 (boltframe reference, older builds). Made it version-robust: read the time base from the framerate dividend (offsets 4/8) and accept whichever offset places the time base right after the numerator. Verified against a real project — render comp frfinal parses to 15.02s (matches project_duration_sec 15.00). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
da3f92fbe8 |
feat(admin): full legacy controller set in scene-inputs editor
Build backend images / build content-svc (push) Failing after 2m19s
Build backend images / build file-svc (push) Failing after 1m18s
Build backend images / build gateway (push) Failing after 2m38s
Build backend images / build identity-svc (push) Failing after 6m44s
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 59s
The V2 scene-inputs editor only exposed ~15 of the content model's ~40 fields. Restore full parity with the legacy admin controller. content-svc: - SaveContentElementRequest + ContentElementResponse widened to the complete field set (text/font, direction/RTL, media, advanced, DP) - ApplyElement / ToElementResponse map every field 1:1 (Enum.TryParse for JustifyKind + AiInputType) frontend (SceneInputsEditor): - common fields up top; an "advanced" toggle reveals grouped sections: Text and Font, Direction (RTL/LTR), Media, Advanced, Design-Presets (DP) - editing an element loads the full field set; rows show font/hidden badges - nullable numbers sent as null, enums as named values (snake_case body) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
bf6c04aba3 |
fix(render): node reports progress → moving bar + ETA (was stuck 0%/Preparing)
Build backend images / build content-svc (push) Failing after 58s
Build backend images / build file-svc (push) Failing after 45s
Build backend images / build gateway (push) Failing after 52s
Build backend images / build identity-svc (push) Failing after 54s
Build backend images / build notification-svc (push) Failing after 56s
Build backend images / build render-svc (push) Failing after 56s
Build backend images / build studio-svc (push) Failing after 49s
The node's onProgress callback only LOGGED — it never POSTed, so render_progress stayed
0 and step stayed Preparing (no bar, no ETA). Add render-svc POST
/v1/internal/render/jobs/{id}/progress (UpdateJobProgress: set render_progress + bump
step Queued/Preparing→Rendering once >0) + client UpdateProgress + wire onProgress to
post it (8s best-effort timeout, AE-CPU/DB-starvation tolerant). Preview already posts;
real-frame preview is epic C.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
fca6bcac53 |
feat(#41): admin/renders pagination + user name link + output + project name
Build backend images / build content-svc (push) Failing after 1m1s
Build backend images / build file-svc (push) Failing after 56s
Build backend images / build gateway (push) Failing after 49s
Build backend images / build identity-svc (push) Failing after 50s
Build backend images / build notification-svc (push) Failing after 49s
Build backend images / build render-svc (push) Failing after 1m2s
Build backend images / build studio-svc (push) Failing after 47s
render-svc admin-renders enriches jobs with user_name/email (cross-schema lookup to identity.users). Page adds prev/next pagination (page_size 30). Table adds User column (name → /admin/users?q=email) and Output column (export → /admin/exports), and shows project_name. Verified: 21 jobs, paginated, names resolved. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
d56bcf1b23 |
feat(#42): FIX projects can't add scenes (studio + admin)
Build backend images / build content-svc (push) Failing after 57s
Build backend images / build file-svc (push) Failing after 56s
Build backend images / build gateway (push) Failing after 54s
Build backend images / build identity-svc (push) Failing after 1m0s
Build backend images / build notification-svc (push) Failing after 47s
Build backend images / build render-svc (push) Failing after 53s
Build backend images / build studio-svc (push) Failing after 57s
Template copy now carries choose_mode from the content project → studio store gets chooseMode; AddSceneMenu returns null for FIX/MusicVisualizer. Admin ProjectScenes hides '+ صحنهٔ جدید' (shows an 'scenes defined in AE' note) for fixed modes. Verified choose_mode=FIX flows end-to-end. (Visible admin nav link added earlier.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
bccebbd006 |
feat(render #36): real per-tier output height (360/540/720/1080/4K)
Build backend images / build content-svc (push) Failing after 50s
Build backend images / build file-svc (push) Failing after 57s
Build backend images / build gateway (push) Failing after 50s
Build backend images / build identity-svc (push) Failing after 58s
Build backend images / build notification-svc (push) Failing after 48s
Build backend images / build render-svc (push) Failing after 53s
Build backend images / build studio-svc (push) Failing after 1m2s
r_height was hardcoded 1080. render-svc now derives r_height from the resolution (ResolutionHeight) on job create; node-agent ffmpeg downscales to the tier height (scale=-2:H). Quality picker now actually changes output size. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
47a4ced973 |
feat(render B2): render binder writes user edits into AE before render
Build backend images / build content-svc (push) Failing after 52s
Build backend images / build file-svc (push) Failing after 56s
Build backend images / build gateway (push) Failing after 53s
Build backend images / build identity-svc (push) Failing after 1m29s
Build backend images / build notification-svc (push) Failing after 1m38s
Build backend images / build render-svc (push) Failing after 1m53s
Build backend images / build studio-svc (push) Failing after 56s
Edits previously never reached the MP4 (the node rendered template defaults). Now: - render-svc claim includes the saved input values as bindings (GetRenderBindings → saved_scene_contents with non-empty value). - node-agent: new binder.go emits a JSON bind-spec + downloads media locally, runs the pre-existing data-driven bind.jsx via afterfx (sets text layers' Source Text, replaces media footage), saves a bound.aep next to the template, then aerender renders THAT. - 12-min timeout + fresh-AE + done-marker polling (mirrors scan). Non-fatal: on bind failure the job still renders template defaults. Verified binding data flows (edited frl_c1t1/frl_c1t2 → claim bindings). Live MP4 verification needs the updated node-agent.exe re-run. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
a69bc62724 |
feat(studio B1): persist input edits to content elements (render-binding foundation)
Build backend images / build content-svc (push) Failing after 1m3s
Build backend images / build file-svc (push) Failing after 1m5s
Build backend images / build gateway (push) Failing after 1m0s
Build backend images / build identity-svc (push) Failing after 1m8s
Build backend images / build notification-svc (push) Failing after 57s
Build backend images / build render-svc (push) Failing after 1m6s
Build backend images / build studio-svc (push) Failing after 1m3s
Studio edits previously went only to edit_state; the render binds saved_scene_contents,
so edits never reached the MP4. Add studio-svc PATCH /v1/saved-projects/{id}/contents
(update saved_scene_contents.value/value_file_id by content key, ExecuteSqlInterpolated
for null-safe params) + Next /api/projects/[id]/contents route + persistence hook pushes
edited values (from bridged c-<key> layers) alongside the scene_data save. Verified
text persists incl. UTF-8 Persian (9 chars/17 bytes).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
ad8796a25d |
feat(admin): edit any user's full profile (PATCH/POST /v1/users/{id} admin + UI modal)
Build backend images / build content-svc (push) Failing after 1m47s
Build backend images / build file-svc (push) Failing after 5m54s
Build backend images / build gateway (push) Failing after 2m8s
Build backend images / build identity-svc (push) Failing after 3m32s
Build backend images / build notification-svc (push) Failing after 12s
Build backend images / build render-svc (push) Failing after 10m27s
Build backend images / build studio-svc (push) Failing after 10s
Identity: admin-only PATCH /v1/users/{id} (reuses UpdateMeAsync) + POST {id}/avatar.
Admin Users panel: «پروفایل» modal to view/edit name/slogan/about/company/website/
country/national-code/birthdate/gender/avatar for any user. Verified admin→other-user edit.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
6ee211fb35 |
feat(studio): copy repeaters, characters/controllers, color presets into editable project
Build backend images / build content-svc (push) Failing after 1m46s
Build backend images / build file-svc (push) Failing after 2m32s
Build backend images / build gateway (push) Failing after 1m18s
Build backend images / build identity-svc (push) Failing after 1m2s
Build backend images / build notification-svc (push) Failing after 2m59s
Build backend images / build render-svc (push) Failing after 6m12s
Build backend images / build studio-svc (push) Failing after 4m14s
Extends CopyTemplateGraphAsync: repeater children flatten into saved_scene_contents (repeater_item_key/index via repeater_items); scene characters+controllers and color presets+items copied, correlated by (new scene, original-id/sort) since studio tables lack original-id columns. studio character.key is a uuid → store original char id. No regression on templates without these (copy 0 rows). All enum cols cast ::text. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
076c2e577f |
fix(render): resolve template id for render jobs + mock-fallback when no .aep
Build backend images / build content-svc (push) Failing after 1m30s
Build backend images / build file-svc (push) Failing after 1m23s
Build backend images / build gateway (push) Failing after 5m47s
Build backend images / build identity-svc (push) Failing after 1m23s
Build backend images / build notification-svc (push) Failing after 1m51s
Build backend images / build render-svc (push) Failing after 1m23s
Build backend images / build studio-svc (push) Failing after 1m23s
THE bug behind "AEPFilePath is required for real AE render": CreateJob inserted
original_project_id = saved_project_id (VALUES $3,$3), so the claim looked for the
render bundle at templates/{saved_project_id}/ — which never exists. The bundle
lives at templates/{TEMPLATE_id}/. Now original_project_id is resolved from
studio.saved_projects.original_project_id (the template the project was built from).
(Direct-SQL test renders masked this by setting the template id explicitly.)
Also harden the node-agent: Run() falls back to mock render when AEPFilePath is
empty even if AE is installed (previously hard-errored), so a missing/un-promoted
template degrades gracefully instead of failing the job.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
62807f5f41 |
fix(node-agent): resilient output upload — 60s HTTP timeout + 4× retry on upload-URL
After a CPU-heavy AE render+transcode the orchestrator/DB can be briefly slow; the 15s client timeout made the post-render output-upload-url call fail and the finished MP4 was dropped (completed without export). Bumped client timeout to 60s and retry the upload-URL call up to 4× with backoff so a finished render's output is never lost to a transient stall. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
e59f07df4e |
fix(node-agent): transcode AE render to MP4 with ffmpeg (real renders deliver MP4)
aerender can't reliably write H.264 directly in modern AE — it renders the project's output module (Lossless AVI/MOV) and ignores the .mp4 extension, producing a multi-GB .avi the agent then failed to find/upload. - findRenderedOutput(): locate the file aerender actually wrote (output.avi/.mov/.mp4) - transcodeToMP4(): ffmpeg → H.264 yuv420p + AAC + faststart; drops the lossless intermediate. ffmpeg located via $FFMPEG_PATH, beside the agent exe, or PATH. - Graceful fallback: if ffmpeg is missing/fails, upload the raw render so the job still delivers a (large but valid) file. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
077b5ac5d5 |
fix(render): export INSERT used wrong column + lowercase enum labels (the real 500)
Build backend images / build content-svc (push) Failing after 59s
Build backend images / build file-svc (push) Failing after 48s
Build backend images / build gateway (push) Failing after 59s
Build backend images / build identity-svc (push) Failing after 53s
Build backend images / build notification-svc (push) Failing after 55s
Build backend images / build render-svc (push) Failing after 59s
Build backend images / build studio-svc (push) Failing after 54s
The output-upload-url 500 was NOT the enum cast — it was:
1. INSERT referenced original_project_id; the exports table column is project_id
2. file_type/create_type literals were lowercase ('video'/'render') but the
export_file_type/export_create_type enums are PascalCase ('Video'/'Render')
Verified the corrected INSERT against the live schema. Now real renders produce
a downloadable export instead of completing with export=nil.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
ddc0a2d0d9 |
feat(admin): manually edit scene inputs (content elements)
Scene content elements (the editable Text/Media/Color/… inputs inside a scene) had no CRUD — only AEP-import created them, so admins couldn't define or edit them. Added full management: content-svc: - SceneElementsController: GET/POST/PUT/DELETE /v1/scene-elements?scene_id= - SceneColorService: Get/Create/Update/DeleteContentElementAsync - ContentElementResponse + SaveContentElementRequest (key, title, type, default_value, hint, position, text-box/font/media flags) gateway: route /v1/scene-elements/*path → content frontend: SceneColorEditor scenes tab → per-scene "ورودیها" expander with full add/edit/delete of inputs (15 element types: Text/Media/Color/Number/…) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
9d499a89de |
fix(render): real AE render — pass -comp, fix export insert, ensure exports bucket
Three bugs surfaced bringing up a real After Effects node (verified: AE 2026
claimed + ran, but produced no usable output):
1. aerender got no -comp/-rqindex → "output argument ignored", nothing rendered.
- Claim now returns comp_name from content.projects.render_aep_comp (e.g. "frfinal")
via new Store.GetTemplateCompName; threaded through ClaimedJob → runner.Job →
aerender args (`-comp <name>`, or `-rqindex 1` fallback when unknown).
2. CreateExportForJob INSERT passed render_quality as a bare param into an enum
column → 500 ("output-upload-url HTTP 500"), so completed renders had no export.
- Cast $8::render.render_quality (+ explicit casts for file_type/create_type enums).
3. flatrender-exports bucket didn't exist → uploads would fail anyway.
- render-svc now MakeBucket(exports, templates) idempotently at startup.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
43d0e10543 |
fix(render+studio): dev mock worker (unstick the queue) + lock predefined layers
Render — "stuck in Queued" fix: - Jobs were created Queued and only a Windows AE node could claim them, so in the dev stack (no node) they queued forever. - New devworker package: in-process mock worker drives Queued jobs through the steps with progress + live preview frames → Done. Enabled via RENDER_DEV_WORKER (default true in compose; set false in prod where real nodes claim jobs). - db: DevClaimNextQueued (atomic oldest-queued → Preparing) + UpdateJobStepProgress - Verified live: a stuck job advanced Preparing→Done in ~10s with frontend polling. Studio — predefined template structure: - Projects are always copied from a template; structure is fixed. Users customise existing layers, they don't add new ones. - New studio-config flag ALLOW_ADD_LAYERS (false): StudioToolbar (add text/image/ video/shape) returns null; SceneEditSidebar "add text layer" button hidden. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
81912cac66 |
feat(render): full-screen render page, one-active-render limit, app-wide progress
Build backend images / build content-svc (push) Failing after 14s
Build backend images / build file-svc (push) Failing after 1m28s
Build backend images / build gateway (push) Failing after 1m43s
Build backend images / build identity-svc (push) Failing after 3m0s
Build backend images / build notification-svc (push) Failing after 51s
Build backend images / build render-svc (push) Failing after 1m3s
Build backend images / build studio-svc (push) Failing after 1m1s
Concurrent-render ceiling (a user runs 1 render at a time unless granted more):
- Identity: TokenService emits max_renders claim from User.ParallelRenderingCeiling
- Identity: admin POST /v1/users/{id}/render-slots (AdminService.SetRenderSlotsAsync,
clamped 1..50) — gamification or admin raises a user's ceiling
- render-svc: middleware reads max_renders (default 1); CreateJob rejects with 409
active_render_limit when active jobs >= ceiling
- render-svc: db.CountActiveJobs + ListActiveJobs; GET /v1/renders/active returns
in-flight renders + can_start_new
Full-screen render page (replaces the modal):
- /studio/render/[projectId]: config (resolution/fps) → live preview + progress →
download; resumes this project's in-flight render on mount; blocks when another
render is active; reads ?preset=
- StudioTopBar export menu now navigates to the page; RenderModal deleted (dead)
App-wide minimal progress:
- GlobalRenderProgress pill mounted in the locale layout for authed users; polls
/api/render/active every 4s, shows thumbnail + step + % on every page, click →
the render page; hidden on the render page and when idle
Admin: UserActions gains a "concurrent render slots" control.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
52be5be93f |
feat(node-agent): production ops kit — Windows service + WireGuard mesh
config:
- LoadEnvFile(): reads agent.env beside the exe (or $AGENT_ENV_FILE) before env,
so the sc.exe service needs no per-service environment plumbing; real env wins
deploy/ (new):
- build-windows.ps1 cross-compile → dist\ + stage the deploy kit
- agent.env.example fully documented config template
- install-service.ps1 register as auto-start Windows service (native sc.exe),
crash-restart 3×/5s, no NSSM dependency
- uninstall-service.ps1 stop + remove
- wireguard-node.conf.template + setup-wireguard.ps1 node dials out only, no
public IP / inbound rules; tunnel installed as boot service
- README.md full control-plane + node walkthrough, ops table, troubleshooting
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
67060c73b2 |
feat(admin): discount edit/delete + project-scoped scene/color editor
Identity (discounts):
- DiscountsController: PUT /v1/discounts/{id}, DELETE /v1/discounts/{id}
- DiscountService.UpdateAsync (partial update, code-clash guard) + DeleteAsync
- UpdateDiscountRequest record (all fields optional incl. is_active)
- Frontend discountsConfig: canEdit + canDelete + is_active field
Content (scenes/colors — UI for existing CRUD endpoints):
- New SceneColorEditor.tsx: 3-tab modal (scenes / shared-colors / color-presets),
project-scoped, full add/edit/delete per tab, colour pickers + palette item editor
- Wired into TemplatesAdmin: "صحنهها و رنگها" button per template variant row
- Routes through the generic admin proxy with ?project_id=
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
0ca11f19dd |
feat(studio): copy template scene graph into editable project (use-template works)
Build backend images / build content-svc (push) Failing after 53s
Build backend images / build file-svc (push) Failing after 51s
Build backend images / build gateway (push) Failing after 1m2s
Build backend images / build identity-svc (push) Failing after 57s
Build backend images / build notification-svc (push) Failing after 45s
Build backend images / build render-svc (push) Failing after 58s
Build backend images / build studio-svc (push) Failing after 53s
Build now created an EMPTY project: (1) the studio binds camelCase but the frontend sent snake_case → original_project_id dropped to Guid.Empty; (2) CreateProjectAsync never copied scenes. Now: - saved-projects.ts sends camelCase (originalProjectId/copyDefaultValues). - /api/projects resolves the container slug → first published variant content project. - StudioService.CreateProjectAsync deep-copies the content scene graph (scenes + content elements + scene colours + shared colours) into the new saved project via one atomic cross-schema SQL copy (enum cols cast to text; temp scene-id map). Verified: insta-promo → 1 scene, 6 content fields, 4 shared colours, loadable by the studio editor. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
d4fee8d1d7 |
feat(profile): role-aware nav + avatar menu + full editable profile
Build backend images / build content-svc (push) Failing after 1m59s
Build backend images / build file-svc (push) Failing after 3m18s
Build backend images / build gateway (push) Failing after 3m28s
Build backend images / build identity-svc (push) Failing after 2m1s
Build backend images / build notification-svc (push) Failing after 4m45s
Build backend images / build render-svc (push) Failing after 5m18s
Build backend images / build studio-svc (push) Failing after 2m12s
Navigation: - UserMenu (avatar + role-aware dropdown: Dashboard, Admin Panel for admins, Profile, Sign out) replaces Sign In/Try Free when logged in (desktop + mobile). - Real avatars in dashboard sidebar + a new admin-shell profile section. - Shared Avatar primitive (image with initials fallback). SiteChrome excludes /admin. Profile (data-collection surface for future AI video generation): - SettingsProfile rebuilt: avatar upload + slogan, about, company, website, country, national code, birthdate, gender. No resume builder (per scope change). - /api/profile forwards all fields; new user-scoped /api/profile/upload (avatar → MinIO via file-svc, sets avatar). Identity UpdateUserRequest/UserResponse widened (country/national/method); no DB migration (columns already exist). - fa+en strings; verified GET/PATCH round-trip + logged-in SSR render. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
718564bce4 |
feat(scan): binary FIX scan reads frl_/frd_ names from .aep (no AE, never hangs)
Build backend images / build content-svc (push) Failing after 15s
Build backend images / build file-svc (push) Failing after 1m51s
Build backend images / build gateway (push) Failing after 51s
Build backend images / build identity-svc (push) Failing after 57s
Build backend images / build notification-svc (push) Failing after 52s
Build backend images / build render-svc (push) Failing after 56s
Build backend images / build studio-svc (push) Failing after 57s
Root cause of 'stuck on AE': heavy expression-driven projects take >10min for AE to open, exceeding the scan timeout → job dies → admin UI stuck 'scanning'. Fix: extend the stdlib .aep RIFX parser to collect every Utf8 name (ParseNames), since FIX media placeholders are renamed footage ITEMS (frl_c1m1), not layers, and text are layer names (frl_c1t1) — both are Utf8 chunks. QuickScan now branches on ?mode= (or auto-detects frl_ names) and scaffolds FIX scenes/elements + frd_*color slots directly from the binary. Verified on the real final.aep that timed out in AE: 1 scene, 6 elements, 4 colors in 0.5s vs 10-min AE timeout. Admin 'Quick scan (no AE)' is now the recommended path and passes the project mode. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
f0ce286527 |
fix(scan): force-kill stale AE processes before each launch (fresh start)
Build backend images / build content-svc (push) Failing after 54s
Build backend images / build file-svc (push) Failing after 56s
Build backend images / build gateway (push) Failing after 57s
Build backend images / build identity-svc (push) Failing after 58s
Build backend images / build notification-svc (push) Failing after 1m4s
Build backend images / build render-svc (push) Failing after 2m27s
Build backend images / build studio-svc (push) Failing after 55s
PrepareFreshAE = taskkill AfterFX/aerender/AfterFXLib/dynamiclinkmanager/QT32 + 2s settle + clear crash markers, then launch. A hung/zombie AE from a prior job would otherwise block or corrupt the new run. RunScan now calls it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
6e5efbdb2c |
fix(scan): also clear AE AppStates registry to stop Safe Mode 'Crash Repair' dialog
Build backend images / build content-svc (push) Failing after 2m1s
Build backend images / build file-svc (push) Failing after 1m0s
Build backend images / build gateway (push) Failing after 56s
Build backend images / build identity-svc (push) Failing after 54s
Build backend images / build notification-svc (push) Failing after 54s
Build backend images / build render-svc (push) Failing after 46s
Build backend images / build studio-svc (push) Failing after 48s
SCRPriorState.json alone didn't suppress it — AE's per-session GUID under HKCU\Software\Adobe\After Effects\AppStates persists after a kill/crash and trips Safe Mode. ClearAECrashState now reg-deletes AppStates too (reg.exe, no dep). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
47dd87c60b |
fix(scan): launch AE with the project as arg to bypass the Home screen
Build backend images / build content-svc (push) Failing after 1m13s
Build backend images / build file-svc (push) Failing after 1m35s
Build backend images / build gateway (push) Failing after 57s
Build backend images / build identity-svc (push) Failing after 1m28s
Build backend images / build notification-svc (push) Failing after 53s
Build backend images / build render-svc (push) Failing after 1m4s
Build backend images / build studio-svc (push) Failing after 55s
afterfx -r alone leaves AE on its empty Home/Start screen, which blocks the script from running (AE sits idle on Untitled Project until the scan times out). Now launch 'afterfx <aep> -r scan.jsx' so the project opens directly; scan.jsx uses the already-open project and only app.open()s as a fallback. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
010f975a0e |
fix(nodes): add disk columns to ListNodes SELECT (scanNodes 37/39 mismatch → 500)
Build backend images / build content-svc (push) Failing after 50s
Build backend images / build file-svc (push) Failing after 56s
Build backend images / build gateway (push) Failing after 54s
Build backend images / build identity-svc (push) Failing after 58s
Build backend images / build notification-svc (push) Failing after 58s
Build backend images / build render-svc (push) Failing after 51s
Build backend images / build studio-svc (push) Failing after 59s
The disk-column append only hit GetNodeByID (whitespace differed); ListNodes lacked last_disk_pct/disk_total_gb, so the node list 500'd and rendered empty. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
0c461ff841 |
fix(import): IgnoreQueryFilters so revive sees soft-deleted scenes; clear AE crash state
Build backend images / build content-svc (push) Failing after 53s
Build backend images / build file-svc (push) Failing after 58s
Build backend images / build gateway (push) Failing after 1m1s
Build backend images / build identity-svc (push) Failing after 57s
Build backend images / build notification-svc (push) Failing after 59s
Build backend images / build render-svc (push) Failing after 49s
Build backend images / build studio-svc (push) Failing after 49s
- AepImportService: the global Scene HasQueryFilter(DeletedAt==null) was hiding soft-deleted rows, so the revive never matched and the importer re-inserted → scenes_project_id_key violation. Add .IgnoreQueryFilters() to the load. (apply now revives + returns 200, verified.) - node-agent: ClearAECrashState() deletes AE's SCRPriorState.json before each launch so the 'Crash Repair Options' dialog can't hang a headless scan/render. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
0a7dd9b84c |
feat(nodes): live CPU/RAM/disk monitoring in the node list
Build backend images / build content-svc (push) Failing after 45s
Build backend images / build file-svc (push) Failing after 55s
Build backend images / build gateway (push) Failing after 53s
Build backend images / build identity-svc (push) Failing after 54s
Build backend images / build notification-svc (push) Failing after 53s
Build backend images / build render-svc (push) Failing after 47s
Build backend images / build studio-svc (push) Failing after 51s
- node-agent: internal/metrics — read CPU% (GetSystemTimes), RAM (GlobalMemoryStatusEx), disk used%/total (GetDiskFreeSpaceEx) via stdlib kernel32 (no external dep; windows build + non-windows stub). Heartbeat now reports cpu_pct/ram_available_mb/disk_used_pct/ disk_total_gb + ae_running. - render-svc: heartbeat persists last_disk_pct + disk_total_gb (migration 29); RenderNode model + node SELECT/scan carry them. - admin: rewrite NodesTable to the real RenderNode shape (fixes a pre-existing items/V2Node mismatch that left the list empty) + a CPU/RAM/disk bars column + stale-heartbeat flag. - assets-bundle ingestion: ProjectMediaBundle (jszip) auto-maps project.zip → project/scene image/demo/colour + music; PatchProject gains image/full_demo/shared_colors_svg. - scan: RGBA (4-number) colours recognised + frshare single-int controls detected. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
6661f53734 |
fix(scan): Fix-mode scanner + dialog suppression + cancel/timer + importer revive
Build backend images / build content-svc (push) Failing after 1m25s
Build backend images / build file-svc (push) Failing after 1m10s
Build backend images / build gateway (push) Failing after 56s
Build backend images / build identity-svc (push) Failing after 53s
Build backend images / build notification-svc (push) Failing after 57s
Build backend images / build render-svc (push) Failing after 48s
Build backend images / build studio-svc (push) Failing after 1m5s
- scan.jsx: app.beginSuppressDialogs() + clean quit (no AE hang on font/footage dialogs); FIX-mode branch parses frl_c(x)t/m(y) layer names → scenes by c(x); flexible/mockup keep comp-based walk; FR_SCAN_MODE selects. - render-svc: scan job carries project mode; cancel endpoint + node watchdog that kills AE on cancel; parseObjectURL handles minio:// (bucket in host); scan with no template fails cleanly; status guards so late results can't un-cancel. - content importer: revive soft-deleted scenes instead of duplicate-inserting (fixes scenes_project_id_key unique violation); orphan diff ignores deleted. - admin: scan dialog gets project-type picker + elapsed timer + Cancel button. - node-agent: AE-2026 wiring (host port 5010, host-reachable presign endpoint), FR_SCAN_MODE plumbing. docs/aep-template-convention.md: per-type naming + bundles. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
ee670552a8 |
feat: cross-aspect project duplication + AEP convention/rule-engine spec
Build backend images / build content-svc (push) Failing after 1s
Build backend images / build file-svc (push) Failing after 0s
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 2s
Build backend images / build studio-svc (push) Failing after 0s
- content-svc: DuplicateProjectAsync clones full scene/element/colour graph
(identical keys, new dimensions/aspect; AEP intentionally not copied;
starts unpublished) + POST /v1/projects/{id}/duplicate.
- admin: «تکثیر» button + modal on each project row; aspects reduced to
supported 16:9/1:1/9:16; free fps default 21 (clamped 1-60).
- docs/aep-template-convention.md: versioned (v1/v2) convention + rule-engine
spec — modes, scene types, flatrender assembly, duration/fade model,
fit-box, input types, expression-driven data flow, output spec.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
1ff6e494c0 |
@
Build backend images / build content-svc (push) Failing after 19s
Build backend images / build file-svc (push) Failing after 1m53s
Build backend images / build gateway (push) Failing after 16s
Build backend images / build identity-svc (push) Failing after 7m1s
Build backend images / build notification-svc (push) Failing after 7m24s
Build backend images / build render-svc (push) Failing after 3m12s
Build backend images / build studio-svc (push) Failing after 43s
feat: AE template scanner + scene editor + AEP bundle pipeline
Scene editor (admin): per-project Scenes / Shared Colors / Color Presets
manager (ProjectScenes) reachable from each project.
AEP bundle pipeline: upload .aep or .zip → stored once per template at
templates/{project_id}/(bundle.zip|template.aep); render claim probes and
returns is_bundle+md5; node-agent extracts the bundle, locates the .aep
(zip-slip guarded), and caches by md5 so repeated renders extract once.
AE template scanner ("read scenes/colours/configs from the AEP"):
- content-svc importer: POST /v1/projects/{id}/scan/{preview,apply} —
review-diff-then-merge into scenes/elements/colours (manual edits kept).
- render-svc Go quick-scan: stdlib RIFX parser extracts comp names+durations
(no AE) → POST /v1/template-scans/{id}/quick.
- render-svc AE scan jobs + node-agent runner: queue → node runs scan.jsx
(reverse of legacy JSXGenerator conventions: frfinal/frshare/frl_/frd_) →
posts ScanResult back. Migration 26_render_scan_jobs.
- admin UI: "اسکن از افترافکت" with quick/full engines + diff-review modal.
Verified: importer preview/apply, Go quick-scan end-to-end (synthetic .aep →
scene imported), bundle extract unit tests, RIFX parser unit tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
|
||
|
|
ebf0e11f22 |
fix(render+admin): render queue shows ALL users' jobs
Build backend images / build content-svc (push) Failing after 53s
Build backend images / build file-svc (push) Failing after 55s
Build backend images / build gateway (push) Failing after 58s
Build backend images / build identity-svc (push) Failing after 1m0s
Build backend images / build notification-svc (push) Failing after 49s
Build backend images / build render-svc (push) Failing after 56s
Build backend images / build studio-svc (push) Failing after 59s
The admin render queue called the user-scoped /v1/renders (so it only showed the admin's own jobs) and parsed items/total instead of data/meta (→ always empty). - render-svc: GET /v1/admin-renders (admin) → ListAllJobs across users, optional ?status= filter; gateway-wired - admin renders page now fetches /v1/admin-renders and reads data/meta correctly Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
928956689b |
feat(render+admin): exports management (all users' rendered videos)
Build backend images / build content-svc (push) Failing after 54s
Build backend images / build file-svc (push) Failing after 55s
Build backend images / build gateway (push) Failing after 52s
Build backend images / build identity-svc (push) Failing after 55s
Build backend images / build notification-svc (push) Failing after 58s
Build backend images / build render-svc (push) Failing after 48s
Build backend images / build studio-svc (push) Failing after 1m0s
- render-svc: admin-scoped store (ListAllExports / GetExportByIDAny / SoftDeleteExportAny) + GET/DELETE/download-url under /v1/admin-exports (admin-gated; separate prefix so it routes to render, not identity's /admin) - gateway: /v1/admin-exports/* → render - admin /admin/exports: paginated table of every rendered export with thumbnail, type/quality, size, duration, dimensions, produce + expiry dates; download (presigned URL) and delete Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
7f2f65dd8a |
feat(render+node-agent+admin): install fonts on all render nodes + verify
Build backend images / build content-svc (push) Failing after 53s
Build backend images / build file-svc (push) Failing after 47s
Build backend images / build gateway (push) Failing after 52s
Build backend images / build identity-svc (push) Failing after 58s
Build backend images / build notification-svc (push) Failing after 55s
Build backend images / build render-svc (push) Failing after 59s
Build backend images / build studio-svc (push) Failing after 48s
Push a font once → every node installs it → admin sees per-node status. - render-svc: font_requests + node_fonts tables (mig 25); admin GET/POST/DELETE /v1/node-fonts (with per-node status matrix); internal (HMAC) GET pending + POST status for node-agents - node-agent: fontSyncLoop polls pending fonts every 60s, downloads, installs (Windows Fonts dir + registry / macOS / linux fc-cache), reports Installed/Failed - gateway: /v1/node-fonts/* → render - admin /admin/node-fonts: upload a .ttf/.otf → install on all nodes; per-node Installed/Pending/Failed badges + counts + delete Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
ca0c05db10 |
fix(identity): internal render-charge request binding (record → class)
Build backend images / build content-svc (push) Failing after 1m0s
Build backend images / build file-svc (push) Failing after 47s
Build backend images / build gateway (push) Failing after 57s
Build backend images / build identity-svc (push) Failing after 1m2s
Build backend images / build notification-svc (push) Failing after 1m0s
Build backend images / build render-svc (push) Failing after 1m1s
Build backend images / build studio-svc (push) Failing after 58s
The nested positional record ChargeReq(Guid UserId) failed System.Text.Json binding under the snake_case policy (400). Use a plain class with a settable property. Verified: consume decrements + blocks at 0, refund restores, bad service token → 401. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
1f52f53cf7 |
feat(render+identity): daily render-limit — consume on submit, refund on admin-stop
Build backend images / build content-svc (push) Failing after 51s
Build backend images / build file-svc (push) Failing after 53s
Build backend images / build gateway (push) Failing after 1m1s
Build backend images / build identity-svc (push) Failing after 48s
Build backend images / build notification-svc (push) Failing after 42s
Build backend images / build render-svc (push) Failing after 47s
Build backend images / build studio-svc (push) Failing after 1m13s
Business rule: each user has a daily render limit. Admin-stop refunds the used
charge (not the user's fault); a user's own cancel does not.
- identity: ConsumeRenderChargeAsync / RefundRenderChargeAsync on DailyRemainRenderCount
with lazy daily reset (mig 24: daily_renders_reset_at). Convention: max=0 ⇒ UNLIMITED,
so existing 0/0 users keep rendering until an admin sets a real limit.
- identity InternalController (service-token): POST /v1/internal/render-charge/{consume,refund}
- render-svc: identityclient + on Create consume (block 429 when limit reached, fail-open
on identity outage); on admin Stop refund the job owner; user /cancel unchanged
- compose: IDENTITY_URL for render-svc, ServiceToken for identity-svc
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
7f7feabb85 |
feat(render+admin): stop a render job (admin, any owner)
Build backend images / build content-svc (push) Failing after 1m0s
Build backend images / build file-svc (push) Failing after 1m3s
Build backend images / build gateway (push) Failing after 1m2s
Build backend images / build identity-svc (push) Failing after 1m20s
Build backend images / build notification-svc (push) Failing after 1m13s
Build backend images / build render-svc (push) Failing after 1m5s
Build backend images / build studio-svc (push) Failing after 1m0s
The render-queue cancel button used the owner-scoped /cancel (WHERE user_id=…),
so an admin couldn't stop another user's job. Added:
- render-svc: POST /v1/renders/:job_id/stop (admin-gated) → store.StopJob cancels
any in-progress job regardless of owner and frees the assigned node
- admin: render-queue button now "توقف" → /api/admin/renders/{id}/stop (with confirm)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
c076345ceb |
feat(render+admin): delete render node
Build backend images / build content-svc (push) Failing after 1m7s
Build backend images / build file-svc (push) Failing after 48s
Build backend images / build gateway (push) Failing after 55s
Build backend images / build identity-svc (push) Failing after 56s
Build backend images / build notification-svc (push) Failing after 1m7s
Build backend images / build render-svc (push) Failing after 53s
Build backend images / build studio-svc (push) Failing after 59s
- render-svc: DELETE /v1/nodes/:node_id (store.DeleteNode + handler + route) - admin: حذف button per node row + DELETE /api/admin/nodes/[nodeId] proxy Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
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>
|
||
|
|
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>
|