"""Synthetic workflow lab, implemented from usecases/generalisation-spec.md.""" from copy import deepcopy from dataclasses import dataclass from testdriver.actions import Surface from testdriver.drivers import Realization class WorkflowDriver: """A completed denial is a protocol response, not a failed realization.""" surface = Surface("workflow", "direct") def __init__(self, lab): self.lab = lab def realize(self, actor, action): action.check_surface(self.surface.id) response = self.lab.request(actor.credentials["token"], action.name, **action.args) return Realization(self.surface.id, {"operation": action.name, "response": response}) class ApprovalLab: tokens = {"requester": "fixture-requester", "reviewer": "fixture-reviewer", "delegate": "fixture-delegate"} def __init__(self, defect=None): self.defect = defect self.state = "draft" self.reviewer = "reviewer" self.approved_by = None self.receipts = [] def may_execute(self, actor): return actor == "requester" and ( self.state == "approved" or self.defect == "premature-execution" ) def request(self, token, operation, **args): actor = next((a for a, t in self.tokens.items() if t == token), None) allowed = False if operation == "submit": allowed = actor == "requester" and self.state == "draft" if allowed: self.state = "pending" elif operation == "delegate": allowed = (actor == self.reviewer and self.state == "pending" and args["to"] == "delegate") if allowed: self.reviewer = args["to"] elif operation == "approve": allowed = self.state == "pending" and ( actor == self.reviewer or (actor == "requester" and self.defect == "self-approval") or (actor == "reviewer" and self.defect == "stale-delegation") ) if allowed: self.state, self.approved_by = "approved", actor elif operation == "execute": allowed = self.may_execute(actor) if allowed: self.state = "executed" else: raise ValueError(operation) receipt = {"actor": actor, "operation": operation, "allowed": allowed} self.receipts.append(receipt) return deepcopy(receipt) @dataclass class ApprovalObserver: lab: ApprovalLab name: str = "approval-observer" def snapshot(self): return deepcopy({ "state": self.lab.state, "reviewer": self.lab.reviewer, "approved_by": self.lab.approved_by, "receipts": self.lab.receipts, "execution_gate": {actor: self.lab.may_execute(actor) for actor in self.lab.tokens}, }) class TenantLab: tokens = {"admin-a": "fixture-admin-a", "admin-b": "fixture-admin-b"} tenants = {"admin-a": "A", "admin-b": "B"} def __init__(self, defect=None): self.defect = defect self.records = {} self.deleted = {} self.receipts = [] def read(self, actor, tenant, resource): if self.tenants.get(actor) != tenant and self.defect != "foreign-read": return {"allowed": False, "content": None} return {"allowed": (tenant, resource) in self.records, "content": self.records.get((tenant, resource))} def request(self, token, operation, tenant, resource="R", content=None): actor = next((a for a, t in self.tokens.items() if t == token), None) allowed = self.tenants.get(actor) == tenant key = (tenant, resource) if operation == "create": allowed = allowed and key not in self.records if allowed: self.records[key] = (self.deleted.get(key, content) if self.defect == "resurrect-content" else content) elif operation == "delete": allowed = (allowed or self.defect == "foreign-delete") and key in self.records if allowed: self.deleted[key] = self.records.pop(key) if self.defect == "unscoped-delete": self.records = {k: v for k, v in self.records.items() if k[1] != resource} else: raise ValueError(operation) receipt = {"actor": actor, "operation": operation, "tenant": tenant, "allowed": allowed} self.receipts.append(receipt) return deepcopy(receipt) @dataclass class TenantObserver: lab: TenantLab name: str = "tenant-observer" def snapshot(self): return deepcopy({ "records": {tenant: self.lab.records.get((tenant, "R")) for tenant in ("A", "B")}, "reads": {f"{actor}:{tenant}": self.lab.read(actor, tenant, "R") for actor in self.lab.tokens for tenant in ("A", "B")}, "receipts": self.lab.receipts, })