• …k, stale-task recovery, pagination
    
    Person reference photos (any subset of full-body/face x front/side/back) +
    one garment image -> async background task generating front/side/view
    composites of that person wearing the garment, via either GPT Image 2
    (万界方舟) or wavespeed.ai's Seedream v4. Split into three pages
    (admin-dressgen.html create / admin-dressgenlist.html list /
    admin-dressgendetail.html detail) since the combined page's operations
    column was easy to lose off-screen; the list page's action column is now
    sticky and every thumbnail opens a click-to-zoom preview.
    
    Default provider (image2) auto-falls-back to wavespeed per view on any
    failure — an explicit, later product decision overriding this session's
    earlier "no auto-switching around moderation" stance, recorded in the code
    comment above WAVESPEED_API_KEY. A crashed/restarted process no longer
    leaves a task stuck in "generating" forever (resumeDressgenTasks(), same
    idea as T8's resumeDressupGenerations()). GET /api/admin/dressgen is now
    paginated (?page=&pageSize=, defaults 20) instead of returning the whole
    file as a bare array.
    
    19 tests in dressgen-generate.test.js, including a real crash-and-restart
    scenario (SIGKILL against a hanging mock, second process reading the same
    on-disk store) and the auto-fallback path.
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01Px7XHxSdWfd5b3vfNMwQjd
    yibo authored
     
    Browse File »

  • T32: moderateFaceBlacklist(imagePath, assetId) — same pluggable seam
    shape as T26, for mode 3's uploaded face photos (需求文档 5 节: filtering
    politically-sensitive likenesses). Default-permissive (auto_pass) when
    unconfigured, per explicit user confirmation this session — deliberately
    not assumed, since a wrong-default here (a real face silently passed
    through) has a different risk profile than T26's garment photos.
    
    T33: forwardToFalAssets (uploads.js) + fal's queue API (falSubmit/
    falPollStatus/falFetchResult) wired into submitGeneration/
    generateDanceVideo, which now dispatches on job.backend between the
    existing H3 Console path (renamed generateDanceVideoViaH3, unchanged
    behavior) and the new generateDanceVideoViaFal. A paid request (userId
    set) routes to fal once FAL_API_KEY is configured; everything else —
    free mode-一, or paid but no key yet — stays on H3 Console exactly as
    before (verified: full suite green, no FAL_API_KEY set in any existing
    test's env).
    
    Endpoints/params (storage/upload/initiate, queue.fal.run/{model}/
    requests/{id}/status vs /requests/{id} as two separate calls,
    Authorization: Key <FAL_API_KEY>) are taken from fal's published docs
    and the fal-js client's own source, not guessed — fal-generation.test.js
    proves this codebase's side of the integration against a mock fal
    server. What remains genuinely unverified (no FAL_API_KEY exists) is
    whether the H3-Console-tuned prompt is interpreted the same way by
    fal's minimax/h3/reference-to-video model, and fal's exact
    terminal-failure status string(s) — flagged in code comments rather
    than guessed at.
    
    Also fixes a real gap T27 shipped with: submitGeneration never received
    userId, so every mode-2 clip's requestedByUserId (M.7) was silently
    null. T27's call site now passes userId (priority stays "normal" —
    only mode 3 skips voting), which also makes mode 2 fal-eligible.
    dance-mode2.test.js's happy-path test now asserts this.
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_011DUiYs6UjxDMkfvnjtsKFo
    yibo authored
     
    Browse File »
  • POST /api/admin/upload-video: mp4 magic-byte sniff (checks the ftyp
    box, not offset-0 like images), 50MB cap, no re-encode needed (unlike
    images, no EXIF/GPS concern for video). Reuses the multipart parser
    and uploads/ layout from T2's image path via a shared placeInUploads
    helper.
    yibo authored
     
    Browse File »
  • POST /api/admin/upload: hand-rolled multipart parser (no deps installed
    in this project), real magic-byte sniffing (rejects extension-spoofed
    files), 8MB cap, and EXIF/GPS stripping via a sips bmp round-trip
    (macOS-native, no dependency — sips's direct jpeg->jpeg re-encode alone
    does NOT strip EXIF, only the bmp intermediate does). GET /uploads/*
    serves the result with a path-traversal guard.
    
    forwardToH3Assets() is the T7/T8 hook for pushing a saved upload to H3
    Console's own POST /v1/assets (found in the S1-S4 spike) — not covered
    by the automated suite since it needs a live network call, same
    treatment as the spike scripts.
    yibo authored
     
    Browse File »