9dfa06ffee
Docker image / Build (linux/amd64) (push) Has been cancelled
Docker image / Build (linux/arm64) (push) Has been cancelled
Docker image / Merge release multi-arch manifest (push) Has been cancelled
Docker image / Merge debug multi-arch manifest (push) Has been cancelled
Docker image / Build public push gateway (linux/amd64) (push) Has been cancelled
Docker image / Build public push gateway (linux/arm64) (push) Has been cancelled
Docker image / Publish public push gateway image (push) Has been cancelled
Sprig image / Build (linux/amd64) (push) Has been cancelled
Sprig image / Build (linux/arm64) (push) Has been cancelled
Sprig image / Merge multi-arch manifest (push) Has been cancelled
Harbor Buzz Orchestra / Python tests and lint (push) Has been cancelled
CI / Detect Changed Paths (push) Has been cancelled
CI / Rust Lint (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Desktop Core (push) Has been cancelled
CI / Desktop Smoke E2E (1) (push) Has been cancelled
CI / Desktop Smoke E2E (2) (push) Has been cancelled
CI / Desktop Smoke E2E (3) (push) Has been cancelled
CI / Desktop Smoke E2E (4) (push) Has been cancelled
CI / Desktop (push) Has been cancelled
CI / Desktop E2E Relay (push) Has been cancelled
CI / Desktop E2E Integration (1/2) (push) Has been cancelled
CI / Desktop E2E Integration (2/2) (push) Has been cancelled
CI / Desktop E2E Integration (push) Has been cancelled
CI / Backend Integration (relay e2e) (push) Has been cancelled
CI / Relay E2E (push) Has been cancelled
CI / Web (push) Has been cancelled
CI / Mobile (push) Has been cancelled
CI / Security (push) Has been cancelled
CI / Dead Token Reference Guard (push) Has been cancelled
CI / Server Cross-Compile (aarch64-unknown-linux-musl) (push) Has been cancelled
CI / Server Cross-Compile (x86_64-unknown-linux-musl) (push) Has been cancelled
CI / Windows Rust (x86_64-pc-windows-msvc) (push) Has been cancelled
CI / Desktop Build (macOS) (push) Has been cancelled
helm chart / lint + unittest + render matrix (push) Has been cancelled
helm chart / install on kind (gated) (push) Has been cancelled
helm chart / publish chart to GHCR (push) Has been cancelled
Mesh Lifecycle / Relay-Driven Mesh Lifecycle Smoke (push) Has been cancelled
Sprig / Build (aarch64-unknown-linux-musl) (push) Has been cancelled
Sprig / Build (x86_64-unknown-linux-musl) (push) Has been cancelled
Sprig / Publish rolling release (push) Has been cancelled
Sprig / Publish tagged release (push) Has been cancelled
Signed-off-by: cls_宁波本机 <908705107@qq.com>
105 lines
4.0 KiB
Python
105 lines
4.0 KiB
Python
"""Bounded model of the shipped stateful public-gateway authority plane.
|
|
|
|
The model deliberately excludes the relay matcher (not shipped here) and checks the
|
|
linearization rules that the gateway does ship: current epoch/generation authority,
|
|
relay confinement, expiry, replay admission, quota charging, terminal burn versus
|
|
transient release, revocation ordering, custody, and the constant APNs body.
|
|
"""
|
|
from itertools import permutations, product
|
|
|
|
FIXED_BODY = b'{"aps":{"alert":{"body":"Reconnect to your relay now"},"mutable-content":1}}'
|
|
|
|
class Gateway:
|
|
def __init__(self):
|
|
self.relay = "relay-a"
|
|
self.epoch = 1
|
|
self.generation = 1
|
|
self.revoked = False
|
|
self.installation_expires = 100
|
|
self.grant_expires = 80
|
|
self.auth_replays = set()
|
|
self.request_replays = set()
|
|
self.quota = 0
|
|
self.sends = []
|
|
|
|
def admit(self, relay="relay-a", epoch=1, generation=1, now=10,
|
|
request_expires=50, auth_id="auth-1", request_id="request-1",
|
|
custody_ok=True):
|
|
if (self.revoked or relay != self.relay or epoch != self.epoch or
|
|
generation != self.generation or now > self.installation_expires or
|
|
now > self.grant_expires or now > request_expires or
|
|
request_expires > self.grant_expires or auth_id in self.auth_replays or
|
|
request_id in self.request_replays):
|
|
return False
|
|
# One durable admission commit: both replay fences and non-refundable quota.
|
|
self.auth_replays.add(auth_id)
|
|
self.request_replays.add(request_id)
|
|
self.quota += 1
|
|
if not custody_ok:
|
|
self.finish(request_id, "transient")
|
|
return False
|
|
self.sends.append((request_id, FIXED_BODY))
|
|
return True
|
|
|
|
def finish(self, request_id, outcome):
|
|
if outcome == "transient":
|
|
self.request_replays.discard(request_id)
|
|
elif outcome != "terminal":
|
|
raise ValueError(outcome)
|
|
|
|
def rotate(self):
|
|
self.epoch += 1
|
|
|
|
def revoke(self):
|
|
self.revoked = True
|
|
|
|
|
|
def explore():
|
|
checked = 0
|
|
for relay_ok, epoch_ok, gen_ok, grant_live, request_live, custody_ok in product(
|
|
[False, True], repeat=6
|
|
):
|
|
checked += 1
|
|
g = Gateway()
|
|
admitted = g.admit(
|
|
relay="relay-a" if relay_ok else "relay-b",
|
|
epoch=1 if epoch_ok else 0,
|
|
generation=1 if gen_ok else 0,
|
|
now=10,
|
|
request_expires=50 if request_live else 9,
|
|
custody_ok=custody_ok,
|
|
) if grant_live else g.admit(now=81)
|
|
expected = all((relay_ok, epoch_ok, gen_ok, grant_live, request_live, custody_ok))
|
|
assert admitted == expected
|
|
assert all(body == FIXED_BODY for _, body in g.sends) # fixed-body noninterference
|
|
|
|
# Whichever authority mutation commits first determines admission.
|
|
for actions in permutations(("admit", "revoke")):
|
|
checked += 1
|
|
g = Gateway(); result = None
|
|
for action in actions:
|
|
result = g.admit() if action == "admit" else (g.revoke() or result)
|
|
assert result == (actions[0] == "admit")
|
|
|
|
# Terminal outcomes burn the request; transient outcomes release only request-id,
|
|
# while every auth event remains burned and every admitted attempt charges quota.
|
|
for outcome in ("terminal", "transient"):
|
|
checked += 1
|
|
g = Gateway(); assert g.admit()
|
|
g.finish("request-1", outcome)
|
|
assert not g.admit(auth_id="auth-1", request_id="request-2")
|
|
retry = g.admit(auth_id="auth-2", request_id="request-1")
|
|
assert retry == (outcome == "transient")
|
|
assert g.quota == (2 if retry else 1)
|
|
|
|
# Rotation invalidates old grants; a current grant remains relay-confined.
|
|
g = Gateway(); g.rotate(); checked += 1
|
|
assert not g.admit(epoch=1)
|
|
assert g.admit(epoch=2)
|
|
return checked
|
|
|
|
if __name__ == "__main__":
|
|
n = explore()
|
|
print(f"stateful delivery combinations/interleavings checked: {n}")
|
|
print("stateful gateway invariants: HOLD")
|