distinct / tests /test_claim_flow.py
User1342's picture
Pentest fixes: pin the runtime source host, evict rather than refuse; say on the page that llama.cpp is fetched
eab2534
Raw History Blame Contribute Delete
7.03 kB
"""Registering without an account must create something that can do nothing.
Pairing runs the other way round now: a worker invents a code, prints it, and
registers here, and somebody signed in enters that code to claim it. That makes
``register_unclaimed`` the only entry point on this server that needs no
account, so every test below is about the same question -- what can a caller do
with a record nobody has claimed? The answer has to be "nothing".
"""
from __future__ import annotations
import pytest
from distinct_server.control_plane import UNASSIGNED_AGENT, ControlPlane
from distinct_server.models import (
AgentCapabilities,
AuthenticationError,
CapacityError,
ConflictError,
)
from distinct_server.security import new_access_code, new_pairing_code
def _caps(name: str = "worker") -> AgentCapabilities:
return AgentCapabilities(
agent_id="",
name=name,
os="linux",
arch="x64",
cpu="test",
ram_gb=8.0,
models=("m1",),
tools=(),
energy_provider="test meter",
)
@pytest.fixture()
def plane() -> ControlPlane:
return ControlPlane()
def test_an_unclaimed_worker_is_invisible_to_everyone(plane: ControlPlane) -> None:
plane.register_unclaimed(_caps(), new_pairing_code())
assert plane.list_agents() == ()
assert plane.list_agents(viewer_id="user:alice") == ()
assert plane.list_agents(viewer_id="user:mallory") == ()
def test_an_unclaimed_workers_access_code_grants_nothing(plane: ControlPlane) -> None:
"""Otherwise a stranger takes a share of a machine still being set up."""
access = new_access_code()
plane.register_unclaimed(_caps(), new_pairing_code(), access_code=access)
with pytest.raises(AuthenticationError):
plane.redeem_access_code(access, "user:mallory")
def test_claiming_requires_an_account(plane: ControlPlane) -> None:
code = new_pairing_code()
plane.register_unclaimed(_caps(), code)
with pytest.raises(AuthenticationError):
plane.claim_agent(code, "")
with pytest.raises(AuthenticationError):
plane.claim_agent(code, " ")
def test_a_wrong_code_says_nothing_about_why(plane: ControlPlane) -> None:
plane.register_unclaimed(_caps(), new_pairing_code())
with pytest.raises(AuthenticationError) as caught:
plane.claim_agent(new_pairing_code(), "user:alice")
assert str(caught.value) == "that code is not valid"
def test_claiming_makes_the_worker_real(plane: ControlPlane) -> None:
code = new_pairing_code()
access = new_access_code()
credential = plane.register_unclaimed(_caps(), code, access_code=access)
assert plane.claim_state(credential.agent_id) == "waiting"
assert plane.claim_agent(code, "user:alice") == credential.agent_id
assert plane.claim_state(credential.agent_id) == "claimed"
assert len(plane.list_agents()) == 1
# and only now does its access code mean anything
assert plane.redeem_access_code(access, "user:bob") == credential.agent_id
def test_a_claim_code_is_used_once(plane: ControlPlane) -> None:
code = new_pairing_code()
plane.register_unclaimed(_caps(), code)
plane.claim_agent(code, "user:alice")
with pytest.raises(AuthenticationError):
plane.claim_agent(code, "user:bob")
def test_two_workers_cannot_wait_on_one_code(plane: ControlPlane) -> None:
"""An ambiguous claim is worse than a refused registration."""
code = new_pairing_code()
plane.register_unclaimed(_caps("first"), code)
with pytest.raises(ConflictError):
plane.register_unclaimed(_caps("second"), code)
def test_an_unclaimed_worker_expires(plane: ControlPlane) -> None:
code = new_pairing_code()
credential = plane.register_unclaimed(_caps(), code, now=1000.0)
later = 1000.0 + plane.limits.claim_ttl_seconds + 1
assert plane.claim_state(credential.agent_id, now=later) == "gone"
with pytest.raises(AuthenticationError):
plane.claim_agent(code, "user:alice", now=later)
def test_the_unclaimed_pool_is_bounded(plane: ControlPlane) -> None:
"""The one unauthenticated write on this server cannot be accumulated."""
for _ in range(plane.limits.max_unclaimed_agents * 3):
plane.register_unclaimed(_caps(), new_pairing_code())
waiting = sum(1 for r in plane._agents.values() if r.claim_digest)
assert waiting <= plane.limits.max_unclaimed_agents
def test_a_flood_never_locks_a_real_volunteer_out(plane: ControlPlane) -> None:
"""A full pool evicts its oldest waiter rather than refusing everybody.
Refusing is what an attacker filling the pool is trying to buy: the feature
turned off for real users. The oldest waiter loses its slot instead, and a
flood mostly evicts its own earlier entries.
"""
for index in range(plane.limits.max_unclaimed_agents):
plane.register_unclaimed(_caps(f"flood{index}"), new_pairing_code(), now=1000.0 + index)
mine = new_pairing_code()
credential = plane.register_unclaimed(_caps("volunteer"), mine, now=2000.0)
assert plane.claim_state(credential.agent_id, now=2000.0) == "waiting"
assert plane.claim_agent(mine, "user:alice", now=2000.0) == credential.agent_id
def test_the_registry_itself_still_has_a_hard_ceiling(plane: ControlPlane) -> None:
"""Eviction bounds the unclaimed pool; claimed agents are still capped."""
codes = [new_pairing_code() for _ in range(plane.limits.max_unclaimed_agents)]
for index, code in enumerate(codes):
plane.register_unclaimed(_caps(f"w{index}"), code)
for index, code in enumerate(codes):
plane.claim_agent(code, f"user:{index}")
made = len(codes)
with pytest.raises(CapacityError):
while made < plane.limits.max_agents + 10:
code = new_pairing_code()
plane.register_unclaimed(_caps(), code)
plane.claim_agent(code, "user:alice")
made += 1
assert made == plane.limits.max_agents
def test_expiry_frees_the_ceiling(plane: ControlPlane) -> None:
for _ in range(plane.limits.max_unclaimed_agents):
plane.register_unclaimed(_caps(), new_pairing_code(), now=1000.0)
later = 1000.0 + plane.limits.claim_ttl_seconds + 1
plane.register_unclaimed(_caps(), new_pairing_code(), now=later)
def test_no_job_can_be_sent_to_an_unclaimed_worker(plane: ControlPlane) -> None:
"""The visibility gate is what dispatch consults, so this is the proof."""
credential = plane.register_unclaimed(_caps(), new_pairing_code())
session = plane.create_session()
conversation = plane.create_conversation(session.session_id)
job = plane.submit_job(
session.session_id,
conversation.conversation_id,
"hello",
"m1",
viewer_id="user:alice",
)
# Nothing to run it, so it is stranded rather than handed to the worker
# that is sitting right there unclaimed.
assert job.spec.target_agent_id != credential.agent_id
assert job.spec.target_agent_id == UNASSIGNED_AGENT