Skip to content

Host agent rejects all built-in extensions from API management — CORE_SERVICE_IDS misused as blocklist #299

@yasinBursali

Description

@yasinBursali

Problem

The host agent's validate_service_id() at bin/dream-host-agent.py:291-305 rejects any service in CORE_SERVICE_IDS with HTTP 403 "Cannot manage core service".

The problem: CORE_SERVICE_IDS (loaded from config/core-service-ids.json) contains all 20 built-in services, including optional extensions like tts, whisper, comfyui, n8n, qdrant, embeddings, searxng, privacy-shield, perplexica, litellm, token-spy, ape, dreamforge, langfuse, openclaw, opencode.

Only 4 of these are truly "always on" base-compose services: llama-server, open-webui, dashboard, dashboard-api. The other 16 are built-in extensions that users should be able to enable/disable/start/stop via the API.

Impact

The dashboard API cannot manage 16 built-in extensions that it knows about:

  • Cannot start them via `POST /v1/extension/start`
  • Cannot stop them via `POST /v1/extension/stop`
  • Cannot get logs via `POST /v1/extension/logs`

This blocks:

Reproduction

  1. Fresh DreamServer install
  2. Disable a built-in extension via CLI: `dream disable tts`
  3. From the dashboard, try to re-enable it (if it appears in the catalog)
  4. Expected: extension starts
  5. Actual: Host agent returns 403 "Cannot manage core service: tts"

Root Cause

The JSON file is misnamed. core-service-ids.json was originally a whitelist of "valid service IDs the agent knows about" but got repurposed as a blocklist of "services the API is not allowed to touch". These are different concepts:

  • Whitelist for input validation: all known built-in service IDs
  • Blocklist for protection: only truly-always-on base-compose services

Suggested Fix

Introduce two separate constants:
```python

Whitelist: all known built-in service IDs (for input validation)

KNOWN_BUILTIN_SERVICES = load_known_services("config/core-service-ids.json")

Blocklist: services that should never be managed via API (always on)

ALWAYS_ON_SERVICES = frozenset({"llama-server", "open-webui", "dashboard", "dashboard-api"})
```

Then in `validate_service_id()`:
```python
if sid in ALWAYS_ON_SERVICES:
json_response(handler, 403, {"error": f"Cannot manage always-on service: {sid}"})
return None

Valid service: either a known built-in OR a user extension with a manifest

if sid not in KNOWN_BUILTIN_SERVICES and not (USER_EXTENSIONS_DIR / sid).is_dir():
json_response(handler, 404, {"error": f"Extension not found: {sid}"})
return None
```

Also update the extension dir check to support built-in extensions (currently only checks `USER_EXTENSIONS_DIR`):
```python
ext_dir = USER_EXTENSIONS_DIR / sid
if not ext_dir.is_dir():
ext_dir = EXTENSIONS_DIR / sid
manifest_exists = any((ext_dir / n).exists() for n in ("manifest.yaml", "manifest.yml", "manifest.json"))
```

Files Affected

  • `dream-server/bin/dream-host-agent.py` — `validate_service_id` function
  • `dream-server/config/core-service-ids.json` — consider renaming to `known-service-ids.json` for clarity
  • `dream-server/extensions/services/dashboard-api/routers/extensions.py` — may also need updates for consistency

Priority

High — blocks multiple in-flight features (PR Light-Heart-Labs#877 deps+hooks, PR 2 templates, any future API-driven extension management).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions