feat(runtime): bind process and job resources to authority

This commit is contained in:
Alexandre Teixeira
2026-10-02 18:54:09 +01:00
parent 7b8ac6f631
commit db41d7e822
36 changed files with 2251 additions and 174 deletions
+19 -3
View File
@@ -67,8 +67,20 @@ class ManageBgJobsTool:
if not session_id:
return {"error": "manage_bg_jobs: no active chat session; background jobs are scoped to a chat.", "exit_code": 1}
from src.agent_runtime.process_resources import active_process_operation, expected_job, require_process_admission
from src.agent_runtime.resources import ResourceIdentityError
bound = active_process_operation()
if bound is None or (bound.owner, bound.thread_id) != (str(ctx.get("owner") or "").strip().casefold(), session_id):
return {"error": "manage_bg_jobs: no exact server resource binding", "exit_code": 1,
"blocked": True, "failure_kind": "resource_identity_denied"}
from src.agent_runtime.authority import ExactOperation
if bound.operation != ExactOperation.normalize("manage_bg_jobs", raw or "{}"):
return {"error": "Job operation changed at producer entry", "exit_code": 1, "blocked": True}
require_process_admission(bound)
if action in _LIST_ACTIONS:
jobs: List[Dict[str, Any]] = bg_jobs.list_for_session(session_id)
bound.validate()
jobs: List[Dict[str, Any]] = [bg_jobs.peek(j.job_id) for j in bound.jobs]
if not jobs:
return {"output": "No background jobs in this chat.", "exit_code": 0}
jobs.sort(key=lambda r: r.get("started_at") or 0, reverse=True)
@@ -78,7 +90,11 @@ class ManageBgJobsTool:
if action in _OUTPUT_ACTIONS or action in _KILL_ACTIONS:
if not job_id:
return {"error": f"manage_bg_jobs: action '{action}' requires a job_id (see action='list').", "exit_code": 1}
rec = bg_jobs.get(job_id)
try:
resource = expected_job(job_id, action=action)
rec = bg_jobs.get(job_id, expected=resource)
except (ResourceIdentityError, OSError, ValueError) as error:
return {"error": str(error), "exit_code": 1, "blocked": True, "failure_kind": "resource_identity_denied"}
# Scope: only the chat that launched a job may see or control it.
if rec is None or rec.get("session_id") != session_id:
return {"error": f"manage_bg_jobs: no background job '{job_id}' in this chat.", "exit_code": 1}
@@ -86,7 +102,7 @@ class ManageBgJobsTool:
if action in _KILL_ACTIONS:
if rec.get("status") != "running":
return {"output": f"Job `{job_id}` already {_status_label(rec)}; nothing to kill.", "exit_code": 0}
killed = bg_jobs.kill(job_id)
killed = bg_jobs.kill(job_id, expected=resource)
if not killed or not killed.get("killed"):
return {"error": f"Could not verify termination of background job `{job_id}`.",
"exit_code": 1, "teardown": (killed or {}).get("teardown")}