Skip to content

Add user-service (NATS request/reply) + consolidate user endpoints + frontend migration#279

Open
amdla wants to merge 13 commits into
mainfrom
claude/cool-davinci-6lYhU
Open

Add user-service (NATS request/reply) + consolidate user endpoints + frontend migration#279
amdla wants to merge 13 commits into
mainfrom
claude/cool-davinci-6lYhU

Conversation

@amdla
Copy link
Copy Markdown
Collaborator

@amdla amdla commented Jun 7, 2026

Summary

Recreates user-service as a standalone NATS request/reply microservice (no JetStream), consolidates the user-facing endpoint surface, removes the superseded mock-user-service, and migrates chat-frontend onto the new contract.

8 endpoints (down from the legacy sprawl): status.getByName, status.set, subscription.list, subscription.getChannels, subscription.getDM, subscription.count, subscription.setAppSubscription, apps.list.

  • getCurrent/getRooms/getApps → unified subscription.list (type param)
  • subscribeApp/unsubscribeApp → idempotent PUT-like subscription.setAppSubscription
  • profile.getByName + the employee endpoint removed

Architecture

Root main.go + unpacked packages: config · models (DTOs) · service (8 handlers + the shared enrichWithRoomInfo) · mongorepo (per-collection stores; $facet/Del--filter/room-join pipelines) · roomclient (room-service/room-worker RPC) · publisher (core-NATS outbox). Built on history-service's patterns (consumer-defined interfaces + mocks, pkg/natsrouter/mongoutil/errcode/shutdown). Cross-site status federation is fire-and-forget core-NATS to all configured sites.

Subscription replies are room-info enriched

list/getChannels/getDM bodies get name/lastMsgAt/alert/hasMention computed from room-service via per-site parallel GetRoomsInfo (per-site degradation; deleted Del- rooms filtered; userCount/lastMsgId for local rooms only). subscription.count uses errgroup all-or-nothing fallback-to-total — deliberately distinct from enrichment's per-site degradation.

Testing

  • Unit (-race): service 96.2%, config 100%, whole repo green.
  • Integration tests run + pass locally against real MongoDB 8.2.9 + NATS (mongorepo/roomclient/publisher). This surfaced and fixed 2 bugs static review missed: missing bson:",inline" on embedded structs (Mongo decoded embedded fields empty/nil) and a _updatedAtupdatedAt field-name error.
  • gosec clean on new code. make lint 0 issues. make generate idempotent.
  • Frontend: npm run typecheck clean, 601 tests pass.

Schema decisions (confirmed with product)

  • HRInfo.Name ← user's chineseName; engName is the English name.
  • updatedWithinDays filters the subscription doc's real updatedAt field.
  • active filter is {$ne: false} — the (scheduled) active field being absent counts as active; only explicit active:false drops the user.

CI notes

govulncheck and semgrep could not run in the dev sandbox (vuln-DB / registry network-blocked) — they run in the sast CI gate. docs/client-api.md + CLAUDE.md updated for the 8 endpoints, new reason codes, enrichment behaviors, and the UserStatusUpdated event.

https://claude.ai/code/session_016ptgodFMgtsDaEnzL15TMG


Generated by Claude Code

Summary by CodeRabbit

  • New Features

    • Unified subscription listing via a single subscription.list API with type/filtering.
    • New user-service with app subscription management and cross-site user status publishing.
  • Bug Fixes

    • Subscriptions include enriched room metadata (counts, last-message info).
    • Stronger DM target validation to prevent invalid DM requests.
  • Documentation

    • Updated API reference, design notes, and project context to reflect the consolidated endpoints and bootstrap changes.
  • Tests

    • Extensive new unit and integration tests covering service, storage, publisher, and client behaviors.
  • Deprecations

    • Removed legacy subscription endpoints and profile-name lookup.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 7, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c0c553cb-5e77-469a-8ca3-f35e32d738e3

📥 Commits

Reviewing files that changed from the base of the PR and between ab6cf7a and 57bf53c.

