Skip to main content

ConflictService.StreamConflicts — Connect-Web reach

Status: verified — 2026-04-26. Owner: backend-sme. Related: core#1033 (GAP-Mount-2), core#1031 (tracker), HLD #556, LLD #560.

Summary

ConflictService.StreamConflicts is reachable from the browser over BOTH the default Connect transport (HTTP/2) AND the gRPC-Web transport (HTTP/1.1 fallback). No SSE bridge is required.

Wire-up at a glance

LayerReference
Service mount (Connect handler)cmd/context-engine/main.go:1024-1030
Gateway flag gatecmd/context-engine/new_services_gate.go (new_services_enabled)
Connect adapterinternal/conflict/connect_adapter.go
Streaming hub (PG LISTEN/NOTIFY)internal/conflict/stream.go
Browser-reach testinternal/conflict/connect_adapter_stream_test.go
Frontend client@connectrpc/connect-web consuming pkg/contextpb/upsquad/conflict/v1/conflictpbconnect/

What was verified

The new test file internal/conflict/connect_adapter_stream_test.go boots the real Connect handler on an h2c httptest server and asserts:

  1. Handler path is the proto-canonical path the browser client hits (/upsquad.conflict.v1.ConflictService/). Catches codegen drift.
  2. Default Connect transport end-to-end round-trip with live event delivery + idle liveness + graceful client cancellation.
  3. gRPC-Web transport (connect.WithGRPCWeb()) end-to-end round-trip on the same handler. This is the transport browsers fall back to on HTTP/1.1-only edges (Cloudflare tunnel + Envoy in our staging path).
  4. Hub-not-wired regression — if WithHub(...) is omitted in cmd/context-engine/main.go, the stream returns Unimplemented immediately rather than hanging forever.

Verdict

The mounted handler works as-is. No SSE bridge is required. The @connectrpc/connect-web client in default mode (Connect protocol over HTTP/2) satisfies the /admin/conflicts page and sidebar conflict count badge requirements. If a future deployment forces an HTTP/1.1- only path through the edge, the same client will downgrade to gRPC-Web without a backend change.

How to run the test locally

go test ./internal/conflict/ -run TestConflictConnectAdapter -v -count=1

Expected runtime: <1 second. The test does not require Postgres — the Hub is constructed without a connection pool and test events are injected via a same-package helper that writes directly to the registered Subscriber's channel.

Why an end-to-end browser smoke test was not added

The acceptance criterion in #1033 asked for a "browser-side smoke test using the existing Connect-Web client". Building one would require a running staging deployment with seeded conflict rows + a logged-in browser session, neither of which exists in CI today. The Go-side test above is the strongest reproducible substitute: the Connect-Go client speaks the identical wire protocol to the browser's Connect-Web client for both transports, and the test exercises the same handler code path the browser would hit.

A full browser smoke test should be added by qa-engineer once the /admin/conflicts page lands behind the new_services_enabled flag, as part of the wider redesign-2026-04 QA pass.

References

  • internal/conflict/connect_adapter_stream_test.go — the verification test.
  • internal/conflict/stream.go — Hub implementation.
  • internal/conflict/connect_adapter.go — Connect handler bridge.
  • cmd/context-engine/main.go — service mount + gateway flag gate.