All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 5s
המאכף האוטומטי של INV-G12 (docs/spec/X15 §4). שני כללים קשיחים: 1. mcp-server/src (שכבת-האינטליגנציה) ללא סמלי-Paperclip — allowlist מנומק לפי substring ל-6 ההפניות הלגיטימיות (pm2-bridge + הערות-מקור company_id). 2. import seam — רק web/agent_platform_port.py (+ קבצי-המעטפת) מייבאים paperclip_*. מימוש קנוני אחד (scripts/leak_guard.py, stdlib-בלבד), משותף לשלושה אכיפנים (G2): • CI hard gate: .gitea/workflows/leak-guard.yaml (pull_request + push→main) • pytest: mcp-server/tests/test_platform_port_leak_guard.py (כולל self-test שמוודא שה-guard תופס הזרקה — לא ירקב) • hook בזמן-אמת: spec-guard.sh בודק את התוכן-הנכתב (new_string/content) על כתיבה ל-mcp-server/src ומזהיר על הזרקת-Paperclip (לא-deduped); תזכורת-הספ עודכנה ל-G1–G12. מחריג קבצים-נוצרים (web-ui types.ts) ומעטפת מוצהרת; הפרונט מחוץ להיקף-האינטליגנציה (ממצא R3). עודכן scripts/SCRIPTS.md. אימות: סריקה נקייה exit 0; הזרקת pc.sh ל-mcp-server → exit 1; seam-violation ב-web → exit 1; hook מזהיר על mcp-server ומזכיר-ספ על web; pytest 3 passed; bash -n + YAML תקינים. Invariants: G12 (אכיפה), G2 (מאכף יחיד לשלושה צרכנים). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
55 lines
1.9 KiB
Python
55 lines
1.9 KiB
Python
"""CI fitness-test for INV-G12 (docs/spec/X15 §4 / R4) — the Agent Platform Port.
|
|
|
|
Hard gate: the intelligence layer (``mcp-server/src``) must contain ZERO
|
|
Paperclip-specific symbols, and only ``web/agent_platform_port.py`` (+ the shell
|
|
itself) may import the Paperclip client. The check lives in
|
|
``scripts/leak_guard.py`` (one canonical implementation, shared with the
|
|
interactive ``spec-guard.sh`` hook); this test runs it and fails the build on any
|
|
violation.
|
|
|
|
Runs OFFLINE — pure source scan, no DB / no imports of the app.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import importlib.util
|
|
from pathlib import Path
|
|
|
|
REPO = Path(__file__).resolve().parents[2]
|
|
_GUARD = REPO / "scripts" / "leak_guard.py"
|
|
|
|
|
|
def _load_guard():
|
|
spec = importlib.util.spec_from_file_location("leak_guard", _GUARD)
|
|
mod = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(mod) # type: ignore[union-attr]
|
|
return mod
|
|
|
|
|
|
def test_leak_guard_script_exists() -> None:
|
|
assert _GUARD.is_file(), "scripts/leak_guard.py is missing (R4)"
|
|
|
|
|
|
def test_intelligence_layer_is_platform_clean() -> None:
|
|
"""No Paperclip symbols in mcp-server/src; import seam intact (INV-G12)."""
|
|
guard = _load_guard()
|
|
violations = guard.scan()
|
|
assert not violations, (
|
|
"INV-G12 leak-guard found Platform Port violations:\n"
|
|
+ "\n".join(f" • {v}" for v in violations)
|
|
)
|
|
|
|
|
|
def test_guard_detects_an_injected_intelligence_leak(tmp_path: Path) -> None:
|
|
"""The guard must FAIL on a planted Paperclip symbol (so it can't rot)."""
|
|
guard = _load_guard()
|
|
probe = REPO / "mcp-server" / "src" / "legal_mcp" / "_leakguard_selftest.py"
|
|
probe.write_text('BAD = "use pc.sh wakeup directly"\n', encoding="utf-8")
|
|
try:
|
|
violations = guard.scan()
|
|
assert any("_leakguard_selftest.py" in v for v in violations), (
|
|
"leak-guard failed to detect a planted intelligence-layer leak"
|
|
)
|
|
finally:
|
|
probe.unlink(missing_ok=True)
|