diff --git a/docs/incidents/INCIDENT_LOG.md b/docs/incidents/INCIDENT_LOG.md index db8544ca..2d4b6170 100644 --- a/docs/incidents/INCIDENT_LOG.md +++ b/docs/incidents/INCIDENT_LOG.md @@ -85,7 +85,7 @@ Commit `d513a0ced549ef2be8903a7b4794256110ba1805` on staging (merged to main via |---|------------|-------|--------| | 1 | ANTHROPIC_AUTH_TOKEN | `sk-cp-lHt-QFSyZwZxeo...KVw` | ⚠️ Revoked or inactive (404 on API call) | | 2 | GITHUB_TOKEN | `github_pat_11BPRRWQI0m...hsIJLIL` | ✅ Revoked (confirmed 401) | -| 3 | ADMIN_TOKEN | `***REDACTED***F1088-CREDENTIAL-3***=` | Needs confirmation — treated as active until proven otherwise | +| 3 | ADMIN_TOKEN | `***REDACTED***` | Needs confirmation — treated as active until proven otherwise | ### Resolution @@ -103,9 +103,9 @@ The commit itself fixed the problem by replacing hardcoded defaults with env-var | # | Credential | Value (redacted reference) | Service | |---|------------|------------------------------|---------| -| 1 | ANTHROPIC_AUTH_TOKEN | `***REDACTED***F1088-CREDENTIAL-1***` | MiniMax API (api.minimax.io/anthropic) | -| 2 | GITHUB_TOKEN | `***REDACTED***F1088-CREDENTIAL-2***` | GitHub (fine-grained PAT, scope unknown) | -| 3 | ADMIN_TOKEN | `***REDACTED***F1088-CREDENTIAL-3***=` | Platform admin authentication | +| 1 | ANTHROPIC_AUTH_TOKEN | `***REDACTED***` | MiniMax API (api.minimax.io/anthropic) | +| 2 | GITHUB_TOKEN | `***REDACTED***` | GitHub (fine-grained PAT, scope unknown) | +| 3 | ADMIN_TOKEN | `***REDACTED***` | Platform admin authentication | ### Affected Files @@ -150,9 +150,9 @@ The commit itself fixed the problem by replacing hardcoded defaults with env-var **Step 1 — Create credentials manifest (`creds.txt`) [NOT NEEDED]:** ``` -***REDACTED***F1088-CREDENTIAL-3***= -***REDACTED***F1088-CREDENTIAL-1*** -***REDACTED***F1088-CREDENTIAL-2*** +***REDACTED*** +***REDACTED*** +***REDACTED*** ``` **Step 2 — Clean origin/main:** diff --git a/workspace/a2a_cli.py b/workspace/a2a_cli.py index 476deaff..5ba7381c 100644 --- a/workspace/a2a_cli.py +++ b/workspace/a2a_cli.py @@ -25,7 +25,10 @@ _WORKSPACE_ID_raw = os.environ.get("WORKSPACE_ID") if not _WORKSPACE_ID_raw: raise RuntimeError("WORKSPACE_ID environment variable is required but not set") WORKSPACE_ID = _WORKSPACE_ID_raw -PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://platform:8080") +if os.path.exists("/.dockerenv") or os.environ.get("DOCKER_VERSION"): + PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://host.docker.internal:8080") +else: + PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://localhost:8080") async def discover(target_id: str) -> dict | None: diff --git a/workspace/a2a_client.py b/workspace/a2a_client.py index 36f27532..1a3e4f76 100644 --- a/workspace/a2a_client.py +++ b/workspace/a2a_client.py @@ -18,7 +18,10 @@ _WORKSPACE_ID_raw = os.environ.get("WORKSPACE_ID") if not _WORKSPACE_ID_raw: raise RuntimeError("WORKSPACE_ID environment variable is required but not set") WORKSPACE_ID = _WORKSPACE_ID_raw -PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://platform:8080") +if os.path.exists("/.dockerenv") or os.environ.get("DOCKER_VERSION"): + PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://host.docker.internal:8080") +else: + PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://localhost:8080") # Cache workspace ID → name mappings (populated by list_peers calls) _peer_names: dict[str, str] = {} diff --git a/workspace/adapter_base.py b/workspace/adapter_base.py index 43996415..3ef48984 100644 --- a/workspace/adapter_base.py +++ b/workspace/adapter_base.py @@ -229,7 +229,7 @@ class BaseAdapter(ABC): from builtin_tools.memory import commit_memory, search_memory from builtin_tools.sandbox import run_code - platform_url = os.environ.get("PLATFORM_URL", "http://platform:8080") + platform_url = os.environ.get("PLATFORM_URL", "http://host.docker.internal:8080") # Load plugins from per-workspace dir first, then shared fallback workspace_plugins_dir = os.path.join(config.config_path, "plugins") diff --git a/workspace/builtin_tools/a2a_tools.py b/workspace/builtin_tools/a2a_tools.py index ac052902..8c7be15f 100644 --- a/workspace/builtin_tools/a2a_tools.py +++ b/workspace/builtin_tools/a2a_tools.py @@ -9,7 +9,7 @@ import uuid import httpx -PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://platform:8080") +PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://host.docker.internal:8080") WORKSPACE_ID = os.environ.get("WORKSPACE_ID", "") diff --git a/workspace/builtin_tools/approval.py b/workspace/builtin_tools/approval.py index fb2465b3..2dd9f978 100644 --- a/workspace/builtin_tools/approval.py +++ b/workspace/builtin_tools/approval.py @@ -54,7 +54,7 @@ from builtin_tools.audit import check_permission, get_workspace_roles, log_event logger = logging.getLogger(__name__) -PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://platform:8080") +PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://host.docker.internal:8080") WORKSPACE_ID = os.environ.get("WORKSPACE_ID", "") APPROVAL_POLL_INTERVAL = float(os.environ.get("APPROVAL_POLL_INTERVAL", "5")) APPROVAL_TIMEOUT = float(os.environ.get("APPROVAL_TIMEOUT", "300")) diff --git a/workspace/builtin_tools/delegation.py b/workspace/builtin_tools/delegation.py index b9c42963..40b76bf0 100644 --- a/workspace/builtin_tools/delegation.py +++ b/workspace/builtin_tools/delegation.py @@ -29,7 +29,7 @@ from builtin_tools.telemetry import ( inject_trace_headers, ) -PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://platform:8080") +PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://host.docker.internal:8080") WORKSPACE_ID = os.environ.get("WORKSPACE_ID", "") DELEGATION_RETRY_ATTEMPTS = int(os.environ.get("DELEGATION_RETRY_ATTEMPTS", "3")) DELEGATION_RETRY_DELAY = float(os.environ.get("DELEGATION_RETRY_DELAY", "5.0")) diff --git a/workspace/builtin_tools/hitl.py b/workspace/builtin_tools/hitl.py index 3a03e627..8c4eb87a 100644 --- a/workspace/builtin_tools/hitl.py +++ b/workspace/builtin_tools/hitl.py @@ -177,7 +177,7 @@ async def _notify_channels( Errors in individual channels are logged but never re-raised so that a misconfigured Slack webhook cannot block the approval flow. """ - platform_url = os.environ.get("PLATFORM_URL", "http://platform:8080") + platform_url = os.environ.get("PLATFORM_URL", "http://host.docker.internal:8080") workspace_id = os.environ.get("WORKSPACE_ID", "") for channel in cfg.channels: diff --git a/workspace/builtin_tools/memory.py b/workspace/builtin_tools/memory.py index 80638f42..e92bccab 100644 --- a/workspace/builtin_tools/memory.py +++ b/workspace/builtin_tools/memory.py @@ -42,7 +42,7 @@ try: # pragma: no cover - optional runtime dependency in lightweight test envs except ImportError: # pragma: no cover httpx = SimpleNamespace(AsyncClient=None) -PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://platform:8080") +PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://host.docker.internal:8080") WORKSPACE_ID = os.environ.get("WORKSPACE_ID", "") diff --git a/workspace/consolidation.py b/workspace/consolidation.py index 4599d447..81e9ec88 100644 --- a/workspace/consolidation.py +++ b/workspace/consolidation.py @@ -18,7 +18,10 @@ from platform_auth import auth_headers logger = logging.getLogger(__name__) -PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://platform:8080") +if os.path.exists("/.dockerenv") or os.environ.get("DOCKER_VERSION"): + PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://host.docker.internal:8080") +else: + PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://localhost:8080") _WORKSPACE_ID_raw = os.environ.get("WORKSPACE_ID") if not _WORKSPACE_ID_raw: raise RuntimeError("WORKSPACE_ID environment variable is required but not set") diff --git a/workspace/coordinator.py b/workspace/coordinator.py index 6028017c..b9df9cfa 100644 --- a/workspace/coordinator.py +++ b/workspace/coordinator.py @@ -22,7 +22,10 @@ from policies.routing import build_team_routing_payload logger = logging.getLogger(__name__) -PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://platform:8080") +if os.path.exists("/.dockerenv") or os.environ.get("DOCKER_VERSION"): + PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://host.docker.internal:8080") +else: + PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://localhost:8080") _WORKSPACE_ID_raw = os.environ.get("WORKSPACE_ID") if not _WORKSPACE_ID_raw: raise RuntimeError("WORKSPACE_ID environment variable is required but not set") diff --git a/workspace/main.py b/workspace/main.py index 6c275c6b..59baee76 100644 --- a/workspace/main.py +++ b/workspace/main.py @@ -52,9 +52,16 @@ from transcript_auth import transcript_authorized as _transcript_authorized async def main(): # pragma: no cover - workspace_id = os.environ.get("WORKSPACE_ID", "workspace-default") + workspace_id = os.environ.get("WORKSPACE_ID", "") + if not workspace_id: + raise SystemExit("FATAL: WORKSPACE_ID env var is not set. Aborting.") config_path = os.environ.get("WORKSPACE_CONFIG_PATH", "/configs") - platform_url = os.environ.get("PLATFORM_URL", "http://platform:8080") + # Docker-aware default — host.docker.internal resolves the platform service + # from inside the Docker network mesh; falls back to localhost for local dev. + if os.path.exists("/.dockerenv") or os.environ.get("DOCKER_VERSION"): + platform_url = os.environ.get("PLATFORM_URL", "http://host.docker.internal:8080") + else: + platform_url = os.environ.get("PLATFORM_URL", "http://localhost:8080") awareness_config = get_awareness_config() # 0. Initialise OpenTelemetry (no-op if packages not installed) diff --git a/workspace/molecule_ai_status.py b/workspace/molecule_ai_status.py index a00f3fcc..6787c38e 100644 --- a/workspace/molecule_ai_status.py +++ b/workspace/molecule_ai_status.py @@ -26,7 +26,7 @@ _WORKSPACE_ID_raw = os.environ.get("WORKSPACE_ID") if not _WORKSPACE_ID_raw: raise RuntimeError("WORKSPACE_ID environment variable is required but not set") WORKSPACE_ID = _WORKSPACE_ID_raw -PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://platform:8080") +PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://host.docker.internal:8080") def set_status(task: str): diff --git a/workspace/scripts/molecule-git-token-helper.sh b/workspace/scripts/molecule-git-token-helper.sh index 4b7a8cca..84753422 100755 --- a/workspace/scripts/molecule-git-token-helper.sh +++ b/workspace/scripts/molecule-git-token-helper.sh @@ -50,7 +50,7 @@ # set -euo pipefail -PLATFORM_URL="${PLATFORM_URL:-http://platform:8080}" +PLATFORM_URL="${PLATFORM_URL:-http://host.docker.internal:8080}" CONFIGS_DIR="${CONFIGS_DIR:-/configs}" TOKEN_FILE="${CONFIGS_DIR}/.auth_token" # #1068: use workspace-scoped path (WorkspaceAuth) instead of admin path