Fix Plan — #127 Redundant + dead env vars in zampp2 .env.worker
Root cause: zampp2 .env.worker has:
NODE_IP=172.18.91.217(stale bridge IP) +NODE_IP=172.18.91.200(dup, second…
Fix Plan — #109 BMD_COUNT override hardcodes wrong device paths
Root cause: node-agent/index.js:288-298 — zampp2 has BMD_COUNT=4, override path stores fake paths `/dev/blackmagic/dv…
Fix Plan — #108 GPU_COUNT env override blocks nvidia-smi enrichment
Root cause: node-agent/index.js:269-284 — zampp2 .env.worker sets GPU_COUNT=1. Override path pushes raw…
Fix Plan — #103 Scheduler race condition (multi-node double-fire)
Root cause: scheduler.js:31-130 polls every 15s. Two mam-api instances both SELECT same pending row, both call…
recorders.js dockerApi has no socket timeout — hung Docker socket blocks recorder start/stop indefinitely
Fix Plan — #91 dockerApi has no socket timeout
Root cause: recorders.js:22-38 — dockerApi() uses http.request() with no timeout. Hung Docker daemon → all recorder start/stop…
jobs row is orphaned — no status lifecycle, job_type enum is stale
Fix Plan — #90 Batch-trim DB jobs row orphaned
Root cause: assets.js:batch-trim INSERTs a row into jobs DB table with type "trim" status "queued", but jobs.js GET route reads…
Fix Plan — #121 GET /recorders N+1 Docker/PG calls
Root cause: recorders.js:198-202 — Promise.all over every recording-status recorder makes N concurrent Docker API + N…
Fix Plan — #120 multer.memoryStorage OOM on concurrent uploads
Root cause: upload.js and assets.js use multer.memoryStorage() with 500MB cap. Each concurrent upload chunk lives in…
Fix Plan — #117 Schedule rows crash on null recorder_id
Root cause: screens-ingest.jsx:1026,1040,1569 call s.recorder_id.slice(0,8) with no null guard. Deleted recorder + orphaned…
Fix Plan — #116 EditorKeyboard crash on document.activeElement = null
Root cause: screens-editor.jsx:711 reads document.activeElement.tagName without null guard. `document.activeEleme…
Fix Plan — #101 Error handler leaks raw Postgres messages
Root cause: src/middleware/errors.js returns err.message verbatim. PG errors expose schema names, column names, SQL state…
Fix Plan — #100 No graceful shutdown handler
Root cause: mam-api has no SIGTERM/SIGINT handler. Docker stop kills mid-tick: corrupted scheduler state, leaked BullMQ Redis…
Fix Plan — #102 UUID path params not validated → 500 on bad input
Root cause: No /:id, /:assetId, /:jobId, /:projectId route validates UUID format before PG query. PG throws…
Fix Plan — #107 Migrations silently swallow failures
Root cause: src/index.js:105-111 wraps each migration in try/catch, console.error, continues loop. Failed migration → partial…
Fix Plan — #118 Path traversal in SDK archive extraction
Root cause: src/routes/sdk.js:91-128 runs spawn("tar",…) / spawn("unzip",…) on user-uploaded archives without traversal…
Fix Plan — #106 Node hijack via POST /cluster/heartbeat
Root cause: cluster.js:102-147 is behind requireAuth (any authed user, including editor). Accepts arbitrary hostname +…
Fix Plan — #105 Secret leak in recorder start error response
Root cause: recorders.js:451 returns details: createRes.data (Docker API error echoes full request body including…
Fix Plan — #104 SSRF via POST /recorders/probe
Root cause: recorders.js:698-744 forwards user-supplied URL to capture sidecar, falls back to raw net.connect/dgram against any…
🔧 Fix plan incoming — token verified, posting all plans now...