molecule-ai-workspace-runtime/molecule_runtime/molecule_ai_status.py
Molecule AI Infra-SRE be9c9997c0 fix(builtin_tools/validation): cover remaining WORKSPACE_ID URL usages
Extend get_validated_workspace_id() to all remaining unguarded URL positions:

- consolidation.py: _consolidate() — validates before GET/POST/DELETE to
  /workspaces/{id}/memories endpoints. Graceful skip on failure (log + return).
- coordinator.py: get_children() — validates before /registry/{id}/peers.
  Graceful skip (empty list) on failure.
- molecule_ai_status.py: set_status() — validates before /registry/heartbeat
  and /workspaces/{id}/activity. Exits with descriptive error on failure.

With these three, every runtime use of WORKSPACE_ID in a URL path is now
validated. Remaining WORKSPACE_ID uses are:
- JSON body fields (not injection-risky): heartbeat, memory POST bodies
- Header values (X-Workspace-ID): lower risk, non-URL-injection
2026-04-21 00:55:08 +00:00

83 lines
2.5 KiB
Python

#!/usr/bin/env python3
"""Update workspace task status on the canvas.
Usage (from any script, cron job, or shell inside the container):
# Set current task (shows on canvas card)
python3 /app/molecule_ai_status.py "Running weekly SEO audit..."
# Clear task (removes banner from canvas)
python3 /app/molecule_ai_status.py ""
# Or use the shell alias:
molecule-monorepo-status "Analyzing competitor data..."
molecule-monorepo-status ""
The status appears as an amber banner on the workspace card in the canvas,
visible to the project owner in real-time.
"""
import os
import sys
import httpx
from builtin_tools.validation import WorkspaceIdValidationError, get_validated_workspace_id
WORKSPACE_ID = os.environ.get("WORKSPACE_ID", "")
PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://platform:8080")
def set_status(task: str):
"""Push current_task to platform via heartbeat."""
try:
try:
from builtin_tools.platform_auth import auth_headers as _auth
_headers = _auth()
except Exception:
_headers = {}
# --- Workspace ID validation (CWE-20 / CWE-88) -----------------------
try:
ws_id = get_validated_workspace_id(caller="molecule_ai_status.set_status")
except WorkspaceIdValidationError as e:
sys.stderr.write(f"molecule_ai_status: {e}\n")
return
httpx.post(
f"{PLATFORM_URL}/registry/heartbeat",
json={
"workspace_id": ws_id,
"current_task": task,
"active_tasks": 1 if task else 0,
"error_rate": 0,
"sample_error": "",
"uptime_seconds": 0,
},
headers=_headers,
timeout=5.0,
)
if task:
# Also log as activity for traceability
httpx.post(
f"{PLATFORM_URL}/workspaces/{ws_id}/activity",
json={
"activity_type": "task_update",
"source_id": ws_id,
"summary": task,
"status": "ok",
},
timeout=5.0,
)
except Exception as e:
print(f"molecule-monorepo-status: failed to update: {e}", file=sys.stderr)
if __name__ == "__main__": # pragma: no cover
if len(sys.argv) < 2:
print("Usage: molecule-monorepo-status 'task description'")
print(" molecule-monorepo-status '' # clear")
sys.exit(1)
set_status(sys.argv[1])