atlas-iac/testing/tests/test_hermes_hux_contract_foundation.py
jenkins 124206b748 hermes(hux): contract 1.1.0 additive revision and Wave A consolidation
Adds receipt evidence kind, 422 unprocessable, optional revision on research
records, audit_stale on the privacy policy, per-route body caps (25 MiB
artifact uploads), promotion checks the project exists, memory rules skip
content-free statuses. Handoff ledger covers every Wave A card.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNPhwu2bsaRNg3DETSAZoM
2026-08-24 00:27:38 -03:00

366 lines
16 KiB
Python

"""HUX-11 foundation: identity, flags, tenant store, audit and the HTTP pipeline.
Security obligations exercised here: identity comes only from trusted headers
(relay/worker keys compared in constant time), every request lands in a
tenant-scoped directory, disabled cards are indistinguishable from unknown
routes, every read and denial leaves an audit outcome, and revisions guard
concurrent writers.
"""
from __future__ import annotations
import json
import sys
import threading
from http.client import HTTPConnection
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[2]
FOUNDATION = ROOT / "dockerfiles" / "hermes-hux-foundation"
if str(FOUNDATION) not in sys.path:
sys.path.insert(0, str(FOUNDATION))
from hux import audit, contracts, errors, flags, identity, store # noqa: E402
from hux.http import Router, Response, page, serve # noqa: E402
from hux.server import build_router # noqa: E402
SCHEMAS = contracts.load_all()
HEADERS = {"X-Hermes-Tenant-Identity": "slot-3", "X-Hux-Subject": "usr_0123456789abcdef", "X-Hux-Surface": "chat"}
ALL_ON = ",".join(card["flag"] for card in contracts.load_flags()["cards"])
def ident(**overrides) -> identity.Identity:
base = {"tenant_slot": "slot-3", "subject": "usr_0123456789abcdef", "surface": "chat", "trust": "router"}
return identity.Identity(**{**base, **overrides})
# --- identity -------------------------------------------------------------------
def test_identity_from_router_headers():
who = identity.resolve(HEADERS, {})
assert who == ident()
assert contracts.validate("common.schema.json", who.record(), SCHEMAS, "/$defs/identity") == []
@pytest.mark.parametrize("bad", [
{"X-Hermes-Tenant-Identity": ""}, {"X-Hermes-Tenant-Identity": "slot-x"}, {"X-Hux-Subject": "brad@bstein.dev"},
{"X-Hux-Subject": ""}, {"X-Hux-Surface": "admin"}, {"X-Hux-Trust": "god"}, {"X-Hux-Surface": "worker"},
])
def test_identity_rejects_bad_headers(bad):
with pytest.raises(errors.Unauthorized):
identity.resolve({**HEADERS, **bad}, {})
def test_relay_and_worker_need_their_keys():
relay = {**HEADERS, "X-Hux-Trust": "relay", "X-Hux-Surface": "telegram"}
with pytest.raises(errors.Unauthorized):
identity.resolve(relay, {})
with pytest.raises(errors.Unauthorized):
identity.resolve({**relay, "X-Hux-Relay-Key": "nope"}, {"HUX_RELAY_KEY": "secret"})
assert identity.resolve({**relay, "X-Hux-Relay-Key": "secret"}, {"HUX_RELAY_KEY": "secret"}).trust == "relay"
worker = {**HEADERS, "X-Hux-Trust": "worker", "X-Hux-Surface": "worker", "X-Hux-Relay-Key": "wk"}
assert identity.resolve(worker, {"HUX_WORKER_KEY": "wk"}).surface == "worker"
assert identity.resolve(HEADERS).trust == "router"
def test_slot_must_match_the_pod_it_reaches():
with pytest.raises(errors.Unauthorized):
identity.resolve(HEADERS, {"HUX_TENANT_SLOT": "slot-4"})
assert identity.resolve(HEADERS, {"HUX_TENANT_SLOT": "slot-3"}).tenant_slot == "slot-3"
def test_server_refuses_non_loopback_bind():
from hux import server
assert server.bind_address({}) == "127.0.0.1"
with pytest.raises(SystemExit):
server.bind_address({"HUX_BIND": "0.0.0.0"})
# --- flags ---------------------------------------------------------------------
def test_flags_fail_closed_and_capabilities_validate():
off = flags.Flags({})
assert not off.enabled("HUX-11")
with pytest.raises(errors.FlagOff):
off.require("HUX-01")
partial = flags.Flags({"HUX_FLAGS": "hux.activity_timeline"})
assert not partial.enabled("HUX-01")
on = flags.Flags({"HUX_FLAGS": ALL_ON})
record = on.capabilities(ident(), {"commit": "d3cbeb06" * 5, "image_digest": "sha256:" + "4a" * 32, "junk": "x"})
assert contracts.validate_record(record, SCHEMAS) == []
assert all(card["enabled"] for card in record["cards"])
assert {card["card"] for card in record["cards"]} == {f"HUX-{n:02d}" for n in range(1, 13)}
assert not on.enabled("HUX-99")
assert flags.build_from_environ({"HUX_BUILD_COMMIT": "abc"}) == {"commit": "abc", "image_digest": ""}
assert "commit" in flags.build_from_environ()
def test_every_declared_route_belongs_to_exactly_one_card():
seen: dict[str, str] = {}
for card, routes in flags.CARD_ROUTES.items():
for route in routes:
assert route.startswith("/hux/v1/")
assert route not in seen, f"{route} owned by {seen[route]} and {card}"
seen[route] = card
# --- store ---------------------------------------------------------------------
def test_store_paths_are_tenant_scoped_and_ids_validated(tmp_path):
a = store.TenantStore(tmp_path, ident())
b = store.TenantStore(tmp_path, ident(subject="usr_fedcba9876543210"))
assert a.root != b.root and a.root.parent == b.root.parent
a.put("things", {"id": "thg_0001", "v": 1})
assert not b.exists("things", "thg_0001")
with pytest.raises(errors.Invalid):
a.get("things", "../../etc/passwd")
with pytest.raises(errors.Invalid):
a.put("things", {"id": "no-prefix"})
with pytest.raises(errors.Invalid):
a.append("ledger", "../x", {})
with pytest.raises(errors.NotFound):
a.get("things", "thg_9999")
assert store.ID_RE.match(store.new_id("evt"))
assert store.now_iso().endswith("Z")
def test_store_revisions_and_conflicts(tmp_path):
s = store.TenantStore(tmp_path, ident())
first = s.put("docs", {"id": "doc_0001", "n": 1})
assert first["revision"] == 1
second = s.put("docs", {"id": "doc_0001", "n": 2}, expected_revision=1)
assert second["revision"] == 2
with pytest.raises(errors.Conflict):
s.put("docs", {"id": "doc_0001", "n": 3}, expected_revision=1)
with pytest.raises(errors.Conflict):
s.put("docs", {"id": "doc_0002", "n": 1}, expected_revision=4)
assert s.put("docs", {"id": "doc_0003"}, expected_revision=0)["revision"] == 1
assert s.count("docs") == 2
assert [d["id"] for d in s.scan("docs")] == ["doc_0001", "doc_0003"]
assert list(s.scan("nothing")) == []
s.delete("docs", "doc_0003")
s.delete("docs", "doc_0003")
assert s.count("docs") == 1
def test_store_bounds(tmp_path, monkeypatch):
s = store.TenantStore(tmp_path, ident())
with pytest.raises(errors.TooLarge):
s.put("docs", {"id": "doc_0001", "blob": "x" * store.MAX_RECORD_BYTES})
with pytest.raises(errors.TooLarge):
s.append("ledger", "big", {"blob": "x" * store.MAX_RECORD_BYTES})
monkeypatch.setattr(store, "MAX_FAMILY_RECORDS", 1)
s.put("docs", {"id": "doc_0001"})
with pytest.raises(errors.TooLarge):
s.put("docs", {"id": "doc_0002"})
s.put("docs", {"id": "doc_0001", "again": True})
def test_store_ledgers_survive_torn_writes(tmp_path):
s = store.TenantStore(tmp_path, ident())
s.append("ledger", "conv_1", {"seq": 1})
s.append("ledger", "conv_1", {"seq": 2})
path = s.root / "ledger" / "conv_1.jsonl"
with open(path, "ab") as handle:
handle.write(b'{"seq": 3, "tru')
assert [r["seq"] for r in s.read("ledger", "conv_1")] == [1, 2]
assert s.read("ledger", "missing") == []
assert s.ledgers("ledger") == ["conv_1"] and s.ledgers("none") == []
s.rewrite("ledger", "conv_1", [{"seq": 9}])
assert s.read("ledger", "conv_1") == [{"seq": 9}]
def test_store_blobs_and_manifest(tmp_path):
s = store.TenantStore(tmp_path, ident())
digest = "ab" * 32
s.put_blob(digest, b"hello")
s.put_blob(digest, b"ignored")
assert s.get_blob(digest) == b"hello"
with pytest.raises(errors.NotFound):
s.get_blob("cd" * 32)
with pytest.raises(errors.Invalid):
s.put_blob("../x", b"")
with pytest.raises(errors.Invalid):
s.get_blob("zz")
manifest = s.manifest("1.0.0")
assert contracts.validate_record(manifest, SCHEMAS) == []
assert s.manifest("1.9.0") == manifest
def test_store_locks_serialise_concurrent_writers(tmp_path):
s = store.TenantStore(tmp_path, ident())
s.put("docs", {"id": "doc_0001", "n": 0})
def bump() -> None:
for _ in range(20):
with s.lock("docs"):
current = s.get("docs", "doc_0001")
s.put("docs", {**current, "n": current["n"] + 1}, expected_revision=current["revision"])
workers = [threading.Thread(target=bump) for _ in range(4)]
for worker in workers:
worker.start()
for worker in workers:
worker.join()
assert s.get("docs", "doc_0001")["n"] == 80
# --- audit ---------------------------------------------------------------------
def test_audit_rows_validate_and_never_carry_bodies(tmp_path):
s = store.TenantStore(tmp_path, ident())
row = audit.record(s, ident(), "memory.read", "mem_0001", "deny", "not owner")
assert contracts.validate("common.schema.json", row, SCHEMAS, "/$defs/audit_outcome") == []
with pytest.raises(ValueError):
audit.record(s, ident(), "x.y", "r", "maybe")
for _ in range(5):
audit.record(s, ident(), "memory.read", "mem_0002", "allow")
assert len(audit.recent(s, limit=3)) == 3
assert audit.recent(s)[0]["outcome"] == "deny"
# --- http pipeline ---------------------------------------------------------------
def _router(tmp_path, flags_value=ALL_ON, environ=None) -> Router:
env = {"HUX_FLAGS": flags_value, **(environ or {})}
return build_router(tmp_path, env)
def _call(router, method, path, headers=HEADERS, body=b"") -> tuple[int, dict]:
response = router.dispatch(method, path, headers, body)
return response.status, response.body
def test_capabilities_and_manifest_roundtrip(tmp_path):
router = _router(tmp_path, environ={"HUX_BUILD_COMMIT": "d3cbeb06" * 5})
status, body = _call(router, "GET", "/hux/v1/capabilities")
assert status == 200 and contracts.validate_record(body, SCHEMAS) == []
assert body["server"] == {"commit": "d3cbeb06" * 5}
status, body = _call(router, "GET", "/hux/v1/manifest")
assert status == 200 and body["schema"] == "hux.manifest.v1"
rows = audit.recent(store.TenantStore(tmp_path, ident()))
assert [r["action"] for r in rows] == ["foundation.capabilities", "foundation.manifest"]
def test_flag_off_and_unknown_route_look_the_same(tmp_path):
off = _router(tmp_path, flags_value="")
status, body = _call(off, "GET", "/hux/v1/capabilities")
assert (status, body["code"]) == (404, "flag_off")
status, body = _call(off, "GET", "/hux/v1/nothing")
assert (status, body["code"]) == (404, "not_found")
assert contracts.validate_record(body, SCHEMAS) == []
status, body = _call(off, "POST", "/hux/v1/capabilities")
assert status == 405
outcomes = [r["outcome"] for r in audit.recent(store.TenantStore(tmp_path, ident()))]
assert outcomes == ["flag_off", "not_found", "not_found"]
def test_unauthorized_requests_never_touch_storage(tmp_path):
router = _router(tmp_path)
status, body = _call(router, "GET", "/hux/v1/capabilities", headers={})
assert (status, body["code"]) == (401, "unauthorized")
assert not (tmp_path / "hux").exists()
def test_body_decoding_and_request_helpers(tmp_path):
router = _router(tmp_path)
captured = {}
def echo(request):
captured.update(body=request.body, if_match=request.if_match(), key=request.idempotency_key(), q=request.query)
return page([request.body], None)
router.add("POST", "/hux/v1/echo/{id}", "HUX-11", "test.echo", echo)
status, body = _call(router, "POST", "/hux/v1/echo/abc?x=1&x=2", {**HEADERS, "If-Match": "3", "Idempotency-Key": "run:1234567"}, b'{"a": 1}')
assert status == 200 and body == {"items": [{"a": 1}], "next": None}
assert captured == {"body": {"a": 1}, "if_match": 3, "key": "run:1234567", "q": {"x": "2"}}
assert _call(router, "POST", "/hux/v1/echo/abc", HEADERS, b"{oops")[1]["code"] == "invalid"
assert _call(router, "POST", "/hux/v1/echo/abc", HEADERS, b"x" * (1024 * 1024 + 1))[1]["code"] == "too_large"
assert _call(router, "POST", "/hux/v1/echo/abc", {**HEADERS, "If-Match": "abc"})[1]["code"] == "invalid"
assert _call(router, "POST", "/hux/v1/echo/abc", {**HEADERS, "Idempotency-Key": "!"})[1]["code"] == "invalid"
_, body = _call(router, "POST", "/hux/v1/echo/abc", HEADERS)
assert body["items"] == [None]
def test_handler_errors_are_audited_with_outcome(tmp_path):
router = _router(tmp_path)
def conflict(request):
raise errors.Conflict("stale")
def denied(request):
raise errors.Forbidden("not yours")
router.add("GET", "/hux/v1/c", "HUX-11", "test.conflict", conflict)
router.add("GET", "/hux/v1/d", "HUX-11", "test.denied", denied)
assert _call(router, "GET", "/hux/v1/c")[0] == 409
assert _call(router, "GET", "/hux/v1/d")[0] == 403
outcomes = [(r["action"], r["outcome"]) for r in audit.recent(store.TenantStore(tmp_path, ident()))]
assert outcomes == [("test.conflict", "conflict"), ("test.denied", "deny")]
def test_real_server_serves_json_and_sse(tmp_path):
router = _router(tmp_path)
def stream(request):
return Response(200, stream=lambda: (b"id: 1\ndata: {}\n\n", b"id: 2\ndata: {}\n\n"))
router.add("GET", "/hux/v1/s", "HUX-11", "test.stream", stream)
server = serve(router, "127.0.0.1", 0)
thread = threading.Thread(target=server.serve_forever, daemon=True)
thread.start()
try:
conn = HTTPConnection("127.0.0.1", server.server_address[1], timeout=5)
conn.request("GET", "/healthz")
assert json.loads(conn.getresponse().read())["status"] == "ok"
conn.request("GET", "/hux/v1/capabilities", headers=HEADERS)
reply = conn.getresponse()
assert reply.status == 200 and json.loads(reply.read())["schema"] == "hux.capabilities.v1"
conn.request("POST", "/hux/v1/capabilities", body=b"{}", headers={**HEADERS, "Content-Length": "2"})
assert conn.getresponse().status == 405
conn.request("GET", "/hux/v1/s", headers=HEADERS)
reply = conn.getresponse()
assert reply.getheader("Content-Type") == "text/event-stream"
assert reply.read() == b"id: 1\ndata: {}\n\nid: 2\ndata: {}\n\n"
finally:
server.shutdown()
server.server_close()
def test_all_errors_serialise_to_contract():
for cls in (errors.Unauthorized, errors.Forbidden, errors.NotFound, errors.FlagOff, errors.Conflict, errors.Invalid, errors.TooLarge, errors.ApprovalRequired, errors.BudgetExhausted):
record = cls("m" * 300, ["d" * 300] * 40).record()
assert contracts.validate_record(record, SCHEMAS) == [], cls
def test_foundation_sources_stay_under_500_lines():
for path in sorted(FOUNDATION.rglob("*.py")):
assert len(path.read_text().splitlines()) <= 500, path
def test_per_route_body_cap(tmp_path):
router = _router(tmp_path)
router.add("POST", "/hux/v1/big", "HUX-11", "test.big", lambda request: page([len(json.dumps(request.body))]), max_body=4 * 1024 * 1024)
payload = json.dumps({"blob": "x" * (2 * 1024 * 1024)}).encode()
assert _call(router, "POST", "/hux/v1/big", HEADERS, payload)[0] == 200
assert _call(router, "POST", "/hux/v1/echo", HEADERS, payload)[0] == 404
router.add("POST", "/hux/v1/small", "HUX-11", "test.small", lambda request: page([]))
assert _call(router, "POST", "/hux/v1/small", HEADERS, payload)[1]["code"] == "too_large"
def test_server_main_wires_environment(tmp_path, monkeypatch):
from hux import server
seen = {}
class Fake:
def serve_forever(self):
seen["served"] = True
monkeypatch.setattr(server, "serve", lambda router, host, port: seen.update(root=router.data_root, host=host, port=port) or Fake())
monkeypatch.setenv("HUX_DATA_ROOT", str(tmp_path))
monkeypatch.setenv("HUX_PORT", "8791")
server.main()
assert seen == {"root": tmp_path, "host": "127.0.0.1", "port": 8791, "served": True}