Publish curated Unraid-AppOps-Gateway source from c61e0e1e292914893b40354f904f23dd9fd4a958

This commit is contained in:
Public Source Publisher committed 2026-10-09 21:29:20 +00:00
1 parent b47ce43436
commit 9b94d8d0f5
18 files changed
+1651 -75

No files matched your search

+96 -11
View File
@@ -55,6 +55,8 @@ APPROVAL_EXECUTOR_ACTIONS = {
"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",
@@ -125,7 +127,12 @@ _DIRECT_STEPS = {
def action_execution_profile(
action: str, policy_decision: str, capability: str
) -> dict[str, Any]:
if policy_decision == "blocked":
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:
@@ -1669,6 +1676,31 @@ def _execute_controller_artifact_promote(
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,
*,
@@ -1678,12 +1710,15 @@ def _execute_runner_fleet_upgrade_v2(
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.statistics.configure" if statistics_configuration else
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/projectbrain-runner-statistics" if statistics_configuration else
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",
@@ -1697,6 +1732,9 @@ def _execute_runner_fleet_upgrade_v2(
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,
@@ -1710,26 +1748,57 @@ def _execute_runner_fleet_upgrade_v2(
set_job_progress(session, job, 25, f"Requesting {action} through the fixed controller endpoint.")
try:
broker = DeploymentBrokerClient()
result = (broker.runner_statistics_configure(reason=reason) if statistics_configuration else
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 ({"configured", "already_configured"} if statistics_configuration else
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 (
("ProjectBrain read-only statistics configuration verified." if statistics_configuration else
("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
("ProjectBrain statistics configuration was rejected or failed." if statistics_configuration 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": "error"}
status = "error"
result = {"status": "unknown" if acceptance == "quiesce" else "error", "effectsPerformed": None}
status = result["status"]
success = False
message = f"{type(exc).__name__}: fixed controller operation failed"
@@ -1749,7 +1818,7 @@ def _execute_runner_fleet_upgrade_v2(
risk=risk,
policy_decision="allowed",
reason=reason,
result="success" if success else "failed",
result="success" if success else "unknown" if acceptance and status in {"unknown", "in_progress", "partial"} else "failed",
execution_plan={"steps": steps, "jobId": completed.id},
after_state={
"status": status,
@@ -1768,7 +1837,7 @@ def _execute_runner_fleet_upgrade_v2(
return {
"success": success,
"status": "success" if success else status,
"result": "success" if success else "failed",
"result": "success" if success else "unknown" if acceptance and status in {"unknown", "in_progress", "partial"} else "failed",
"message": message,
"jobId": completed.id,
"auditId": audit.id,
@@ -1778,6 +1847,11 @@ def _execute_runner_fleet_upgrade_v2(
"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 else None,
"noMutation": result.get("noMutation") if acceptance else None,
"maintenancePhase": result.get("maintenancePhase") if acceptance else None,
}
@@ -2065,6 +2139,10 @@ def execute_governed_action(
"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 {
@@ -2603,6 +2681,13 @@ def execute_approved_action(session: Session, approval: Approval) -> dict[str, A
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 {
+6
View File
@@ -9,6 +9,8 @@ ACTIONS = [
'runner.fleet.upgrade_v2',
'runner.fleet.specialize',
'runner.statistics.configure',
'runner.acceptance.preflight',
'runner.acceptance.quiesce',
'controller.artifact.promote',
'controller.managed-storage.initialize',
'hub.migration.prepare_permissions',
@@ -222,6 +224,8 @@ ACTION_RISK = {
'runner.fleet.upgrade_v2': 'high',
'runner.fleet.specialize': 'high',
'runner.statistics.configure': 'high',
'runner.acceptance.preflight': 'low',
'runner.acceptance.quiesce': 'high',
'controller.artifact.promote': 'high',
'controller.managed-storage.initialize': 'high',
'hub.migration.prepare_permissions': 'high',
@@ -553,6 +557,8 @@ def action_default_target(action: str) -> str:
return 'tower/runner-fleet-v2'
if action == 'runner.fleet.specialize':
return 'tower/runner-fleet-specialized'
if action in {'runner.acceptance.preflight', 'runner.acceptance.quiesce'}:
return 'tower/ci-acceptance-residue'
if action == 'runner.statistics.configure':
return 'tower/projectbrain-runner-statistics'
if action == 'deployment.targets.sync':
@@ -5,7 +5,7 @@ from typing import Any
SOURCE_REPOSITORY = "jens/unraid-appops-gateway"
HELPER_NAME = "itworx-controller-artifact-promoter-modern"
CONTROLLER_VERSION = "2.1.20"
CONTROLLER_VERSION = "2.1.21"
HELPER_LABEL = "itworx.controller.promoter"
_REVISION = re.compile(r"^[0-9a-f]{40}$")
_IMAGE_ID = re.compile(r"^sha256:[0-9a-f]{64}$")
+13 -1
View File
@@ -174,6 +174,7 @@ class DeploymentBrokerClient:
secret: str,
payload: dict[str, Any] | None = None,
error_response_fields: frozenset[str] = frozenset(),
request_timeout: httpx.Timeout | None = None,
) -> dict[str, Any]:
if not self.is_configured():
return {"status": "missing_config", "reason": self.configuration_error()}
@@ -194,7 +195,7 @@ class DeploymentBrokerClient:
headers["Content-Type"] = "application/json"
try:
with httpx.Client(
timeout=self.timeout_seconds,
timeout=request_timeout or self.timeout_seconds,
verify=self._verify_option(),
) as client:
response = client.request(method, f"{self.base_url}{path}", content=body, headers=headers)
@@ -990,6 +991,17 @@ class DeploymentBrokerClient:
secret=settings.mcp_token or "", payload={"reason": reason[:1000]},
)
def runner_acceptance(self, *, reason: str, preflight: bool) -> dict[str, Any]:
result = self._request(
"POST", "/v1/appops/runner-acceptance/preflight" if preflight else "/v1/appops/runner-acceptance/quiesce",
secret=settings.mcp_token or "", payload={"reason": reason[:1000]},
request_timeout=httpx.Timeout(connect=5, write=5, pool=5, read=350),
)
if not preflight and result.get("status") in {"unreachable", "error", "rejected"}:
return {"status": "unknown", "noMutation": False, "effectsPerformed": None,
"blockers": ["maintenance_outcome_unknown"]}
return result
def hub_migration_prepare_permissions(self, *, reason: str) -> dict[str, Any]:
"""Prepare only the fixed Hub backup and controller-state permissions."""
return self._request(
+9 -1
View File
@@ -59,6 +59,14 @@ def _reconciliation_required_response(
}
def mcp_policy_source(action: str, target: str) -> str:
"""Normalize only the fixed acceptance authority at the authenticated MCP boundary."""
if (action in {"runner.acceptance.preflight", "runner.acceptance.quiesce"}
and target == "tower/ci-acceptance-residue"):
return "chatgpt-mcp"
return "automation"
def request_operation(
session: Session,
*,
@@ -97,7 +105,7 @@ def request_operation(
session,
action=safe_action,
target=safe_target,
source="automation",
source=mcp_policy_source(safe_action, safe_target),
)
risk = str(policy.get("risk") or ACTION_RISK.get(safe_action, "critical"))
if capability == "read_only":
+10
View File
@@ -210,6 +210,16 @@ def evaluate_policy(
"scope_decision": "allowed" if allowed else None,
}
if action in {'runner.acceptance.preflight', 'runner.acceptance.quiesce'}:
# Dedicated finite maintenance authority; wildcard and database rows
# cannot redirect this source-qualified action to other containers.
eligible = target == 'tower/ci-acceptance-residue' and source in {'manual', 'chatgpt-mcp'}
return {
'decision': ('allowed' if action.endswith('.preflight') else 'approval_required') if eligible else 'blocked',
'reason': 'Fixed CI acceptance maintenance requires current native origin, dispatch and product-exclusion proofs.',
'risk': ACTION_RISK[action], 'policy_id': None, 'scope_decision': None,
}
if action in _DEFAULT_DECISIONS:
reason = _DEFAULT_REASONS.get(action, 'Action uses default governance policy.')
return {