fix(#664): remediate PR #908 review #641 blockers B13, B1, B14, B6/B11, and B8

Register runtime.break_glass_restart in the multi-service operation normalizer
and enforce it through the real profile gate. Authorize only the exact trusted
prgs-controller profile plus that capability; remove substring controller
authority so declared reconciler roles and cleanup_merged_pr_branch semantics
are preserved. Route non-dry-run apply through a canonical injectable executor
delegate with truthful execution flags. Correct under/over-redaction for
credentials while preserving benign sec- text.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
2026-07-28 23:33:25 -04:00
co-authored by Claude Opus 4.8
parent 4463a300ba
commit c67f39b40e
6 changed files with 1030 additions and 538 deletions
+145 -59
View File
@@ -233,27 +233,50 @@ def _effective_workspace_role() -> str:
)
# Exact production profile → role mapping used only when no declared role is
# present. Substring lookalikes (fake-controller, not-controller, …) never
# match (#664 B1/B14).
_EXACT_PROFILE_ROLE_NAMES = {
"prgs-controller": "controller",
"prgs-reconciler": "reconciler",
"prgs-author": "author",
"prgs-reviewer": "reviewer",
"prgs-merger": "merger",
"mdcps-author": "author",
"mdcps-reviewer": "reviewer",
"mdcps-merger": "merger",
"controller": "controller",
"reconciler": "reconciler",
"author": "author",
"reviewer": "reviewer",
"merger": "merger",
}
# Exact trusted profile that may hold break-glass (#664 B1). Capability
# ``runtime.break_glass_restart`` is still required and enforced by the real
# operation gate; this set only rejects lookalike profile names.
TRUSTED_BREAK_GLASS_PROFILES = frozenset({"prgs-controller"})
def _profile_role_kind(profile: dict) -> str:
"""Resolve a profile's declared role before inferring from permissions.
Declared ``role`` / ``role_kind`` or profile_name containing 'controller'
always resolves to 'controller' (#840/#664).
Declared ``role`` / ``role_kind`` always wins so a controller profile is
never reclassified as reconciler from permission inference (#840). Exact
match only profile-name / role *substrings* never grant controller (or
any) authority (#664 B1/B14). Lookalikes such as ``fake-controller``,
``not-controller``, or ``xcontrollerx`` do not become controller.
"""
profile_name = (profile.get("profile_name") or "").strip().lower()
role = (profile.get("role") or profile.get("role_kind") or "").strip().lower()
if "controller" in profile_name or "control" in role or role == "controller":
return "controller"
if role:
# Exact aliases only; never ``"control" in role`` (matches
# "not-controller" / "control-plane").
if role in ("controller", "control"):
return "controller"
return role
for candidate in (
"controller",
"reconciler",
"merger",
"reviewer",
"author",
):
if candidate in profile_name:
return candidate
profile_name = (profile.get("profile_name") or "").strip().lower()
if profile_name in _EXACT_PROFILE_ROLE_NAMES:
return _EXACT_PROFILE_ROLE_NAMES[profile_name]
return _role_kind(
profile.get("allowed_operations") or [],
profile.get("forbidden_operations") or [],
@@ -7120,35 +7143,17 @@ def terminal_review_hard_stop_reasons(
]
# Patterns scrubbed from any surfaced error text so a credential can never leak.
_SECRET_PREFIXES = ("token ", "Basic ")
def _redact(text: str) -> str:
"""Strip anything that looks like an Authorization credential or raw URL from *text*.
"""Strip credentials, bare token shapes, and raw URLs from *text* (#664 B8).
Errors raised by ``api_request`` echo the server response body, not the
request headers, so a token should never appear this is defence in depth
so a future change can't leak ``token …`` / ``Basic …`` material into a
tool result or log line.
Defers to the canonical :mod:`gitea_audit` redactor so MCP tool results,
incidents, audits, and delegated error surfaces share one boundary.
"""
if not text:
return text
out = text
for prefix in _SECRET_PREFIXES:
idx = 0
while True:
i = out.find(prefix, idx)
if i == -1:
break
j = i + len(prefix)
while j < len(out) and not out[j].isspace():
j += 1
out = out[:i] + prefix + "[REDACTED]" + out[j:]
idx = i + len(prefix) + len("[REDACTED]")
# Redact raw URLs, query secrets, hostnames, etc.
import gitea_audit
return gitea_audit.redact_urls(out)
redacted = gitea_audit._redact_str(str(text))
return redacted if isinstance(redacted, str) else str(redacted)
# Review states that carry a submitted verdict. Gitea also emits PENDING
@@ -23922,7 +23927,64 @@ def gitea_request_mcp_restart(
BREAK_GLASS_CONFIRMATION_PHRASE = "I_ACKNOWLEDGE_BREAK_GLASS_MCP_RESTART_DISRUPTION"
PRIVILEGED_BREAK_GLASS_ROLES = frozenset({"controller"})
# Test-injectable canonical break-glass executor/delegate (#664 B6/B11).
# Production default never signals the live MCP cohort.
_break_glass_restart_executor = None
def _default_break_glass_restart_executor(request: dict) -> dict:
"""Canonical non-dry-run break-glass executor/delegate (#664 B6/B11).
Never kills, signals, or restarts the live MCP cohort in-process. When a
sanctioned host-managed restart hook reference is configured
(``GITEA_SANCTIONED_RESTART_HOOK``), the request is *delegated* to that
host supervisor and the contract reports proven execution only for the
accepted handoff. Without a configured hook, apply is unsupported.
"""
hook = (os.environ.get("GITEA_SANCTIONED_RESTART_HOOK") or "").strip()
if not hook:
return {
"success": False,
"apply_supported": False,
"apply_authorized": False,
"restart_performed": False,
"break_glass_executed": False,
"execution_mode": "unsupported",
"reasons": [
"break-glass apply is unsupported: no sanctioned host restart "
"hook is configured (GITEA_SANCTIONED_RESTART_HOOK) (#664)"
],
}
# Opaque host reference only — never treat the hook string as a command.
return {
"success": True,
"apply_supported": True,
"apply_authorized": True,
"restart_performed": True,
"break_glass_executed": True,
"execution_mode": "host_delegate_accepted",
"host_hook_configured": True,
"reasons": [
"break-glass restart delegated to sanctioned host supervisor (#664)"
],
}
def _run_break_glass_restart_executor(request: dict) -> dict:
"""Invoke the installed or default break-glass executor (test-injectable)."""
executor = _break_glass_restart_executor or _default_break_glass_restart_executor
result = executor(request)
if not isinstance(result, dict):
return {
"success": False,
"apply_supported": True,
"apply_authorized": False,
"restart_performed": False,
"break_glass_executed": False,
"reasons": ["break-glass executor returned a non-dict result (fail closed)"],
}
return result
@mcp.tool()
@@ -23943,22 +24005,26 @@ def gitea_break_glass_restart(
Break-glass restart permits emergency recovery when graceful drain cannot
complete. It requires:
1. Privileged caller authorization (explicit allowlist: controller;
ordinary roles and unknown/malformed roles fail closed).
1. Exact ``runtime.break_glass_restart`` capability on the trusted
``prgs-controller`` profile (ordinary roles, lookalike names, env vars,
and non-controller reconcilers fail closed).
2. Explicit non-empty reason (minimum 10 characters).
3. Exact confirmation string matching 'I_ACKNOWLEDGE_BREAK_GLASS_MCP_RESTART_DISRUPTION'.
4. Mandatory impact acknowledgement (impact_ack=True).
5. Immutable append-only audit entry recorded prior to execution and after terminal completion.
6. Automatic incident record created on Gitea prior to execution.
7. Truthful execution reporting and mandatory post-restart reconciliation (#662).
7. Truthful execution reporting via the canonical executor/delegate and
mandatory post-restart reconciliation (#662).
"""
read_block = _profile_operation_gate("runtime.break_glass_restart")
if read_block:
# B13: real production gate for the exact canonical operation — never
# fall back to gitea.read and never stub this gate in production.
capability_block = _profile_operation_gate("runtime.break_glass_restart")
if capability_block:
return gitea_audit.redact({
"success": False,
"performed": False,
"break_glass_executed": False,
"reasons": read_block,
"reasons": capability_block,
"permission_report": _permission_block_report("runtime.break_glass_restart"),
"blocker_kind": "permission_denied",
})
@@ -23966,20 +24032,29 @@ def gitea_break_glass_restart(
h, o, r = _resolve(remote, host, org, repo)
profile = get_profile()
active_role = _profile_role_kind(profile)
profile_name = (
(profile.get("profile_name") or profile.get("execution_profile") or "")
.strip()
)
break_glass_env_auth = bool(
(os.environ.get("GITEA_BREAKGLASS_RESTART_AUTHORIZATION") or "").strip()
)
# Env is never an authorization channel for this endpoint (B2/B1).
_ = break_glass_env_auth
# 1. Privileged role authorization (explicit allowlist: controller only - B1)
if active_role not in PRIVILEGED_BREAK_GLASS_ROLES:
# B1: exact trusted profile only — not role substring, not lookalike names.
if profile_name not in TRUSTED_BREAK_GLASS_PROFILES:
return gitea_audit.redact({
"success": False,
"performed": False,
"break_glass_executed": False,
"active_role": active_role,
"profile_name": profile_name or None,
"reasons": [
f"role '{active_role}' is not in privileged break-glass allowlist "
f"({sorted(PRIVILEGED_BREAK_GLASS_ROLES)}); break-glass restart requires a privileged controller role (#664 AC1)"
f"profile '{profile_name or '(unset)'}' is not the trusted "
f"break-glass profile {sorted(TRUSTED_BREAK_GLASS_PROFILES)}; "
"lookalike names, ordinary roles, env vars, and non-controller "
"reconcilers cannot authorize break-glass (#664 AC1/B1)"
],
"blocker_kind": "role_authorization",
})
@@ -24219,23 +24294,34 @@ def gitea_break_glass_restart(
incident_number = incident_issue_result.get("number")
# Execute or delegate canonical non-dry-run restart (B6/B11)
restart_exec_result = gitea_request_mcp_restart(
remote=remote,
host=host,
org=org,
repo=repo,
dry_run=False,
restart_class=restart_class,
request_break_glass=True,
)
# B6/B11: reach the canonical non-dry-run executor/delegate.
# Authorization and apply_authorized do not mean execution occurred.
# Dry-run never reaches this path (returned earlier).
restart_exec_result = _run_break_glass_restart_executor({
"remote": remote,
"host": host,
"org": o,
"repo": r,
"restart_class": restart_class,
"correlation_id": correlation_id,
"reason": clean_reason,
"confirmation": clean_confirmation,
"profile_name": profile_name,
"active_role": active_role,
"incident_number": incident_number,
"disrupted_sessions_count": disrupted_count,
"request_break_glass": True,
"dry_run": False,
})
apply_supported = bool(restart_exec_result.get("apply_supported", False))
apply_authorized = bool(restart_exec_result.get("apply_authorized", False))
exec_success = bool(restart_exec_result.get("success", False))
# break_glass_executed is true only when the executor contract proves
# execution (or accepted host delegation) occurred.
restart_performed = bool(
restart_exec_result.get("restart_performed", False)
or restart_exec_result.get("break_glass_executed", False)
and restart_exec_result.get("break_glass_executed", False)
)
if not apply_supported: