coulomb-social/tests/test_selected_mailbox_check.py
tegwick a769024c94
Some checks failed
Use-case regression gate / usecase-regressions (push) Failing after 8m30s
Verify platform sender and selected mail operations
Preserve the four unpublished T02 checkpoints with identical implementation and test contents. Represent Kubernetes resource UIDs as explicit kind/resource_uid metadata so they are not mistaken for credential values. Standard staged-blob scanner clean; full repository gate 764 passed. T02 remains open for received authentication and native return acceptance.

Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a198ed-70cc-7362-a569-d5dbef39b86a
2026-11-02 00:55:04 +01:00

383 lines
14 KiB
Python

"""Selected read-only IMAP and temporary-policy lifecycle, with no network."""
import copy
import hashlib
import importlib
import json
import os
import sqlite3
import subprocess
import sys
from pathlib import Path
import pytest
SCRIPTS = Path(__file__).resolve().parents[1] / "scripts"
sys.path.insert(0, str(SCRIPTS))
check = importlib.import_module("selected_mailbox_check")
probe = importlib.import_module("platform_mail_probe")
REFERENCE = "<fixture-message@example.test>"
RAW = (
"From: operator@example.test\r\nTo: platform@example.test\r\n"
"In-Reply-To: " + REFERENCE + "\r\n\r\nSelected fixture reply.\r\n"
).encode()
class Mailbox:
def __init__(self, *args, **kwargs):
assert args == ("imap.example.test", 993)
assert kwargs["ssl_context"].check_hostname
self.calls = []
self.count = b"1"
self.raw = RAW
def login(self, username, password):
assert (username, password) == ("platform@example.test", "fixture-password")
self.calls.append("login")
return "OK", []
def select(self, name, *, readonly):
assert name == "INBOX" and readonly is True
self.calls.append("readonly")
return "OK", []
def uid(self, action, *args):
self.calls.append((action, args))
if action == "search":
assert args == (None, "TEXT", '"' + REFERENCE + '"')
return "OK", [self.count]
assert action == "fetch" and args[0] == b"1"
if args[1] == "(RFC822.SIZE)":
return "OK", [b"1 (UID 1 RFC822.SIZE " + str(len(self.raw)).encode() + b")"]
assert args[1] == "(BODY.PEEK[])"
return "OK", [(b"1 (BODY[])", self.raw), b")"]
def logout(self):
self.calls.append("logout")
@pytest.fixture
def mailbox(monkeypatch):
monkeypatch.setattr(check, "HOST", "imap.example.test")
return Mailbox("imap.example.test", 993, ssl_context=__import__("ssl").create_default_context())
def retrieve(mailbox):
return check.retrieve(
REFERENCE,
"person@example.test",
"platform@example.test",
"fixture-password",
client=lambda *a, **k: mailbox,
)
def test_only_exact_reference_readonly_and_peek_are_used(mailbox):
result = retrieve(mailbox)
assert len(result) == 1 and result[0]["kind"] == "reply"
assert mailbox.calls[0:2] == ["login", "readonly"]
assert mailbox.calls[-1] == "logout"
def test_unrelated_matching_text_is_not_retained(mailbox):
mailbox.raw = b"From: fixture@example.test\r\n\r\nMention " + REFERENCE.encode()
assert retrieve(mailbox) == []
def test_more_than_five_matches_refuses_before_fetch_and_logs_out(mailbox):
mailbox.count = b"1 2 3 4 5 6"
with pytest.raises(check.operation.Refused):
retrieve(mailbox)
assert not any(isinstance(c, tuple) and c[0] == "fetch" for c in mailbox.calls)
assert mailbox.calls[-1] == "logout"
def test_oversized_message_refuses_before_body_fetch(mailbox, monkeypatch):
monkeypatch.setattr(check, "MAX_BYTES", 10)
with pytest.raises(check.operation.Refused):
retrieve(mailbox)
assert not any(isinstance(c, tuple) and "(BODY.PEEK[])" in c[1] for c in mailbox.calls)
def test_imap_search_injection_refused_before_connect():
with pytest.raises(check.operation.Refused):
check.retrieve(
'<bad" ALL>',
"fixture@example.test",
"fixture",
"fixture",
client=lambda *a, **k: pytest.fail("connected"),
)
@pytest.mark.parametrize("addresses", [[], ["127.0.0.1"], ["10.1.2.3"], ["::1"]])
def test_egress_rejects_private_and_non_ipv4_destinations(addresses):
with pytest.raises(check.operation.Refused):
check.policy_for("fixture", addresses)
class Cluster:
def __init__(self, monkeypatch):
self.context = {
"cluster_uid": "cluster",
"namespace_uid": "namespace",
"deployment_uid": "deployment",
"image": "fixture@sha256:abc",
"pod_name": "fixture",
"generation": 79,
}
monkeypatch.setattr(check.native, "identity", lambda command: self.context)
self.obj = None
self.calls = []
self.fail_exec = False
self.fail_cleanup = False
def __call__(self, args, payload=None):
self.calls.append(args)
if args[0] == "get":
return {"items": [self.obj] if self.obj else []}
if args[0] == "create":
self.obj = json.loads(payload)
self.obj["metadata"]["uid"] = "owned-policy-uid"
return copy.deepcopy(self.obj)
if args[0] == "delete":
assert json.loads(payload)["preconditions"] == {"uid": "owned-policy-uid"}
if self.fail_cleanup:
raise OSError("modeled deletion failure")
self.obj = None
return {"status": "Success"}
assert args[0] == "exec"
if self.fail_exec:
raise OSError("modeled IMAP failure")
return {"messages": []}
def request(self, action="fetch"):
return {
"action": action,
"packet": {
"context": copy.deepcopy(self.context),
"reference": REFERENCE,
"binding": {"caller_policy_sha256": "fixture-policy"},
"policy": check.policy_for("email-connect-selected-0123456789abcdef", ["1.1.1.1"]),
},
"sources": {n: (SCRIPTS / n).read_text() for n in check.FILES},
}
def test_native_attempt_cleans_only_its_owned_policy(monkeypatch):
cluster = Cluster(monkeypatch)
result = check.run_node(cluster.request(), cluster)
assert result["temporary_policy_absent"] and cluster.obj is None
assert [c[0] for c in cluster.calls] == ["get", "create", "exec", "get", "delete", "get"]
def test_imap_failure_still_removes_temporary_egress(monkeypatch):
cluster = Cluster(monkeypatch)
cluster.fail_exec = True
with pytest.raises(OSError):
check.run_node(cluster.request(), cluster)
assert cluster.obj is None
def test_lost_cleanup_refuses_then_explicit_cleanup_removes_same_uid(monkeypatch):
cluster = Cluster(monkeypatch)
cluster.fail_cleanup = True
with pytest.raises(OSError):
check.run_node(cluster.request(), cluster)
assert cluster.obj is not None
cluster.fail_cleanup = False
assert check.run_node(cluster.request("cleanup"), cluster)["temporary_policy_absent"]
assert cluster.obj is None
def test_changed_receiver_or_prior_policy_refuses_without_mailbox_access(monkeypatch):
cluster = Cluster(monkeypatch)
request = cluster.request()
request["packet"]["context"]["generation"] = 78
with pytest.raises(check.operation.Refused):
check.run_node(request, cluster)
assert cluster.calls == []
cluster.obj = copy.deepcopy(cluster.request()["packet"]["policy"])
with pytest.raises(check.operation.Refused):
check.run_node(cluster.request(), cluster)
assert all(c[0] == "get" for c in cluster.calls)
@pytest.fixture
def probe_packet(monkeypatch, tmp_path):
monkeypatch.setattr(probe, "ENDPOINT", "https://users.example.test/api/v1/public/registrations")
monkeypatch.setattr(
probe,
"TESTS",
{"fixture-one": "person@example.test", "fixture-two": "fixture@example.invalid"},
)
tmp_path.chmod(0o700)
return probe.prepare(), tmp_path / "probe.json"
def test_probe_exact_bodies_idempotency_and_no_replay(probe_packet):
packet, path = probe_packet
calls = []
class Response:
status = 202
def __enter__(self):
return self
def __exit__(self, *args):
pass
def read(self, size):
return b'{"status":"verification_requested"}'
def open_request(request, **kwargs):
calls.append(request)
return Response()
result = probe.send(packet, path, probe.operation.digest(packet), opener=open_request)
assert len(calls) == 2 and not result["identity_provisioned"]
assert len({c.headers["Idempotency-key"] for c in calls}) == 2
with pytest.raises(FileExistsError):
probe.send(packet, path, probe.operation.digest(packet), opener=open_request)
assert len(calls) == 2
def test_uncertain_probe_stops_before_second_and_keeps_intent(probe_packet):
packet, path = probe_packet
calls = []
def failure(*args, **kwargs):
calls.append(1)
raise TimeoutError("modeled lost response")
result = probe.send(packet, path, probe.operation.digest(packet), opener=failure)
assert len(calls) == 1 and path.with_suffix(".intent.json").exists()
assert result["requests"][0]["status"] == "unconfirmed_inspect_before_retry"
def test_actual_pod_program_loads_capsule_and_binds_accepted_sqlite_send(tmp_path):
package = tmp_path / "email_connect"
package.mkdir()
(package / "__init__.py").write_text("")
hashes = {}
for name in ("transactional", "callers"):
source = b"# Fixture installed module.\n"
(package / (name + ".py")).write_bytes(source)
hashes[name] = hashlib.sha256(source).hexdigest()
database = tmp_path / "fixture.db"
policy_path = tmp_path / "callers.json"
document = {
"schema_version": 1,
"callers": [
{
"caller_id": "user-engine",
"bindings": [["tenant:coulomb", "coulomb-social"]],
"adopt_legacy_verifications": True,
}
],
}
policy_path.write_text(json.dumps(document))
with sqlite3.connect(database) as db:
db.executescript(
"CREATE TABLE verifications(request_id,username,email,caller_id,tenant,client_id);"
"CREATE TABLE verification_attempts(request_id,provider_ref,state);"
)
db.execute(
"INSERT INTO verifications VALUES(?,?,?,?,?,?)",
(
"request",
"fixture-user",
"person@example.test",
"user-engine",
"tenant:coulomb",
"coulomb-social",
),
)
db.execute(
"INSERT INTO verification_attempts VALUES(?,?,?)", ("request", REFERENCE, "accepted")
)
sources = {name: (SCRIPTS / name).read_text() for name in check.FILES}
sources["selected_mailbox_check.py"] = sources["selected_mailbox_check.py"].replace(
'HOST = "imap.ionos.de"', 'HOST = "imap.example.test"'
)
request = {
"action": "fetch",
"reference": REFERENCE,
"sources": sources,
"tests": {"fixture-user": "person@example.test"},
**hashes,
}
# Substitute only fixture identity/path/installed-package and IMAP transport.
# The SQL binding, reviewed capsule loader and retrieval implementation run.
program = check.POD.replace("os.getuid()==10001", "os.getuid()==" + str(os.getuid()))
program = program.replace("/data/email-connect.db", str(database)).replace(
"platform@coulomb.social", "platform@example.test"
)
program = program.replace("/etc/email-connect-callers/callers.json", str(policy_path))
prefix = "import sys,types\nsys.path.insert(0," + repr(str(tmp_path)) + ")\n"
prefix += (
"def no_network(event,args):\n"
" if event in {'socket.connect','socket.getaddrinfo','socket.bind'}:\n"
" raise RuntimeError('fixture network forbidden')\n"
"sys.addaudithook(no_network)\n"
)
prefix += "class Fake:\n"
prefix += " def __init__(self,host,port,**kw):assert (host,port)==('imap.example.test',993)\n"
prefix += (
" def login(self,user,password):\n"
" assert (user,password)==('platform@example.test','fixture-password')\n"
" return 'OK',[]\n"
)
prefix += (
" def select(self,box,readonly=False):\n"
" assert box=='INBOX' and readonly\n"
" return 'OK',[]\n"
)
prefix += " def uid(self,action,*args):\n"
prefix += " if action=='search':return 'OK',[b'1']\n"
prefix += (
" if args[1]=='(RFC822.SIZE)':return 'OK',[b'1 (RFC822.SIZE " + str(len(RAW)) + ")']\n"
)
prefix += (
" assert args[1]=='(BODY.PEEK[])'\n return 'OK',[(b'BODY[]'," + repr(RAW) + "),b')']\n"
)
prefix += " def logout(self):pass\n"
prefix += "imap=types.ModuleType('imaplib');imap.IMAP4_SSL=Fake;sys.modules['imaplib']=imap\n"
environment = {
**os.environ,
"EMAIL_CONNECT_DATABASE_PATH": str(database),
"EMAIL_CONNECT_SMTP_USERNAME": "platform@example.test",
"EMAIL_CONNECT_SENDER": "platform@example.test",
"EMAIL_CONNECT_SMTP_PASSWORD": "fixture-password",
"EMAIL_CONNECT_CALLERS_FILE": str(policy_path),
}
def execute():
return subprocess.run(
[sys.executable, "-I", "-c", prefix + program],
input=json.dumps(request).encode(),
capture_output=True,
timeout=20,
check=False,
env=environment,
)
result = execute()
assert result.returncode == 0, result.stderr.decode()
assert json.loads(result.stdout)["messages"][0]["kind"] == "reply"
with sqlite3.connect(database) as db:
db.execute("UPDATE verifications SET caller_id=''")
assert execute().returncode == 0 # Explicit policy adoption is required.
document["callers"][0]["adopt_legacy_verifications"] = False
policy_path.write_text(json.dumps(document))
assert execute().returncode != 0
document["callers"][0]["adopt_legacy_verifications"] = True
policy_path.write_text(json.dumps(document))
request["policy_sha256"] = "changed-policy"
assert execute().returncode != 0
request.pop("policy_sha256")
with sqlite3.connect(database) as db:
db.execute("UPDATE verification_attempts SET state='in_flight'")
assert execute().returncode != 0