Skip to content

docs(#265): messaging authorization contract catalogue + realtime C29#328

Merged
TortoiseWolfe merged 2 commits into
mainfrom
docs/265-authorization-contract-catalogue
Jul 19, 2026
Merged

docs(#265): messaging authorization contract catalogue + realtime C29#328
TortoiseWolfe merged 2 commits into
mainfrom
docs/265-authorization-contract-catalogue

Conversation

@TortoiseWolfe

Copy link
Copy Markdown
Owner

What & why

#265 / #280. The messaging provider seam is guarded by a shared conformance suite that both the Supabase and .NET providers must pass. The roadmap item was "broaden coverage to groups/archive/realtime/C15–C28." Investigation found that "C1–C29" was an aspirational banner, not a populated 29-item list:

  • Only 13 clauses ever had canonical rule text: C1, C2, C3, C5, C7–C14, C29.
  • C4, C6, C15–C28 (16 numbers) were never authored — no rule text in source, tests, SQL, or docs. The "Modular backend: abstract messaging so it swaps Supabase↔.NET (EF Core) by env var #266 plan" the code kept citing never existed.
  • Asserted before this PR: C1, C2, C5, C7–C14 (19 cases). Defined-but-unasserted: C3 (no createConversation in the seam) and C29 (realtime — testable, never exercised).

Inventing 16 clauses to hit a round number would be the manufactured-green anti-pattern this project forbids. So this PR writes down the real contract and makes the code's own claims true.

Changes

  • New docs/messaging/AUTHORIZATION-CONTRACT.md — the canonical catalogue the code referenced but that was never written: the 13 real clauses (rule text + enforced-at RLS/provider/.NET refs + asserted-in-suite), the C29 two-mechanism note, and the real deferred seam-expansion backlog (C3 createConversation, group management, keys, GDPR) — the honest "broaden coverage" work for [EPIC] Enterprise-ready: make ScriptHammer a repo you can build real work on (eval-3 → eval-1) #280.
  • New C29 realtime conformance case — subscribe as the outsider → their authorized refetch still yields [] → any delivered event carries no readable row. Deterministic and non-flaky by design: no live-websocket wait (the conformance stack deliberately omits the supabase-realtime container, and wall-clock realtime waits are a known flake source). 20 cases/provider.
  • Doc-truth — corrected the 7 false "C1–C29 / Modular backend: abstract messaging so it swaps Supabase↔.NET (EF Core) by env var #266 plan" claims (types.ts, contract.ts, dotnet.test.ts, dotnet-provider.ts, README ×3) to reference the new catalogue; refreshed the stale dotnet-provider "typed skeleton (server is a follow-up)" status and the README "12/12 / migration currently fails" known-gaps to reflect the now-live, CI-gated backend.

Verification

Local dual-provider run (in-container against a local Supabase + .NET stack):

  • pnpm run type-check
  • pnpm run lint
  • pnpm test:rls129/129 green, both [supabase] and [dotnet] contract runners at 20/20; the suite does not hang despite the realtime container being absent.

No behaviour / interface / migration changes — docs + one test only. The Conformance gate re-runs the full suite against both backends.

Out of scope (tracked follow-up)

The real seam-expansion backlog (C3 createConversation, group mgmt, keys, GDPR endpoints behind the provider + .NET server) is named in the new doc — each is its own future increment for #280. This PR does not invent C4/C6/C15–C28.

🤖 Generated with Claude Code

TurtleWolfe and others added 2 commits July 19, 2026 00:18
"C1–C29" was an aspirational banner, not a populated list. An Explore pass found
only 13 clauses ever had rule text (C1,C2,C3,C5,C7–C14,C29); C4,C6,C15–C28 were
never authored, and the "#266 plan" the code kept citing never existed. Inventing
16 clauses to hit a round number would be the manufactured-green anti-pattern the
project forbids — so this writes down the REAL contract and makes the code's own
claims true.

- Add docs/messaging/AUTHORIZATION-CONTRACT.md — the canonical catalogue the code
  referenced but that was never written: the 13 real clauses (rule text +
  enforced-at RLS/provider/.NET refs + asserted-in-suite), the C29 two-mechanism
  note (RLS-filtered postgres_changes vs. payload-free poll), and the real
  deferred seam-expansion backlog (C3 createConversation, group mgmt, keys, GDPR)
  — the honest "broaden coverage" work for #280.
- Add a C29 realtime conformance case: subscribe as the outsider → their
  authorized refetch still yields [] → any delivered event carries no readable
  row. Deterministic and non-flaky by design — no live-websocket wait (the
  conformance stack deliberately omits the realtime container). 20 cases/provider.
- Doc-truth: correct the 7 false "C1–C29 / #266 plan" claims (types.ts,
  contract.ts, dotnet.test.ts, dotnet-provider.ts, README ×3) to point at the new
  catalogue; refresh the stale dotnet-provider "typed skeleton (server is a
  follow-up)" status and the README "12/12 / migration currently fails" gaps to
  reflect the now-live, CI-gated backend.

Verified locally: type-check, lint, and dual-provider conformance all green —
test:rls 129/129, both [supabase] and [dotnet] runners at 20/20.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nnected

The new C29 conformance case exposed a latent realtime-provider bug. When the
realtime socket never connected — offline, or a stack without the realtime
service (e.g. the conformance stack) — SupabaseRealtimeProvider.unsubscribe
rejected asynchronously from realtime-js removeChannel → disconnect
("this.conn.close is not a function"). Unhandled, that hard-fails the whole
vitest run: the CI Conformance gate went red even though all 129 tests passed
(it slipped past locally only because the async reject fired after vitest's
summary — a timing fluke).

Harden unsubscribe: attach a `.catch` SYNCHRONOUSLY (so the promise is never
"unhandled" regardless of when it rejects) and swallow the sync-throw path too.
Unsubscribing a never-connected channel is a no-op, not an error — this also
makes production teardown crash-safe when offline.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@TortoiseWolfe
TortoiseWolfe merged commit ccab3ce into main Jul 19, 2026
19 checks passed
@TortoiseWolfe
TortoiseWolfe deleted the docs/265-authorization-contract-catalogue branch July 19, 2026 01:33
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