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
| Layer | Reference |
|---|---|
| Service mount (Connect handler) | cmd/context-engine/main.go:1024-1030 |
| Gateway flag gate | cmd/context-engine/new_services_gate.go (new_services_enabled) |
| Connect adapter | internal/conflict/connect_adapter.go |
| Streaming hub (PG LISTEN/NOTIFY) | internal/conflict/stream.go |
| Browser-reach test | internal/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:
- Handler path is the proto-canonical path the browser client hits
(
/upsquad.conflict.v1.ConflictService/). Catches codegen drift. - Default Connect transport end-to-end round-trip with live event delivery + idle liveness + graceful client cancellation.
- 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). - Hub-not-wired regression — if
WithHub(...)is omitted incmd/context-engine/main.go, the stream returnsUnimplementedimmediately 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.