Correct audit engagement and idempotent fixture setup

Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a0260c-4067-7052-9647-ad000d576e38
This commit is contained in:
tegwick 2026-08-22 00:05:15 +02:00
parent edc9df0491
commit 8a97fac17f
5 changed files with 34 additions and 10 deletions

View file

@ -6,7 +6,8 @@
"expires_at": "2026-08-21T23:15:00Z", "expires_at": "2026-08-21T23:15:00Z",
"target": "http://audit-core.audit-core.svc.cluster.local:8080", "target": "http://audit-core.audit-core.svc.cluster.local:8080",
"target_owner": "audit-core / infrastructure operator", "target_owner": "audit-core / infrastructure operator",
"target_owner_acknowledged_at": "2026-08-21T21:56:00Z", "target_owner_acknowledged_at": null,
"target_owner_acknowledgement_status": "pending corrected adapter/record review; target review received 2026-08-21T22:04:19Z",
"environment": "production", "environment": "production",
"production_approval": "Explicit user approval of engagements/2026-08-21-e2-proposals.md in the coordinating session", "production_approval": "Explicit user approval of engagements/2026-08-21-e2-proposals.md in the coordinating session",
"namespace": "audit-core", "namespace": "audit-core",

View file

@ -53,8 +53,9 @@ invented tenant claim is not acceptable evidence.
## Explicitly excluded ## Explicitly excluded
These E2 approvals do not cover direct PostgreSQL access, RLS probes, schema or These E2 approvals cover only the two exact named production deployments and
role changes, connection/load saturation, recovery, production, adjacent do not cover any other production target, direct PostgreSQL access, RLS
probes, schema or role changes, connection/load saturation, recovery, adjacent
services, real tenant identifiers, or collection of response bodies. E3 and services, real tenant identifiers, or collection of response bodies. E3 and
P1/P2 each receive a separate approval package after E2 establishes the safe P1/P2 each receive a separate approval package after E2 establishes the safe
execution path. execution path.

View file

@ -80,12 +80,8 @@ class Client:
self.args.base_url + path, self.args.base_url + path,
data=raw, data=raw,
method=method, method=method,
headers={ headers=request_headers(token, self.args.engagement_id,
"Authorization": f"Bearer {token}", self.args.correlation, payload),
"Content-Type": "application/json",
"User-Agent": f"whitehat-security/{self.args.engagement_id}",
"X-Correlation-ID": self.args.correlation,
},
) )
started = time.monotonic() started = time.monotonic()
try: try:
@ -141,6 +137,19 @@ def _p95(samples: list[float]) -> float:
return ordered[max(0, math.ceil(len(ordered) * .95) - 1)] return ordered[max(0, math.ceil(len(ordered) * .95) - 1)]
def request_headers(token: str, engagement_id: str, correlation: str,
payload: dict[str, Any] | None) -> dict[str, str]:
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
"User-Agent": f"whitehat-security/{engagement_id}",
"X-Correlation-ID": correlation,
}
if payload is not None:
headers["Idempotency-Key"] = str(payload["id"])
return headers
def event(event_id: str, tenant: str, correlation: str) -> dict[str, Any]: def event(event_id: str, tenant: str, correlation: str) -> dict[str, Any]:
return { return {
"id": event_id, "id": event_id,
@ -276,4 +285,3 @@ def main() -> None:
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View file

@ -42,6 +42,8 @@ class Engagement:
end = _timestamp(self.raw["window_end"]) end = _timestamp(self.raw["window_end"])
expiry = _timestamp(self.raw["expires_at"]) expiry = _timestamp(self.raw["expires_at"])
approved = _timestamp(self.raw["approved_at"]) approved = _timestamp(self.raw["approved_at"])
if not self.raw["target_owner_acknowledged_at"]:
raise AuthorizationError("target-owner acknowledgement is pending")
acknowledged = _timestamp(self.raw["target_owner_acknowledged_at"]) acknowledged = _timestamp(self.raw["target_owner_acknowledged_at"])
if not approved <= current <= min(end, expiry): if not approved <= current <= min(end, expiry):
raise AuthorizationError("engagement is outside its approved time/expiry window") raise AuthorizationError("engagement is outside its approved time/expiry window")

View file

@ -30,3 +30,15 @@ def test_event_is_synthetic_and_correlation_bound():
def test_p95_is_conservative_for_small_runs(): def test_p95_is_conservative_for_small_runs():
assert runner._p95([10, 20, 30]) == 30 assert runner._p95([10, 20, 30]) == 30
def test_post_headers_bind_idempotency_key_to_event_id():
headers = runner.request_headers(
"secret-not-rendered", "eng-1", "corr-1", {"id": "event-1"}
)
assert headers["Idempotency-Key"] == "event-1"
assert headers["User-Agent"] == "whitehat-security/eng-1"
def test_get_headers_have_no_idempotency_key():
headers = runner.request_headers("secret", "eng-1", "corr-1", None)
assert "Idempotency-Key" not in headers