📒 Files selected for processing (63)
  • CLAUDE.md
  • chat-frontend/src/api/_transport/subjects.test.js
  • chat-frontend/src/api/_transport/subjects.ts
  • chat-frontend/src/api/fetchSidebarBuckets/index.ts
  • chat-frontend/src/api/types.ts
  • chat-frontend/src/context/RoomEventsContext/RoomEventsContext.test.jsx
  • chat-frontend/src/context/RoomEventsContext/RoomEventsContext.tsx
  • chat-frontend/src/context/RoomKeysContext/RoomKeysContext.tsx
  • docs/client-api.md
  • docs/superpowers/plans/2026-06-04-user-service.md
  • docs/superpowers/specs/2026-06-04-user-service-design.md
  • docs/user-service-endpoint-consolidation.md
  • mock-user-service/deploy/Dockerfile
  • mock-user-service/handler.go
  • mock-user-service/handler_test.go
  • mock-user-service/main.go
  • pkg/errcode/codes_test.go
  • pkg/errcode/codes_user.go
  • pkg/errcode/codes_user_test.go
  • pkg/model/event.go
  • pkg/model/model_test.go
  • pkg/model/subscription.go
  • pkg/subject/subject.go
  • pkg/subject/subject_test.go
  • tools/loadgen/daily_actions.go
  • tools/loadgen/daily_actions_test.go
  • user-service/config/config.go
  • user-service/config/config_test.go
  • user-service/deploy/Dockerfile
  • user-service/deploy/azure-pipelines.yml
  • user-service/deploy/docker-compose.yml
  • user-service/main.go
  • user-service/models/app.go
  • user-service/models/app_test.go
  • user-service/models/status.go
  • user-service/models/status_test.go
  • user-service/models/subscription.go
  • user-service/models/subscription_test.go
  • user-service/mongorepo/apps.go
  • user-service/mongorepo/apps_test.go
  • user-service/mongorepo/main_test.go
  • user-service/mongorepo/setup_test.go
  • user-service/mongorepo/store.go
  • user-service/mongorepo/store_test.go
  • user-service/mongorepo/subscriptions.go
  • user-service/mongorepo/subscriptions_test.go
  • user-service/mongorepo/users.go
  • user-service/mongorepo/users_test.go
  • user-service/publisher/publisher.go
  • user-service/publisher/publisher_integration_test.go
  • user-service/roomclient/client.go
  • user-service/roomclient/client_integration_test.go
  • user-service/service/apps.go
  • user-service/service/apps_test.go
  • user-service/service/enrich_test.go
  • user-service/service/metrics.go
  • user-service/service/mocks/mock_repository.go
  • user-service/service/service.go
  • user-service/service/service_test.go
  • user-service/service/status.go
  • user-service/service/status_test.go
  • user-service/service/subscriptions.go
  • user-service/service/subscriptions_test.go
💤 Files with no reviewable changes (4)
  • mock-user-service/main.go
  • mock-user-service/deploy/Dockerfile
  • mock-user-service/handler_test.go
  • mock-user-service/handler.go
✅ Files skipped from review due to trivial changes (5)
  • user-service/deploy/Dockerfile
  • chat-frontend/src/context/RoomKeysContext/RoomKeysContext.tsx
  • CLAUDE.md
  • user-service/service/metrics.go
  • chat-frontend/src/context/RoomEventsContext/RoomEventsContext.tsx
🚧 Files skipped from review as they are similar to previous changes (45)
  • pkg/errcode/codes_test.go
  • user-service/service/service_test.go
  • user-service/mongorepo/setup_test.go
  • chat-frontend/src/api/_transport/subjects.test.js
  • tools/loadgen/daily_actions_test.go
  • tools/loadgen/daily_actions.go
  • user-service/publisher/publisher.go
  • user-service/config/config_test.go
  • user-service/models/app.go
  • pkg/errcode/codes_user.go
  • user-service/mongorepo/store_test.go
  • user-service/mongorepo/users_test.go
  • user-service/models/status.go
  • user-service/deploy/azure-pipelines.yml
  • user-service/mongorepo/main_test.go
  • chat-frontend/src/api/_transport/subjects.ts
  • user-service/service/mocks/mock_repository.go
  • user-service/models/subscription_test.go
  • pkg/model/event.go
  • user-service/models/status_test.go
  • chat-frontend/src/api/types.ts
  • user-service/service/enrich_test.go
  • pkg/model/subscription.go
  • pkg/model/model_test.go
  • user-service/models/app_test.go
  • user-service/service/service.go
  • user-service/mongorepo/apps.go
  • user-service/config/config.go
  • user-service/mongorepo/apps_test.go
  • user-service/service/status.go
  • user-service/service/apps_test.go
  • pkg/subject/subject_test.go
  • user-service/service/status_test.go
  • chat-frontend/src/api/fetchSidebarBuckets/index.ts
  • user-service/roomclient/client_integration_test.go
  • user-service/roomclient/client.go
  • docs/client-api.md
  • user-service/main.go
  • user-service/mongorepo/store.go
  • user-service/mongorepo/subscriptions_test.go
  • user-service/service/subscriptions.go
  • user-service/mongorepo/subscriptions.go
  • chat-frontend/src/context/RoomEventsContext/RoomEventsContext.test.jsx
  • user-service/service/subscriptions_test.go
  • pkg/subject/subject.go

📝 Walkthrough

Walkthrough

Consolidates subscription RPCs into a single subscription.list, adds a new user-service implementation (config, service, mongorepo, roomclient, publisher), updates frontend callsites/tests and loadgen, removes mock-user-service, and updates docs and deployment manifests.

Changes

User-service rollout and contract migration

Layer / File(s) Summary
Backend subject and shared wire contracts
pkg/subject/*, pkg/errcode/*, pkg/model/*, user-service/models/*, docs/*
Adds subscription.list, subscription.setAppSubscription, new user error reasons and event UserStatusUpdated, plus matching contract and model tests.
Service foundation and runtime wiring
user-service/config/*, user-service/service/*, user-service/main.go, user-service/service/mocks/*
Introduces user-service config loader, service interfaces/implementation, handler registration, generated gomock mocks, and test helpers.
Mongo repository implementation and integration coverage
user-service/mongorepo/*
Adds mongorepo Store, aggregation pipelines, subscription/app/user accessors, index creation, and extensive integration tests for queries and mutations.
Room RPC client and outbox publisher integrations
user-service/roomclient/*, user-service/publisher/*
Implements NATS-backed room info RPC client and outbox publisher with integration tests for request/reply and publish error paths.
Status and apps handlers
user-service/service/status.go, user-service/service/apps.go
Implements status get/set (with cross-site outbox publish) and app subscription/apps list handlers with unit tests and validation.
Subscription handlers, enrichment, counting, and metrics
user-service/service/subscriptions.go, user-service/service/metrics.go
Adds List/GetChannels/GetDM/Count handlers, room-info enrichment with per-site degradation, unread counting with fallback metric, and tests.
Frontend and loadgen migration to subscription.list
chat-frontend/src/api/*, chat-frontend/src/context/*, tools/loadgen/*
Replaces three subscription subjects with userSubscriptionList, updates fetchSidebarBuckets and RoomEventsContext tests, and updates loadgen payloads.
Runtime wiring and deployment switch
user-service/deploy/*, mock-user-service/*
Adds Dockerfile/docker-compose/pipeline for user-service and removes mock-user-service files and Dockerfile.
Documentation and design/spec rollout
CLAUDE.md, docs/client-api.md, docs/superpowers/*
Adds §3.4 user-service API docs, endpoint consolidation notes, design/spec and plan documents, and updates client API and CLAUDE.md.

Sequence Diagram(s)

sequenceDiagram
  participant ChatFrontend
  participant UserService
  participant Mongorepo
  participant RoomClient
  participant Publisher
  ChatFrontend->>UserService: subscription.list / subscription.count / subscription.setAppSubscription / status.set / apps.list
  UserService->>Mongorepo: query or update user, subscription, app data
  UserService->>RoomClient: GetRoomsInfo or CreateDMRoom RPC
  UserService->>Publisher: publish UserStatusUpdated event to outbox subjects
  UserService-->>ChatFrontend: reply payload or typed error
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

  • hmchangw/chat#175: Earlier mock user-service RPC surface that this PR removes in favor of the new user-service.
  • hmchangw/chat#241: Related front/backend changes for Subscription.u.isBot field used across services.
  • hmchangw/chat#192: Implements subscription.count usage and is related to the new count handler/subject.

Suggested labels

ready

Suggested reviewers

  • mliu33

Poem

🐰 I hopped through subjects old and new,
One list now carries all the view.
NATS bells ring and Mongo sings,
Keys and statuses on eager wings.
Hooray — the rabbit nets the queue.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/cool-davinci-6lYhU

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 15

🧹 Nitpick comments (2)
user-service/mongorepo/store_test.go (1)

19-25: ⚡ Quick win

Assert concrete index definitions instead of minimum counts.

This test can still pass if an expected index is removed but another unrelated index exists. Consider asserting index names (or key specs) explicitly for subscriptions and users.

🤖 Prompt for 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.

In `@user-service/mongorepo/store_test.go` around lines 19 - 25, The test
currently only checks minimum index counts for the subscriptions and users index
lists (variables idx and uidx), which can miss missing specific indexes; update
the assertions to verify the exact index definitions instead: after loading idx
and uidx (from s.subscriptions.Raw().Indexes().List and
s.users.Raw().Indexes().List via ucur), assert that the expected index entries
exist by checking either the index "name" values or the "key" specs (e.g., that
an index with key {"account": 1} or the known index name is present) rather than
using require.GreaterOrEqual; implement this by building a set of found index
names/keys from idx/uidx and asserting the expected names/keys are contained.
user-service/service/service.go (1)

13-13: ⚡ Quick win

Align mock generation with the repo’s test-mock convention.

Line 13 generates mocks into a non-test file under service/mocks. Repository guidance for store mocks is to generate test-only mocks (mock_store_test.go) and regenerate via make generate.

As per coding guidelines, “Define the store interface in store.go … include a //go:generate mockgen directive to auto-generate mocks into mock_store_test.go.”

🤖 Prompt for 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.

In `@user-service/service/service.go` at line 13, Update the mockgen directive so
mocks follow the repo convention: move the //go:generate line out of service.go
and place it into store.go (where the store interfaces are defined) and change
the directive to generate test-only mocks into mock_store_test.go (targeting the
UserStore interface); remove or stop generating non-test mocks for
RoomClient/EventPublisher from service/mocks so only store mocks are produced
via mock_store_test.go as per the project guideline.

Source: Coding guidelines

🤖 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 `@chat-frontend/src/context/RoomEventsContext/RoomEventsContext.tsx`:
- Around line 382-385: Update the cold-start fallback comment in
RoomEventsContext.tsx to remove the stale reference to listRooms and instead
state that summaries can be populated from subscription.list results;
specifically, replace the phrase "listRooms may have populated `summaries`" with
wording that `subscription.list` may have already populated `summaries` so the
comment correctly reflects the current bootstrap flow used by the sidebar (see
references to `subscription.list` and the `summaries` variable).

In `@claude_its_a_gift_for_u.txt`:
- Line 534: Remove the stray raw closing tag '</content>' that appears in the
markdown-style guide in claude_its_a_gift_for_u.txt; locate the literal string
"</content>" and delete it so the markdown renders correctly and no extraneous
XML/HTML tag remains in the document.

In `@docs/client-api.md`:
- Line 3118: Update the stale cross-reference in the "Initial key bootstrap on
(re)connect" paragraph to reference the consolidated user-service subscription
endpoints instead of the removed subscription.get* APIs: replace the mention of
`subscription.get*` with the current bootstrap path (e.g.,
`subscription.list`-based bootstrap) and point to §3.4's consolidated
user-service contract; ensure the text clarifies that the initial set of keys
for already-subscribed rooms is delivered via the subscription.list (or
equivalent user-service subscription endpoint) rather than live events only.

In `@docs/superpowers/specs/2026-06-04-user-service-design.md`:
- Around line 336-338: Remove the impossible "Each method first guards the site"
sentence and replace it with a clear statement that site isolation is
structural: explain that the *Pattern builders (e.g.,
UserStatusGetByNamePattern(siteID)) bake siteID as a literal token (only
{account} is captured), so c.Param("siteID") will be empty and per-request
guards are not used; state that service instances subscribe only to subjects
containing their cfg.SiteID so handlers should start directly with
validation/business logic, and note that s.siteID and s.allSiteIDs are used by
publishStatus for cross-site outbox routing (this mirrors the behavior seen in
service.go where no per-request site guard is present).

In `@pkg/model/model_test.go`:
- Around line 3051-3061: The test TestUserStatusUpdated_RoundTrip only covers
the non-nil StatusIsShow path; add a second subtest that constructs src :=
model.UserStatusUpdated with StatusIsShow set to nil (and the same other
fields), roundTrips it into dst using the existing roundTrip helper, and asserts
the deserialized dst.StatusIsShow is nil to lock the omitempty/wire-shape
behavior; update or add assertions consistent with the existing test style so
both the non-nil and nil cases are covered.

In `@tools/loadgen/daily_actions_test.go`:
- Around line 75-78: The test currently asserts the raw JSON string for the
subscription.list payload; change it to unmarshal c.reqs[0].Data into the typed
request struct from pkg/model (e.g. model.SubscriptionListRequest or the struct
used for subscription.list) and assert the struct equals the expected value
(Type: "rooms") instead of using require.JSONEq; update the assertion after
refreshRoomList(ctx, u) so it decodes c.reqs[0].Data with encoding/json into the
model struct and uses require.Equal/require.EqualValues against the expected
model struct, leaving subject.UserSubscriptionList("user-1", "site-test") check
intact.

In `@tools/loadgen/daily_actions.go`:
- Around line 94-99: Replace the ad-hoc map payload with a typed request struct
from pkg/model (e.g. add or use pkg/model.SubscriptionListRequest with a Type
string field), then marshal that struct instead of the map before calling
a.Request; update the code in daily_actions.go where payload is created
(currently json.Marshal(map[string]string{"type":"rooms"})) to
json.Marshal(model.SubscriptionListRequest{Type: "rooms"}), add the struct in
pkg/model if missing, and add the necessary import for pkg/model so the
compile-time contract is enforced.

In `@user-service/models/subscription_test.go`:
- Around line 81-106: TestCountRequest_RoundTrip lacks a case for a non-nil
false pointer; add a subtest under TestCountRequest_RoundTrip that constructs in
:= CountRequest{Unread: ptr(false)}, marshals and unmarshals it, asserts
equality with in, and specifically checks out.Unread is non-nil and *out.Unread
== false to ensure the JSON contains "unread": false; reference the
TestCountRequest_RoundTrip function and the CountRequest.Unread field when
adding this new subtest.

In `@user-service/mongorepo/apps_test.go`:
- Around line 21-26: Add a collision seed with the same subscription name but a
different roomType and assert it doesn't affect the botDM-only check: use the
existing seed helper to insert another document for user "u-alice" with "name":
"helper.bot" and "roomType": "channel" (or similar) into the "subscriptions"
collection, then call the same IsSubscribed check (the function/method under
test, e.g., IsSubscribed on the service `s`) and assert the result still
reflects only the botDM subscription; repeat the same change for the other test
block referenced (lines 55-63).

In `@user-service/mongorepo/apps.go`:
- Around line 26-30: In ListApps where the subscription lookup pipeline builds
the $match $expr (the bson.A $and array used in the pipeline variable), add a
condition to require the subscription's roomType equals "botDM" so isSubscribed
only flips for bot DM subscriptions; update the bson.M{"$and": bson.A{...}} to
include a bson.M{"$eq": bson.A{"$roomType", "botDM"}} (or equivalent constant)
alongside the existing account/name/isSubscribed checks so the subscription
match is restricted to botDM records.

In `@user-service/mongorepo/users_test.go`:
- Around line 53-79: The two subtests in TestSetUserStatus_Integration are
sharing mutable state; make them independent by seeding the user state
separately for each t.Run (or resetting the store) before calling
SetUserStatus/GetUserStatus. Specifically, inside each subtest body re-run
seed(...) to create a fresh document for account "bob" with the exact initial
fields you need (first subtest: initial StatusIsShow nil/false as appropriate;
second subtest: initial StatusIsShow true) so SetUserStatus and GetUserStatus
operate on an isolated state; ensure you use the same store instance s and
context ctx but avoid relying on the first subtest to set status for the second.

In `@user-service/publisher/publisher.go`:
- Around line 19-20: The Publisher.Publish method currently returns the raw
error from the transport call p.nc.Publish; change it to wrap that error with
contextual text (e.g., using fmt.Errorf("publish to %s failed: %w", subject,
err)) so callers see the operation boundary and subject; update the Publish
function to capture the error from p.nc.Publish and return a wrapped error when
non-nil.

In `@user-service/service/service.go`:
- Around line 69-77: The handler registration is using the passed-in siteID
instead of the service's configured site ID; update RegisterHandlers to use the
service configuration (e.g., s.cfg.SiteID or s.SiteID depending on your struct)
when calling natsrouter.Register and natsrouter.RegisterNoBody (function:
RegisterHandlers), replacing occurrences of the local siteID variable with the
configured site ID; optionally remove the siteID parameter from RegisterHandlers
to avoid future divergence and update all call sites accordingly.

In `@user-service/service/status.go`:
- Line 66: The publish-failure log call using slog.Error should include the
request/correlation ID from the current context: extract the ID from ctx (using
your existing helper like RequestIDFromContext(ctx) or ctx.Value("request_id")
if available), handle a missing value with a sensible default, and add it as an
explicit field (e.g. "request_id" or "correlation_id") to the slog.Error call
alongside the existing "error", "dest", and "account" fields so the log line is
traceable across services; update the logging call that currently passes err,
dest, account to include this ID and ensure the extraction is safe when ctx is
nil.

In `@user-service/service/subscriptions.go`:
- Around line 212-213: The unread count is undercounted because
GetActiveSubscriptions is called with s.maxSubs instead of the already-computed
total; change the call to s.store.GetActiveSubscriptions(ctx, account, total)
(or otherwise use the precomputed total variable) so that subs is fetched using
the correct cap used for unread calculation (ensure the existing variable named
total is in scope where subs is requested and remove/replace s.maxSubs there).

---

Nitpick comments:
In `@user-service/mongorepo/store_test.go`:
- Around line 19-25: The test currently only checks minimum index counts for the
subscriptions and users index lists (variables idx and uidx), which can miss
missing specific indexes; update the assertions to verify the exact index
definitions instead: after loading idx and uidx (from
s.subscriptions.Raw().Indexes().List and s.users.Raw().Indexes().List via ucur),
assert that the expected index entries exist by checking either the index "name"
values or the "key" specs (e.g., that an index with key {"account": 1} or the
known index name is present) rather than using require.GreaterOrEqual; implement
this by building a set of found index names/keys from idx/uidx and asserting the
expected names/keys are contained.

In `@user-service/service/service.go`:
- Line 13: Update the mockgen directive so mocks follow the repo convention:
move the //go:generate line out of service.go and place it into store.go (where
the store interfaces are defined) and change the directive to generate test-only
mocks into mock_store_test.go (targeting the UserStore interface); remove or
stop generating non-test mocks for RoomClient/EventPublisher from service/mocks
so only store mocks are produced via mock_store_test.go as per the project
guideline.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5e9c5ed7-0650-4124-8b68-f0329807f601

📥 Commits

Reviewing files that changed from the base of the PR and between 622618d and fcae691.

📒 Files selected for processing (64)
  • CLAUDE.md
  • chat-frontend/src/api/_transport/subjects.test.js
  • chat-frontend/src/api/_transport/subjects.ts
  • chat-frontend/src/api/fetchSidebarBuckets/index.ts
  • chat-frontend/src/api/types.ts
  • chat-frontend/src/context/RoomEventsContext/RoomEventsContext.test.jsx
  • chat-frontend/src/context/RoomEventsContext/RoomEventsContext.tsx
  • chat-frontend/src/context/RoomKeysContext/RoomKeysContext.tsx
  • claude_its_a_gift_for_u.txt
  • docs/client-api.md
  • docs/superpowers/plans/2026-06-04-user-service.md
  • docs/superpowers/specs/2026-06-04-user-service-design.md
  • docs/user-service-endpoint-consolidation.md
  • mock-user-service/deploy/Dockerfile
  • mock-user-service/handler.go
  • mock-user-service/handler_test.go
  • mock-user-service/main.go
  • pkg/errcode/codes_test.go
  • pkg/errcode/codes_user.go
  • pkg/errcode/codes_user_test.go
  • pkg/model/event.go
  • pkg/model/model_test.go
  • pkg/model/subscription.go
  • pkg/model/user.go
  • pkg/subject/subject.go
  • pkg/subject/subject_test.go
  • tools/loadgen/daily_actions.go
  • tools/loadgen/daily_actions_test.go
  • user-service/config/config.go
  • user-service/config/config_test.go
  • user-service/deploy/Dockerfile
  • user-service/deploy/azure-pipelines.yml
  • user-service/deploy/docker-compose.yml
  • user-service/main.go
  • user-service/models/app.go
  • user-service/models/app_test.go
  • user-service/models/status.go
  • user-service/models/status_test.go
  • user-service/models/subscription.go
  • user-service/models/subscription_test.go
  • user-service/mongorepo/apps.go
  • user-service/mongorepo/apps_test.go
  • user-service/mongorepo/main_test.go
  • user-service/mongorepo/setup_test.go
  • user-service/mongorepo/store.go
  • user-service/mongorepo/store_test.go
  • user-service/mongorepo/subscriptions.go
  • user-service/mongorepo/subscriptions_test.go
  • user-service/mongorepo/users.go
  • user-service/mongorepo/users_test.go
  • user-service/publisher/publisher.go
  • user-service/publisher/publisher_integration_test.go
  • user-service/roomclient/client.go
  • user-service/roomclient/client_integration_test.go
  • user-service/service/apps.go
  • user-service/service/apps_test.go
  • user-service/service/enrich_test.go
  • user-service/service/mocks/mock_repository.go
  • user-service/service/service.go
  • user-service/service/service_test.go
  • user-service/service/status.go
  • user-service/service/status_test.go
  • user-service/service/subscriptions.go
  • user-service/service/subscriptions_test.go
💤 Files with no reviewable changes (4)
  • mock-user-service/deploy/Dockerfile
  • mock-user-service/handler.go
  • mock-user-service/handler_test.go
  • mock-user-service/main.go

Comment thread chat-frontend/src/context/RoomEventsContext/RoomEventsContext.tsx
Comment thread claude_its_a_gift_for_u.txt Outdated
Comment thread docs/client-api.md Outdated
Comment thread docs/superpowers/specs/2026-06-04-user-service-design.md Outdated
Comment thread pkg/model/model_test.go
Comment thread user-service/mongorepo/users_test.go
Comment thread user-service/publisher/publisher.go Outdated
Comment thread user-service/service/service.go Outdated
Comment thread user-service/service/status.go Outdated
Comment thread user-service/service/subscriptions.go Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/superpowers/specs/2026-06-04-user-service-design.md (1)

546-554: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Remove the siteID mismatch error row; it conflicts with the structural routing model.

Line 553 reintroduces a per-request site-check outcome (NotFound("unknown site")), but this spec now states that siteID is not captured and handlers do not perform site guards. Keep the table aligned with Line 338 to avoid re-implementing the old bug.

🤖 Prompt for 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.

In `@docs/superpowers/specs/2026-06-04-user-service-design.md` around lines 546 -
554, The table in the reply conditions includes a "siteID mismatch" row that
conflicts with the new routing model; remove the `siteID` mismatch →
`NotFound("unknown site")` entry so handlers no longer perform per-request site
guards and the table stays consistent with the earlier spec (see the same
conditions table around Line 338); ensure only the remaining rows (e.g., `type`
checks, `getDM` targets, app not found/disabled, DM not found, Mongo error)
remain.
🧹 Nitpick comments (1)
docs/superpowers/specs/2026-06-04-user-service-design.md (1)

66-67: ⚡ Quick win

Drop the stale + checkSite mention in the service.go layout note.

This text is now inconsistent with the updated handler behavior section and can confuse implementers about expected service structure.

🤖 Prompt for 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.

In `@docs/superpowers/specs/2026-06-04-user-service-design.md` around lines 66 -
67, Update the layout note that documents service.go to remove the outdated "+
checkSite" mention: edit the "service.go          #   UserService struct, New(),
RegisterHandlers; interfaces + mockgen + checkSite" line so it no longer
references "+ checkSite", leaving only the current items (e.g., "interfaces +
mockgen") to match the updated handler behavior; ensure the note matches the
actual responsibilities of UserService, New(), and RegisterHandlers and update
any adjacent wording if necessary to avoid future confusion.
🤖 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.

Outside diff comments:
In `@docs/superpowers/specs/2026-06-04-user-service-design.md`:
- Around line 546-554: The table in the reply conditions includes a "siteID
mismatch" row that conflicts with the new routing model; remove the `siteID`
mismatch → `NotFound("unknown site")` entry so handlers no longer perform
per-request site guards and the table stays consistent with the earlier spec
(see the same conditions table around Line 338); ensure only the remaining rows
(e.g., `type` checks, `getDM` targets, app not found/disabled, DM not found,
Mongo error) remain.

---

Nitpick comments:
In `@docs/superpowers/specs/2026-06-04-user-service-design.md`:
- Around line 66-67: Update the layout note that documents service.go to remove
the outdated "+ checkSite" mention: edit the "service.go          #  
UserService struct, New(), RegisterHandlers; interfaces + mockgen + checkSite"
line so it no longer references "+ checkSite", leaving only the current items
(e.g., "interfaces + mockgen") to match the updated handler behavior; ensure the
note matches the actual responsibilities of UserService, New(), and
RegisterHandlers and update any adjacent wording if necessary to avoid future
confusion.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c7f44c44-9608-4bb9-bd4c-15286da628af

📥 Commits

Reviewing files that changed from the base of the PR and between fcae691 and d5e6e43.

📒 Files selected for processing (25)
  • chat-frontend/src/context/RoomEventsContext/RoomEventsContext.tsx
  • docs/client-api.md
  • docs/superpowers/specs/2026-06-04-user-service-design.md
  • pkg/model/event.go
  • pkg/model/model_test.go
  • tools/loadgen/daily_actions.go
  • tools/loadgen/daily_actions_test.go
  • user-service/config/config.go
  • user-service/config/config_test.go
  • user-service/deploy/docker-compose.yml
  • user-service/main.go
  • user-service/models/subscription_test.go
  • user-service/mongorepo/apps.go
  • user-service/mongorepo/apps_test.go
  • user-service/mongorepo/store.go
  • user-service/mongorepo/subscriptions.go
  • user-service/mongorepo/subscriptions_test.go
  • user-service/mongorepo/users_test.go
  • user-service/publisher/publisher.go
  • user-service/service/metrics.go
  • user-service/service/mocks/mock_repository.go
  • user-service/service/service.go
  • user-service/service/status.go
  • user-service/service/subscriptions.go
  • user-service/service/subscriptions_test.go
✅ Files skipped from review due to trivial changes (2)
  • chat-frontend/src/context/RoomEventsContext/RoomEventsContext.tsx
  • user-service/service/mocks/mock_repository.go
🚧 Files skipped from review as they are similar to previous changes (17)
  • pkg/model/event.go
  • user-service/mongorepo/apps.go
  • pkg/model/model_test.go
  • user-service/mongorepo/apps_test.go
  • tools/loadgen/daily_actions.go
  • tools/loadgen/daily_actions_test.go
  • user-service/mongorepo/store.go
  • user-service/deploy/docker-compose.yml
  • user-service/mongorepo/users_test.go
  • user-service/main.go
  • docs/client-api.md
  • user-service/service/status.go
  • user-service/mongorepo/subscriptions_test.go
  • user-service/models/subscription_test.go
  • user-service/service/subscriptions_test.go
  • user-service/mongorepo/subscriptions.go
  • user-service/service/subscriptions.go

claude added 13 commits June 7, 2026 11:32
@amdla amdla force-pushed the claude/cool-davinci-6lYhU branch from 24ec624 to 57bf53c Compare June 7, 2026 11: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