Skip to content

Conversation

eyeinsky
Copy link
Collaborator

@eyeinsky eyeinsky commented Sep 23, 2025

Task checklist:

  • add field searchable
  • default value is True
  • must only be changed from the new /users/:uid/searchable API endpoint and by team admin, and nowhere else
  • add permission SetMemberSearchable
  • must be exposed from user profile
  • must be indexed by ES
  • /search/contacts must filter based on searchable = True
  • /teams/:tid/members must expose a filter to find non-searchable users; otherwise ignore it
  • exact handle search via public endpoint must return 404
  • calling HEAD should ignore the field: used to check whether handle is taken
  • add documentation of searchable field behavior
  • adds a test to check the above
  • exact handle search via internal endpoint should ignore this property
    • if no such endpoint exists, it should be created

Open questions

  • is the changed admin toggle API type ok? The task designates this as POST /users/:uid/searchable, but as TeamId is required, then it currently is POST /users/:uid/:tid/searchable -- could this be improved?
  • POST /handles: should this endpoint also filter based on searchability?
  • are there no other locations than /search/contacts to take searchability into account?
  • should the test be moved into the integration package?

Checklist

  • Add a new entry in an appropriate subdirectory of changelog.d
  • Read and follow the PR guidelines

@zebot zebot added the ok-to-test Approved for running tests in CI, overrides not-ok-to-test if both labels exist label Sep 23, 2025
@eyeinsky eyeinsky force-pushed the ml/WPB-20214-user-searchable branch 5 times, most recently from bc31287 to 78ad65e Compare September 25, 2025 08:44
@eyeinsky
Copy link
Collaborator Author

eyeinsky commented Sep 25, 2025

The below is now resolved.


The current error when running the test is this:

[[email protected]] E, IO Exception occurred, message=cql-io: protocol error: parse error: response body reading: Failed reading: column count: 24 =/= 26 Empty call stack , request=37d3c1fa-f1ee-4050-b623-e4c9c79e5584
[[email protected]] E, request=37d3c1fa-f1ee-4050-b623-e4c9c79e5584, code=500, label=server-error, "Server Error"
brig-integration: Assertions failed:
 1: 201 =/= 500

Response was:

Response {responseStatus = Status {statusCode = 500, statusMessage = "Internal Server Error"}, responseVersion = HTTP/1.1, responseHeaders = [("Transfer-Encoding","chunked"),("Date","Thu, 25 Sep 2025 09:00:01 GMT"),("Server","Warp/3.4.2"),("traceparent","00-96836cd3b1eedf0553338dde6b2d4b0c-1ced0252881c377c-01"),("tracestate",""),("Content-Encoding","gzip"),("Content-Type","application/json"),("Vary","Accept-Encoding")], responseBody = Just "{\"code\":500,\"label\":\"server-error\",\"message\":\"Internal Server Error\"}", responseCookieJar = CJ {expose = []}, responseClose' = ResponseClose, responseOriginalRequest = Request {
  host                 = "127.0.0.1"
  port                 = 8082
  secure               = False
  requestHeaders       = [("Content-Type","application/json")]
  path                 = "/i/users"
  queryString          = ""
  method               = "POST"
  proxy                = Nothing
  rawBody              = False
  redirectCount        = 10
  responseTimeout      = ResponseTimeoutDefault
  requestVersion       = HTTP/1.1
  proxySecureMode      = ProxySecureWithConnect
}
, responseEarlyHints = []}
CallStack (from HasCallStack):
  error, called at src/Bilge/Assert.hs:91:5 in bilge-0.22.0-inplace:Bilge.Assert
  <!!, called at test/integration/API/Team/Util.hs:140:9 in brig-2.0-inplace-brig-integration:API.Team.Util
  createUserWithTeam', called at test/integration/API/Team/Util.hs:89:21 in brig-2.0-inplace-brig-integration:API.Team.Util
  createPopulatedBindingTeamWithNames, called at test/integration/API/Team/Util.hs:68:25 in brig-2.0-inplace-brig-integration:API.Team.Util
  createPopulatedBindingTeamWithNamesAndHandles, called at test/integration/API/Search.hs:165:38 in brig-2.0-inplace-brig-integration:API.Search

From running this command: make c package=all && ./hack/bin/cabal-run-integration.sh brig -p '/testUserSearchable/'

@eyeinsky eyeinsky force-pushed the ml/WPB-20214-user-searchable branch 3 times, most recently from 9891c56 to 6a1a1b8 Compare October 3, 2025 07:56
@eyeinsky eyeinsky marked this pull request as ready for review October 3, 2025 08:17
@eyeinsky eyeinsky requested a review from a team as a code owner October 3, 2025 08:17
@eyeinsky eyeinsky force-pushed the ml/WPB-20214-user-searchable branch from 6a1a1b8 to 4790b05 Compare October 6, 2025 09:59
@eyeinsky
Copy link
Collaborator Author

eyeinsky commented Oct 6, 2025

@akshaymankar Noting here what you asked about in the standup: the /search/contacts endpoint fetches the results from ES which is populated from Cassandra's user table. This has the searchable field, so filtering there is easy. The /team/:tid/members?searchable=false on the other hand gets its results from Cassandra's team_member table, which doesn't have a searchable field.. But since I need to return all non-searchable users from this table, then I think the current (pre-postgres) way to do it would be to get all rows from team_member and then filter that down to only non-searchable users by the help of users table. With large table this might costly to do. 🤔

When we had all data in postgres though, the query could entirely be done on the database side: join team_member with user, then filter by searchable.

@akshaymankar
Copy link
Member

@eyeinsky I think we shouldn't support this query param on /teams/:tid/members endpoint, but rather on /teams/:tid/search endpoint. I just saw the ticket and it seems like I made a mistake in the name of this endpoint. Sorry about that 😞

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ok-to-test Approved for running tests in CI, overrides not-ok-to-test if both labels exist
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants