Seeded repo with intent and initial content.
This commit is contained in:
parent
86b9063721
commit
12d0c31cff
27 changed files with 2683 additions and 1 deletions
89
tests/test_determinism.py
Normal file
89
tests/test_determinism.py
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
"""Determinism and idempotency of the decision function (canon A3, G9)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
|
||||
import pytest
|
||||
|
||||
from fixture_loading import decision_cases
|
||||
|
||||
from emergent_security.decide import decide
|
||||
from emergent_security.delegation import Delegation
|
||||
from emergent_security.memory import MemoryEntry
|
||||
from emergent_security.model import Request
|
||||
from emergent_security.tenant import TenantContext
|
||||
|
||||
CASES = decision_cases()
|
||||
|
||||
|
||||
def _decide(request_dict, context, envelope, scales, tenant, registry_order=1):
|
||||
registry = [Delegation.from_dict(d) for d in context.get("registry", [])][::registry_order]
|
||||
return decide(
|
||||
Request.from_dict(request_dict),
|
||||
envelope=envelope,
|
||||
scales=scales,
|
||||
registry=registry,
|
||||
tenant=tenant,
|
||||
memory=[MemoryEntry.from_dict(m) for m in context.get("memory", [])],
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("request_dict", "context", "expect"), CASES)
|
||||
def test_same_inputs_same_decision(request_dict, context, expect, default_envelope, scales, tenant_context_from):
|
||||
tenant = tenant_context_from(context)
|
||||
first = _decide(request_dict, context, default_envelope, scales, tenant)
|
||||
second = _decide(request_dict, context, default_envelope, scales, tenant)
|
||||
assert first == second
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("request_dict", "context", "expect"), CASES)
|
||||
def test_inputs_are_not_mutated(request_dict, context, expect, default_envelope, scales, tenant_context_from):
|
||||
snapshot = copy.deepcopy((request_dict, context))
|
||||
_decide(request_dict, context, default_envelope, scales, tenant_context_from(context))
|
||||
assert (request_dict, context) == snapshot
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("request_dict", "context", "expect"), CASES)
|
||||
def test_registry_order_does_not_matter(request_dict, context, expect, default_envelope, scales, tenant_context_from):
|
||||
tenant = tenant_context_from(context)
|
||||
forward = _decide(request_dict, context, default_envelope, scales, tenant, registry_order=1)
|
||||
backward = _decide(request_dict, context, default_envelope, scales, tenant, registry_order=-1)
|
||||
assert forward == backward
|
||||
|
||||
|
||||
def test_most_specific_registry_delegation_wins(default_envelope, scales):
|
||||
request = {
|
||||
"request_id": "r", "principal": "agent://a", "decision_class": "git.merge_protected",
|
||||
"scope": {"level": "L0", "temperature": "hot", "phase": "build", "tenant": "none",
|
||||
"repository": "factory/billing", "environment": "dev"},
|
||||
"risk": {}, "attributes": {}, "evidence": [],
|
||||
}
|
||||
broad = {"id": "delegation://broad", "decision_class": "git.merge_protected", "scope": {},
|
||||
"mode": "autonomous", "risk_envelope": {}}
|
||||
narrow = {"id": "delegation://narrow", "decision_class": "git.merge_protected",
|
||||
"scope": {"repository": "factory/billing"}, "mode": "autonomous", "risk_envelope": {}}
|
||||
for order in ([broad, narrow], [narrow, broad]):
|
||||
decision = _decide(request, {"registry": order}, default_envelope, scales, None)
|
||||
assert decision.source == "delegation://narrow"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("request_dict", "context", "expect"),
|
||||
[c for c in CASES if "tenant_governance" not in c.values[1] and "platform_envelope" in c.values[1]],
|
||||
)
|
||||
def test_auto_mode_equals_no_tenant_configuration(request_dict, context, expect, default_envelope, scales, tenant_context_from):
|
||||
"""G7: `auto` mode yields the same decision as having no tenant governance at all."""
|
||||
from emergent_security.tenant import TenantGovernance
|
||||
|
||||
without = tenant_context_from(context)
|
||||
auto = TenantContext(
|
||||
platform=without.platform,
|
||||
governance=TenantGovernance.from_dict(
|
||||
{"tenant": without.platform.tenant, "mode": "auto", "bounded_by": without.platform.id,
|
||||
"established_by": "human://acme/admin-1", "on_deadline": "escalate_to_next_admin"}
|
||||
),
|
||||
)
|
||||
assert _decide(request_dict, context, default_envelope, scales, without) == _decide(
|
||||
request_dict, context, default_envelope, scales, auto
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue