fix: audit batch 2 visibility (I-1 shadow dropped rows, I-2 partial policy failure, I-5 failure policy table)
- I-1: evaluate_shadow counts dropped rows by cause (unparseable / unknown_tier / explicit / duplicate) with the identity audit_rows_total == routed_task_n + dropped_total; the shadow endpoint passes created_at/id through and reports audit totals next to sample counts. - I-2 (option b): parse logs a warning naming each tier dropped for an invalid mode/requires; load attaches partial_failures to the policy; the worker records a task-level worker_routing_policy_load_failed audit for partial failures (same action as full failure, detail says failure=partial); the shadow report carries the policy fingerprint, dropped tiers and partial failures (no task context on that path, so no task-level audit there). - I-5: coordinator gate audit lookup failure now raises _CoordGateLookupFailed and the merge converts it to escalate (no requeue, no round consumed); persisted-model lookup failure and required-tools check failure each write a named audit row before falling through to dispatch/allow; audit-loop evaluate failure stays escalate (regression test). - Test fixtures: coordinator suites build audit_log via AuthStore as production's first real audit does, since their stubbed _audit never creates the table.
This commit is contained in:
1 parent
44e0f4f1d6
commit
a7f77c8a98
7 files changed
+648
-40
No files matched your search
@@ -25,11 +25,13 @@ from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
|
||||
try:
|
||||
from cloud.auth import AuthStore
|
||||
from cloud.coordinator import build_report, evaluate_outcome
|
||||
from cloud.server import init_db
|
||||
from cloud.worker import Worker
|
||||
except ImportError:
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
|
||||
from cloud.auth import AuthStore
|
||||
from cloud.coordinator import build_report, evaluate_outcome
|
||||
from cloud.server import init_db
|
||||
from cloud.worker import Worker
|
||||
@@ -111,6 +113,13 @@ class CoordFixTestCase(unittest.TestCase):
|
||||
self.tmp = tempfile.TemporaryDirectory()
|
||||
self.db_path = os.path.join(self.tmp.name, "control.db")
|
||||
init_db(self.db_path)
|
||||
# Audit batch 2 (I-5),与 test_audit_loop_coord.py 同款
|
||||
# 理由:生产里 audit_log 由首次真实 _audit 经 AuthStore
|
||||
# 建好,合流时表一定存在;本文件把 _audit 桩成列表,
|
||||
# 表永远不会出现,夹具里按生产实际补建表,否则合流
|
||||
# 测试会因缺表改走 escalate,与被测行为无关。
|
||||
_store = AuthStore(self.db_path)
|
||||
_store.conn.close()
|
||||
self.env = {"XCM_API_KEY": "test-placeholder"}
|
||||
self.audits = []
|
||||
self.worker = Worker(self.db_path, "/fake/host.py",
|
||||
@@ -200,10 +209,14 @@ class CoordFixTestCase(unittest.TestCase):
|
||||
# 最旧 id 的子任务必须不在,且集合恰好 5000 条。
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
try:
|
||||
# Audit batch 2 (I-5):setUp 已按生产实际经 AuthStore
|
||||
# 建好含 id 自增列的 audit_log 表,建表改 IF NOT
|
||||
# EXISTS——生产表与本测试要的表在 id 语义上一致,
|
||||
# tie-break 断言不受影响。
|
||||
conn.execute(
|
||||
"CREATE TABLE audit_log(id INTEGER PRIMARY KEY"
|
||||
" AUTOINCREMENT, user_id TEXT, project_id TEXT,"
|
||||
" action TEXT, detail TEXT,"
|
||||
"CREATE TABLE IF NOT EXISTS audit_log(id INTEGER"
|
||||
" PRIMARY KEY AUTOINCREMENT, user_id TEXT,"
|
||||
" project_id TEXT, action TEXT, detail TEXT,"
|
||||
" created_at DOUBLE PRECISION)")
|
||||
now = time.time()
|
||||
conn.executemany(
|
||||
|
||||
Reference in new issue
Block a user