Harden production authorization and service auth
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a0217e-8c4c-7383-be6b-f50a6e485306
This commit is contained in:
parent
f579f3761c
commit
70371649af
20 changed files with 1268 additions and 54 deletions
|
|
@ -47,6 +47,7 @@ class EvidenceWriter:
|
|||
topic_id: str = ""
|
||||
workstream_id: str = ""
|
||||
author: str = "secrets-engine"
|
||||
repo_slug: str = "secrets-engine"
|
||||
actor: str = field(default_factory=lambda: os.environ.get("USER", "unknown"))
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
|
|
@ -91,8 +92,13 @@ class EvidenceWriter:
|
|||
}
|
||||
self._append_local(record)
|
||||
if hub_requested:
|
||||
delivery_result = self._post_hub(
|
||||
action, result, catalog_id, stage, decision_id
|
||||
delivery = self._post_hub(
|
||||
action,
|
||||
result,
|
||||
catalog_id,
|
||||
stage,
|
||||
decision_id,
|
||||
record_id=record_id,
|
||||
)
|
||||
# Append-only companion evidence makes an unavailable State Hub
|
||||
# visible without rewriting or delaying the primary local record.
|
||||
|
|
@ -102,23 +108,32 @@ class EvidenceWriter:
|
|||
"related_record_id": record_id,
|
||||
"ts": datetime.now(timezone.utc).isoformat(),
|
||||
"action": "evidence-delivery",
|
||||
"result": delivery_result,
|
||||
"result": delivery.status,
|
||||
"actor": self.actor,
|
||||
"catalog_id": catalog_id,
|
||||
"stage": stage,
|
||||
"decision_id": decision_id,
|
||||
"detail": {},
|
||||
"detail": {"outbox_id": delivery.outbox_id}
|
||||
if delivery.outbox_id
|
||||
else {},
|
||||
"hub_delivery_requested": False,
|
||||
}
|
||||
)
|
||||
return record
|
||||
|
||||
def _post_hub(
|
||||
self, action: str, result: str, catalog_id: str, stage: str, decision_id: str
|
||||
) -> str:
|
||||
self,
|
||||
action: str,
|
||||
result: str,
|
||||
catalog_id: str,
|
||||
stage: str,
|
||||
decision_id: str,
|
||||
*,
|
||||
record_id: str,
|
||||
) -> "HubDelivery":
|
||||
"""Best-effort progress note; return a non-secret delivery outcome."""
|
||||
if not self.topic_id:
|
||||
return "skipped-no-topic"
|
||||
return HubDelivery("skipped-no-topic")
|
||||
summary = f"secrets-engine {action}: {result}"
|
||||
if catalog_id:
|
||||
summary += f" [{catalog_id}{'/' + stage if stage else ''}]"
|
||||
|
|
@ -133,17 +148,47 @@ class EvidenceWriter:
|
|||
if decision_id:
|
||||
payload["detail"] = {"decision_id": decision_id, "catalog_id": catalog_id}
|
||||
try:
|
||||
idempotency_key = f"secrets-engine:{record_id}"
|
||||
req = urllib.request.Request(
|
||||
self.hub_url.rstrip("/") + "/progress/",
|
||||
data=json.dumps(payload).encode(),
|
||||
headers={"Content-Type": "application/json"},
|
||||
headers={
|
||||
"Content-Type": "application/json",
|
||||
"Idempotency-Key": idempotency_key,
|
||||
"X-StateHub-Source-Agent": self.author,
|
||||
"X-StateHub-Repo-Slug": self.repo_slug,
|
||||
},
|
||||
method="POST",
|
||||
)
|
||||
urllib.request.urlopen(req, timeout=3).read()
|
||||
return "delivered"
|
||||
response = urllib.request.urlopen(req, timeout=3)
|
||||
body = response.read()
|
||||
status = getattr(response, "status", 200)
|
||||
if status == 202:
|
||||
try:
|
||||
receipt = json.loads(body or b"{}")
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
receipt = {}
|
||||
if isinstance(receipt, dict) and receipt.get("queued") is True:
|
||||
outbox_id = receipt.get("outbox_id", "")
|
||||
if isinstance(outbox_id, str):
|
||||
try:
|
||||
if str(uuid.UUID(outbox_id)) == outbox_id:
|
||||
return HubDelivery("queued", outbox_id=outbox_id)
|
||||
except ValueError:
|
||||
pass
|
||||
return HubDelivery("failed")
|
||||
return HubDelivery("delivered")
|
||||
except (urllib.error.URLError, OSError, ValueError):
|
||||
# Hub being offline must never block secret work or leak anything.
|
||||
return "failed"
|
||||
return HubDelivery("failed")
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class HubDelivery:
|
||||
"""Non-secret outcome returned by State Hub or its edge relay."""
|
||||
|
||||
status: str
|
||||
outbox_id: str = ""
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue