Skip to content

test(#265): broaden messaging conformance beyond C7–C14/1:1 (+ fix a .NET pagination bug)#327

Merged
TortoiseWolfe merged 1 commit into
mainfrom
fix/265-broaden-conformance-coverage
Jul 18, 2026
Merged

test(#265): broaden messaging conformance beyond C7–C14/1:1 (+ fix a .NET pagination bug)#327
TortoiseWolfe merged 1 commit into
mainfrom
fix/265-broaden-conformance-coverage

Conversation

@TortoiseWolfe

Copy link
Copy Markdown
Owner

What & why

The shared conformance suite (the anti-drift alarm across the Supabase↔.NET seam) covered only C7–C14 on a 1:1 conversation — the honest DoD from #265. This extends it (both providers run the identical cases) to close the biggest gaps, keeping the owner-blocking #280 arc moving.

New cases (12 → 19 per provider)

  • C7 getMessageById — a participant reads the row; an outsider gets null.
  • getProfiles — batch display-name/avatar lookup returns the requested users.
  • markAsDelivered — a participant sets delivered_at; a non-participant outsider cannot.
  • C7 pagination — newest-first, cursor + hasMore.
  • C5 archive/unarchive — a per-participant view flag (the other participant's view is untouched).
  • C1/C2 group scoping — a new group conversation + conversation_members in the harness; a member reads it, an outsider gets no metadata and no rows.

Full pnpm test:rls = 127/127 (both providers + the RLS suite + the #321 backstop).

Caught + fixed a real bug 🎯

The pagination case exposed a genuine .NET provider bug: DotnetMessagingProvider.getMessages returned the raw server JSON as MessagesPage, but the server serializes with the global snake_case policy, so the flag arrives as has_more — meaning hasMore was undefined. Pagination would silently break whenever the app runs on the .NET backend. Fixed the provider to map has_morehasMore (the rows are already snake_case MessageRow, matching the wire). This is exactly the anti-drift catch the suite exists for — the existing tests never checked hasMore, so it was latent.

Harness (symmetric in both runners)

groupConversationId + group seeding (NULL participants per the check_group_participants constraint; membership via conversation_members), a conversationId param on seedMessage, delivered_at on readMessage, and a readConversation helper.

Still out of scope (honest)

  • Realtime (C29) — the .NET realtime provider is a 5s polling fallback; a deterministic cross-provider assertion is timing-sensitive. Deferred (C29 is already indirectly covered by the outsider-sees-zero-rows check).
  • C15–C28 — unallocated rule numbers (the interface defines only C1–C14 + C29). Materializing them is a design task (what rules?), not test-writing.

Self-validates: the diff touches tests/contract/** + src/services/messaging/**, both in the Conformance gate's path filter, so that gate runs the full test:rls against a fresh dual-provider stack.

Refs #265, #280.

🤖 Generated with Claude Code

….NET pagination bug)

The shared conformance suite covered only C7-C14 on a 1:1 conversation. Extended
it (both providers run the identical cases) to close the biggest gaps:
- C7 getMessageById (participant reads; outsider gets null)
- getProfiles (batch profile lookup)
- markAsDelivered (participant sets delivered_at; a non-participant cannot)
- C7 pagination (newest-first, cursor + hasMore)
- C5 archive/unarchive (per-participant view flag)
- C1/C2 group membership scoping (new group conversation + conversation_members
  in the harness; creator-or-active-member access, outsider excluded)

19 cases per provider (was 12). Full `pnpm test:rls` = 127/127 (both providers +
the RLS suite + the #321 backstop).

The pagination case caught a REAL .NET provider bug: DotnetMessagingProvider
.getMessages returned the raw server JSON as MessagesPage, but the server emits
snake_case (has_more), so `hasMore` was `undefined` — pagination would silently
break whenever the app runs on the .NET backend. Fixed the provider to map
has_more -> hasMore. This is exactly the anti-drift catch the suite exists for.

Harness (symmetric in both .supabase + .dotnet runners): added groupConversationId
+ group seeding, a conversationId param to seedMessage, delivered_at to
readMessage, and a readConversation helper.

Still out of scope: realtime (C29 - timing/polling non-determinism) and C15-C28
(unallocated rule numbers; materializing them is a design task, not test-writing).

Refs #265, #280.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@TortoiseWolfe
TortoiseWolfe merged commit 13cf4fa into main Jul 18, 2026
3 checks passed
@TortoiseWolfe
TortoiseWolfe deleted the fix/265-broaden-conformance-coverage branch July 18, 2026 22:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants