179 lines
5.0 KiB
Rego
179 lines
5.0 KiB
Rego
# METADATA
|
|
# scope: package
|
|
# title: Block Magic Numbers
|
|
# description: Blocks introduction of magic numbers outside constants modules
|
|
# custom:
|
|
# routing:
|
|
# required_events: ["PreToolUse"]
|
|
# required_tools: ["ApplyPatch", "Edit", "MultiEdit", "NotebookEdit", "Patch", "Write"]
|
|
package cupcake.policies.opencode.block_magic_numbers
|
|
import rego.v1
|
|
|
|
tool_name := input.tool_name
|
|
tool_input := input.tool_input
|
|
|
|
resolved_file_path := input.resolved_file_path if {
|
|
input.resolved_file_path != null
|
|
} else := tool_input.file_path if {
|
|
tool_input.file_path != null
|
|
} else := tool_input.filePath if {
|
|
tool_input.filePath != null
|
|
} else := tool_input.path if {
|
|
tool_input.path != null
|
|
} else := tool_input.notebook_path if {
|
|
tool_input.notebook_path != null
|
|
} else := tool_input.notebookPath if {
|
|
tool_input.notebookPath != null
|
|
} else := ""
|
|
|
|
new_content := tool_input.new_string if {
|
|
tool_input.new_string != null
|
|
} else := tool_input.newText if {
|
|
tool_input.newText != null
|
|
} else := tool_input.new_text if {
|
|
tool_input.new_text != null
|
|
} else := tool_input.content if {
|
|
tool_input.content != null
|
|
} else := ""
|
|
|
|
old_content := tool_input.old_string if {
|
|
tool_input.old_string != null
|
|
} else := tool_input.oldText if {
|
|
tool_input.oldText != null
|
|
} else := tool_input.old_text if {
|
|
tool_input.old_text != null
|
|
} else := tool_input.previousContent if {
|
|
tool_input.previousContent != null
|
|
} else := ""
|
|
|
|
patch_content := tool_input.patch if {
|
|
tool_input.patch != null
|
|
} else := tool_input.patchText if {
|
|
tool_input.patchText != null
|
|
} else := tool_input.patch_text if {
|
|
tool_input.patch_text != null
|
|
} else := ""
|
|
|
|
edit_path(edit) := path if {
|
|
edit.resolved_file_path != null
|
|
path := edit.resolved_file_path
|
|
} else := path if {
|
|
edit.file_path != null
|
|
path := edit.file_path
|
|
} else := path if {
|
|
edit.filePath != null
|
|
path := edit.filePath
|
|
} else := path if {
|
|
edit.path != null
|
|
path := edit.path
|
|
} else := ""
|
|
|
|
edit_new_content(edit) := content if {
|
|
edit.new_string != null
|
|
content := edit.new_string
|
|
} else := content if {
|
|
edit.newText != null
|
|
content := edit.newText
|
|
} else := content if {
|
|
edit.new_text != null
|
|
content := edit.new_text
|
|
} else := content if {
|
|
edit.content != null
|
|
content := edit.content
|
|
} else := ""
|
|
|
|
edit_old_content(edit) := content if {
|
|
edit.old_string != null
|
|
content := edit.old_string
|
|
} else := content if {
|
|
edit.oldText != null
|
|
content := edit.oldText
|
|
} else := content if {
|
|
edit.old_text != null
|
|
content := edit.old_text
|
|
} else := ""
|
|
|
|
|
|
patch_targets_path(pattern) if {
|
|
patch := patch_content
|
|
patch != null
|
|
lines := split(patch, "\n")
|
|
some line in lines
|
|
startswith(line, "+++ b/")
|
|
path := replace(line, "+++ b/", "")
|
|
regex.match(pattern, path)
|
|
}
|
|
|
|
patch_targets_path(pattern) if {
|
|
patch := patch_content
|
|
patch != null
|
|
lines := split(patch, "\n")
|
|
some line in lines
|
|
startswith(line, "--- a/")
|
|
path := replace(line, "--- a/", "")
|
|
regex.match(pattern, path)
|
|
}
|
|
|
|
file_path_pattern := `\.(py|ts|tsx|js|jsx)$`
|
|
number_pattern := `(?:timeout|delay|interval|duration|limit|max|min|size|count|threshold|retry|retries|attempts|port|width|height|margin|padding|offset|index|length|capacity|buffer|batch|chunk|page|rate|fps|dpi|quality|level|priority|weight|score|factor|multiplier|divisor|percentage|ratio|scale)\s*[=:]\s*([2-9]|[1-9]\d+)|(?:if|while|for|elif|range|slice|sleep|wait|setTimeout|setInterval)\s*\([^)]*([2-9]|[1-9]\d+)`
|
|
|
|
# Block Write/Edit operations that introduce magic numbers
|
|
|
|
deny contains decision if {
|
|
input.hook_event_name == "PreToolUse"
|
|
tool_name in {"Write", "Edit", "NotebookEdit"}
|
|
|
|
file_path := resolved_file_path
|
|
regex.match(file_path_pattern, file_path)
|
|
not contains(lower(file_path), "constants")
|
|
|
|
content := new_content
|
|
content != null
|
|
regex.match(number_pattern, content)
|
|
|
|
decision := {
|
|
"rule_id": "STYLE-001",
|
|
"reason": "Magic numbers are prohibited. Use named constants.",
|
|
"severity": "HIGH"
|
|
}
|
|
}
|
|
|
|
deny contains decision if {
|
|
input.hook_event_name == "PreToolUse"
|
|
tool_name == "MultiEdit"
|
|
|
|
some edit in tool_input.edits
|
|
file_path := edit_path(edit)
|
|
regex.match(file_path_pattern, file_path)
|
|
not contains(lower(file_path), "constants")
|
|
|
|
content := edit_new_content(edit)
|
|
content != null
|
|
regex.match(number_pattern, content)
|
|
|
|
decision := {
|
|
"rule_id": "STYLE-001",
|
|
"reason": "Magic numbers are prohibited. Use named constants.",
|
|
"severity": "HIGH"
|
|
}
|
|
}
|
|
|
|
deny contains decision if {
|
|
input.hook_event_name == "PreToolUse"
|
|
tool_name in {"Patch", "ApplyPatch"}
|
|
|
|
patch := patch_content
|
|
patch != null
|
|
|
|
patch_targets_path(file_path_pattern)
|
|
not contains(lower(patch), "constants")
|
|
|
|
regex.match(number_pattern, patch)
|
|
|
|
decision := {
|
|
"rule_id": "STYLE-001",
|
|
"reason": "Magic numbers are prohibited. Use named constants.",
|
|
"severity": "HIGH"
|
|
}
|
|
}
|