feat: add SubscribeEvents stream and consolidate gRPC-Web transport into @compass/client - #2
Conversation
…import fence
SubscribeEvents adds the server-streaming half of compass.v1 (compass.md §7.2): an Event envelope with a daemon-assigned monotonic `seq` and `since_seq` resubscribe for gap-free reconnect, carrying a typed DaemonState payload that grows to board/agent/audit variants behind the buf breaking gate. buf lint excepts RPC_RESPONSE_STANDARD_NAME so the stream stays `Event`, not a one-shot response.
Enforces the owned door: @compass/client gains createCompassWebClient (bundling the gRPC-Web transport) and a biome noRestrictedImports fence bans @connectrpc/connect{,-web} outside the client, so UI code reaches the daemon only through the generated client. apps/ui drops its redundant transport wrapper and imports only @compass/client.
Closes SEA-1024.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughSummary by CodeRabbit
WalkthroughAdds a ChangesSubscribeEvents RPC and client consolidation
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
This stack of pull requests is managed by Graphite. Learn more about stacking. |
Greptile SummaryThis PR introduces the
Confidence Score: 5/5Clean, well-scoped change — proto contract, generated bindings, TypeScript client, and lint fence are all consistent with each other and with the existing codebase patterns. All layers (proto, Rust tonic stubs, TypeScript generated bindings, client package, UI wiring, lint fence) are aligned. No missing guards, no stale state, no dropped side effects. The previous thread concerns (global buf lint suppression, missing No files require special attention. Important Files Changed
Reviews (4): Last reviewed commit: "fix(ui): track tsconfig.json in test cac..." | Re-trigger Greptile |
There was a problem hiding this comment.
cubic analysis
2 issues found across 17 files
Linked issue analysis
Linked issue: SEA-1024: compass.v1 gRPC contract crate + generated clients (CI drift-gated)
| Status | Acceptance criteria | Notes |
|---|---|---|
| ✅ | Add SubscribeEvents server‑streaming RPC and Event message (seq, at_unix_ms, oneof payload with DaemonStatus and ResyncRequired) and DaemonState enum | The proto, generated Rust, and generated TS all include the SubscribeEvents RPC, SubscribeEventsRequest, Event message with seq/at_unix_ms/payload variants, DaemonStatus, ResyncRequired, and DaemonState enum. |
| ✅ | Expose a single web entrypoint that bundles the gRPC‑Web transport (createCompassWebClient) and re‑export new types from @compass/client | createCompassWebClient was added to the client index, the transport is constructed there, and the package re-exports Event/DaemonStatus/ResyncRequired/SubscribeEventsRequest and DaemonState. |
| ✅ | Consolidate UI to use @compass/client (remove direct @connectrpc/connect-web usage and local client module) | apps/ui no longer depends on @connectrpc/connect-web, the local client.ts and its test were removed, and package.json and build/test scripts were updated to use the client package. |
| ✅ | Enforce lint rule banning direct imports of @connectrpc/connect and @connectrpc/connect-web except inside packages/compass-client | biome.json now defines noRestrictedImports for those packages with an override turning the rule off for packages/compass-client. |
| ✅ | Check in generated clients and add compile/usage tests that verify the generated schema surface | Generated Rust and TS artifacts were updated/checked in, and tests were added/updated to exercise the new types and client surface (Rust contract tests, TS client test). |
| ✅ | Suppress the buf RPC response name lint for this stream (SubscribeEvents) | buf.yaml now excludes the RPC_RESPONSE_STANDARD_NAME lint with a comment referencing SubscribeEvents semantics. |
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
…ransport export
- Rename the streamed `Event` to `SubscribeEventsResponse` (buf's standard
`<Rpc>Response` name), removing the module-wide RPC_RESPONSE_STANDARD_NAME
except so every RPC stays lint-gated with no per-RPC suppression.
- biome fence: add `patterns` banning `@connectrpc/connect{,-web}` subpaths so
the owned `@compass/client` door can't be bypassed via deep imports.
- Re-export `Transport` from `@compass/client` so non-web consumers can type a
custom transport without importing the fenced connect package.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/ui/moon.yml`:
- Line 26: The Moon cache inputs for the UI tasks are missing
`packages/compass-client/package.json`, so changes to that package’s exports or
dependencies can be missed and stale `build` or `typecheck` results reused.
Update the relevant input lists in the moon config for the affected tasks to
include `packages/compass-client/package.json` alongside the existing `src/**/*`
and other project files, so resolution/bundling changes invalidate the cache
correctly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 958c7c05-f096-42d5-acb9-70c321ad163a
⛔ Files ignored due to path filters (4)
bun.lockis excluded by!**/*.lockcrates/compass-proto/src/gen/compass/v1/compass.v1.rsis excluded by!**/gen/**crates/compass-proto/src/gen/compass/v1/compass.v1.tonic.rsis excluded by!**/gen/**packages/compass-client/src/gen/compass/v1/compass_pb.tsis excluded by!**/gen/**
📒 Files selected for processing (12)
apps/ui/moon.ymlapps/ui/package.jsonapps/ui/src/client.test.tsapps/ui/src/client.tsapps/ui/tsconfig.jsonapps/ui/tsconfig.test.jsonbiome.jsoncrates/compass-proto/proto/compass/v1/compass.protocrates/compass-proto/tests/contract.rspackages/compass-client/package.jsonpackages/compass-client/src/index.test.tspackages/compass-client/src/index.ts
💤 Files with no reviewable changes (4)
- apps/ui/package.json
- apps/ui/src/client.ts
- apps/ui/tsconfig.test.json
- apps/ui/src/client.test.ts
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/ui/moon.yml`:
- Line 35: The test cache inputs for the `test` task do not include
`tsconfig.json`, so config-only changes can reuse stale `bun test` results.
Update the `inputs` list in the `moon.yml` test layer to track `tsconfig.json`
alongside the existing entries, keeping the cache invalidation aligned with the
main TypeScript config.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: ec733174-3a2a-46bf-a50b-890fdff5584e
📒 Files selected for processing (1)
apps/ui/moon.yml
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Fix all with cubic | Re-trigger cubic
Two review-loop test additions on the durable sink-ack handler (PR #43), both defending an invariant the first-round suite left to inference: - runnerhub/commit_frame_test.go: a hub UPDATE-arm test symmetric to the posted happy path. The ConversationUpdated dispatch arm was proven only at the comms layer + via the fake recorder, never through Hub.commitFrame itself; this asserts the arm forwards under the bound account with the key threaded and returns the UPDATE's own row id (m-99) — a mis-wire that returned the posted id or the wrong frame now fails here (verified red). - runnerhub/auth_test.go: TestAccountTokenRejectedOnEveryRPCPath gains a commit_conversation_frame subtest, replacing two dead duplicate relay_comms_call slots (Go suffixed #1/#2, so they ran but covered nothing new). The new RPC's door-interceptor wiring is now asserted Unauthenticated for an account token, closing the door-coverage gap. Refs SEA-1364 Co-Authored-By: seal <noreply@sealedsecurity.com>

Add
SubscribeEventsserver-streaming RPC and consolidate the gRPC-Web transport into@compass/clientWhat changed
Proto contract
A
SubscribeEventsserver-streaming RPC is added toCompassService. It accepts aSubscribeEventsRequestwith asince_seqcursor (0 = snapshot-then-tail, >0 = gap-free resubscribe) and streamsEventmessages. EachEventcarries a daemon-assigned monotonicseq, a Unix-ms timestamp, and aoneof payloadthat currently coversDaemonStatusandResyncRequired.DaemonStateis a new enum withUNSPECIFIEDandREADYvariants. TheRPC_RESPONSE_STANDARD_NAMEbuf lint rule is suppressed for this RPC because the stream delivers domain events rather than a one-shot response.@compass/clientcreateCompassWebClient(baseUrl)is introduced as the single entry point for web UI code. It internally constructs the gRPC-Web transport, so callers no longer need to import or depend on@connectrpc/connect-webdirectly.createCompassClient(transport)is kept for non-web consumers that supply their own transport.@connectrpc/connect-webis promoted from a dev dependency to a runtime dependency of the package.Event,DaemonStatus,ResyncRequired,SubscribeEventsRequest) and theDaemonStateenum are re-exported from the package index.apps/ui@connectrpc/connect-webdependency is removed; the UI now reaches the daemon exclusively through@compass/client.client.tsmodule and its test are deleted;createCompassWebClientfrom@compass/clientreplaces them.tsconfig.test.jsonand the test-file exclusion intsconfig.jsonare removed, simplifying the TypeScript configuration to a single config.typechecktask is simplified to a singletsc --noEmitinvocation.testtask passes--pass-with-no-testsso the task does not fail when no test files are present.Linter
Biome is configured to error on direct imports of
@connectrpc/connectand@connectrpc/connect-webeverywhere except insidepackages/compass-client, enforcing that all other code reaches the daemon only through the owned@compass/clientdoor.Summary by cubic
Adds the
SubscribeEventsserver-streaming RPC and introducescreateCompassWebClientto centralize gRPC‑Web behind@compass/client, making the UI use a single, owned door to the daemon. Aligns with SEA-1024 by delivering the event channel and fencing raw Connect imports.New Features
SubscribeEventsstream withsince_seqcursor; responses includeseq,at_unix_ms, and payloads:DaemonStatusandResyncRequired. Uses the standard<Rpc>Responsename.@compass/clientexportscreateCompassWebClient(baseUrl);createCompassClient(transport)remains. Re-exports streaming types,DaemonState, andTransport.Refactors
@connectrpc/connect-webto a runtime dependency of@compass/client; removed fromapps/ui.createCompassWebClient; removed the local wrapper and its test. Simplified TS config and tasks (single tsconfig;tsc --noEmit;bun test --pass-with-no-tests).@connectrpc/connect/@connectrpc/connect-weboutsidepackages/compass-client.apps/uitask inputs to track/packages/compass-client/package.jsonandtsconfig.json(test) for accurate cache keys.Written for commit 27ba8c6. Summary will update on new commits.
Closes SEA-1024