Context
From schema consistency discussion #17876 (2026-02-23 run, findings 1–5).
Objective
Fix five related network/firewall bugs where the schema, documentation, and code are inconsistent about which engines support the firewall feature and how firewall config is parsed.
Issues to Fix
1. Schema network.firewall description incorrectly says "Only supported for Copilot engine"
- File:
pkg/parser/schemas/main_workflow_schema.json:2225
- All four engines (
copilot, claude, codex, gemini) have supportsFirewall: true — remove the Copilot-only restriction from the description.
2. log_level vs log-level key name mismatch
- Files:
pkg/workflow/engine.go:220, pkg/workflow/frontmatter_extraction_security.go:123
engine.go uses firewallObj["log_level"] (underscore) while the security extraction path uses firewallObj["log-level"] (hyphen).
- Standardize to
log-level (hyphen) in engine.go:220 to match frontmatter_extraction_security.go.
3. cleanup_script field missing from schema
- Files:
pkg/workflow/engine.go:227, pkg/parser/schemas/main_workflow_schema.json
engine.go:227 reads firewallObj["cleanup_script"] but the field is absent from the schema (which has additionalProperties: false).
- Add
cleanup_script to the appropriate schema object so users can discover and use this field.
4. hasNetworkRestrictions() ignores Blocked domain list
- File:
pkg/workflow/engine_firewall_support.go:17-35
- The function only checks
Allowed list; a workflow with only network: blocked: [...] returns false, skipping firewall validation.
- Add:
if len(networkPermissions.Blocked) > 0 { return true }.
5. computeAllowedDomainsForSanitization missing gemini case
- File:
pkg/workflow/domains.go:695-706
- Gemini falls into
default which calls GetAllowedDomains() instead of GetGeminiAllowedDomainsWithToolsAndRuntimes().
- Add
case "gemini": return GetGeminiAllowedDomainsWithToolsAndRuntimes(...) to the switch.
Files to Modify
pkg/parser/schemas/main_workflow_schema.json
pkg/workflow/engine.go
pkg/workflow/engine_firewall_support.go
pkg/workflow/domains.go
Acceptance Criteria
Generated by Plan Command for issue #discussion #17876
Context
From schema consistency discussion #17876 (2026-02-23 run, findings 1–5).
Objective
Fix five related network/firewall bugs where the schema, documentation, and code are inconsistent about which engines support the firewall feature and how firewall config is parsed.
Issues to Fix
1. Schema
network.firewalldescription incorrectly says "Only supported for Copilot engine"pkg/parser/schemas/main_workflow_schema.json:2225copilot,claude,codex,gemini) havesupportsFirewall: true— remove the Copilot-only restriction from the description.2.
log_levelvslog-levelkey name mismatchpkg/workflow/engine.go:220,pkg/workflow/frontmatter_extraction_security.go:123engine.gousesfirewallObj["log_level"](underscore) while the security extraction path usesfirewallObj["log-level"](hyphen).log-level(hyphen) inengine.go:220to matchfrontmatter_extraction_security.go.3.
cleanup_scriptfield missing from schemapkg/workflow/engine.go:227,pkg/parser/schemas/main_workflow_schema.jsonengine.go:227readsfirewallObj["cleanup_script"]but the field is absent from the schema (which hasadditionalProperties: false).cleanup_scriptto the appropriate schema object so users can discover and use this field.4.
hasNetworkRestrictions()ignoresBlockeddomain listpkg/workflow/engine_firewall_support.go:17-35Allowedlist; a workflow with onlynetwork: blocked: [...]returnsfalse, skipping firewall validation.if len(networkPermissions.Blocked) > 0 { return true }.5.
computeAllowedDomainsForSanitizationmissinggeminicasepkg/workflow/domains.go:695-706defaultwhich callsGetAllowedDomains()instead ofGetGeminiAllowedDomainsWithToolsAndRuntimes().case "gemini": return GetGeminiAllowedDomainsWithToolsAndRuntimes(...)to the switch.Files to Modify
pkg/parser/schemas/main_workflow_schema.jsonpkg/workflow/engine.gopkg/workflow/engine_firewall_support.gopkg/workflow/domains.goAcceptance Criteria
network.firewallno longer says "Only supported for Copilot engine"cleanup_scriptis documented in the schemaengine.gouseslog-level(hyphen) consistent with security extraction pathhasNetworkRestrictions()returnstruewhen onlyBlockedlist is non-emptycomputeAllowedDomainsForSanitizationcalls the Gemini-specific function for"gemini"enginemake agent-finishwith no errors before committing