Skip to content

fix(gateway): make chat restart policy fail closed - #10

Merged
Gabriel300p merged 4 commits into
mainfrom
fix/restart-command-policy-final-20260810
Aug 10, 2026
Merged

fix(gateway): make chat restart policy fail closed#10
Gabriel300p merged 4 commits into
mainfrom
fix/restart-command-policy-final-20260810

Conversation

@Gabriel300p

Copy link
Copy Markdown
Collaborator

Contexto

Reconstrução final e mínima do DTC-03 sobre o main atual. Substitui #9, #7 e o trecho equivalente do PR contaminado #4.

Mudança

Adiciona o plugin opt-in restart-command-policy:

  • intercepta /restart em pre_gateway_dispatch, antes do handler interno;
  • com policy desabilitada, reescreve a solicitação para um comando sem efeitos colaterais;
  • não altera arquivos core do gateway;
  • não captura lookalikes como /restart-now ou texto comum.

Semântica fail-closed

  • ambas as chaves ausentes: mantém o comportamento legado habilitado;
  • qualquer false explícito: bloqueia;
  • chave legada e canônica conflitantes: bloqueia;
  • valor não booleano, bloco gateway malformado ou config ilegível: bloqueia;
  • a chave legada é aceita, mas nunca pode sobrepor um disable canônico.

Redaction

Falhas de parser/loader não registram texto da exceção. A regressão injeta uma string sensível na exceção e comprova que ela não chega ao log.

Ativação

plugins:
  enabled:
    - restart-command-policy

gateway:
  restart_command_enabled: false

É necessário um único restart supervisionado após o deploy para carregar o plugin.

Propriedades de segurança

Uma solicitação bloqueada nunca chega ao handler interno. Portanto, não cria .restart_notify.json ou .restart_last_processed.json, não inicia drain, não sinaliza o processo e não solicita reinicialização.

Verificação local

  • python -m py_compile: aprovado;
  • suíte focada tests/test_restart_command_policy_plugin.py: aprovada;
  • cobre variantes, bot mention, argumentos, lookalikes, default, legado, conflitos nas duas direções, valores inválidos, mapping malformado, redaction, registro do hook e resposta sem efeitos colaterais.

Gates restantes

  • CI integral deste SHA;
  • revisão do diff final sem finding bloqueante;
  • merge;
  • deploy e canário live no host: plugin carregado, /restart bloqueado, PID invariável, nenhum marker novo, /status saudável e rollback comprovado.

@Gabriel300p
Gabriel300p merged commit 3c87bbb into main Aug 10, 2026
32 of 33 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a62fcb16df

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

"Use the supervised host deployment/restart procedure."
)
_RESTART_COMMAND = re.compile(
r"^\s*/restart(?:@[A-Za-z0-9_]+)?(?:\s+.*)?\s*$",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Match every command form the gateway treats as restart

On free-form gateway platforms, /restart@- or /restart@ does not match this regex, but MessageEvent.get_command() in gateway/platforms/base.py strips everything after @ and returns restart, after which gateway/run.py invokes the built-in restart handler. An authorized chat user can therefore bypass the disabled policy using input the gateway already treats as the same command; base the gate on the gateway's canonical command parsing rather than this narrower regex.

AGENTS.md reference: AGENTS.md:L54-L57

Useful? React with 👍 / 👎.

return None
if _restart_command_enabled():
return None
return {"action": "rewrite", "text": _BLOCKED_COMMAND}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle blocked restarts before running-agent busy logic

When the session already has a running agent, this rewrite is not side-effect-free: the running-agent fast path in gateway/run.py recognizes only built-in commands via resolve_command(), so the plugin-only /restart-policy-blocked falls into the queue, steer, or interrupt branches instead of reaching the plugin handler later in dispatch. Consequently, a denied /restart can interrupt the current turn or be queued rather than returning the policy explanation; route the denial through a path handled safely before busy-input processing and cover the real gateway flow.

AGENTS.md reference: AGENTS.md:L84-L87

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant