kingkong

kingkong pushed to feature/phase6-guest-comments-finalization at kingkong/vidreview

  • 9c716fb08a fix: display guest name correctly instead of "Unknown" Root cause: guestName scalar field was placed inside Prisma's user relation select block (guestName: true) — Prisma doesn't have a guestName relation on User, so this silently dropped the field. Fix: - share.ts: removed erroneous guestName: true from user select in both GET and POST comment include blocks. Scalar fields are returned automatically at top level; no explicit select needed. - api.ts: added optional guestName field to Comment interface. - CommentPanel.tsx: CommentItem and replies now prefer comment.guestName over comment.user.name to show the actual guest-provided name. Avatar initials also use guestName. - share/[token]/page.tsx: PanelComment interface now includes guestName field; toPanelComment passes it through. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

1 month ago

kingkong pushed to feature/phase6-guest-comments-finalization at kingkong/vidreview

  • f5f245db1a fix: include guestName in share comment responses The GET /comments and POST /comments endpoints were omitting guestName from the Prisma select/include, causing guest comment names to be "Unknown" on the share page.

1 month ago

kingkong pushed to feature/phase6-guest-comments-finalization at kingkong/vidreview

  • edbe0f2591 fix: annotation canvas always reads size from boundingRect Canvas was getting 0×0 on first render because the parent div with aspect-ratio CSS hadn't resolved yet. Now getBoundingClientRect() is called directly on the canvas element each time.

1 month ago

kingkong pushed to feature/phase6-guest-comments-finalization at kingkong/vidreview

  • 4360db5752 feat: add annotation drawing to guest comment form on share page Guest users can now draw annotations (pen, arrow, rect, ellipse) on the video before posting a comment. Strokes are sent as annotations[] in the comment payload and cleared on submit.

1 month ago

kingkong pushed to feature/phase6-guest-comments-finalization at kingkong/vidreview

  • 8e32c504f6 feat: add timecode to guest comments on share token page Guest comments now capture the current video playback position (timestamp) on submit, matching registered user comment behavior. Shows "Comment at HH:MM:SS" preview above the Post button.

1 month ago

kingkong pushed to feature/phase6-guest-comments-finalization at kingkong/vidreview

  • 5b7e87e3ab fix: add DB indexes and fix watchdog transcodePaused handling Root cause fixes for stuck jobs: - Add composite index on (transcodeStatus, transcodePaused) — claimOneJob() hot path was doing full table scans with every poll cycle - Add composite index on (transcodeStatus, updatedAt) — resetStuckJobs() watchdog was also full scanning on every watchdog tick - resetStuckJobs(): also clear transcodePaused when resetting a job (was leaving paused=true on reset → job reset to PENDING but still invisible to claimOneJob() because of the AND transcodePaused=false guard) Indexes created manually on test DB: idx_asset_transcode_queue, idx_asset_watchdog Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

1 month ago

kingkong pushed to feature/phase6-guest-comments-finalization at kingkong/vidreview

  • 0eec6d685d feat: project-scoped Force Start Stuck Jobs for admins and editors - Both global ADMIN and project ADMIN/EDITOR can now: - See the "Force Start Stuck Jobs" button - Call /api/assets/admin/stuck-count (projectId param) - Call /api/assets/admin/reprocess-all (projectId in body) - stuck-count endpoint: if projectId provided, checks project membership (ADMIN/EDITOR) instead of global ADMIN only - reprocess-all endpoint: same project-scoped auth - Button renamed from "Force Reprocess All" → "Force Start Stuck Jobs" - Badge shows project-wide stuck count (was workspace-wide before) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

1 month ago

kingkong pushed to feature/phase6-guest-comments-finalization at kingkong/vidreview

  • f100cee2ec chore: show Force Reprocess All button for editors and admins TranscodeTasksPanel button now checks canManage (ADMIN | EDITOR in project) instead of only globalRole ADMIN. Editors can also force-reset stuck jobs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

1 month ago

kingkong pushed to feature/phase6-guest-comments-finalization at kingkong/vidreview

  • 86bd5f0ac4 chore: add STUCK_TIMEOUT_MS to test worker in docker-compose.yml Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

1 month ago

