fix: respect readonly flag on config-profile mounts in compose tool types

- modify_compose_file now appends :ro when a config-profile volume entry
  has readonly=true, matching the manifest compiler behavior.
- Add a guard for missing tool_type in prepare_manifest_instance.

Quality gates: python3 -m pytest (313 passed, 34 skipped)
This commit is contained in:
Developer
2026-06-13 12:12:12 +00:00
parent 31f1ce00d3
commit efe5e4ae50
7 changed files with 19 additions and 14 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src
## role
Core application package for the Headquarter API, providing configuration, database connectivity, structured logging, and FastAPI application initialization.
Core application package for the Headquarter API, providing configuration, database connectivity, logging infrastructure, and FastAPI application initialization.
## parent
index: apps/api/.pi-map.index.md
map: apps/api/.pi-map.md
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src/services
## role
Provides a Python package namespace for organizing service-layer modules in the API application.
Marks the services directory as a Python package for business logic layer components.
## parent
index: apps/api/src/.pi-map.index.md
map: apps/api/src/.pi-map.md
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src/services/tool
## role
Provides Docker container lifecycle management for tool instances with git repository integration and configuration validation.
Provides backend infrastructure for provisioning and managing isolated development tool instances with their dependencies and network access.
## parent
index: apps/api/src/services/.pi-map.index.md
map: apps/api/src/services/.pi-map.md
File diff suppressed because one or more lines are too long
@@ -583,10 +583,13 @@ def modify_compose_file(
source = vol.get("source", "")
target = expand_container_path(vol.get("target", ""), home_dir)
vol_type = vol.get("type", "bind")
readonly = ":ro" if vol.get("readonly") else ""
if vol_type == "bind":
service_config["volumes"].append(f"{source}:{target}")
service_config["volumes"].append(f"{source}:{target}{readonly}")
else:
service_config["volumes"].append(f"{source}:{target}:{vol_type}")
service_config["volumes"].append(
f"{source}:{target}:{vol_type}{readonly}"
)
# Sort volumes so parent paths come before child paths
if service_config.get("volumes"):
@@ -792,8 +795,10 @@ async def prepare_manifest_instance(
from src.models import ToolDefinitionManifest
tool_type = await session.get(ToolType, instance.tool_type_id)
manifest_def = await session.get(ToolDefinitionManifest, tool_type.manifest_id)
if not tool_type:
raise RuntimeError(f"Tool type not found for instance {instance.id}")
manifest_def = await session.get(ToolDefinitionManifest, tool_type.manifest_id)
if not manifest_def:
raise RuntimeError(f"Manifest not found for tool type {tool_type.id}")