2898 lines
104 KiB
Python
2898 lines
104 KiB
Python
from __future__ import annotations
|
|
|
|
from collections.abc import Callable
|
|
from typing import Any
|
|
|
|
from sqlmodel import Session, select
|
|
|
|
from ..connectors.deluge import DelugeConnector
|
|
from ..connectors.plex import PlexConnector
|
|
from ..db.models import Approval, JobRun
|
|
from .audit_logger import log_event
|
|
from .job_runner import (
|
|
complete_job,
|
|
create_job,
|
|
prepare_job,
|
|
set_job_progress,
|
|
start_job,
|
|
)
|
|
from .setup_service import apply_stored_connector_settings
|
|
|
|
GENERIC_EXECUTOR_ACTIONS = {
|
|
"container.restart",
|
|
"controller.artifact.promote",
|
|
"controller.managed-storage.initialize",
|
|
"deployment.targets.sync",
|
|
"deployment.runnerless.provision",
|
|
"deployment.target.deploy_workmesh",
|
|
"deployment.target.register_portfolio",
|
|
"deployment.target.register_privatemuse",
|
|
"deployment.target.reconcile_media_codec_dashboard",
|
|
"deployment.webhook.repair_privatemuse",
|
|
"privatemuse.comfyui.install_artifact",
|
|
}
|
|
|
|
DEDICATED_ENDPOINT_ACTIONS = {
|
|
"deluge.pause_torrent",
|
|
"deluge.resume_torrent",
|
|
"media_pipeline.check",
|
|
"media_pipeline.diagnose",
|
|
"notifications.evaluate_safety",
|
|
"plex.scan_library",
|
|
"prowlarr.search_test",
|
|
"radarr.add_movie",
|
|
"sonarr.add_series",
|
|
"unraid.vm.start",
|
|
"unraid.vm.resume",
|
|
"unraid.vm.pause",
|
|
"widefrog.retry_failed",
|
|
"widefrog.scan_library",
|
|
}
|
|
|
|
APPROVAL_EXECUTOR_ACTIONS = {
|
|
"container.restart",
|
|
"controller.artifact.promote",
|
|
"runner.fleet.upgrade_v2",
|
|
"runner.fleet.specialize",
|
|
"runner.statistics.configure",
|
|
"runner.acceptance.preflight",
|
|
"runner.acceptance.quiesce",
|
|
"hub.migration.prepare_permissions",
|
|
"deployment.targets.sync",
|
|
"deployment.runnerless.provision",
|
|
"deployment.target.deploy_workmesh",
|
|
"deployment.target.promote_workmesh",
|
|
"deployment.target.register_portfolio",
|
|
"deployment.target.register_privatemuse",
|
|
"deployment.target.reconcile_media_codec_dashboard",
|
|
"deployment.webhook.repair_privatemuse",
|
|
"privatemuse.comfyui.install_artifact",
|
|
"deluge.pause_all",
|
|
"deluge.resume_all",
|
|
"plex.scan_all_libraries",
|
|
"unraid.vm.start",
|
|
"unraid.vm.resume",
|
|
"unraid.vm.pause",
|
|
}
|
|
|
|
MCP_TYPED_EXECUTOR_ACTIONS = APPROVAL_EXECUTOR_ACTIONS | {
|
|
"controller.managed-storage.initialize",
|
|
}
|
|
|
|
HUMAN_APPROVAL_ONLY_ACTIONS = {"deployment.target.promote_workmesh", "privatemuse.comfyui.install_artifact"}
|
|
|
|
_APPROVAL_STEPS = {
|
|
"deluge.pause_all": [
|
|
"Load approved request",
|
|
"Reload connector settings",
|
|
"Pause all torrents",
|
|
"Record result",
|
|
],
|
|
"deluge.resume_all": [
|
|
"Load approved request",
|
|
"Reload connector settings",
|
|
"Resume all torrents",
|
|
"Record result",
|
|
],
|
|
"plex.scan_all_libraries": [
|
|
"Load approved request",
|
|
"Reload connector settings",
|
|
"Scan all Plex libraries",
|
|
"Record result",
|
|
],
|
|
}
|
|
|
|
_DIRECT_STEPS = {
|
|
"deluge.pause_all": [
|
|
"Validate MCP policy",
|
|
"Reload connector settings",
|
|
"Pause all torrents",
|
|
"Record result",
|
|
],
|
|
"deluge.resume_all": [
|
|
"Validate MCP policy",
|
|
"Reload connector settings",
|
|
"Resume all torrents",
|
|
"Record result",
|
|
],
|
|
"plex.scan_all_libraries": [
|
|
"Validate MCP policy",
|
|
"Reload connector settings",
|
|
"Scan all Plex libraries",
|
|
"Record result",
|
|
],
|
|
}
|
|
|
|
|
|
def action_execution_profile(
|
|
action: str, policy_decision: str, capability: str
|
|
) -> dict[str, Any]:
|
|
if action in {"runner.acceptance.preflight", "runner.acceptance.quiesce"} and policy_decision != "blocked":
|
|
# The fixed MCP typed authority is separate from Command Center's
|
|
# manual route; do not advertise an unsupported manual executor.
|
|
mode = "governance_only"
|
|
surface = None
|
|
elif policy_decision == "blocked":
|
|
mode = "blocked"
|
|
surface = None
|
|
elif action in GENERIC_EXECUTOR_ACTIONS:
|
|
mode = "command_center"
|
|
surface = "/command-center"
|
|
elif action in APPROVAL_EXECUTOR_ACTIONS and policy_decision == "approval_required":
|
|
mode = "approval_then_execute"
|
|
surface = "/approvals"
|
|
elif action in DEDICATED_ENDPOINT_ACTIONS or capability == "read_only":
|
|
mode = "dedicated_surface"
|
|
surface = None
|
|
else:
|
|
mode = "governance_only"
|
|
surface = None
|
|
|
|
return {
|
|
"executionMode": mode,
|
|
"executionSupported": mode
|
|
in {"command_center", "approval_then_execute", "dedicated_surface"},
|
|
"commandExecutionSupported": mode == "command_center",
|
|
"executionSurface": surface,
|
|
}
|
|
|
|
|
|
def approval_execution_supported(action: str) -> bool:
|
|
return action in APPROVAL_EXECUTOR_ACTIONS
|
|
|
|
|
|
def mcp_execution_supported(action: str) -> bool:
|
|
"""MCP is a no-human-approval surface; never admit human-only executors."""
|
|
return action in MCP_TYPED_EXECUTOR_ACTIONS and action not in HUMAN_APPROVAL_ONLY_ACTIONS
|
|
|
|
|
|
def _execute_deployment_target_sync(
|
|
session: Session,
|
|
*,
|
|
source: str,
|
|
risk: str,
|
|
reason: str,
|
|
original_policy_decision: str,
|
|
) -> dict[str, Any]:
|
|
from .gitea_project_auto_registration import GiteaProjectAutoRegistration
|
|
|
|
action = "deployment.targets.sync"
|
|
target = "jens/*"
|
|
steps = [
|
|
"Read owned Gitea repositories through the bounded catalog client",
|
|
"Validate repository deployment descriptors and Compose topology",
|
|
"Register exact-SHA controller targets where contracts are valid",
|
|
"Install exact-target deployment policies without deploying applications",
|
|
]
|
|
job = create_job(
|
|
session,
|
|
action_id=action,
|
|
target=target,
|
|
source=source,
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
steps=steps,
|
|
)
|
|
start_job(session, job)
|
|
set_job_progress(session, job, 20, "Reconciling bounded Gitea deployment targets.")
|
|
try:
|
|
result = GiteaProjectAutoRegistration().sync(session, force=True)
|
|
status = str(result.get("status") or "error")
|
|
summary = result.get("summary") if isinstance(result.get("summary"), dict) else {}
|
|
success = status == "ok"
|
|
message = (
|
|
"Deployment target catalog reconciled."
|
|
if success
|
|
else str(result.get("reason") or "Deployment target catalog reconciliation failed.")
|
|
)
|
|
except Exception as exc:
|
|
success = False
|
|
status = "error"
|
|
summary = {}
|
|
message = f"{type(exc).__name__}: deployment target catalog reconciliation failed"
|
|
result = {"status": status}
|
|
|
|
completed = complete_job(
|
|
session,
|
|
job,
|
|
status="succeeded" if success else "failed",
|
|
result_summary=message,
|
|
)
|
|
audit = log_event(
|
|
session,
|
|
source="action",
|
|
identity=source,
|
|
action_id=action,
|
|
target=target,
|
|
target_type="deployment-project-catalog",
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
reason=reason,
|
|
result="success" if success else "failed",
|
|
execution_plan={"steps": steps, "jobId": completed.id},
|
|
after_state={
|
|
"status": status,
|
|
"total": summary.get("total", 0),
|
|
"registered": summary.get("registered", 0),
|
|
"knownUnconfigured": summary.get("knownUnconfigured", 0),
|
|
"conflicts": summary.get("conflicts", 0),
|
|
"errors": summary.get("errors", 0),
|
|
"changed": summary.get("changedThisSync", 0),
|
|
},
|
|
redacted_metadata={
|
|
"executor": action,
|
|
"integration": "mcp" if source == "chatgpt-mcp" else "operator",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
},
|
|
)
|
|
return {
|
|
"success": success,
|
|
"status": "success" if success else "failed",
|
|
"result": "success" if success else "failed",
|
|
"message": message,
|
|
"jobId": completed.id,
|
|
"auditId": audit.id,
|
|
"policyDecision": "allowed",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
"summary": {
|
|
"total": summary.get("total", 0),
|
|
"registered": summary.get("registered", 0),
|
|
"knownUnconfigured": summary.get("knownUnconfigured", 0),
|
|
"conflicts": summary.get("conflicts", 0),
|
|
"errors": summary.get("errors", 0),
|
|
"changed": summary.get("changedThisSync", 0),
|
|
},
|
|
}
|
|
|
|
|
|
def _execute_workmesh_first_deployment(
|
|
session: Session,
|
|
*,
|
|
source: str,
|
|
risk: str,
|
|
reason: str,
|
|
original_policy_decision: str,
|
|
) -> dict[str, Any]:
|
|
from .workmesh_first_deployment import WorkMeshFirstDeployment
|
|
|
|
action = "deployment.target.deploy_workmesh"
|
|
target = "jens/workmesh"
|
|
steps = [
|
|
"Verify the fixed WorkMesh v0.1.0 protected-main release contract",
|
|
"Create or validate the external mode-0600 WorkMesh runtime environment",
|
|
"Reserve the fixed loopback port set and reconcile the exact-source controller target",
|
|
"Run the official deployment-controller preflight and transactional first deploy",
|
|
"Verify the controller-owned deployment receipt without exposing secret values",
|
|
]
|
|
service = WorkMeshFirstDeployment()
|
|
tracked_job_id = service.tracked_job_id(session)
|
|
job = session.get(JobRun, tracked_job_id) if tracked_job_id else None
|
|
orphan_running = False
|
|
if job is None:
|
|
job = session.exec(
|
|
select(JobRun)
|
|
.where(JobRun.action_id == action, JobRun.target == target, JobRun.status == "running")
|
|
.order_by(JobRun.started_at.desc())
|
|
).first()
|
|
if job is not None:
|
|
orphan_running = True
|
|
else:
|
|
job = create_job(
|
|
session,
|
|
action_id=action,
|
|
target=target,
|
|
source=source,
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
steps=steps,
|
|
)
|
|
start_job(session, job)
|
|
|
|
try:
|
|
deployment = (
|
|
{
|
|
"status": "outcome_unknown",
|
|
"reason": "An earlier WorkMesh deployment job is running without matching durable execution state; reconcile it before another deploy",
|
|
}
|
|
if orphan_running
|
|
else service.run(session, job=job)
|
|
)
|
|
status = str(deployment.get("status") or "error")
|
|
execution_id = str(deployment.get("execution_id") or "")
|
|
if status == "deployed":
|
|
success = True
|
|
message = "WorkMesh v0.1.0 first deployment completed with controller receipt evidence."
|
|
elif status == "in_progress":
|
|
success = False
|
|
message = "WorkMesh v0.1.0 first deployment is still running."
|
|
elif status == "outcome_unknown":
|
|
success = False
|
|
message = str(deployment.get("reason") or "WorkMesh deployment outcome requires reconciliation.")
|
|
else:
|
|
success = False
|
|
message = str(deployment.get("reason") or "WorkMesh v0.1.0 first deployment failed closed.")
|
|
except Exception as exc:
|
|
status = "error"
|
|
execution_id = ""
|
|
success = False
|
|
deployment = {"status": status}
|
|
message = f"{type(exc).__name__}: WorkMesh first-deploy reconciliation failed"
|
|
|
|
if status in {"in_progress", "outcome_unknown"}:
|
|
if job.status not in {"succeeded", "failed", "cancelled"}:
|
|
completed = set_job_progress(
|
|
session,
|
|
job,
|
|
max(job.progress, 90 if status == "outcome_unknown" else 25),
|
|
message,
|
|
)
|
|
else:
|
|
completed = job
|
|
elif job.status in {"succeeded", "failed", "cancelled"}:
|
|
completed = job
|
|
else:
|
|
completed = complete_job(
|
|
session,
|
|
job,
|
|
status="succeeded" if success else "failed",
|
|
result_summary=message,
|
|
)
|
|
|
|
outward_status = (
|
|
status
|
|
if status in {"in_progress", "outcome_unknown"}
|
|
else "success"
|
|
if success
|
|
else "failed"
|
|
)
|
|
audit = log_event(
|
|
session,
|
|
source="action",
|
|
identity=source,
|
|
action_id=action,
|
|
target=target,
|
|
target_type="deployment-target",
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
reason=reason,
|
|
result=outward_status,
|
|
execution_plan={"steps": steps, "jobId": completed.id},
|
|
after_state={
|
|
"status": status,
|
|
"repository": deployment.get("repository", target),
|
|
"revision": deployment.get("revision"),
|
|
"composeProject": deployment.get("compose_project"),
|
|
"containers": deployment.get("containers"),
|
|
"ports": deployment.get("ports"),
|
|
"executionId": execution_id or None,
|
|
},
|
|
redacted_metadata={
|
|
"executor": action,
|
|
"integration": "mcp" if source == "chatgpt-mcp" else "operator",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
"secretsReturned": False,
|
|
},
|
|
)
|
|
return {
|
|
"success": success,
|
|
"status": outward_status,
|
|
"result": outward_status,
|
|
"message": message,
|
|
"jobId": completed.id,
|
|
"auditId": audit.id,
|
|
**({"executionId": execution_id} if execution_id else {}),
|
|
"policyDecision": "allowed",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
|
|
|
|
def _execute_portfolio_target_enrollment(
|
|
session: Session,
|
|
*,
|
|
source: str,
|
|
risk: str,
|
|
reason: str,
|
|
original_policy_decision: str,
|
|
) -> dict[str, Any]:
|
|
from .portfolio_deployment_recovery import PortfolioDeploymentRecovery
|
|
|
|
action = "deployment.target.register_portfolio"
|
|
target = "jens/portfolio"
|
|
steps = [
|
|
"Validate the fixed Portfolio deployment contract",
|
|
"Verify or re-attest the proven live Portfolio web/API pair",
|
|
"Atomically reconcile the paired controller target state",
|
|
"Preserve exact-source deployment provenance",
|
|
]
|
|
job = create_job(
|
|
session,
|
|
action_id=action,
|
|
target=target,
|
|
source=source,
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
steps=steps,
|
|
)
|
|
start_job(session, job)
|
|
set_job_progress(session, job, 20, "Validating fixed Portfolio deployment target.")
|
|
try:
|
|
enrollment = PortfolioDeploymentRecovery().run()
|
|
status = str(enrollment.get("status") or "error")
|
|
success = status in {"enrolled", "already-enrolled", "reconciled"}
|
|
message = str(
|
|
enrollment.get("reason")
|
|
or (
|
|
"Portfolio deployment target state verified."
|
|
if success
|
|
else "Portfolio deployment target enrollment failed."
|
|
)
|
|
)
|
|
except Exception as exc:
|
|
success = False
|
|
status = "error"
|
|
message = f"{type(exc).__name__}: Portfolio deployment target enrollment failed"
|
|
enrollment = {"status": status}
|
|
|
|
completed = complete_job(
|
|
session,
|
|
job,
|
|
status="succeeded" if success else "failed",
|
|
result_summary=message,
|
|
)
|
|
audit = log_event(
|
|
session,
|
|
source="action",
|
|
identity=source,
|
|
action_id=action,
|
|
target=target,
|
|
target_type="deployment-target",
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
reason=reason,
|
|
result="success" if success else "failed",
|
|
execution_plan={"steps": steps, "jobId": completed.id},
|
|
after_state={
|
|
"status": status,
|
|
"repository": enrollment.get("repository"),
|
|
"composeProject": enrollment.get("compose_project"),
|
|
"containers": enrollment.get("containers"),
|
|
},
|
|
redacted_metadata={
|
|
"executor": action,
|
|
"integration": "mcp" if source == "chatgpt-mcp" else "operator",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
},
|
|
)
|
|
return {
|
|
"success": success,
|
|
"status": "success" if success else "failed",
|
|
"result": "success" if success else "failed",
|
|
"message": message,
|
|
"jobId": completed.id,
|
|
"auditId": audit.id,
|
|
"policyDecision": "allowed",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
|
|
|
|
def _execute_privatemuse_target_enrollment(
|
|
session: Session,
|
|
*,
|
|
source: str,
|
|
risk: str,
|
|
reason: str,
|
|
original_policy_decision: str,
|
|
) -> dict[str, Any]:
|
|
from .privatemuse_deployment_recovery import PrivateMuseDeploymentRecovery
|
|
|
|
action = "deployment.target.register_privatemuse"
|
|
target = "jens/privatemuse"
|
|
steps = [
|
|
"Validate the fixed PrivateMuse deployment contract",
|
|
"Verify or re-attest the proven live PrivateMuse production trio",
|
|
"Atomically reconcile only the bounded controller receipt state",
|
|
"Preserve immutable images, media, models and exact-source provenance",
|
|
]
|
|
recovery = PrivateMuseDeploymentRecovery()
|
|
candidate_job = prepare_job(
|
|
action_id=action,
|
|
target=target,
|
|
source=source,
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
steps=steps,
|
|
)
|
|
tracked, admitted = recovery.admit_job(session, candidate_job)
|
|
tracked_job_id = str(tracked.get("jobId") or "")
|
|
job = session.get(JobRun, tracked_job_id)
|
|
if job is None:
|
|
raise RuntimeError("PrivateMuse recovery owner job is unavailable")
|
|
if admitted:
|
|
start_job(session, job)
|
|
set_job_progress(
|
|
session, job, 20, "Validating fixed PrivateMuse deployment target."
|
|
)
|
|
try:
|
|
enrollment = recovery.run(
|
|
session=session,
|
|
job_id=job.id if admitted else candidate_job.id,
|
|
)
|
|
status = str(enrollment.get("status") or "error")
|
|
success = status in {"enrolled", "already-enrolled", "reconciled"}
|
|
message = str(
|
|
enrollment.get("reason")
|
|
or (
|
|
"PrivateMuse deployment target state verified."
|
|
if success
|
|
else "PrivateMuse deployment target enrollment failed."
|
|
)
|
|
)
|
|
except Exception as exc:
|
|
guarded = recovery.guarded_unknown_result(
|
|
session,
|
|
reason=(
|
|
"PrivateMuse recovery crossed its durable execution boundary but "
|
|
"local result handling failed; reconcile the recorded execution and "
|
|
"do not retry"
|
|
),
|
|
)
|
|
if guarded is not None:
|
|
success = False
|
|
status = "outcome_unknown"
|
|
message = str(guarded["reason"])
|
|
enrollment = guarded
|
|
else:
|
|
success = False
|
|
status = "error"
|
|
message = (
|
|
f"{type(exc).__name__}: PrivateMuse deployment target enrollment failed"
|
|
)
|
|
enrollment = {"status": status}
|
|
|
|
execution_id = str(enrollment.get("execution_id") or "")
|
|
original_job_id = str(enrollment.get("original_job_id") or job.id)
|
|
original_job = session.get(JobRun, original_job_id)
|
|
result_job = original_job or job
|
|
evidence_summary = (
|
|
f"{status}; executionId={execution_id}; {message}"
|
|
if execution_id
|
|
else f"{status}; {message}"
|
|
)
|
|
if status in {"in_progress", "outcome_unknown"}:
|
|
if result_job.status not in {"succeeded", "failed", "cancelled"}:
|
|
completed = set_job_progress(
|
|
session,
|
|
result_job,
|
|
max(result_job.progress, 90 if status == "outcome_unknown" else 5),
|
|
evidence_summary,
|
|
)
|
|
else:
|
|
completed = result_job
|
|
elif result_job.status in {"succeeded", "failed", "cancelled"}:
|
|
completed = result_job
|
|
else:
|
|
completed = complete_job(
|
|
session,
|
|
result_job,
|
|
status="succeeded" if success else "failed",
|
|
result_summary=evidence_summary,
|
|
)
|
|
outward_status = (
|
|
status
|
|
if status in {"in_progress", "outcome_unknown"}
|
|
else "success"
|
|
if success
|
|
else "failed"
|
|
)
|
|
audit = log_event(
|
|
session,
|
|
source="action",
|
|
identity=source,
|
|
action_id=action,
|
|
target=target,
|
|
target_type="deployment-target",
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
reason=reason,
|
|
result=outward_status,
|
|
execution_plan={"steps": steps, "jobId": completed.id},
|
|
after_state={
|
|
"status": status,
|
|
"repository": enrollment.get("repository"),
|
|
"composeProject": enrollment.get("compose_project"),
|
|
"containers": enrollment.get("containers"),
|
|
"executionId": execution_id or None,
|
|
"originalJobId": original_job_id,
|
|
},
|
|
redacted_metadata={
|
|
"executor": action,
|
|
"integration": "mcp" if source == "chatgpt-mcp" else "operator",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
},
|
|
)
|
|
return {
|
|
"success": success,
|
|
"status": outward_status,
|
|
"result": outward_status,
|
|
"message": message,
|
|
"jobId": completed.id,
|
|
"auditId": audit.id,
|
|
**({"executionId": execution_id} if execution_id else {}),
|
|
"policyDecision": "allowed",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
|
|
|
|
|
|
def _execute_media_codec_dashboard_reconciliation(
|
|
session: Session,
|
|
*,
|
|
source: str,
|
|
risk: str,
|
|
reason: str,
|
|
original_policy_decision: str,
|
|
) -> dict[str, Any]:
|
|
from .media_codec_dashboard_deployment_reconciliation import (
|
|
MediaCodecDashboardDeploymentReconciliation,
|
|
)
|
|
|
|
action = "deployment.target.reconcile_media_codec_dashboard"
|
|
target = "jens/media-codec-dashboard"
|
|
steps = [
|
|
"Validate the fixed Media Codec Dashboard deployment contract",
|
|
"Verify the live immutable dashboard runtime",
|
|
"Reconcile only the bounded controller deployment state",
|
|
"Preserve containers, images, mounts and exact-source provenance",
|
|
]
|
|
job = create_job(
|
|
session,
|
|
action_id=action,
|
|
target=target,
|
|
source=source,
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
steps=steps,
|
|
)
|
|
start_job(session, job)
|
|
set_job_progress(
|
|
session,
|
|
job,
|
|
20,
|
|
"Validating fixed Media Codec Dashboard deployment state.",
|
|
)
|
|
try:
|
|
reconciliation = MediaCodecDashboardDeploymentReconciliation().run()
|
|
status = str(reconciliation.get("status") or "error")
|
|
success = status == "reconciled"
|
|
message = str(
|
|
reconciliation.get("reason")
|
|
or (
|
|
"Media Codec Dashboard deployment state reconciled."
|
|
if success
|
|
else "Media Codec Dashboard deployment-state reconciliation failed."
|
|
)
|
|
)
|
|
except Exception as exc:
|
|
success = False
|
|
status = "error"
|
|
reconciliation = {"status": status}
|
|
message = (
|
|
f"{type(exc).__name__}: "
|
|
"Media Codec Dashboard deployment-state reconciliation failed"
|
|
)
|
|
|
|
completed = complete_job(
|
|
session,
|
|
job,
|
|
status="succeeded" if success else "failed",
|
|
result_summary=message,
|
|
)
|
|
audit = log_event(
|
|
session,
|
|
source="action",
|
|
identity=source,
|
|
action_id=action,
|
|
target=target,
|
|
target_type="deployment-target",
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
reason=reason,
|
|
result="success" if success else "failed",
|
|
execution_plan={"steps": steps, "jobId": completed.id},
|
|
after_state={
|
|
"status": status,
|
|
"repository": reconciliation.get("repository"),
|
|
"container": reconciliation.get("container"),
|
|
},
|
|
redacted_metadata={
|
|
"executor": action,
|
|
"integration": "mcp" if source == "chatgpt-mcp" else "operator",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
},
|
|
)
|
|
return {
|
|
"success": success,
|
|
"status": "success" if success else "failed",
|
|
"result": "success" if success else "failed",
|
|
"message": message,
|
|
"jobId": completed.id,
|
|
"auditId": audit.id,
|
|
"policyDecision": "allowed",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
|
|
|
|
def _execute_privatemuse_webhook_repair(
|
|
session: Session,
|
|
*,
|
|
source: str,
|
|
risk: str,
|
|
reason: str,
|
|
original_policy_decision: str,
|
|
) -> dict[str, Any]:
|
|
from .privatemuse_webhook_repair import PrivateMuseWebhookRepair
|
|
|
|
action = "deployment.webhook.repair_privatemuse"
|
|
target = "jens/privatemuse"
|
|
steps = [
|
|
"Validate the fixed PrivateMuse runnerless webhook contract",
|
|
"Verify controller-owned webhook secret and Gitea repository identity",
|
|
"Create or repair only the exact PrivateMuse push hook",
|
|
"Re-read the hook and verify active main-only push delivery metadata",
|
|
]
|
|
job = create_job(
|
|
session,
|
|
action_id=action,
|
|
target=target,
|
|
source=source,
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
steps=steps,
|
|
)
|
|
start_job(session, job)
|
|
set_job_progress(session, job, 20, "Validating fixed PrivateMuse webhook state.")
|
|
try:
|
|
repair = PrivateMuseWebhookRepair().run()
|
|
status = str(repair.get("status") or "error")
|
|
success = status == "repaired"
|
|
message = str(
|
|
repair.get("reason")
|
|
or (
|
|
"PrivateMuse runnerless webhook verified or repaired."
|
|
if success
|
|
else "PrivateMuse runnerless webhook repair failed."
|
|
)
|
|
)
|
|
except Exception as exc:
|
|
success = False
|
|
status = "error"
|
|
message = f"{type(exc).__name__}: PrivateMuse runnerless webhook repair failed"
|
|
repair = {"status": status}
|
|
|
|
completed = complete_job(
|
|
session,
|
|
job,
|
|
status="succeeded" if success else "failed",
|
|
result_summary=message,
|
|
)
|
|
audit = log_event(
|
|
session,
|
|
source="action",
|
|
identity=source,
|
|
action_id=action,
|
|
target=target,
|
|
target_type="deployment-webhook",
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
reason=reason,
|
|
result="success" if success else "failed",
|
|
execution_plan={"steps": steps, "jobId": completed.id},
|
|
after_state={
|
|
"status": status,
|
|
"repository": repair.get("repository"),
|
|
"endpoint": repair.get("endpoint"),
|
|
"branch": repair.get("branch"),
|
|
"event": repair.get("event"),
|
|
},
|
|
redacted_metadata={
|
|
"executor": action,
|
|
"integration": "mcp" if source == "chatgpt-mcp" else "operator",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
"secretMaterialReturned": False,
|
|
},
|
|
)
|
|
return {
|
|
"success": success,
|
|
"status": "success" if success else status,
|
|
"result": "success" if success else "failed",
|
|
"message": message,
|
|
"jobId": completed.id,
|
|
"auditId": audit.id,
|
|
"policyDecision": "allowed",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
|
|
|
|
def _execute_runnerless_target_provisioning(
|
|
session: Session,
|
|
*,
|
|
target: str,
|
|
source: str,
|
|
risk: str,
|
|
reason: str,
|
|
original_policy_decision: str,
|
|
) -> dict[str, Any]:
|
|
from .gitea_project_auto_registration import GiteaProjectAutoRegistration
|
|
from .runnerless_target_provisioning import RunnerlessTargetProvisioning
|
|
|
|
action = "deployment.runnerless.provision"
|
|
application_id = target.strip().lower()
|
|
catalog = GiteaProjectAutoRegistration.catalog(session)
|
|
projects = catalog.get("projects") if isinstance(catalog, dict) else None
|
|
matches = [
|
|
item
|
|
for item in projects or []
|
|
if isinstance(item, dict)
|
|
and str(item.get("applicationId") or "").strip().lower() == application_id
|
|
and bool(item.get("deploymentRegistered"))
|
|
and str(item.get("state") or "") in {"registered", "registered_existing"}
|
|
]
|
|
if len(matches) != 1:
|
|
return {
|
|
"success": False,
|
|
"status": "failed",
|
|
"result": "blocked",
|
|
"message": (
|
|
"Runnerless provisioning requires exactly one auto-registered "
|
|
"deployment target."
|
|
),
|
|
"policyDecision": "blocked",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
|
|
project = matches[0]
|
|
repository = str(project.get("repository") or "").strip().lower()
|
|
branch = str(project.get("defaultBranch") or "").strip()
|
|
revision = str(project.get("revision") or "").strip().lower()
|
|
if (
|
|
not repository.startswith("jens/")
|
|
or not branch
|
|
or len(revision) != 40
|
|
or any(character not in "0123456789abcdef" for character in revision)
|
|
):
|
|
return {
|
|
"success": False,
|
|
"status": "failed",
|
|
"result": "blocked",
|
|
"message": "Auto-registered deployment target metadata is incomplete.",
|
|
"policyDecision": "blocked",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
|
|
steps = [
|
|
"Resolve the exact auto-registered application target",
|
|
"Verify controller target, repository identity and private Gitea reachability",
|
|
"Create or verify one repository-specific runnerless webhook secret",
|
|
"Install the exact main-push validation triplet and signed Gitea hook",
|
|
"Verify the hook without returning credentials",
|
|
]
|
|
job = create_job(
|
|
session,
|
|
action_id=action,
|
|
target=application_id,
|
|
source=source,
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
steps=steps,
|
|
)
|
|
start_job(session, job)
|
|
set_job_progress(
|
|
session,
|
|
job,
|
|
20,
|
|
"Provisioning exact-target runnerless delivery metadata.",
|
|
)
|
|
try:
|
|
provisioned = RunnerlessTargetProvisioning().run(
|
|
repository=repository,
|
|
branch=branch,
|
|
)
|
|
status = str(provisioned.get("status") or "error")
|
|
success = status == "ready"
|
|
message = str(
|
|
provisioned.get("reason")
|
|
or (
|
|
"Runnerless delivery is ready for the registered target."
|
|
if success
|
|
else "Runnerless delivery provisioning failed."
|
|
)
|
|
)
|
|
except Exception as exc:
|
|
provisioned = {"status": "error"}
|
|
status = "error"
|
|
success = False
|
|
message = (
|
|
f"{type(exc).__name__}: runnerless target provisioning failed"
|
|
)
|
|
|
|
completed = complete_job(
|
|
session,
|
|
job,
|
|
status="succeeded" if success else "failed",
|
|
result_summary=message,
|
|
)
|
|
audit = log_event(
|
|
session,
|
|
source="action",
|
|
identity=source,
|
|
action_id=action,
|
|
target=application_id,
|
|
target_type="deployment-webhook",
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
reason=reason,
|
|
result="success" if success else "failed",
|
|
execution_plan={"steps": steps, "jobId": completed.id},
|
|
after_state={
|
|
"status": status,
|
|
"applicationId": application_id,
|
|
"repository": repository,
|
|
"revision": revision,
|
|
"branch": provisioned.get("branch"),
|
|
"endpoint": provisioned.get("endpoint"),
|
|
},
|
|
redacted_metadata={
|
|
"executor": action,
|
|
"integration": "mcp" if source == "chatgpt-mcp" else "operator",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
"secretMaterialReturned": False,
|
|
"repositoryCallerSelectable": False,
|
|
"branchCallerSelectable": False,
|
|
},
|
|
)
|
|
return {
|
|
"success": success,
|
|
"status": "success" if success else status,
|
|
"result": "success" if success else "failed",
|
|
"message": message,
|
|
"jobId": completed.id,
|
|
"auditId": audit.id,
|
|
"policyDecision": "allowed",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
"applicationId": application_id,
|
|
"repository": repository,
|
|
"revision": revision,
|
|
}
|
|
|
|
|
|
def _execute_workmesh_first_deployment(
|
|
session: Session,
|
|
*,
|
|
source: str,
|
|
risk: str,
|
|
reason: str,
|
|
original_policy_decision: str,
|
|
) -> dict[str, Any]:
|
|
from .workmesh_first_deployment import WorkMeshFirstDeployment
|
|
|
|
action = "deployment.target.deploy_workmesh"
|
|
target = "jens/workmesh"
|
|
steps = [
|
|
"Verify the fixed WorkMesh v0.1.0 protected-main release contract",
|
|
"Create or validate the external mode-0600 WorkMesh runtime environment",
|
|
"Reserve the fixed loopback port set and reconcile the exact-source controller target",
|
|
"Run the official deployment-controller preflight and transactional first deploy",
|
|
"Verify the controller-owned deployment receipt without exposing secret values",
|
|
]
|
|
service = WorkMeshFirstDeployment()
|
|
tracked_job_id = service.tracked_job_id(session)
|
|
job = session.get(JobRun, tracked_job_id) if tracked_job_id else None
|
|
orphan_running = False
|
|
if job is None:
|
|
job = session.exec(
|
|
select(JobRun)
|
|
.where(JobRun.action_id == action, JobRun.target == target, JobRun.status == "running")
|
|
.order_by(JobRun.started_at.desc())
|
|
).first()
|
|
if job is not None:
|
|
orphan_running = True
|
|
else:
|
|
job = create_job(
|
|
session,
|
|
action_id=action,
|
|
target=target,
|
|
source=source,
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
steps=steps,
|
|
)
|
|
start_job(session, job)
|
|
|
|
try:
|
|
deployment = (
|
|
{
|
|
"status": "outcome_unknown",
|
|
"reason": "An earlier WorkMesh deployment job is running without matching durable execution state; reconcile it before another deploy",
|
|
}
|
|
if orphan_running
|
|
else service.run(session, job=job)
|
|
)
|
|
status = str(deployment.get("status") or "error")
|
|
execution_id = str(deployment.get("execution_id") or "")
|
|
if status == "deployed":
|
|
success = True
|
|
message = "WorkMesh v0.1.0 first deployment completed with controller receipt evidence."
|
|
elif status == "in_progress":
|
|
success = False
|
|
message = "WorkMesh v0.1.0 first deployment is still running."
|
|
elif status == "outcome_unknown":
|
|
success = False
|
|
message = str(deployment.get("reason") or "WorkMesh deployment outcome requires reconciliation.")
|
|
else:
|
|
success = False
|
|
message = str(deployment.get("reason") or "WorkMesh v0.1.0 first deployment failed closed.")
|
|
except Exception as exc:
|
|
status = "error"
|
|
execution_id = ""
|
|
success = False
|
|
deployment = {"status": status}
|
|
message = f"{type(exc).__name__}: WorkMesh first-deploy reconciliation failed"
|
|
|
|
if status in {"in_progress", "outcome_unknown"}:
|
|
if job.status not in {"succeeded", "failed", "cancelled"}:
|
|
completed = set_job_progress(
|
|
session,
|
|
job,
|
|
max(job.progress, 90 if status == "outcome_unknown" else 25),
|
|
message,
|
|
)
|
|
else:
|
|
completed = job
|
|
elif job.status in {"succeeded", "failed", "cancelled"}:
|
|
completed = job
|
|
else:
|
|
completed = complete_job(
|
|
session,
|
|
job,
|
|
status="succeeded" if success else "failed",
|
|
result_summary=message,
|
|
)
|
|
|
|
outward_status = (
|
|
status
|
|
if status in {"in_progress", "outcome_unknown"}
|
|
else "success"
|
|
if success
|
|
else "failed"
|
|
)
|
|
audit = log_event(
|
|
session,
|
|
source="action",
|
|
identity=source,
|
|
action_id=action,
|
|
target=target,
|
|
target_type="deployment-target",
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
reason=reason,
|
|
result=outward_status,
|
|
execution_plan={"steps": steps, "jobId": completed.id},
|
|
after_state={
|
|
"status": status,
|
|
"repository": deployment.get("repository", target),
|
|
"revision": deployment.get("revision"),
|
|
"composeProject": deployment.get("compose_project"),
|
|
"containers": deployment.get("containers"),
|
|
"ports": deployment.get("ports"),
|
|
"executionId": execution_id or None,
|
|
},
|
|
redacted_metadata={
|
|
"executor": action,
|
|
"integration": "mcp" if source == "chatgpt-mcp" else "operator",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
"secretsReturned": False,
|
|
},
|
|
)
|
|
return {
|
|
"success": success,
|
|
"status": outward_status,
|
|
"result": outward_status,
|
|
"message": message,
|
|
"jobId": completed.id,
|
|
"auditId": audit.id,
|
|
**({"executionId": execution_id} if execution_id else {}),
|
|
"policyDecision": "allowed",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
|
|
|
|
def _execute_portfolio_target_enrollment(
|
|
session: Session,
|
|
*,
|
|
source: str,
|
|
risk: str,
|
|
reason: str,
|
|
original_policy_decision: str,
|
|
) -> dict[str, Any]:
|
|
from .portfolio_deployment_recovery import PortfolioDeploymentRecovery
|
|
|
|
action = "deployment.target.register_portfolio"
|
|
target = "jens/portfolio"
|
|
steps = [
|
|
"Validate the fixed Portfolio deployment contract",
|
|
"Verify or re-attest the proven live Portfolio web/API pair",
|
|
"Atomically reconcile the paired controller target state",
|
|
"Preserve exact-source deployment provenance",
|
|
]
|
|
job = create_job(
|
|
session,
|
|
action_id=action,
|
|
target=target,
|
|
source=source,
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
steps=steps,
|
|
)
|
|
start_job(session, job)
|
|
set_job_progress(session, job, 20, "Validating fixed Portfolio deployment target.")
|
|
try:
|
|
enrollment = PortfolioDeploymentRecovery().run()
|
|
status = str(enrollment.get("status") or "error")
|
|
success = status in {"enrolled", "already-enrolled", "reconciled"}
|
|
message = str(
|
|
enrollment.get("reason")
|
|
or (
|
|
"Portfolio deployment target state verified."
|
|
if success
|
|
else "Portfolio deployment target enrollment failed."
|
|
)
|
|
)
|
|
except Exception as exc:
|
|
success = False
|
|
status = "error"
|
|
message = f"{type(exc).__name__}: Portfolio deployment target enrollment failed"
|
|
enrollment = {"status": status}
|
|
|
|
completed = complete_job(
|
|
session,
|
|
job,
|
|
status="succeeded" if success else "failed",
|
|
result_summary=message,
|
|
)
|
|
audit = log_event(
|
|
session,
|
|
source="action",
|
|
identity=source,
|
|
action_id=action,
|
|
target=target,
|
|
target_type="deployment-target",
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
reason=reason,
|
|
result="success" if success else "failed",
|
|
execution_plan={"steps": steps, "jobId": completed.id},
|
|
after_state={
|
|
"status": status,
|
|
"repository": enrollment.get("repository"),
|
|
"composeProject": enrollment.get("compose_project"),
|
|
"containers": enrollment.get("containers"),
|
|
},
|
|
redacted_metadata={
|
|
"executor": action,
|
|
"integration": "mcp" if source == "chatgpt-mcp" else "operator",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
},
|
|
)
|
|
return {
|
|
"success": success,
|
|
"status": "success" if success else "failed",
|
|
"result": "success" if success else "failed",
|
|
"message": message,
|
|
"jobId": completed.id,
|
|
"auditId": audit.id,
|
|
"policyDecision": "allowed",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
|
|
|
|
def _execute_privatemuse_target_enrollment(
|
|
session: Session,
|
|
*,
|
|
source: str,
|
|
risk: str,
|
|
reason: str,
|
|
original_policy_decision: str,
|
|
) -> dict[str, Any]:
|
|
from .privatemuse_deployment_recovery import PrivateMuseDeploymentRecovery
|
|
|
|
action = "deployment.target.register_privatemuse"
|
|
target = "jens/privatemuse"
|
|
steps = [
|
|
"Validate the fixed PrivateMuse deployment contract",
|
|
"Verify or re-attest the proven live PrivateMuse production trio",
|
|
"Atomically reconcile only the bounded controller receipt state",
|
|
"Preserve immutable images, media, models and exact-source provenance",
|
|
]
|
|
recovery = PrivateMuseDeploymentRecovery()
|
|
candidate_job = prepare_job(
|
|
action_id=action,
|
|
target=target,
|
|
source=source,
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
steps=steps,
|
|
)
|
|
tracked, admitted = recovery.admit_job(session, candidate_job)
|
|
tracked_job_id = str(tracked.get("jobId") or "")
|
|
job = session.get(JobRun, tracked_job_id)
|
|
if job is None:
|
|
raise RuntimeError("PrivateMuse recovery owner job is unavailable")
|
|
if admitted:
|
|
start_job(session, job)
|
|
set_job_progress(
|
|
session, job, 20, "Validating fixed PrivateMuse deployment target."
|
|
)
|
|
try:
|
|
enrollment = recovery.run(
|
|
session=session,
|
|
job_id=job.id if admitted else candidate_job.id,
|
|
)
|
|
status = str(enrollment.get("status") or "error")
|
|
success = status in {"enrolled", "already-enrolled", "reconciled"}
|
|
message = str(
|
|
enrollment.get("reason")
|
|
or (
|
|
"PrivateMuse deployment target state verified."
|
|
if success
|
|
else "PrivateMuse deployment target enrollment failed."
|
|
)
|
|
)
|
|
except Exception as exc:
|
|
guarded = recovery.guarded_unknown_result(
|
|
session,
|
|
reason=(
|
|
"PrivateMuse recovery crossed its durable execution boundary but "
|
|
"local result handling failed; reconcile the recorded execution and "
|
|
"do not retry"
|
|
),
|
|
)
|
|
if guarded is not None:
|
|
success = False
|
|
status = "outcome_unknown"
|
|
message = str(guarded["reason"])
|
|
enrollment = guarded
|
|
else:
|
|
success = False
|
|
status = "error"
|
|
message = (
|
|
f"{type(exc).__name__}: PrivateMuse deployment target enrollment failed"
|
|
)
|
|
enrollment = {"status": status}
|
|
|
|
execution_id = str(enrollment.get("execution_id") or "")
|
|
original_job_id = str(enrollment.get("original_job_id") or job.id)
|
|
original_job = session.get(JobRun, original_job_id)
|
|
result_job = original_job or job
|
|
evidence_summary = (
|
|
f"{status}; executionId={execution_id}; {message}"
|
|
if execution_id
|
|
else f"{status}; {message}"
|
|
)
|
|
if status in {"in_progress", "outcome_unknown"}:
|
|
if result_job.status not in {"succeeded", "failed", "cancelled"}:
|
|
completed = set_job_progress(
|
|
session,
|
|
result_job,
|
|
max(result_job.progress, 90 if status == "outcome_unknown" else 5),
|
|
evidence_summary,
|
|
)
|
|
else:
|
|
completed = result_job
|
|
elif result_job.status in {"succeeded", "failed", "cancelled"}:
|
|
completed = result_job
|
|
else:
|
|
completed = complete_job(
|
|
session,
|
|
result_job,
|
|
status="succeeded" if success else "failed",
|
|
result_summary=evidence_summary,
|
|
)
|
|
outward_status = (
|
|
status
|
|
if status in {"in_progress", "outcome_unknown"}
|
|
else "success"
|
|
if success
|
|
else "failed"
|
|
)
|
|
audit = log_event(
|
|
session,
|
|
source="action",
|
|
identity=source,
|
|
action_id=action,
|
|
target=target,
|
|
target_type="deployment-target",
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
reason=reason,
|
|
result=outward_status,
|
|
execution_plan={"steps": steps, "jobId": completed.id},
|
|
after_state={
|
|
"status": status,
|
|
"repository": enrollment.get("repository"),
|
|
"composeProject": enrollment.get("compose_project"),
|
|
"containers": enrollment.get("containers"),
|
|
"executionId": execution_id or None,
|
|
"originalJobId": original_job_id,
|
|
},
|
|
redacted_metadata={
|
|
"executor": action,
|
|
"integration": "mcp" if source == "chatgpt-mcp" else "operator",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
},
|
|
)
|
|
return {
|
|
"success": success,
|
|
"status": outward_status,
|
|
"result": outward_status,
|
|
"message": message,
|
|
"jobId": completed.id,
|
|
"auditId": audit.id,
|
|
**({"executionId": execution_id} if execution_id else {}),
|
|
"policyDecision": "allowed",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
|
|
|
|
|
|
def _execute_media_codec_dashboard_reconciliation(
|
|
session: Session,
|
|
*,
|
|
source: str,
|
|
risk: str,
|
|
reason: str,
|
|
original_policy_decision: str,
|
|
) -> dict[str, Any]:
|
|
from .media_codec_dashboard_deployment_reconciliation import (
|
|
MediaCodecDashboardDeploymentReconciliation,
|
|
)
|
|
|
|
action = "deployment.target.reconcile_media_codec_dashboard"
|
|
target = "jens/media-codec-dashboard"
|
|
steps = [
|
|
"Validate the fixed Media Codec Dashboard deployment contract",
|
|
"Verify the live immutable dashboard runtime",
|
|
"Reconcile only the bounded controller deployment state",
|
|
"Preserve containers, images, mounts and exact-source provenance",
|
|
]
|
|
job = create_job(
|
|
session,
|
|
action_id=action,
|
|
target=target,
|
|
source=source,
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
steps=steps,
|
|
)
|
|
start_job(session, job)
|
|
set_job_progress(
|
|
session,
|
|
job,
|
|
20,
|
|
"Validating fixed Media Codec Dashboard deployment state.",
|
|
)
|
|
try:
|
|
reconciliation = MediaCodecDashboardDeploymentReconciliation().run()
|
|
status = str(reconciliation.get("status") or "error")
|
|
success = status == "reconciled"
|
|
message = str(
|
|
reconciliation.get("reason")
|
|
or (
|
|
"Media Codec Dashboard deployment state reconciled."
|
|
if success
|
|
else "Media Codec Dashboard deployment-state reconciliation failed."
|
|
)
|
|
)
|
|
except Exception as exc:
|
|
success = False
|
|
status = "error"
|
|
reconciliation = {"status": status}
|
|
message = (
|
|
f"{type(exc).__name__}: "
|
|
"Media Codec Dashboard deployment-state reconciliation failed"
|
|
)
|
|
|
|
completed = complete_job(
|
|
session,
|
|
job,
|
|
status="succeeded" if success else "failed",
|
|
result_summary=message,
|
|
)
|
|
audit = log_event(
|
|
session,
|
|
source="action",
|
|
identity=source,
|
|
action_id=action,
|
|
target=target,
|
|
target_type="deployment-target",
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
reason=reason,
|
|
result="success" if success else "failed",
|
|
execution_plan={"steps": steps, "jobId": completed.id},
|
|
after_state={
|
|
"status": status,
|
|
"repository": reconciliation.get("repository"),
|
|
"container": reconciliation.get("container"),
|
|
},
|
|
redacted_metadata={
|
|
"executor": action,
|
|
"integration": "mcp" if source == "chatgpt-mcp" else "operator",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
},
|
|
)
|
|
return {
|
|
"success": success,
|
|
"status": "success" if success else "failed",
|
|
"result": "success" if success else "failed",
|
|
"message": message,
|
|
"jobId": completed.id,
|
|
"auditId": audit.id,
|
|
"policyDecision": "allowed",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
|
|
|
|
def _execute_privatemuse_webhook_repair(
|
|
session: Session,
|
|
*,
|
|
source: str,
|
|
risk: str,
|
|
reason: str,
|
|
original_policy_decision: str,
|
|
) -> dict[str, Any]:
|
|
from .privatemuse_webhook_repair import PrivateMuseWebhookRepair
|
|
|
|
action = "deployment.webhook.repair_privatemuse"
|
|
target = "jens/privatemuse"
|
|
steps = [
|
|
"Validate the fixed PrivateMuse runnerless webhook contract",
|
|
"Verify controller-owned webhook secret and Gitea repository identity",
|
|
"Create or repair only the exact PrivateMuse push hook",
|
|
"Re-read the hook and verify active main-only push delivery metadata",
|
|
]
|
|
job = create_job(
|
|
session,
|
|
action_id=action,
|
|
target=target,
|
|
source=source,
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
steps=steps,
|
|
)
|
|
start_job(session, job)
|
|
set_job_progress(session, job, 20, "Validating fixed PrivateMuse webhook state.")
|
|
try:
|
|
repair = PrivateMuseWebhookRepair().run()
|
|
status = str(repair.get("status") or "error")
|
|
success = status == "repaired"
|
|
message = str(
|
|
repair.get("reason")
|
|
or (
|
|
"PrivateMuse runnerless webhook verified or repaired."
|
|
if success
|
|
else "PrivateMuse runnerless webhook repair failed."
|
|
)
|
|
)
|
|
except Exception as exc:
|
|
success = False
|
|
status = "error"
|
|
message = f"{type(exc).__name__}: PrivateMuse runnerless webhook repair failed"
|
|
repair = {"status": status}
|
|
|
|
completed = complete_job(
|
|
session,
|
|
job,
|
|
status="succeeded" if success else "failed",
|
|
result_summary=message,
|
|
)
|
|
audit = log_event(
|
|
session,
|
|
source="action",
|
|
identity=source,
|
|
action_id=action,
|
|
target=target,
|
|
target_type="deployment-webhook",
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
reason=reason,
|
|
result="success" if success else "failed",
|
|
execution_plan={"steps": steps, "jobId": completed.id},
|
|
after_state={
|
|
"status": status,
|
|
"repository": repair.get("repository"),
|
|
"endpoint": repair.get("endpoint"),
|
|
"branch": repair.get("branch"),
|
|
"event": repair.get("event"),
|
|
},
|
|
redacted_metadata={
|
|
"executor": action,
|
|
"integration": "mcp" if source == "chatgpt-mcp" else "operator",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
"secretMaterialReturned": False,
|
|
},
|
|
)
|
|
return {
|
|
"success": success,
|
|
"status": "success" if success else status,
|
|
"result": "success" if success else "failed",
|
|
"message": message,
|
|
"jobId": completed.id,
|
|
"auditId": audit.id,
|
|
"policyDecision": "allowed",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
|
|
|
|
|
|
def _execute_controller_artifact_promote(
|
|
session: Session,
|
|
*,
|
|
source: str,
|
|
risk: str,
|
|
reason: str,
|
|
original_policy_decision: str,
|
|
) -> dict[str, Any]:
|
|
from .controller_artifact_promoter import (
|
|
ControllerArtifactPromoter,
|
|
helper_failure_diagnostics,
|
|
safe_helper_diagnostics,
|
|
)
|
|
|
|
action = "controller.artifact.promote"
|
|
target = "tower/deployment-controller"
|
|
steps = [
|
|
"Resolve protected current main and successful push validation",
|
|
"Reuse the immutable image of the live deployment controller",
|
|
"Run one fixed ephemeral controller-promoter helper",
|
|
"Execute the existing rollbackable root controller upgrade procedure",
|
|
"Verify the installed controller release identity",
|
|
]
|
|
job = create_job(
|
|
session,
|
|
action_id=action,
|
|
target=target,
|
|
source=source,
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
steps=steps,
|
|
)
|
|
start_job(session, job)
|
|
set_job_progress(session, job, 20, "Promoting fixed root deployment-controller artifact.")
|
|
try:
|
|
result = ControllerArtifactPromoter().run()
|
|
status = str(result.get("status") or "error")
|
|
success = status in {"promoted", "already_applied"}
|
|
message = str(
|
|
result.get("reason")
|
|
or (
|
|
"Root deployment-controller artifact verified."
|
|
if success
|
|
else "Root deployment-controller promotion failed."
|
|
)
|
|
)
|
|
except Exception as exc:
|
|
result = {"status": "error"}
|
|
status = "error"
|
|
success = False
|
|
message = f"{type(exc).__name__}: controller artifact promotion failed"
|
|
|
|
diagnostics = None
|
|
if status == "failed" and result.get("reason") == "controller_promoter_helper_failed":
|
|
diagnostics = safe_helper_diagnostics(result.get("diagnostics"))
|
|
if diagnostics is None:
|
|
diagnostics = helper_failure_diagnostics(result.get("exitCode"))
|
|
exit_code = diagnostics["exitCode"]
|
|
exit_code_summary = str(exit_code) if exit_code is not None else "unknown"
|
|
message = (
|
|
f"Controller promotion helper failed: {diagnostics['code']}; "
|
|
f"phase={diagnostics['phase']}; exitCode={exit_code_summary}."
|
|
)
|
|
|
|
completed = complete_job(
|
|
session,
|
|
job,
|
|
status="succeeded" if success else "failed",
|
|
result_summary=message,
|
|
)
|
|
after_state = {
|
|
"status": status,
|
|
"revision": result.get("revision"),
|
|
"controllerVersion": result.get("controllerVersion"),
|
|
"artifactSha256": result.get("artifactSha256"),
|
|
}
|
|
redacted_metadata = {
|
|
"executor": action,
|
|
"integration": "mcp" if source == "chatgpt-mcp" else "operator",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
"callerRevisionSelectable": False,
|
|
"callerCommandSelectable": False,
|
|
"callerMountSelectable": False,
|
|
"helperTargetSelectable": False,
|
|
}
|
|
if diagnostics is not None:
|
|
after_state["diagnostics"] = diagnostics
|
|
redacted_metadata["diagnostics"] = diagnostics
|
|
|
|
audit = log_event(
|
|
session,
|
|
source="action",
|
|
identity=source,
|
|
action_id=action,
|
|
target=target,
|
|
target_type="deployment-controller",
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
reason=reason,
|
|
result="success" if success else "failed",
|
|
execution_plan={"steps": steps, "jobId": completed.id},
|
|
after_state=after_state,
|
|
redacted_metadata=redacted_metadata,
|
|
)
|
|
operation_result = {
|
|
"success": success,
|
|
"status": "success" if success else status,
|
|
"result": "success" if success else "failed",
|
|
"message": message,
|
|
"jobId": completed.id,
|
|
"auditId": audit.id,
|
|
"policyDecision": "allowed",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
"revision": result.get("revision"),
|
|
"controllerVersion": result.get("controllerVersion"),
|
|
"artifactSha256": result.get("artifactSha256"),
|
|
}
|
|
if diagnostics is not None:
|
|
operation_result["diagnostics"] = diagnostics
|
|
return operation_result
|
|
|
|
|
|
def _execute_runner_acceptance(session: Session, *, action: str, target: str, source: str,
|
|
risk: str, reason: str, original_policy_decision: str) -> dict[str, Any]:
|
|
from ..db.models import GatewayUser
|
|
from .user_access import actor_identity
|
|
|
|
actor = actor_identity.get()
|
|
admin = False
|
|
if actor:
|
|
provider, _, subject = actor.partition(":")
|
|
user = session.exec(select(GatewayUser).where(GatewayUser.provider == provider,
|
|
GatewayUser.subject == subject)).first()
|
|
admin = bool(user and user.enabled and user.role == "admin")
|
|
authorized = (source == "chatgpt-mcp" and actor is None) or admin
|
|
if (target != "tower/ci-acceptance-residue" or not authorized
|
|
or source not in {"manual", "chatgpt-mcp", "approved_operator"}
|
|
or original_policy_decision not in {"allowed", "approval_required"}):
|
|
return {"success": False, "status": "blocked", "result": "blocked",
|
|
"message": "Fixed CI maintenance requires the authenticated administrator boundary.",
|
|
"policyDecision": "blocked"}
|
|
return _execute_runner_fleet_upgrade_v2(
|
|
session, source=source, risk=risk, reason=reason,
|
|
original_policy_decision=original_policy_decision, acceptance=action.rsplit(".", 1)[-1],
|
|
)
|
|
|
|
|
|
def _execute_runner_fleet_upgrade_v2(
|
|
session: Session,
|
|
*,
|
|
source: str,
|
|
risk: str,
|
|
reason: str,
|
|
original_policy_decision: str,
|
|
specialized: bool = False,
|
|
statistics_configuration: bool = False,
|
|
acceptance: str | None = None,
|
|
) -> dict[str, Any]:
|
|
from .deployment_broker import DeploymentBrokerClient
|
|
|
|
action = ("runner.acceptance." + acceptance if acceptance else
|
|
"runner.statistics.configure" if statistics_configuration else
|
|
"runner.fleet.specialize" if specialized else "runner.fleet.upgrade_v2")
|
|
target = ("tower/ci-acceptance-residue" if acceptance else
|
|
"tower/projectbrain-runner-statistics" if statistics_configuration else
|
|
"tower/runner-fleet-specialized" if specialized else "tower/runner-fleet-v2")
|
|
steps = [
|
|
"Validate exact fixed runner-fleet target",
|
|
"Call HMAC-signed root controller endpoint",
|
|
"Prove protected main and successful push validation",
|
|
"Execute exact-revision specialized migration script" if specialized
|
|
else "Execute exact-revision fleet-v2 migration script",
|
|
"Verify specialized runner topology",
|
|
]
|
|
if statistics_configuration:
|
|
steps = ["Verify fixed read-only statistics target", "Prove protected controller/runtime source",
|
|
"Lock production configuration", "Provision private independent credential with durable CAS",
|
|
"Configure ProjectBrain for its governed delivery"]
|
|
if acceptance:
|
|
steps = ["Prove protected controller/runtime source", "Attest finite CI origin and complete private identities",
|
|
"Verify dispatch barrier and production exclusion", "Preserve all resources and data"]
|
|
job = create_job(
|
|
session,
|
|
action_id=action,
|
|
target=target,
|
|
source=source,
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
steps=steps,
|
|
)
|
|
start_job(session, job)
|
|
set_job_progress(session, job, 25, f"Requesting {action} through the fixed controller endpoint.")
|
|
try:
|
|
broker = DeploymentBrokerClient()
|
|
result = (broker.runner_acceptance(reason=reason, preflight=acceptance == "preflight") if acceptance else
|
|
broker.runner_statistics_configure(reason=reason) if statistics_configuration else
|
|
broker.runner_fleet_specialize(reason=reason) if specialized else broker.runner_fleet_upgrade_v2(reason=reason))
|
|
if acceptance:
|
|
allowed_blockers = {
|
|
"terminal_origin_claim_missing", "terminal_origin_task_binding_unavailable",
|
|
"terminal_origin_unavailable", "active_product_receipt_exclusion_unavailable",
|
|
"dispatch_barrier_guard_unverified", "preflight_evidence_rejected",
|
|
"acceptance_evidence_rejected", "term_timeout", "controller_response_untrusted",
|
|
"maintenance_outcome_unknown", "maintenance_receipt_untrusted", "maintenance_execution_deadline",
|
|
}
|
|
blockers = result.get("blockers", [])
|
|
clean_blockers = (blockers if isinstance(blockers, list) and len(blockers) <= 20
|
|
and all(isinstance(code, str) and code in allowed_blockers for code in blockers)
|
|
else ["controller_response_untrusted"])
|
|
result = {
|
|
"status": result.get("status") if result.get("status") in {
|
|
"ready", "blocked", "partial", "quiesced", "already_quiesced", "unknown", "in_progress"
|
|
} else "blocked",
|
|
"revision": result.get("revision") if isinstance(result.get("revision"), str)
|
|
and len(result["revision"]) == 40 and all(char in "0123456789abcdef" for char in result["revision"]) else None,
|
|
"blockers": clean_blockers,
|
|
"preservedContainers": 18 if result.get("preservedContainers") == 18 else None,
|
|
"effectsPerformed": result.get("effectsPerformed") if type(result.get("effectsPerformed")) is bool else None,
|
|
"noMutation": result.get("noMutation") if type(result.get("noMutation")) is bool else None,
|
|
"maintenancePhase": result.get("maintenance", {}).get("phase") if isinstance(result.get("maintenance"), dict)
|
|
and result["maintenance"].get("phase") in {"guarding", "quiescing", "restoring", "complete"} else result.get("phase")
|
|
if result.get("phase") in {"guarding", "quiescing", "restoring", "complete"} else None,
|
|
}
|
|
status = str(result.get("status") or "error")
|
|
success = status in ({"ready"} if acceptance == "preflight" else {"quiesced", "already_quiesced"} if acceptance else
|
|
{"configured", "already_configured"} if statistics_configuration else
|
|
{"specialized", "already_applied"} if specialized else {"upgraded", "already_applied"})
|
|
message = str(
|
|
result.get("reason")
|
|
or (
|
|
("Finite CI acceptance maintenance verified." if acceptance else
|
|
"ProjectBrain read-only statistics configuration verified." if statistics_configuration else
|
|
"Tower runner specialization verified." if specialized
|
|
else "Tower runner-fleet v2 migration verified.")
|
|
if success else
|
|
("Maintenance outcome is unknown or still active; use read-only preflight status before any explicit resume." if acceptance and status in {"unknown", "in_progress", "partial"} else
|
|
"Finite CI acceptance maintenance is blocked by required evidence." if acceptance else
|
|
"ProjectBrain statistics configuration was rejected or failed." if statistics_configuration else
|
|
"Tower runner specialization was rejected or failed." if specialized
|
|
else "Tower runner-fleet v2 migration was rejected or failed.")
|
|
)
|
|
)
|
|
except Exception as exc:
|
|
result = {"status": "unknown" if acceptance == "quiesce" or specialized else "error", "effectsPerformed": None}
|
|
status = result["status"]
|
|
success = False
|
|
message = f"{type(exc).__name__}: fixed controller operation failed"
|
|
|
|
completed = complete_job(
|
|
session,
|
|
job,
|
|
status="succeeded" if success else "failed",
|
|
result_summary=message,
|
|
)
|
|
audit = log_event(
|
|
session,
|
|
source="action",
|
|
identity=source,
|
|
action_id=action,
|
|
target=target,
|
|
target_type="runner-fleet",
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
reason=reason,
|
|
result="success" if success else "unknown" if (acceptance or specialized) and status in {"unknown", "in_progress", "partial"} else "failed",
|
|
execution_plan={"steps": steps, "jobId": completed.id},
|
|
after_state={
|
|
"status": status,
|
|
"revision": result.get("revision"),
|
|
"verifiedRunners": result.get("verifiedRunners"),
|
|
"projectbrainDeliveryRequired": result.get("projectbrainDeliveryRequired"),
|
|
},
|
|
redacted_metadata={
|
|
"executor": action,
|
|
"integration": "mcp" if source == "chatgpt-mcp" else "operator",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
"scriptPathCallerSelectable": False,
|
|
"runnerTargetCallerSelectable": False,
|
|
},
|
|
)
|
|
return {
|
|
"success": success,
|
|
"status": "success" if success else status,
|
|
"result": "success" if success else "unknown" if (acceptance or specialized) and status in {"unknown", "in_progress", "partial"} else "failed",
|
|
"message": message,
|
|
"jobId": completed.id,
|
|
"auditId": audit.id,
|
|
"policyDecision": "allowed",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
"controllerStatus": status,
|
|
"revision": result.get("revision"),
|
|
"verifiedRunners": result.get("verifiedRunners"),
|
|
"projectbrainDeliveryRequired": result.get("projectbrainDeliveryRequired"),
|
|
"blockers": result.get("blockers") if acceptance else None,
|
|
"preservedContainers": result.get("preservedContainers") if acceptance else None,
|
|
"effectsPerformed": result.get("effectsPerformed") if acceptance or specialized else None,
|
|
"noMutation": result.get("noMutation") if acceptance or specialized else None,
|
|
"maintenancePhase": result.get("maintenancePhase") if acceptance else None,
|
|
}
|
|
|
|
|
|
def _execute_hub_migration_prepare_permissions(
|
|
session: Session,
|
|
*,
|
|
source: str,
|
|
risk: str,
|
|
reason: str,
|
|
original_policy_decision: str,
|
|
) -> dict[str, Any]:
|
|
from .deployment_broker import DeploymentBrokerClient
|
|
|
|
action = "hub.migration.prepare_permissions"
|
|
target = "tower/itworx-mcp-hub-permissions"
|
|
state_file = "/mnt/cache/appdata/gitea-deploy-runners/state/itworx-mcp-hub.json"
|
|
fixed_targets = {state_file}
|
|
steps = [
|
|
"Validate the exact fixed MCP Hub permission target",
|
|
"Authenticate the fixed root-controller request with HMAC and replay protection",
|
|
"Verify the running controller is the protected current main release with full-push validation",
|
|
"Reinspect the fixed Hub state file and shared deployment lock",
|
|
"Apply only the fixed state-file mode correction and verify its final metadata",
|
|
]
|
|
job = create_job(
|
|
session,
|
|
action_id=action,
|
|
target=target,
|
|
source=source,
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
steps=steps,
|
|
)
|
|
start_job(session, job)
|
|
set_job_progress(session, job, 25, "Requesting fixed MCP Hub permission preparation through the controller.")
|
|
try:
|
|
result = DeploymentBrokerClient().hub_migration_prepare_permissions(reason=reason)
|
|
status = str(result.get("status") or "blocked")
|
|
revision_value = result.get("revision")
|
|
revision = (
|
|
revision_value
|
|
if isinstance(revision_value, str)
|
|
and len(revision_value) == 40
|
|
and all(character in "0123456789abcdef" for character in revision_value)
|
|
else None
|
|
)
|
|
|
|
changed_value = result.get("changedTargets", [])
|
|
changed_targets = (
|
|
changed_value
|
|
if isinstance(changed_value, list)
|
|
and all(isinstance(path, str) and path in fixed_targets for path in changed_value)
|
|
and len(changed_value) == len(set(changed_value))
|
|
else None
|
|
)
|
|
changed_details_value = result.get("changedTargetDetails", [])
|
|
target_names = {
|
|
state_file: "state_file",
|
|
}
|
|
changed_details = (
|
|
changed_details_value
|
|
if isinstance(changed_details_value, list)
|
|
and all(
|
|
isinstance(item, dict)
|
|
and set(item) == {"name", "path", "observedMode", "sameIdentityAtPath"}
|
|
and isinstance(item.get("path"), str)
|
|
and item.get("path") in fixed_targets
|
|
and item.get("name") == target_names.get(item.get("path"))
|
|
and isinstance(item.get("observedMode"), str)
|
|
and len(item["observedMode"]) == 4
|
|
and item["observedMode"].startswith("0")
|
|
and all(character in "01234567" for character in item["observedMode"])
|
|
and isinstance(item.get("sameIdentityAtPath"), bool)
|
|
and changed_targets is not None
|
|
and item["path"] in changed_targets
|
|
for item in changed_details_value
|
|
)
|
|
and len({item["path"] for item in changed_details_value}) == len(changed_details_value)
|
|
else None
|
|
)
|
|
uncertain_value = result.get("uncertainTargets", [])
|
|
uncertain_targets = (
|
|
uncertain_value
|
|
if isinstance(uncertain_value, list)
|
|
and all(isinstance(path, str) and path in fixed_targets for path in uncertain_value)
|
|
and len(uncertain_value) == len(set(uncertain_value))
|
|
else None
|
|
)
|
|
expected_verified = {
|
|
"state_file": {
|
|
"path": state_file,
|
|
"uid": 0,
|
|
"gid": 0,
|
|
"mode": "0600",
|
|
"aclPresent": False,
|
|
},
|
|
}
|
|
verified_value = result.get("verifiedTargets")
|
|
verified_targets = None
|
|
if isinstance(verified_value, list) and len(verified_value) == len(expected_verified):
|
|
by_name = {
|
|
item.get("name"): item
|
|
for item in verified_value
|
|
if isinstance(item, dict) and isinstance(item.get("name"), str)
|
|
}
|
|
if set(by_name) == set(expected_verified) and all(
|
|
all(by_name[name].get(key) == value for key, value in expected.items())
|
|
for name, expected in expected_verified.items()
|
|
):
|
|
verified_targets = [
|
|
{"name": name, **expected_verified[name]}
|
|
for name in ("state_file",)
|
|
]
|
|
|
|
has_controller_projection = all(
|
|
key in result
|
|
for key in (
|
|
"revision",
|
|
"changedTargets",
|
|
"changedTargetDetails",
|
|
"uncertainTargets",
|
|
)
|
|
)
|
|
success = (
|
|
status in {"prepared", "already_compliant"}
|
|
and has_controller_projection
|
|
and revision is not None
|
|
and changed_targets is not None
|
|
and changed_details is not None
|
|
and uncertain_targets == []
|
|
and verified_targets is not None
|
|
and (bool(changed_targets) if status == "prepared" else not changed_targets)
|
|
)
|
|
if success:
|
|
message = (
|
|
"The fixed MCP Hub state-file permission was prepared and verified."
|
|
if status == "prepared"
|
|
else "The fixed MCP Hub state-file permission was already compliant and verified."
|
|
)
|
|
elif (
|
|
status == "partial"
|
|
and has_controller_projection
|
|
and revision is not None
|
|
and changed_targets is not None
|
|
and changed_details is not None
|
|
and uncertain_targets is not None
|
|
and (changed_targets or uncertain_targets)
|
|
and len(changed_details) == len(changed_targets)
|
|
and {item["path"] for item in changed_details} == set(changed_targets)
|
|
):
|
|
message = "Permission preparation stopped partway; inspect the exact changed and uncertain fixed targets before retrying."
|
|
elif (
|
|
status in {
|
|
"blocked",
|
|
"unauthorized",
|
|
"missing_config",
|
|
"missing_secret",
|
|
"runtime_identity_unavailable",
|
|
"controller_source_mismatch",
|
|
"preflight_rejected",
|
|
"configuration_unavailable",
|
|
"exact_source_unavailable",
|
|
"invalid_request",
|
|
"invalid_body_size",
|
|
"authentication_rejected",
|
|
"forbidden",
|
|
}
|
|
and changed_targets == []
|
|
and changed_details == []
|
|
and uncertain_targets == []
|
|
):
|
|
status = "blocked"
|
|
message = "The fixed MCP Hub permission request was rejected before any target change."
|
|
else:
|
|
status = "outcome_unknown"
|
|
changed_targets = []
|
|
changed_details = []
|
|
uncertain_targets = sorted(fixed_targets)
|
|
verified_targets = None
|
|
message = (
|
|
"The controller request outcome is unknown; the fixed Hub state file may have changed. "
|
|
"Inspect it before retrying."
|
|
)
|
|
except Exception:
|
|
result = {"status": "outcome_unknown"}
|
|
status = "outcome_unknown"
|
|
revision = None
|
|
changed_targets = []
|
|
changed_details = []
|
|
uncertain_targets = sorted(fixed_targets)
|
|
verified_targets = None
|
|
success = False
|
|
message = (
|
|
"The controller request outcome is unknown; the fixed Hub state file may have changed. "
|
|
"Inspect it before retrying."
|
|
)
|
|
|
|
completed = complete_job(
|
|
session,
|
|
job,
|
|
status="succeeded" if success else "failed",
|
|
result_summary=message,
|
|
)
|
|
audit = log_event(
|
|
session,
|
|
source="action",
|
|
identity=source,
|
|
action_id=action,
|
|
target=target,
|
|
target_type="mcp-hub-permissions",
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
reason=reason,
|
|
result="success" if success else "outcome_unknown" if status == "outcome_unknown" else "failed",
|
|
execution_plan={"steps": steps, "jobId": completed.id},
|
|
after_state={
|
|
"status": status,
|
|
"revision": revision,
|
|
"changedTargets": changed_targets,
|
|
"changedTargetDetails": changed_details,
|
|
"uncertainTargets": uncertain_targets,
|
|
"verifiedTargets": verified_targets,
|
|
},
|
|
redacted_metadata={
|
|
"executor": action,
|
|
"integration": "mcp" if source == "chatgpt-mcp" else "operator",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
"targetSelectionCallerSelectable": False,
|
|
"pathOrCommandCallerSelectable": False,
|
|
},
|
|
)
|
|
return {
|
|
"success": success,
|
|
"status": "success" if success else status,
|
|
"result": "success" if success else "outcome_unknown" if status == "outcome_unknown" else "failed",
|
|
"message": message,
|
|
"jobId": completed.id,
|
|
"auditId": audit.id,
|
|
"policyDecision": "allowed",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
"controllerStatus": status,
|
|
"revision": revision,
|
|
"changedTargets": changed_targets,
|
|
"changedTargetDetails": changed_details,
|
|
"uncertainTargets": uncertain_targets,
|
|
"verifiedTargets": verified_targets,
|
|
}
|
|
|
|
|
|
def _approved_connector_call(action: str) -> tuple[Callable[[], dict[str, Any]], str]:
|
|
if action == "deluge.pause_all":
|
|
return lambda: DelugeConnector().pause_all(), "all_torrents_paused"
|
|
if action == "deluge.resume_all":
|
|
return lambda: DelugeConnector().resume_all(), "all_torrents_resumed"
|
|
if action == "plex.scan_all_libraries":
|
|
return lambda: PlexConnector().scan_all_libraries(), "scan_all_started"
|
|
raise ValueError("No approved executor is registered for this action.")
|
|
|
|
|
|
def execute_governed_action(
|
|
session: Session,
|
|
*,
|
|
action: str,
|
|
target: str,
|
|
source: str,
|
|
risk: str,
|
|
reason: str,
|
|
original_policy_decision: str,
|
|
) -> dict[str, Any]:
|
|
"""Execute a typed action after the trusted MCP boundary has evaluated policy.
|
|
|
|
This path deliberately does not create or consume an Approval row. It is used by
|
|
authenticated MCP automation in no-human-approval mode. The central policy still
|
|
fails closed for ``blocked`` actions before this function is called, and only the
|
|
small allowlist of typed rollback/post-check capable executors below is reachable.
|
|
"""
|
|
|
|
if not mcp_execution_supported(action):
|
|
return {
|
|
"success": False,
|
|
"status": "failed",
|
|
"result": "unsupported",
|
|
"message": "No typed MCP executor is registered for this action.",
|
|
"policyDecision": "blocked",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
|
|
if action in {"runner.acceptance.preflight", "runner.acceptance.quiesce"}:
|
|
return _execute_runner_acceptance(session, action=action, target=target, source=source,
|
|
risk=risk, reason=reason, original_policy_decision=original_policy_decision)
|
|
|
|
if action == "controller.artifact.promote":
|
|
if target.strip().lower() != "tower/deployment-controller":
|
|
return {
|
|
"success": False,
|
|
"status": "failed",
|
|
"result": "blocked",
|
|
"message": "Controller artifact promotion accepts only tower/deployment-controller.",
|
|
"policyDecision": "blocked",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
return _execute_controller_artifact_promote(
|
|
session,
|
|
source=source,
|
|
risk=risk,
|
|
reason=reason,
|
|
original_policy_decision=original_policy_decision,
|
|
)
|
|
|
|
if action == "controller.managed-storage.initialize":
|
|
if target != "tower/deployment-controller":
|
|
return {
|
|
"success": False,
|
|
"status": "failed",
|
|
"result": "blocked",
|
|
"message": "Managed storage initialization accepts only tower/deployment-controller.",
|
|
"policyDecision": "blocked",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
return _execute_managed_appdata_initialize(
|
|
session,
|
|
source=source,
|
|
risk=risk,
|
|
reason=reason,
|
|
original_policy_decision=original_policy_decision,
|
|
)
|
|
|
|
if action == "hub.migration.prepare_permissions":
|
|
if target.strip().lower() != "tower/itworx-mcp-hub-permissions":
|
|
return {
|
|
"success": False,
|
|
"status": "failed",
|
|
"result": "blocked",
|
|
"message": "MCP Hub permission preparation accepts only tower/itworx-mcp-hub-permissions.",
|
|
"policyDecision": "blocked",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
return _execute_hub_migration_prepare_permissions(
|
|
session,
|
|
source=source,
|
|
risk=risk,
|
|
reason=reason,
|
|
original_policy_decision=original_policy_decision,
|
|
)
|
|
|
|
if action == "runner.fleet.upgrade_v2":
|
|
if target.strip().lower() != "tower/runner-fleet-v2":
|
|
return {
|
|
"success": False,
|
|
"status": "failed",
|
|
"result": "blocked",
|
|
"message": "Runner fleet v2 upgrade accepts only tower/runner-fleet-v2.",
|
|
"policyDecision": "blocked",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
return _execute_runner_fleet_upgrade_v2(
|
|
session,
|
|
source=source,
|
|
risk=risk,
|
|
reason=reason,
|
|
original_policy_decision=original_policy_decision,
|
|
)
|
|
|
|
if action == "runner.statistics.configure":
|
|
if target.strip().lower() != "tower/projectbrain-runner-statistics":
|
|
return {"success": False, "status": "failed", "result": "blocked",
|
|
"message": "Statistics configuration accepts only tower/projectbrain-runner-statistics.",
|
|
"policyDecision": "blocked", "originalPolicyDecision": original_policy_decision}
|
|
return _execute_runner_fleet_upgrade_v2(
|
|
session, source=source, risk=risk, reason=reason,
|
|
original_policy_decision=original_policy_decision, statistics_configuration=True,
|
|
)
|
|
|
|
if action == "runner.fleet.specialize":
|
|
if target.strip().lower() != "tower/runner-fleet-specialized":
|
|
return {
|
|
"success": False, "status": "failed", "result": "blocked",
|
|
"message": "Runner specialization accepts only tower/runner-fleet-specialized.",
|
|
"policyDecision": "blocked", "originalPolicyDecision": original_policy_decision,
|
|
}
|
|
return _execute_runner_fleet_upgrade_v2(
|
|
session, source=source, risk=risk, reason=reason,
|
|
original_policy_decision=original_policy_decision, specialized=True,
|
|
)
|
|
|
|
if action == "deployment.runnerless.provision":
|
|
return _execute_runnerless_target_provisioning(
|
|
session,
|
|
target=target,
|
|
source=source,
|
|
risk=risk,
|
|
reason=reason,
|
|
original_policy_decision=original_policy_decision,
|
|
)
|
|
|
|
if action == "deployment.target.deploy_workmesh":
|
|
if target.strip().lower() != "jens/workmesh":
|
|
return {
|
|
"success": False,
|
|
"status": "failed",
|
|
"result": "blocked",
|
|
"message": "WorkMesh first deploy accepts only the fixed jens/workmesh target.",
|
|
"policyDecision": "blocked",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
return _execute_workmesh_first_deployment(
|
|
session,
|
|
source=source,
|
|
risk=risk,
|
|
reason=reason,
|
|
original_policy_decision=original_policy_decision,
|
|
)
|
|
|
|
if action == "deployment.target.promote_workmesh":
|
|
return {
|
|
"success": False,
|
|
"status": "failed",
|
|
"result": "approval_required",
|
|
"message": (
|
|
"WorkMesh promotion requires the exact-revision preflight and human approval flow."
|
|
),
|
|
"policyDecision": "blocked",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
|
|
if action == "deployment.targets.sync":
|
|
if target.strip().lower() != "jens/*":
|
|
return {
|
|
"success": False,
|
|
"status": "failed",
|
|
"result": "blocked",
|
|
"message": "Deployment target sync accepts only the fixed jens/* catalog target.",
|
|
"policyDecision": "blocked",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
return _execute_deployment_target_sync(
|
|
session,
|
|
source=source,
|
|
risk=risk,
|
|
reason=reason,
|
|
original_policy_decision=original_policy_decision,
|
|
)
|
|
|
|
if action in {"unraid.vm.start", "unraid.vm.resume", "unraid.vm.pause"}:
|
|
from .unraid_vm_service import VM_ACTIONS, execute_vm_action
|
|
|
|
vm_action = next(
|
|
(
|
|
name
|
|
for name, definition in VM_ACTIONS.items()
|
|
if definition["action_id"] == action
|
|
),
|
|
None,
|
|
)
|
|
if vm_action not in {"start", "resume", "pause"}:
|
|
return {
|
|
"success": False,
|
|
"status": "failed",
|
|
"result": "unsupported",
|
|
"message": "No safe VM executor is registered for this action.",
|
|
"policyDecision": "blocked",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
result = execute_vm_action(
|
|
session,
|
|
vm_id=target,
|
|
action=vm_action,
|
|
source=source,
|
|
policy_decision="allowed",
|
|
reason=reason,
|
|
)
|
|
return {
|
|
**result,
|
|
"policyDecision": "allowed",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
|
|
if action == "deployment.target.register_portfolio":
|
|
if target.strip().lower() != "jens/portfolio":
|
|
return {
|
|
"success": False,
|
|
"status": "failed",
|
|
"result": "blocked",
|
|
"message": "Portfolio target registration accepts only jens/portfolio.",
|
|
"policyDecision": "blocked",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
return _execute_portfolio_target_enrollment(
|
|
session,
|
|
source=source,
|
|
risk=risk,
|
|
reason=reason,
|
|
original_policy_decision=original_policy_decision,
|
|
)
|
|
if action == "deployment.target.register_privatemuse":
|
|
if target.strip().lower() != "jens/privatemuse":
|
|
return {
|
|
"success": False,
|
|
"status": "failed",
|
|
"result": "blocked",
|
|
"message": "PrivateMuse target registration accepts only jens/privatemuse.",
|
|
"policyDecision": "blocked",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
return _execute_privatemuse_target_enrollment(
|
|
session,
|
|
source=source,
|
|
risk=risk,
|
|
reason=reason,
|
|
original_policy_decision=original_policy_decision,
|
|
)
|
|
if action == "deployment.target.reconcile_media_codec_dashboard":
|
|
if target.strip().lower() != "jens/media-codec-dashboard":
|
|
return {
|
|
"success": False,
|
|
"status": "failed",
|
|
"result": "blocked",
|
|
"message": (
|
|
"Media Codec Dashboard reconciliation accepts only "
|
|
"jens/media-codec-dashboard."
|
|
),
|
|
"policyDecision": "blocked",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
return _execute_media_codec_dashboard_reconciliation(
|
|
session,
|
|
source=source,
|
|
risk=risk,
|
|
reason=reason,
|
|
original_policy_decision=original_policy_decision,
|
|
)
|
|
if action == "deployment.webhook.repair_privatemuse":
|
|
if target.strip().lower() != "jens/privatemuse":
|
|
return {
|
|
"success": False,
|
|
"status": "failed",
|
|
"result": "blocked",
|
|
"message": "PrivateMuse webhook repair accepts only jens/privatemuse.",
|
|
"policyDecision": "blocked",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
return _execute_privatemuse_webhook_repair(
|
|
session,
|
|
source=source,
|
|
risk=risk,
|
|
reason=reason,
|
|
original_policy_decision=original_policy_decision,
|
|
)
|
|
if action == "container.restart":
|
|
from .container_restart_service import execute_container_restart
|
|
|
|
result = execute_container_restart(
|
|
session=session,
|
|
action=action,
|
|
target=target,
|
|
source=source,
|
|
risk=risk,
|
|
steps=[
|
|
"Validate MCP policy",
|
|
"Resolve container",
|
|
"Restart container",
|
|
"Post-check health",
|
|
],
|
|
policy_override={
|
|
"decision": "allowed",
|
|
"reason": reason,
|
|
"risk": risk,
|
|
},
|
|
)
|
|
return {
|
|
**result,
|
|
"policyDecision": "allowed",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
|
|
apply_stored_connector_settings(session)
|
|
connector_call, default_message = _approved_connector_call(action)
|
|
steps = _DIRECT_STEPS[action]
|
|
job = create_job(
|
|
session,
|
|
action_id=action,
|
|
target=target,
|
|
source=source,
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
steps=steps,
|
|
)
|
|
start_job(session, job)
|
|
set_job_progress(session, job, 35, "MCP policy authorized; calling typed connector.")
|
|
|
|
try:
|
|
connector_result = connector_call()
|
|
success = bool(connector_result.get("success"))
|
|
message = str(
|
|
connector_result.get("message")
|
|
or (default_message if success else "connector_action_failed")
|
|
)
|
|
except Exception as exc: # Connector errors must become an audited failed job.
|
|
success = False
|
|
message = f"{type(exc).__name__}: connector action failed"
|
|
connector_result = {"status": "error"}
|
|
|
|
completed = complete_job(
|
|
session,
|
|
job,
|
|
status="succeeded" if success else "failed",
|
|
result_summary=message,
|
|
)
|
|
audit = log_event(
|
|
session,
|
|
source="action",
|
|
identity=source,
|
|
action_id=action,
|
|
target=target,
|
|
target_type="approval",
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
reason=reason,
|
|
result="success" if success else "failed",
|
|
execution_plan={"steps": steps, "jobId": completed.id},
|
|
after_state={"status": connector_result.get("status"), "message": message},
|
|
redacted_metadata={
|
|
"executor": action,
|
|
"integration": "mcp",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
},
|
|
)
|
|
return {
|
|
"success": success,
|
|
"status": "success" if success else "failed",
|
|
"result": "success" if success else "failed",
|
|
"message": message,
|
|
"jobId": completed.id,
|
|
"auditId": audit.id,
|
|
"policyDecision": "allowed",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
|
|
|
|
def _execute_managed_appdata_initialize(
|
|
session: Session,
|
|
*,
|
|
source: str,
|
|
risk: str,
|
|
reason: str,
|
|
original_policy_decision: str,
|
|
) -> dict[str, Any]:
|
|
"""Initialize only the fixed storage marker after trust and policy opt-in."""
|
|
from .deployment_broker import DeploymentBrokerClient
|
|
from .enrollment_plane import EnrollmentPlane
|
|
from .secret_store import get_secret
|
|
|
|
action = "controller.managed-storage.initialize"
|
|
target = "tower/deployment-controller"
|
|
trust = EnrollmentPlane.get_trust_config(session)
|
|
if (
|
|
trust is None
|
|
or trust.trusted_appdata_root != "/var/lib/docker/volumes/itworx-managed-appdata/_data"
|
|
or trust.managed_appdata_backup_acknowledged is not True
|
|
):
|
|
audit = log_event(
|
|
session,
|
|
source="action",
|
|
identity=source,
|
|
action_id=action,
|
|
target=target,
|
|
target_type="controller",
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
reason="Managed Docker-root storage requires an explicit trusted selector and backup acknowledgement.",
|
|
result="blocked",
|
|
redacted_metadata={"executor": action, "trustOptIn": False},
|
|
)
|
|
return {
|
|
"success": False,
|
|
"status": "failed",
|
|
"result": "blocked",
|
|
"message": "Managed storage is not explicitly selected and acknowledged in enrollment trust.",
|
|
"auditId": audit.id,
|
|
"policyDecision": "allowed",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
|
|
bootstrap_secret = get_secret(session, trust.bootstrap_secret_ref, touch=False)
|
|
if not bootstrap_secret:
|
|
audit = log_event(
|
|
session,
|
|
source="action",
|
|
identity=source,
|
|
action_id=action,
|
|
target=target,
|
|
target_type="controller",
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
reason="Controller bootstrap capability is unavailable by its configured reference.",
|
|
result="failed",
|
|
redacted_metadata={"executor": action, "secretMaterialReturned": False},
|
|
)
|
|
return {
|
|
"success": False,
|
|
"status": "failed",
|
|
"result": "failed",
|
|
"message": "Controller bootstrap capability is unavailable.",
|
|
"auditId": audit.id,
|
|
"policyDecision": "allowed",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
|
|
steps = [
|
|
"Verify the exact target, trust selector and backup acknowledgement",
|
|
"Authenticate the fixed controller request with bootstrap HMAC and replay protection",
|
|
"Validate the protected controller, target registry, repository root and fixed Docker volume",
|
|
"Initialize the selector only if the managed Docker volume is empty and unchanged",
|
|
"Re-read the fixed selector and record sanitized controller readiness",
|
|
]
|
|
job = create_job(
|
|
session,
|
|
action_id=action,
|
|
target=target,
|
|
source=source,
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
steps=steps,
|
|
)
|
|
start_job(session, job)
|
|
set_job_progress(session, job, 20, "Validating fixed managed-storage initialization prerequisites.")
|
|
try:
|
|
result = DeploymentBrokerClient().initialize_managed_appdata(secret=bootstrap_secret)
|
|
reported_status = result.get("status")
|
|
status = (
|
|
reported_status
|
|
if isinstance(reported_status, str)
|
|
and reported_status in {"initialized", "already_initialized"}
|
|
else "refused"
|
|
)
|
|
success = (
|
|
status in {"initialized", "already_initialized"}
|
|
and result.get("trustedAppdataRoot") == trust.trusted_appdata_root
|
|
and result.get("backupLocation") == "dockerRootDir"
|
|
)
|
|
message = (
|
|
"Managed storage selector initialized and verified."
|
|
if success
|
|
else "Managed storage initialization was refused or unavailable."
|
|
)
|
|
except Exception:
|
|
result = {"status": "error"}
|
|
status = "error"
|
|
success = False
|
|
message = "Managed storage initialization was refused or unavailable."
|
|
|
|
completed = complete_job(
|
|
session,
|
|
job,
|
|
status="succeeded" if success else "failed",
|
|
result_summary=message,
|
|
)
|
|
audit = log_event(
|
|
session,
|
|
source="action",
|
|
identity=source,
|
|
action_id=action,
|
|
target=target,
|
|
target_type="controller",
|
|
risk=risk,
|
|
policy_decision="allowed",
|
|
reason=reason,
|
|
result="success" if success else "failed",
|
|
execution_plan={"steps": steps, "jobId": completed.id},
|
|
after_state={
|
|
"status": status,
|
|
"trustedAppdataRoot": trust.trusted_appdata_root if success else None,
|
|
"backupLocation": "dockerRootDir" if success else None,
|
|
},
|
|
redacted_metadata={
|
|
"executor": action,
|
|
"target": target,
|
|
"integration": "mcp" if source == "chatgpt-mcp" else "operator",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
"secretMaterialReturned": False,
|
|
},
|
|
)
|
|
return {
|
|
"success": success,
|
|
"status": "success" if success else "failed",
|
|
"result": "success" if success else "failed",
|
|
"message": message,
|
|
"jobId": completed.id,
|
|
"auditId": audit.id,
|
|
"policyDecision": "allowed",
|
|
"originalPolicyDecision": original_policy_decision,
|
|
}
|
|
|
|
|
|
def execute_approved_action(session: Session, approval: Approval) -> dict[str, Any]:
|
|
if not approval_execution_supported(approval.action):
|
|
return {
|
|
"success": False,
|
|
"status": "failed",
|
|
"result": "unsupported",
|
|
"message": "Deze goedgekeurde actie heeft nog geen rollback-veilige executor.",
|
|
}
|
|
|
|
if approval.action == "controller.artifact.promote":
|
|
if approval.target.strip().lower() != "tower/deployment-controller":
|
|
return {
|
|
"success": False,
|
|
"status": "failed",
|
|
"result": "blocked",
|
|
"message": "Controller artifact promotion accepts only tower/deployment-controller.",
|
|
}
|
|
return _execute_controller_artifact_promote(
|
|
session,
|
|
source="approved_operator",
|
|
risk=approval.risk,
|
|
reason=approval.reason or f"Approved through {approval.id}.",
|
|
original_policy_decision="approval_required",
|
|
)
|
|
|
|
if approval.action == "deployment.runnerless.provision":
|
|
return _execute_runnerless_target_provisioning(
|
|
session,
|
|
target=approval.target,
|
|
source="approved_operator",
|
|
risk=approval.risk,
|
|
reason=approval.reason or f"Approved through {approval.id}.",
|
|
original_policy_decision="approval_required",
|
|
)
|
|
|
|
if approval.action in {"runner.acceptance.preflight", "runner.acceptance.quiesce"}:
|
|
return _execute_runner_acceptance(
|
|
session, action=approval.action, target=approval.target, source="approved_operator",
|
|
risk=approval.risk, reason=approval.reason or f"Approved through {approval.id}.",
|
|
original_policy_decision="approval_required",
|
|
)
|
|
|
|
if approval.action == "runner.fleet.upgrade_v2":
|
|
if approval.target.strip().lower() != "tower/runner-fleet-v2":
|
|
return {
|
|
"success": False,
|
|
"status": "failed",
|
|
"result": "blocked",
|
|
"message": "Runner fleet v2 upgrade accepts only tower/runner-fleet-v2.",
|
|
}
|
|
return _execute_runner_fleet_upgrade_v2(
|
|
session,
|
|
source="approved_operator",
|
|
risk=approval.risk,
|
|
reason=approval.reason or f"Approved through {approval.id}.",
|
|
original_policy_decision="approval_required",
|
|
)
|
|
|
|
if approval.action == "runner.statistics.configure":
|
|
if approval.target.strip().lower() != "tower/projectbrain-runner-statistics":
|
|
return {"success": False, "status": "failed", "result": "blocked",
|
|
"message": "Statistics configuration accepts only tower/projectbrain-runner-statistics."}
|
|
return _execute_runner_fleet_upgrade_v2(
|
|
session, source="approved_operator", risk=approval.risk,
|
|
reason=approval.reason or f"Approved through {approval.id}.",
|
|
original_policy_decision="approval_required", statistics_configuration=True,
|
|
)
|
|
|
|
if approval.action == "runner.fleet.specialize":
|
|
if approval.target.strip().lower() != "tower/runner-fleet-specialized":
|
|
return {
|
|
"success": False, "status": "failed", "result": "blocked",
|
|
"message": "Runner specialization accepts only tower/runner-fleet-specialized.",
|
|
}
|
|
return _execute_runner_fleet_upgrade_v2(
|
|
session, source="approved_operator", risk=approval.risk,
|
|
reason=approval.reason or f"Approved through {approval.id}.",
|
|
original_policy_decision="approval_required", specialized=True,
|
|
)
|
|
|
|
if approval.action == "hub.migration.prepare_permissions":
|
|
if approval.target.strip().lower() != "tower/itworx-mcp-hub-permissions":
|
|
return {
|
|
"success": False,
|
|
"status": "failed",
|
|
"result": "blocked",
|
|
"message": "MCP Hub permission preparation accepts only tower/itworx-mcp-hub-permissions.",
|
|
}
|
|
return _execute_hub_migration_prepare_permissions(
|
|
session,
|
|
source="approved_operator",
|
|
risk=approval.risk,
|
|
reason=approval.reason or f"Approved through {approval.id}.",
|
|
original_policy_decision="approval_required",
|
|
)
|
|
|
|
if approval.action in {"unraid.vm.start", "unraid.vm.resume", "unraid.vm.pause"}:
|
|
from .unraid_vm_service import execute_approved_vm_action
|
|
|
|
return execute_approved_vm_action(session, approval)
|
|
|
|
if approval.action == "deployment.target.promote_workmesh":
|
|
from .workmesh_promotion import WorkMeshPromotionService
|
|
|
|
return WorkMeshPromotionService().execute_approved(session, approval)
|
|
|
|
if approval.action == "deployment.target.register_portfolio":
|
|
if approval.target.strip().lower() != "jens/portfolio":
|
|
return {
|
|
"success": False,
|
|
"status": "failed",
|
|
"result": "blocked",
|
|
"message": "Portfolio target registration accepts only jens/portfolio.",
|
|
}
|
|
return _execute_portfolio_target_enrollment(
|
|
session,
|
|
source="approved_operator",
|
|
risk=approval.risk,
|
|
reason=approval.reason or f"Approved through {approval.id}.",
|
|
original_policy_decision="approval_required",
|
|
)
|
|
if approval.action == "deployment.target.register_privatemuse":
|
|
if approval.target.strip().lower() != "jens/privatemuse":
|
|
return {
|
|
"success": False,
|
|
"status": "failed",
|
|
"result": "blocked",
|
|
"message": "PrivateMuse target registration accepts only jens/privatemuse.",
|
|
}
|
|
return _execute_privatemuse_target_enrollment(
|
|
session,
|
|
source="approved_operator",
|
|
risk=approval.risk,
|
|
reason=approval.reason or f"Approved through {approval.id}.",
|
|
original_policy_decision="approval_required",
|
|
)
|
|
if approval.action == "deployment.target.reconcile_media_codec_dashboard":
|
|
if approval.target.strip().lower() != "jens/media-codec-dashboard":
|
|
return {
|
|
"success": False,
|
|
"status": "failed",
|
|
"result": "blocked",
|
|
"message": (
|
|
"Media Codec Dashboard reconciliation accepts only "
|
|
"jens/media-codec-dashboard."
|
|
),
|
|
}
|
|
return _execute_media_codec_dashboard_reconciliation(
|
|
session,
|
|
source="approved_operator",
|
|
risk=approval.risk,
|
|
reason=approval.reason or f"Approved through {approval.id}.",
|
|
original_policy_decision="approval_required",
|
|
)
|
|
if approval.action == "deployment.webhook.repair_privatemuse":
|
|
if approval.target.strip().lower() != "jens/privatemuse":
|
|
return {
|
|
"success": False,
|
|
"status": "failed",
|
|
"result": "blocked",
|
|
"message": "PrivateMuse webhook repair accepts only jens/privatemuse.",
|
|
}
|
|
return _execute_privatemuse_webhook_repair(
|
|
session,
|
|
source="approved_operator",
|
|
risk=approval.risk,
|
|
reason=approval.reason or f"Approved through {approval.id}.",
|
|
original_policy_decision="approval_required",
|
|
)
|
|
if approval.action == "container.restart":
|
|
from .container_restart_service import execute_container_restart
|
|
|
|
return execute_container_restart(
|
|
session=session,
|
|
action=approval.action,
|
|
target=approval.target,
|
|
source="approved_operator",
|
|
risk=approval.risk,
|
|
steps=[
|
|
"Load approved request",
|
|
"Resolve container",
|
|
"Restart container",
|
|
"Post-check health",
|
|
],
|
|
approved=True,
|
|
)
|
|
|
|
apply_stored_connector_settings(session)
|
|
connector_call, default_message = _approved_connector_call(approval.action)
|
|
steps = _APPROVAL_STEPS[approval.action]
|
|
job = create_job(
|
|
session,
|
|
action_id=approval.action,
|
|
target=approval.target,
|
|
source="approved_operator",
|
|
risk=approval.risk,
|
|
policy_decision="approval_required",
|
|
steps=steps,
|
|
)
|
|
start_job(session, job)
|
|
set_job_progress(
|
|
session, job, 35, f"Approval {approval.id} validated; calling connector."
|
|
)
|
|
|
|
try:
|
|
connector_result = connector_call()
|
|
success = bool(connector_result.get("success"))
|
|
message = str(
|
|
connector_result.get("message")
|
|
or (default_message if success else "connector_action_failed")
|
|
)
|
|
except Exception as exc: # Connector errors must become an audited failed job.
|
|
success = False
|
|
message = f"{type(exc).__name__}: connector action failed"
|
|
connector_result = {"status": "error"}
|
|
|
|
completed = complete_job(
|
|
session,
|
|
job,
|
|
status="succeeded" if success else "failed",
|
|
result_summary=message,
|
|
)
|
|
audit = log_event(
|
|
session,
|
|
source="approval",
|
|
identity="operator",
|
|
action_id=approval.action,
|
|
target=approval.target,
|
|
target_type="approval",
|
|
risk=approval.risk,
|
|
policy_decision="approval_required",
|
|
reason=approval.reason or f"Approved through {approval.id}.",
|
|
result="success" if success else "failed",
|
|
execution_plan={
|
|
"steps": steps,
|
|
"approvalId": approval.id,
|
|
"jobId": completed.id,
|
|
},
|
|
after_state={"status": connector_result.get("status"), "message": message},
|
|
redacted_metadata={"approvalId": approval.id, "executor": approval.action},
|
|
)
|
|
return {
|
|
"success": success,
|
|
"status": "success" if success else "failed",
|
|
"result": "success" if success else "failed",
|
|
"message": message,
|
|
"jobId": completed.id,
|
|
"auditId": audit.id,
|
|
}
|