// Omnipus - Ultra-lightweight personal AI agent
// License: MIT
// Copyright (c) 2026 Omnipus contributors

package agent

// prompt_guard.go — SEC-25 trust classification for tool results.
//
// The agent loop feeds tool output back into the LLM's context. Tools that
// pull content from the outside world (web search, HTTP fetch, page DOM,
// arbitrary files) return attacker-controllable data that can contain
// prompt-injection payloads. Trust classification decides whether the
// PromptGuard sanitizes a tool's result before it reaches the LLM.
//
// Design: explicit allowlist of UNTRUSTED tools.
//
//   - Internal tools (exec, spawn, message, task_*, file writes, …) produce
//     output that was either authored by the user or generated by a peer
//     agent inside the same trust boundary. Sanitizing these would corrupt
//     legitimate output and confuse the model.
//   - External-world tools (web_search, web_fetch, browser.*, read_file)
//     return adversary-controlled content. Sanitizing is mandatory.
//
// When a new external-world tool is added it MUST be appended to
// untrustedToolResults below. TestIsUntrustedToolResult in loop_wave3_test.go
// pins the classification for every known tool name.
var untrustedToolResults = map[string]struct{}{
	// Web search providers — return attacker-controlled snippets.
	"web_search": {},
	// Web fetch — body is fully attacker-controlled.
	"web_fetch": {},
	// Browser automation — page DOM is attacker-controlled.
	// Tool names use dot notation per pkg/tools/browser/tools.go.
	"browser.navigate": {},
	"browser.click":    {},
	"browser.type":     {},
	// browser.screenshot is intentionally EXCLUDED — its output is base64 PNG
	// image data, not attacker-controlled text. Sanitizing it corrupts the JSON
	// structure and prevents the frontend from rendering the inline preview.
	"browser.get_text": {},
	"browser.wait":     {},
	"browser.evaluate": {},
	// File read — paths may point outside the workspace (allowed paths)
	// and files on disk may have been written by prior web_fetch calls.
	// Without per-path trust labeling we conservatively treat read_file
	// output as untrusted. This is stricter than necessary for purely
	// internal files but removes an entire class of indirect injection.
	"read_file": {},
}

// isUntrustedToolResult returns true when the given tool name produces
// output that should be passed through the prompt guard before being shown
// to the LLM (SEC-25). Returns false for internal tools (exec, spawn, etc.)
// whose output is trusted and must not be mutated.
//
// The check is case-sensitive because tool names in the registry are
// case-sensitive.
func isUntrustedToolResult(toolName string) bool {
	_, ok := untrustedToolResults[toolName]
	return ok
}
