enforce: Anthropic ban — linter, pre-commit, tests, and policy doc
Some checks failed
PR Checklist / pr-checklist (pull_request) Failing after 1m20s
Some checks failed
PR Checklist / pr-checklist (pull_request) Failing after 1m20s
Anthropic is not just removed — it is banned. This commit adds enforcement at every gate to prevent re-introduction. 1. architecture_linter.py — 9 BANNED rules for Anthropic patterns (provider, model slugs, API endpoints, keys, model names). Scans all yaml/py/sh/json/md. Skips training data and historical docs. 2. pre-commit.py — scan_banned_providers() runs on every staged file. Blocks any commit that introduces Anthropic references. Exempt: training/, evaluations/, changelogs, historical cost data. 3. test_sovereignty_enforcement.py — TestAnthropicBan class with 4 tests: - No Anthropic in wizard configs - No Anthropic in playbooks - No Anthropic in fallback chain - No Anthropic API key in bootstrap 4. BANNED_PROVIDERS.md — Hard policy document. Golden state config. Replacement table. Exception list. Not advisory — mandatory.
This commit is contained in:
@@ -272,6 +272,48 @@ def get_file_content_at_staged(filepath: str) -> bytes:
|
||||
return result.stdout
|
||||
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# BANNED PROVIDER CHECK — Anthropic is permanently banned
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
_BANNED_PROVIDER_PATTERNS = [
|
||||
(re.compile(r"provider:\s*anthropic", re.IGNORECASE), "Anthropic provider reference"),
|
||||
(re.compile(r"anthropic/claude", re.IGNORECASE), "Anthropic model slug"),
|
||||
(re.compile(r"api\.anthropic\.com"), "Anthropic API endpoint"),
|
||||
(re.compile(r"claude-opus", re.IGNORECASE), "Claude Opus model"),
|
||||
(re.compile(r"claude-sonnet", re.IGNORECASE), "Claude Sonnet model"),
|
||||
(re.compile(r"claude-haiku", re.IGNORECASE), "Claude Haiku model"),
|
||||
]
|
||||
|
||||
# Files exempt from the ban (training data, historical docs, tests)
|
||||
_BAN_EXEMPT = {
|
||||
"training/", "evaluations/", "RELEASE_v", "PERFORMANCE_",
|
||||
"scores.json", "docs/design-log/", "FALSEWORK.md",
|
||||
"test_sovereignty_enforcement.py", "test_metrics_helpers.py",
|
||||
"metrics_helpers.py", "sonnet-workforce.md",
|
||||
}
|
||||
|
||||
|
||||
def _is_ban_exempt(filepath: str) -> bool:
|
||||
return any(exempt in filepath for exempt in _BAN_EXEMPT)
|
||||
|
||||
|
||||
def scan_banned_providers(filepath: str, content: str) -> List[Finding]:
|
||||
"""Block any commit that introduces banned provider references."""
|
||||
if _is_ban_exempt(filepath):
|
||||
return []
|
||||
findings = []
|
||||
for line_no, line in enumerate(content.splitlines(), start=1):
|
||||
for pattern, desc in _BANNED_PROVIDER_PATTERNS:
|
||||
if pattern.search(line):
|
||||
findings.append(Finding(
|
||||
filepath, line_no,
|
||||
f"🚫 BANNED PROVIDER: {desc}. Anthropic is permanently banned from this system."
|
||||
))
|
||||
return findings
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Main
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -295,11 +337,21 @@ def main() -> int:
|
||||
if line.startswith("+") and not line.startswith("+++"):
|
||||
findings.extend(scan_line(line[1:], "<diff>", line_no))
|
||||
|
||||
# Scan for banned providers
|
||||
for filepath in staged_files:
|
||||
file_content = get_file_content_at_staged(filepath)
|
||||
if not is_binary_content(file_content):
|
||||
try:
|
||||
text = file_content.decode("utf-8") if isinstance(file_content, bytes) else file_content
|
||||
findings.extend(scan_banned_providers(filepath, text))
|
||||
except UnicodeDecodeError:
|
||||
pass
|
||||
|
||||
if not findings:
|
||||
print(f"{GREEN}✓ No potential secret leaks detected{NC}")
|
||||
print(f"{GREEN}✓ No potential secret leaks or banned providers detected{NC}")
|
||||
return 0
|
||||
|
||||
print(f"{RED}✗ Potential secret leaks detected:{NC}\n")
|
||||
print(f"{RED}✗ Violations detected:{NC}\n")
|
||||
for finding in findings:
|
||||
loc = finding.filename
|
||||
print(
|
||||
@@ -308,7 +360,7 @@ def main() -> int:
|
||||
|
||||
print()
|
||||
print(f"{RED}╔════════════════════════════════════════════════════════════╗{NC}")
|
||||
print(f"{RED}║ COMMIT BLOCKED: Potential secrets detected! ║{NC}")
|
||||
print(f"{RED}║ COMMIT BLOCKED: Secrets or banned providers detected! ║{NC}")
|
||||
print(f"{RED}╚════════════════════════════════════════════════════════════╝{NC}")
|
||||
print()
|
||||
print("Recommendations:")
|
||||
|
||||
Reference in New Issue
Block a user