feat: re-check central RTC authorization right before every write (GET /v1/agents/me/authorizations), human labels on the cClassTrib control page, final corpus/scale evidence; 1.2.1
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -21,6 +21,7 @@ class HubClient:
|
||||
response = httpx.get(f"{self.url}{path}", headers=self._headers(), timeout=30)
|
||||
response.raise_for_status(); return response.json()
|
||||
def identity(self): return self.get_json("/v1/agents/me/identity")
|
||||
def authorizations(self): return self.get_json("/v1/agents/me/authorizations")
|
||||
def health(self):
|
||||
response = httpx.get(f"{self.url}/health", timeout=10)
|
||||
return response.status_code == 200
|
||||
|
||||
@@ -9,7 +9,7 @@ import os
|
||||
import sqlite3
|
||||
from pathlib import Path
|
||||
|
||||
AGENT_VERSION_DEFAULT = "1.2.0"
|
||||
AGENT_VERSION_DEFAULT = "1.2.1"
|
||||
REQUIRED_ENV = ("GTI_HUB_URL", "AGENT_TOKEN", "FIREBIRD_DATABASE_PATH", "FB_USER", "FB_PASSWORD")
|
||||
REQUIRED_CAPABILITIES = ("supports_ncm", "supports_ipi", "supports_cest")
|
||||
FISCAL_MODES = ("DRY_RUN", "AUTO_APPLY")
|
||||
|
||||
@@ -147,10 +147,18 @@ def apply_candidate(conn, candidate: dict, *, company: dict, decision: dict, now
|
||||
raise
|
||||
|
||||
|
||||
def apply_candidates(conn, candidates: list[dict], *, company: dict, decision: dict, now: str, job_id=None, today: date | None = None) -> dict:
|
||||
"""Applies each candidate independently; a failure or an abort never stops the rest and never leaves a partial change."""
|
||||
def apply_candidates(conn, candidates: list[dict], *, company: dict, decision: dict, now: str, job_id=None, today: date | None = None, authorize=None) -> dict:
|
||||
"""Applies each candidate independently; a failure or an abort never stops the rest and never leaves a partial change.
|
||||
`authorize(product_code)` (optional) re-asks the Hub, right before each UPDATE, whether the central authorization still permits it: it returns None to proceed or a
|
||||
reason (AUTHORIZATION_CHANGED / AUTHORIZATION_UNVERIFIABLE) to skip the product with zero writes."""
|
||||
applied, aborted, reasons = [], [], {}
|
||||
for candidate in candidates:
|
||||
if authorize is not None:
|
||||
denied = authorize(candidate["product_code"])
|
||||
if denied:
|
||||
aborted.append({"outcome": "ABORTED", "product_code": candidate["product_code"], "field": "CCLASSTRIB", "reason": denied, "rule_id": candidate["rule_id"], "job_id": job_id, "timestamp": now, "action": "APPLY", "authorization_origin": decision.get("origin")})
|
||||
reasons[denied] = reasons.get(denied, 0) + 1
|
||||
continue
|
||||
try:
|
||||
applied.append(apply_candidate(conn, candidate, company=company, decision=decision, now=now, job_id=job_id, today=today))
|
||||
except RtcApplyAborted as stop:
|
||||
|
||||
Reference in New Issue
Block a user