kingkong pushed to feature/phase6-guest-comments-finalization at kingkong/vidreview

  • 0e852341e3 fix: eliminate stuck job root causes — button visibility, watchdog, and cancel bugs - isAdmin: check user.globalRole === 'ADMIN' instead of project membership (button was invisible to workspace admins who weren't project ADMINs) - Add GET /api/assets/admin/stuck-count: lightweight workspace-wide PROCESSING count (registered before /:id to prevent Express shadowing bug) - TranscodeTasksPanel: use globalStuckCount (polled from API every 30s) for button disabled/badge state instead of per-page count - Watchdog: move from poll() idle path to setInterval(STUCK_TIMEOUT_MS) so stuck jobs are detected even when the queue is perpetually full - Watchdog grace period: recentlyReset Set prevents same worker from immediately re-claiming a job it just watchdog-reset (WATCHDOG_GRACE_MS = 50% of timeout or 30s) - Cancel endpoint: also clears transcodePaused so paused+cancelled jobs are re-claimable - docker-compose.dev.yml: pass STUCK_TIMEOUT_MS (default 300s) to worker container - Dockerfile.api: remove read-only file system DNS override that broke builds Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
  • e194038778 fix: eliminate stuck job root causes — button visibility, watchdog, and cancel bugs - isAdmin: check user.globalRole === 'ADMIN' instead of project membership (button was invisible to workspace admins who weren't project ADMINs) - Add GET /api/assets/admin/stuck-count: lightweight workspace-wide PROCESSING count - TranscodeTasksPanel: use globalStuckCount (polled from API) for button disabled/badge state instead of per-page count that was always zero when stuck jobs were on other pages - Watchdog: move from poll() idle path to setInterval(STUCK_TIMEOUT_MS) so stuck jobs are detected even when the queue is perpetually full - Watchdog grace period: recentlyReset Set tracks jobs reset by watchdog; they can't be re-claimed by the same worker for WATCHDOG_GRACE_MS (50% of timeout or 30s min) to prevent tight reset→re-claim→fail→reset loops - Cancel endpoint: also clears transcodePaused so paused+cancelled jobs become re-claimable - docker-compose.dev.yml: pass STUCK_TIMEOUT_MS (default 300s) to worker container (5 min is appropriate for dev with slow software encoding) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
  • View comparison for these 2 commits »

1 month ago

kingkong pushed to feature/phase6-guest-comments-finalization at kingkong/vidreview

  • e194038778 fix: eliminate stuck job root causes — button visibility, watchdog, and cancel bugs - isAdmin: check user.globalRole === 'ADMIN' instead of project membership (button was invisible to workspace admins who weren't project ADMINs) - Add GET /api/assets/admin/stuck-count: lightweight workspace-wide PROCESSING count - TranscodeTasksPanel: use globalStuckCount (polled from API) for button disabled/badge state instead of per-page count that was always zero when stuck jobs were on other pages - Watchdog: move from poll() idle path to setInterval(STUCK_TIMEOUT_MS) so stuck jobs are detected even when the queue is perpetually full - Watchdog grace period: recentlyReset Set tracks jobs reset by watchdog; they can't be re-claimed by the same worker for WATCHDOG_GRACE_MS (50% of timeout or 30s min) to prevent tight reset→re-claim→fail→reset loops - Cancel endpoint: also clears transcodePaused so paused+cancelled jobs become re-claimable - docker-compose.dev.yml: pass STUCK_TIMEOUT_MS (default 300s) to worker container (5 min is appropriate for dev with slow software encoding) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

1 month ago

kingkong pushed to feature/phase6-guest-comments-finalization at kingkong/vidreview

  • 8477e27892 feat: add watchdog timeout, admin reprocess-all button, and fix Dockerfile DNS - Worker: add STUCK_TIMEOUT_MS watchdog (2 min default) that runs in poll loop when queue is empty — resets PROCESSING jobs stale > threshold to PENDING - API: add POST /api/assets/admin/reprocess-all (admin-only) to manually force-reset all stuck jobs from the UI - Frontend: add "Force Reprocess All" button in TranscodeTasksPanel visible only to ADMIN members, shows stuck count badge - Dockerfile.api: write /etc/resolv.conf with 1.1.1.1/8.8.8.8 before apt-get to resolve mirror timeouts; copy worker JS to src/worker (not dist/workers) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

1 month ago

kingkong pushed to feature/phase6-guest-comments-finalization at kingkong/vidreview

  • c37fefa98d fix: move stale job recovery to master process (before workers fork) recoverStaleJobs() was called by each worker independently on startup, creating a race condition where multiple workers would all see the same PROCESSING jobs and try to claim/recover them simultaneously — causing the same jobs to be reset multiple times and never actually claimed. Fix: run recovery once in the master process before forking workers, using a separate PrismaClient. Workers no longer call recoverStaleJobs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

1 month ago

kingkong pushed to feature/phase6-guest-comments-finalization at kingkong/vidreview

  • ac10542fb8 fix: docker-compose.dev.yml remove env overrides that clobber .env.dev values environment: block vars override env_file: vars for same-name variables. Removed JWT_SECRET, JWT_EXPIRES_IN, API_PORT, UPLOAD_DIR, MAX_FILE_SIZE_MB, RESEND_API_KEY from environment block so .env.dev values are used instead. This ensures api-dev uses the dev-specific JWT_SECRET (matching the dev frontend cookie) and correct dev database URL. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

1 month ago

kingkong pushed to feature/phase6-guest-comments-finalization at kingkong/vidreview

  • ff72caa603 fix: health endpoint at /api/health, docker-compose.dev.yml DATABASE_URL, worker env_file - Move Express health route from /health to /api/health so it works behind Caddy proxy that forwards /api/* unchanged (not handle_path) - docker-compose.dev.yml: remove DATABASE_URL from api-dev and worker-dev environment blocks — .env.dev provides the correct value and env_file already loads it - docker-compose.dev.yml: add env_file to worker-dev so it gets DATABASE_URL from .env.dev - docker-compose.dev.yml: fix healthcheck from /health to /api/health - packages/api/src/worker/index.js: remove duplicate env section (env vars are now correctly provided by docker-compose) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

1 month ago

kingkong pushed to feature/phase6-guest-comments-finalization at kingkong/vidreview

  • afb1fac7be fix: Caddyfile.dev routes /api/* via handle directive (not handle_path) handle_path was inadvertently stripping /api prefix, but Express mounts routes at /api/* so the full path must be forwarded. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

1 month ago

kingkong pushed to feature/phase6-guest-comments-finalization at kingkong/vidreview

  • dffc671e59 fix: Caddyfile.dev strips /api prefix before proxying to API container handle_path /api/* rewrites the path to / before forwarding to the Express backend, fixing 502 Bad Gateway from Caddy passing /api/health instead of /health to the API container. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

1 month ago

kingkong pushed to feature/phase6-guest-comments-finalization at kingkong/vidreview

  • 4caaa7a7fb feat: guest comments, portrait video, and share token page Phase 6 finalization — Guest Comments + 4K Support feature: - Allow unregistered (guest) comments on shared video reviews with name prompt; Comment.userId becomes nullable with guestName - AssetShareLink gains allowUnregisteredComments toggle wired through ShareModal create/edit forms and share.ts API - VideoPlayer accepts isPortrait prop for 9:16 portrait videos (maxWidth: min(100%, 55vh), aspectRatio: 9/16) - Share token page (/share/[token]) for public video review with guest comment form when allowUnregisteredComments is enabled - Dockerfile.api now regenerates Prisma client from scratch - docker-compose.yml Caddy port aligned to 8080 - CLAUDE.md documents dev/test environment workflow Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
  • 813023ea04 feat: video player buffer, bitrate display, upload queue, and hook fixes - VideoPlayer: eager buffer strategy pre-loads 300s, HLS startLoad fix, poster thumbnail - VideoInfoPanel: display resolution, original bitrate, codec info - Worker: ffprobe extracts bitrate → stored in DB asset record - Prisma: bitrate column added via direct SQL (migration bypass) - UploadQueue: XHR upload with progress tracking, queue panel component - FolderTree: improved folder navigation - Claude hooks: PostToolUse deduplicated, UserPromptSubmit removed, Setup/SessionStart/PreToolUse retained with ${CLAUDE_PLUGIN_ROOT} fallback - .claude: custom skills (debug-issue, explore-codebase, refactor-safely, review-changes) - CLAUDE.md: code-review-graph MCP tools documented Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
  • 8c9eb194c2 fix: global BigInt → Number serialization for all Express JSON responses Problem: BigInt fields (storageQuota, storageUsed, fileSize) crashed Express with "Do not know how to serialize a BigInt" when returned from res.json() — including Prisma query results. Solution: Add BigInt.prototype.toJSON in index.ts (after all routes registered, before server starts) so all JSON.stringify calls automatically convert BigInt → Number. Also fixed route handlers that manually returned BigInt fields. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
  • d3a714c8b4 chore: align Caddy port (8080), add DB_CONTAINER env, improve init script - Caddyfile: listen on :8080 (matches Synology port mapping) - docker-compose.yml: Caddy ports 8080:8080 / 8443:8443, add DB_CONTAINER - init-admin.sh: use DB_CONTAINER, stronger password generation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
  • 644d5b229b fix: change storageQuota/storageUsed/fileSize from Int to BigInt Root cause: storageQuota was Int (32-bit, max 2.1 GB). Setting >2 GB caused "Unable to fit integer value into INT4" errors. Migrated: - User.storageQuota Int → BigInt - User.storageUsed Int → BigInt - Asset.fileSize Int → BigInt Also: added bigintToNumber() helper for JSON serialization in Express, updated quota editor to auto-select GB/MB unit, added safeCopy() fallback. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

1 month ago

kingkong pushed to main at kingkong/vidreview

  • 813023ea04 feat: video player buffer, bitrate display, upload queue, and hook fixes - VideoPlayer: eager buffer strategy pre-loads 300s, HLS startLoad fix, poster thumbnail - VideoInfoPanel: display resolution, original bitrate, codec info - Worker: ffprobe extracts bitrate → stored in DB asset record - Prisma: bitrate column added via direct SQL (migration bypass) - UploadQueue: XHR upload with progress tracking, queue panel component - FolderTree: improved folder navigation - Claude hooks: PostToolUse deduplicated, UserPromptSubmit removed, Setup/SessionStart/PreToolUse retained with ${CLAUDE_PLUGIN_ROOT} fallback - .claude: custom skills (debug-issue, explore-codebase, refactor-safely, review-changes) - CLAUDE.md: code-review-graph MCP tools documented Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
  • 8c9eb194c2 fix: global BigInt → Number serialization for all Express JSON responses Problem: BigInt fields (storageQuota, storageUsed, fileSize) crashed Express with "Do not know how to serialize a BigInt" when returned from res.json() — including Prisma query results. Solution: Add BigInt.prototype.toJSON in index.ts (after all routes registered, before server starts) so all JSON.stringify calls automatically convert BigInt → Number. Also fixed route handlers that manually returned BigInt fields. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
  • d3a714c8b4 chore: align Caddy port (8080), add DB_CONTAINER env, improve init script - Caddyfile: listen on :8080 (matches Synology port mapping) - docker-compose.yml: Caddy ports 8080:8080 / 8443:8443, add DB_CONTAINER - init-admin.sh: use DB_CONTAINER, stronger password generation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
  • 644d5b229b fix: change storageQuota/storageUsed/fileSize from Int to BigInt Root cause: storageQuota was Int (32-bit, max 2.1 GB). Setting >2 GB caused "Unable to fit integer value into INT4" errors. Migrated: - User.storageQuota Int → BigInt - User.storageUsed Int → BigInt - Asset.fileSize Int → BigInt Also: added bigintToNumber() helper for JSON serialization in Express, updated quota editor to auto-select GB/MB unit, added safeCopy() fallback. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
  • 57fcd7c7cd fix: quota auto-unit GB/MB, improve copy invite link, UI refinements - openQuotaEdit: auto-select GB when quota >= 1GB to avoid 2048 MB display - handleInvite: use safeCopy() fallback for clipboard API - settings: UI improvements for workspace invite section - project: refine member invite copy link button Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
  • View comparison for these 5 commits »

1 month ago