Conversation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Updates webhook link to set vcon version to 0.3.0 for compatibility with vcon-mcp REST API. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Configure apt to use HTTPS sources for environments where HTTP port 80 is blocked. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Includes docker-compose and config files for SigNoz observability stack with OpenTelemetry collector. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Public endpoint (no auth) that returns the depth of any Redis list, used by the audio adapter for backpressure control. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 5 potential issues.
Bugbot Free Tier Details
Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.
To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Comment @cursor review or bugbot run to trigger another review on this PR
| return JSONResponse(content={"list_name": list_name, "depth": depth}) | ||
| except Exception as e: | ||
| logger.error(f"Error getting queue depth for '{list_name}': {str(e)}") | ||
| raise HTTPException(status_code=500, detail="Failed to get queue depth") |
There was a problem hiding this comment.
Unauthenticated endpoint allows probing arbitrary Redis keys
High Severity
The /stats/queue endpoint is registered directly on @app.get() (bypassing the api_router auth), and accepts an arbitrary list_name parameter passed directly to redis_async.llen(). This allows unauthenticated users to probe any Redis key to discover queue names, check if specific keys exist, and observe queue depths — enabling reconnaissance of the system's internal state. The list_name parameter has no validation or allowlist restricting it to known queue names.
| ### Start without SigNoz (normal operation) | ||
|
|
||
| ```bash | ||
| cd /home/thomas/bds/vcon-dev/vcon-server |
There was a problem hiding this comment.
Hardcoded personal dev paths in shared documentation
Low Severity
The README contains hardcoded absolute paths (/home/thomas/bds/vcon-dev/vcon-server) from a developer's local machine. These are developer-specific and not meaningful for other contributors. Relative paths or a generic placeholder would be appropriate here.
| # Other Content | ||
| "other": { | ||
| "profanity": ["fuck", "shit", "damn", "ass"], | ||
| "mentions_torn": ["torn"], |
There was a problem hiding this comment.
Substring matching causes excessive false positives for profanity
Medium Severity
The find_keywords function uses plain substring matching (if search_keyword in text). The profanity list includes short words like "ass" which will match extremely common words such as "class", "pass", "massage", "assist", "assembly", etc. This will incorrectly tag a large number of vCons with the profanity tag, undermining the reliability of the keyword tagger.
Additional Locations (1)
| # Send audio to vfun server | ||
| files = {"file": (filename, audio_content, mimetype)} | ||
| data = { | ||
| "diarize": str(opts.get("diarize", True)), |
There was a problem hiding this comment.
Diarize parameter sent as "True" instead of "true"
Medium Severity
str(opts.get("diarize", True)) produces "True" (capital T) in Python, but the vfun server expects lowercase "true" — as shown in the README's curl example (-F "diarize=true") and consistent with the adjacent "block": "true" field. If the server does a strict string comparison, diarization would silently fail to activate despite being enabled.
| elif encoding == "base64": | ||
| return base64.b64decode(dialog["body"]) | ||
| else: | ||
| return dialog["body"].encode() if isinstance(dialog["body"], str) else dialog["body"] |
There was a problem hiding this comment.
Unhandled base64 decode error crashes entire link processing
Medium Severity
get_audio_content wraps file I/O and HTTP fetches in try/except blocks, returning None on failure, but the base64.b64decode / base64.urlsafe_b64decode calls at lines 80–82 are unprotected. Since the call to get_audio_content at line 261 sits outside the per-dialog try/except block (which starts at line 269), a corrupt or truncated base64 body will raise binascii.Error, crash the run() function, and abort processing of all remaining dialogs in the vCon.


Note
Medium Risk
Adds new unauthenticated
GET /stats/queueendpoint and introduces new link code that performs external HTTP requests and mutates stored vCons, which could impact security/performance if misconfigured. Docker/compose changes are low risk but expand the local deployment footprint.Overview
Adds an optional SigNoz observability stack (
docker-compose.signoz.ymlplus ClickHouse/collector configs) to run alongside the existing deployment for OTEL traces/metrics/logs.Updates the runtime image build to force Debian APT sources to HTTPS, improving compatibility in networks where HTTP (port 80) is blocked.
Extends the API with a public
GET /stats/queueendpoint that returns Redis list depth for monitoring/backpressure, and updates the webhook link to normalize outgoing vCon payloads tovcon: "0.3.0".Introduces two new processing links:
wtf_transcribe(posts recording dialogs to a vfun transcription server and stores results aswtf_transcriptionanalysis) andkeyword_tagger(scans transcription/WTF analysis text for predefined/custom keywords and adds matching tags).Written by Cursor Bugbot for commit cefef64. Configure here.