Finish approval engine spine
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a05e2e-805b-7042-a750-71f473bceea2
This commit is contained in:
parent
e7c210bf56
commit
c3f1dfbc07
18 changed files with 526 additions and 75 deletions
|
|
@ -27,16 +27,86 @@ def test_create_entry_claim_roundtrip(app):
|
|||
assert "decision" not in claim
|
||||
|
||||
|
||||
def test_no_check_or_authorize_or_consume(app):
|
||||
def test_no_check_or_authorize(app):
|
||||
for path in (
|
||||
"/v1/check",
|
||||
"/authorize",
|
||||
"/v1/approvals/00000000-0000-0000-0000-000000000001/consume",
|
||||
"/v1/approvals/abc/consume",
|
||||
):
|
||||
status, body = call(app, "POST", path, {})
|
||||
assert status == 404
|
||||
assert "consume is not implemented" in body.get("message", "") or body["error"] == "not_found"
|
||||
assert body["error"] == "not_found"
|
||||
|
||||
|
||||
def test_consume_endpoint_is_a_mutation_not_a_decision(app):
|
||||
_, created = call(
|
||||
app,
|
||||
"POST",
|
||||
"/v1/approvals",
|
||||
{"binding": binding(), "validity": validity()},
|
||||
)
|
||||
aid = created["id"]
|
||||
call(app, "POST", f"/v1/approvals/{aid}/entries", {"subject_id": "user:alice"})
|
||||
digest = "sha256:" + "12" * 32
|
||||
status, result = call(
|
||||
app,
|
||||
"POST",
|
||||
f"/v1/approvals/{aid}/consume",
|
||||
{"request_digest": digest, "decision_id": "decision:123"},
|
||||
)
|
||||
assert status == 200
|
||||
assert result == {
|
||||
"approval_id": aid,
|
||||
"status": "consumed",
|
||||
"request_digest": digest,
|
||||
"decision_id": "decision:123",
|
||||
"consumed_at": "2026-08-29T12:00:00+00:00",
|
||||
"idempotent": False,
|
||||
}
|
||||
assert not ({"effect", "decision", "allow", "deny"} & set(result))
|
||||
|
||||
|
||||
def test_consume_requires_request_digest(app):
|
||||
_, created = call(
|
||||
app,
|
||||
"POST",
|
||||
"/v1/approvals",
|
||||
{"binding": binding(), "validity": validity()},
|
||||
)
|
||||
aid = created["id"]
|
||||
call(app, "POST", f"/v1/approvals/{aid}/entries", {"subject_id": "user:alice"})
|
||||
status, body = call(app, "POST", f"/v1/approvals/{aid}/consume", {})
|
||||
assert status == 422
|
||||
assert body["error"] == "unprocessable"
|
||||
|
||||
status, body = call(
|
||||
app,
|
||||
"POST",
|
||||
f"/v1/approvals/{aid}/consume",
|
||||
{"request_digest": ["not", "a", "digest"]},
|
||||
)
|
||||
assert status == 422
|
||||
assert body["error"] == "unprocessable"
|
||||
|
||||
|
||||
def test_consume_endpoint_rejects_different_digest_replay(app):
|
||||
_, created = call(
|
||||
app,
|
||||
"POST",
|
||||
"/v1/approvals",
|
||||
{"binding": binding(), "validity": validity()},
|
||||
)
|
||||
aid = created["id"]
|
||||
call(app, "POST", f"/v1/approvals/{aid}/entries", {"subject_id": "user:alice"})
|
||||
first = "sha256:" + "45" * 32
|
||||
second = "sha256:" + "67" * 32
|
||||
assert call(
|
||||
app, "POST", f"/v1/approvals/{aid}/consume", {"request_digest": first}
|
||||
)[0] == 200
|
||||
status, body = call(
|
||||
app, "POST", f"/v1/approvals/{aid}/consume", {"request_digest": second}
|
||||
)
|
||||
assert status == 409
|
||||
assert body["error"] == "conflict"
|
||||
|
||||
|
||||
def test_claim_after_revoke(app):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue