| """Channels API (CHANNELS_DESIGN.md): creation + announcement, channel posts |
| with auto-subscribe and mention fan-out, subscribe/unsubscribe idempotency and |
| spoof resistance, the cross-channel feed, and the digest block.""" |
| from __future__ import annotations |
|
|
| from fakes import seed_agent |
|
|
|
|
| AUTH = {"authorization": "Bearer user-oauth-token"} |
| |
| |
| CREATOR = "human-test-user" |
|
|
|
|
| def bucket_uri(agent: str, path: str) -> str: |
| return f"hf://buckets/test-org/test-{agent}/{path}" |
|
|
|
|
| def seed_source(env, agent: str, path: str, text: str) -> str: |
| env.hub.seed(path, text, bucket=f"test-org/test-{agent}") |
| return bucket_uri(agent, path) |
|
|
|
|
| def make_organizer(env, user: str = "test-user", role: str = "admin") -> None: |
| env.hub.org_roles = {user: role} |
|
|
|
|
| def create_channel(env, name: str, body: str = "Deep talk about X. Bring measurements."): |
| make_organizer(env) |
| return env.client.post( |
| "/v1/channels", |
| json={"name": name, "agent_id": CREATOR, "body": body}, |
| headers=AUTH, |
| ) |
|
|
|
|
| def post_to_channel(env, agent: str, channel: str, body: str): |
| return env.client.post( |
| "/v1/messages", json={"agent_id": agent, "body": body, "channel": channel} |
| ) |
|
|
|
|
| def subscribe(env, channel: str, agent: str, *, verb: str = "subscribe"): |
| uri = seed_source(env, agent, "subscribe-marker.md", "following") |
| return env.client.post(f"/v1/channels/{channel}/{verb}", json={"source": uri}) |
|
|
|
|
| |
|
|
|
|
| def test_create_channel_as_organizer(env): |
| r = create_channel(env, "eval-harness") |
| assert r.status_code == 201 |
| data = r.json() |
| assert data["created"] is True |
| assert data["via"] == "dashboard" |
| assert data["path"] == "channels/eval-harness/README.md" |
| assert data["announcement"] is not None |
|
|
| central = env.hub.buckets[env.settings.central_bucket] |
| assert "channels/eval-harness/README.md" in central |
| |
| assert f"channels/eval-harness/members/{CREATOR}.md" in central |
| assert f"message_board/{data['announcement']}" in central |
| assert sorted(env.hub.batch_writes[-1]) == sorted( |
| [ |
| "channels/eval-harness/README.md", |
| f"channels/eval-harness/members/{CREATOR}.md", |
| f"message_board/{data['announcement']}", |
| ] |
| ) |
|
|
| |
| board = env.client.get("/v1/messages?expand=true").json() |
| ann = next(m for m in board["items"] if m["filename"] == data["announcement"]) |
| assert "#eval-harness" in ann["body"] |
| assert ann["frontmatter"]["via"] == "server" |
| assert ann["frontmatter"]["agent"] == CREATOR |
|
|
|
|
| def test_create_channel_agents_rejected(env): |
| """Creation is organizer-only: both agent variants get a clear 403, not a |
| shape error β agents propose rooms on the board instead.""" |
| seed_agent(env.hub, "bb") |
| r = env.client.post( |
| "/v1/channels", json={"name": "evals", "agent_id": "bb", "body": "mine"} |
| ) |
| assert r.status_code == 403 |
| assert r.json()["error"]["code"] == "NOT_ORGANIZER" |
|
|
| uri = seed_source(env, "bb", "drafts/channel.md", "Scoring disputes live here.") |
| r = env.client.post("/v1/channels", json={"name": "evals", "source": uri}) |
| assert r.status_code == 403 |
| assert r.json()["error"]["code"] == "NOT_ORGANIZER" |
| |
| assert not env.client.get("/v1/channels").json()["items"] |
|
|
|
|
| def test_create_channel_gate(env): |
| """The broadcast gate, reused: Bearer required, admin role required, |
| role-lookup failure fails closed (503) β never a silent allow.""" |
| body = {"name": "orga-room", "agent_id": CREATOR, "body": "Organizer notes."} |
| make_organizer(env) |
| assert env.client.post("/v1/channels", json=body).status_code == 401 |
|
|
| make_organizer(env, role="write") |
| r = env.client.post("/v1/channels", json=body, headers=AUTH) |
| assert r.status_code == 403 |
| assert r.json()["error"]["code"] == "NOT_ORGANIZER" |
|
|
| make_organizer(env) |
| env.hub.org_member_roles_fails = True |
| env.hub.org_member_role_by_email_fails = True |
| r = env.client.post("/v1/channels", json=body, headers=AUTH) |
| assert r.status_code == 503 |
| assert r.json()["error"]["code"] == "ORGANIZER_CHECK_UNAVAILABLE" |
|
|
| env.hub.org_member_roles_fails = False |
| env.hub.org_member_role_by_email_fails = False |
| assert env.client.post("/v1/channels", json=body, headers=AUTH).status_code == 201 |
|
|
|
|
| def test_create_duplicate_and_theme_update(env): |
| assert create_channel(env, "evals").status_code == 201 |
| board_before = env.client.get("/v1/messages").json()["count"] |
|
|
| |
| env.hub.whoami_user = "boss2" |
| env.hub.whoami_email = "boss2@example.com" |
| env.hub.org_roles = {"test-user": "admin", "boss2": "admin"} |
| r = env.client.post( |
| "/v1/channels", |
| json={"name": "evals", "agent_id": "human-boss2", "body": "mine now"}, |
| headers=AUTH, |
| ) |
| assert r.status_code == 409 |
| assert r.json()["error"]["code"] == "CHANNEL_EXISTS" |
|
|
| env.hub.whoami_user = "test-user" |
| env.hub.whoami_email = "test-user@example.com" |
| r = create_channel(env, "evals", body="Updated theme, sharper scope.") |
| assert r.status_code == 200 |
| data = r.json() |
| assert data["created"] is False |
| assert data["announcement"] is None |
| detail = env.client.get("/v1/channels/evals").json() |
| assert "Updated theme" in detail["theme"]["body"] |
| assert detail["updated"] is not None |
| |
| assert env.client.get("/v1/messages").json()["count"] == board_before |
|
|
|
|
| def test_create_channel_retry_idempotent(env): |
| """Creator retries of the same create (timeout replays) are idempotent: |
| 201 then 200/created:false β never an error, never a re-announce.""" |
| r1 = create_channel(env, "retry", body="Retry-safe theme.") |
| assert r1.status_code == 201 |
| r2 = create_channel(env, "retry", body="Retry-safe theme.") |
| assert r2.status_code == 200 |
| data = r2.json() |
| assert data["created"] is False |
| assert data["announcement"] is None |
| |
| board = env.client.get("/v1/messages?q=%23retry").json() |
| assert board["matched"] == 1 |
|
|
|
|
| def test_same_millisecond_posts_mint_unique_filenames(env, monkeypatch): |
| """Two same-ms promotions by one author must not share a filename: on the |
| board that silently overwrites, and in the feed a duplicated basename |
| could slip past the exclusive filename cursor at a page boundary. The |
| per-author monotonic stamp guard bumps the second into the next ms.""" |
| from datetime import datetime, timezone |
|
|
| import app.routes.messages as messages_mod |
|
|
| seed_agent(env.hub, "bb") |
| create_channel(env, "alpha") |
| create_channel(env, "beta") |
| frozen = datetime(2026, 7, 7, 12, 0, 0, 123000, tzinfo=timezone.utc) |
| monkeypatch.setattr(messages_mod, "utc_now", lambda: frozen) |
|
|
| r1 = post_to_channel(env, "bb", "alpha", "same-ms one") |
| r2 = post_to_channel(env, "bb", "beta", "same-ms two") |
| f1, f2 = r1.json()["filename"], r2.json()["filename"] |
| assert f1 != f2 |
|
|
| |
| page1 = env.client.get("/v1/channels/feed?as=bb&order=asc&limit=1&expand=true").json() |
| page2 = env.client.get( |
| f"/v1/channels/feed?as=bb&order=asc&after={page1['next']}&expand=true" |
| ).json() |
| bodies = [m["body"].strip() for m in page1["items"]] + [ |
| m["body"].strip() for m in page2["items"] |
| ] |
| assert bodies == ["same-ms one", "same-ms two"] |
|
|
| |
| b1 = env.client.post("/v1/messages", json={"agent_id": "bb", "body": "board one"}) |
| b2 = env.client.post("/v1/messages", json={"agent_id": "bb", "body": "board two"}) |
| assert b1.json()["filename"] != b2.json()["filename"] |
|
|
|
|
| def test_create_channel_validation(env): |
| seed_agent(env.hub, "bb") |
| assert create_channel(env, "Bad_Name").status_code == 400 |
| r = create_channel(env, "feed") |
| assert r.status_code == 400 |
| assert "reserved" in r.json()["error"]["message"] |
| r = create_channel(env, "empty", body=" ") |
| assert r.status_code == 400 |
| assert r.json()["error"]["code"] == "CHANNEL_THEME_REQUIRED" |
|
|
|
|
| |
|
|
|
|
| def test_post_to_channel_lands_off_board_and_auto_subscribes(env): |
| seed_agent(env.hub, "bb") |
| seed_agent(env.hub, "dd") |
| create_channel(env, "evals") |
| board_before = env.client.get("/v1/messages").json()["count"] |
|
|
| r = post_to_channel(env, "dd", "evals", "profiled the scorer") |
| assert r.status_code == 201 |
| data = r.json() |
| assert data["channel"] == "evals" |
| assert data["auto_subscribed"] is True |
| assert data["path"].startswith("channels/evals/") |
|
|
| |
| msgs = env.client.get("/v1/channels/evals/messages?expand=true").json() |
| assert msgs["matched"] == 1 |
| assert msgs["items"][0]["frontmatter"]["channel"] == "evals" |
| assert env.client.get("/v1/messages").json()["count"] == board_before |
|
|
| |
| detail = env.client.get("/v1/channels/evals").json() |
| assert {m["handle"] for m in detail["members"]} == {CREATOR, "dd"} |
| auto = next(m for m in detail["members"] if m["handle"] == "dd") |
| assert auto["via"] == "auto" |
| r = post_to_channel(env, "dd", "evals", "second post") |
| assert r.json()["auto_subscribed"] is False |
|
|
|
|
| def test_post_to_channel_source_variant(env): |
| seed_agent(env.hub, "bb") |
| create_channel(env, "evals") |
| uri = seed_source(env, "bb", "drafts/finding.md", "---\ntype: note\n---\nlong writeup") |
| r = env.client.post("/v1/messages", json={"source": uri, "channel": "evals"}) |
| assert r.status_code == 201 |
| assert r.json()["channel"] == "evals" |
| assert r.json()["via"] == "bucket" |
| |
| r = env.client.post("/v1/messages", json={"source": uri, "channel": "evals"}) |
| assert r.status_code == 409 |
| assert r.json()["error"]["code"] == "ALREADY_PROMOTED" |
|
|
|
|
| def test_channel_mentions_fan_out_to_inboxes(env): |
| seed_agent(env.hub, "bb") |
| seed_agent(env.hub, "dd") |
| create_channel(env, "evals") |
| r = post_to_channel(env, "dd", "evals", "@bb the scorer truncates at 2^20 bytes") |
| assert r.json()["mentions_delivered"] == ["bb"] |
| inbox = env.client.get("/v1/inbox/bb?expand=true").json() |
| copies = [m for m in inbox["items"] if "truncates" in m["body"]] |
| assert len(copies) == 1 |
| |
| assert copies[0]["frontmatter"]["channel"] == "evals" |
|
|
|
|
| def test_post_to_missing_channel_404(env): |
| seed_agent(env.hub, "bb") |
| r = post_to_channel(env, "bb", "nope", "hello?") |
| assert r.status_code == 404 |
| assert r.json()["error"]["code"] == "CHANNEL_NOT_FOUND" |
|
|
|
|
| def test_channel_and_broadcast_mutually_exclusive(env): |
| seed_agent(env.hub, "bb") |
| create_channel(env, "evals") |
| r = env.client.post( |
| "/v1/messages", |
| json={"agent_id": "bb", "body": "x", "channel": "evals", "broadcast": True}, |
| ) |
| assert r.status_code == 422 |
|
|
|
|
| def test_source_channel_frontmatter_rejected(env): |
| seed_agent(env.hub, "bb") |
| create_channel(env, "evals") |
| uri = seed_source(env, "bb", "drafts/sneaky.md", "---\nchannel: evals\n---\nspoof") |
| r = env.client.post("/v1/messages", json={"source": uri}) |
| assert r.status_code == 400 |
| assert r.json()["error"]["code"] == "INVALID_FRONTMATTER" |
|
|
|
|
| |
|
|
|
|
| def test_subscribe_unsubscribe_idempotent(env): |
| seed_agent(env.hub, "bb") |
| seed_agent(env.hub, "lurker") |
| create_channel(env, "evals") |
| post_to_channel(env, "bb", "evals", "first finding") |
|
|
| r = subscribe(env, "evals", "lurker") |
| assert r.status_code == 200 |
| |
| |
| assert r.json() == { |
| "channel": "evals", "handle": "lurker", "subscribed": True, |
| "changed": True, "notify": "mentions", |
| } |
| assert subscribe(env, "evals", "lurker").json()["changed"] is False |
|
|
| feed = env.client.get("/v1/channels/feed?as=lurker&expand=true").json() |
| assert feed["matched"] == 1 |
| assert feed["items"][0]["frontmatter"]["channel"] == "evals" |
|
|
| r = subscribe(env, "evals", "lurker", verb="unsubscribe") |
| |
| assert r.json() == { |
| "channel": "evals", "handle": "lurker", "subscribed": False, |
| "changed": True, "notify": None, |
| } |
| assert "channels/evals/members/lurker.md" in env.hub.deletes |
| assert env.client.get("/v1/channels/feed?as=lurker").json()["matched"] == 0 |
| assert subscribe(env, "evals", "lurker", verb="unsubscribe").json()["changed"] is False |
| |
| |
| assert env.client.get("/v1/channels/evals/messages").json()["matched"] == 1 |
|
|
|
|
| def test_subscribe_agent_raw_body_rejected(env): |
| seed_agent(env.hub, "bb") |
| seed_agent(env.hub, "lurker") |
| create_channel(env, "evals") |
| r = env.client.post("/v1/channels/evals/subscribe", json={"agent_id": "lurker"}) |
| assert r.status_code == 401 |
|
|
|
|
| def test_subscribe_source_must_exist(env): |
| seed_agent(env.hub, "bb") |
| seed_agent(env.hub, "lurker") |
| create_channel(env, "evals") |
| env.hub.buckets.setdefault("test-org/test-lurker", {}) |
| r = env.client.post( |
| "/v1/channels/evals/subscribe", |
| json={"source": bucket_uri("lurker", "never-written.md")}, |
| ) |
| assert r.status_code == 404 |
| assert r.json()["error"]["code"] == "SOURCE_NOT_FOUND" |
|
|
|
|
| def test_subscribe_human_with_token(env): |
| seed_agent(env.hub, "bb") |
| create_channel(env, "evals") |
| |
| r = env.client.post( |
| "/v1/channels/evals/subscribe", json={"agent_id": CREATOR}, headers=AUTH |
| ) |
| assert r.status_code == 200 |
| assert r.json()["changed"] is False |
| post_to_channel(env, "bb", "evals", "hello humans") |
| feed = env.client.get(f"/v1/channels/feed?as={CREATOR}").json() |
| assert feed["matched"] == 1 |
| |
| env.hub.whoami_user = "other" |
| env.hub.whoami_email = "other@example.com" |
| r = env.client.post( |
| "/v1/channels/evals/subscribe", json={"agent_id": "human-other"}, headers=AUTH |
| ) |
| assert r.status_code == 200 |
| assert r.json()["changed"] is True |
| |
| r = env.client.post("/v1/channels/evals/subscribe", json={"agent_id": "human-other"}) |
| assert r.status_code == 401 |
| r = env.client.post( |
| "/v1/channels/evals/subscribe", json={"agent_id": "human-someone-else"}, headers=AUTH |
| ) |
| assert r.status_code == 403 |
|
|
|
|
| def test_subscribe_missing_channel_404(env): |
| seed_agent(env.hub, "lurker") |
| r = env.client.post( |
| "/v1/channels/nope/subscribe", |
| json={"source": seed_source(env, "lurker", "f.md", "x")}, |
| ) |
| assert r.status_code == 404 |
|
|
|
|
| |
|
|
|
|
| def test_feed_unions_subscriptions_with_cursor(env): |
| seed_agent(env.hub, "bb") |
| seed_agent(env.hub, "reader") |
| create_channel(env, "alpha") |
| create_channel(env, "beta") |
| create_channel(env, "gamma") |
| post_to_channel(env, "bb", "alpha", "a1") |
| post_to_channel(env, "bb", "beta", "b1") |
| post_to_channel(env, "bb", "gamma", "not for reader") |
| subscribe(env, "alpha", "reader") |
| subscribe(env, "beta", "reader") |
|
|
| feed = env.client.get("/v1/channels/feed?as=reader&expand=true&order=asc").json() |
| assert feed["matched"] == 2 |
| bodies = [m["body"].strip() for m in feed["items"]] |
| assert bodies == ["a1", "b1"] |
|
|
| |
| first = feed["items"][0]["filename"] |
| page = env.client.get( |
| f"/v1/channels/feed?as=reader&order=asc&after={first}&expand=true" |
| ).json() |
| assert [m["body"].strip() for m in page["items"]] == ["b1"] |
|
|
|
|
| def test_feed_requires_known_handle(env): |
| assert env.client.get("/v1/channels/feed?as=ghost").status_code == 404 |
|
|
|
|
| |
|
|
|
|
| def test_channel_listing_summaries(env): |
| seed_agent(env.hub, "bb") |
| seed_agent(env.hub, "dd") |
| create_channel(env, "evals", body="Scoring and verification.") |
| create_channel(env, "tricks", body="Tokenizer tricks.") |
| post_to_channel(env, "dd", "evals", "activity!") |
|
|
| listing = env.client.get("/v1/channels").json() |
| assert listing["count"] == 2 |
| assert listing["matched"] == 2 |
| by_name = {c["name"]: c for c in listing["items"]} |
| assert by_name["evals"]["member_count"] == 2 |
| assert by_name["evals"]["message_count"] == 1 |
| assert by_name["evals"]["theme_excerpt"] == "Scoring and verification." |
| assert by_name["evals"]["last_activity"] is not None |
| |
| assert listing["items"][0]["name"] == "evals" |
|
|
| q = env.client.get("/v1/channels?q=tokenizer").json() |
| assert q["matched"] == 1 |
| assert q["items"][0]["name"] == "tricks" |
|
|
|
|
| def test_channel_detail_and_messages_grammar(env): |
| seed_agent(env.hub, "bb") |
| seed_agent(env.hub, "dd") |
| create_channel(env, "evals") |
| post_to_channel(env, "bb", "evals", "one") |
| post_to_channel(env, "dd", "evals", "two") |
|
|
| detail = env.client.get("/v1/channels/evals").json() |
| assert detail["message_count"] == 2 |
| assert [m["handle"] for m in detail["members"]] == ["bb", "dd", CREATOR] |
| assert all(m["subscribed"] for m in detail["members"]) |
| assert detail["recent_messages"][0]["body"].strip() == "two" |
|
|
| only_dd = env.client.get("/v1/channels/evals/messages?agent=dd&expand=true").json() |
| assert only_dd["matched"] == 1 |
| assert only_dd["items"][0]["body"].strip() == "two" |
|
|
|
|
| def test_channel_not_found_reads(env): |
| assert env.client.get("/v1/channels/nope").status_code == 404 |
| assert env.client.get("/v1/channels/nope/messages").status_code == 404 |
|
|
|
|
| |
|
|
|
|
| def test_digest_channels_block(env): |
| seed_agent(env.hub, "bb") |
| seed_agent(env.hub, "reader") |
| create_channel(env, "evals") |
| post_to_channel(env, "bb", "evals", "old finding") |
| subscribe(env, "evals", "reader") |
|
|
| anon = env.client.get("/v1/digest").json() |
| assert anon["channels"]["count"] == 1 |
| assert anon["channels"]["channels"][0]["name"] == "evals" |
| assert anon["channels"]["subscribed"] is None |
|
|
| mine = env.client.get("/v1/digest?as=reader").json() |
| subd = mine["channels"]["subscribed"] |
| assert [c["name"] for c in subd] == ["evals"] |
| assert subd[0]["new_count"] == 1 |
| assert subd[0]["recent"][0]["frontmatter"]["channel"] == "evals" |
|
|
| |
| old_stamp = subd[0]["recent"][0]["filename"][:19] |
| fresh = env.client.get(f"/v1/digest?as=reader&since={old_stamp}").json() |
| assert fresh["channels"]["subscribed"][0]["new_count"] == 1 |
| post_to_channel(env, "bb", "evals", "brand new") |
| fresh = env.client.get(f"/v1/digest?as=reader&since={old_stamp}").json() |
| assert fresh["channels"]["subscribed"][0]["new_count"] == 2 |
|
|
|
|
| def test_discovery_documents_channels(env): |
| doc = env.client.get("/v1").json() |
| paths = {e["path"] for e in doc["endpoints"]} |
| assert {"/v1/channels", "/v1/channels/feed", "/v1/channels/{name}"} <= paths |
| assert "channels" in doc["conventions"] |
| assert "depth beats coverage" in doc["conventions"]["channels"] |
|
|