Skip to content

fix(users): filter removed members from tdc users by default#10

Merged
scottlovegrove merged 2 commits into
mainfrom
feat/users-include-removed
May 28, 2026
Merged

fix(users): filter removed members from tdc users by default#10
scottlovegrove merged 2 commits into
mainfrom
feat/users-include-removed

Conversation

@scottlovegrove
Copy link
Copy Markdown
Collaborator

Summary

Port of Doist/twist-cli#245 to comms-cli.

tdc users was listing users who had been removed from the workspace, polluting tdc users [--json] output and silently breaking name/email resolution — any command that takes a user ref (tdc channel add, tdc group add-user, tdc thread … with notify) could resolve to a tombstoned user and then 403 from the backend with User N is not part of workspace.

Root cause: the Comms API's workspace_users/get returns both active and removed members with a removed: boolean flag. The SDK already exposed the field but the CLI ignored it. Comms SDK 0.3.0 adds an includeRemoved option that filters removed === true by default, mirroring @doist/twist-sdk@2.8.1.

Changes

Layer File Notes
Dependency package.json, package-lock.json @doist/comms-sdk 0.2.0 → 0.3.0
API helper src/lib/api.ts getWorkspaceUsers(workspaceId, { includeRemoved? }); cache keyed by (workspaceId, includeRemoved) so the two variants don't collide. Fixes tdc users, resolveUserRefs (src/lib/refs.ts), and resolveNotifyIds (src/commands/thread/helpers.ts) in one shot.
Command src/commands/user.ts New --include-removed flag. Human output appends a red [removed] chip.
JSON src/lib/output.ts removed added to USER_ESSENTIAL_FIELDS so callers can distinguish the two states without --full.
Docs src/lib/skills/content.ts, skills/comms-cli/SKILL.md New tdc users --include-removed example.
Tests src/commands/user.test.ts 3 new cases: default omits removed users, flag passes through, curated --json exposes removed without leaking shortName.
Tests src/lib/api.test.ts New file: 2 cases verifying we forward includeRemoved to the SDK unchanged.

Why a flag, not always filter

Audit / recovery cases occasionally do want the historical roster (e.g. "who used to be in here?"). --include-removed covers that without making the common case noisy.

Test plan

  • npm run type-check
  • npm run lint:check
  • npm run check:skill-sync
  • npm test — 689/689 passing (5 new)
  • Manual smoke against a real workspace:
    • tdc users --json | jq 'length' vs tdc users --include-removed --json | jq 'length' → counts differ
    • tdc users --include-removed shows red [removed] chip for removed members
    • tdc users --json | jq '.[0] | has("removed")'true
    • Try a write path that previously 403'd on a removed-by-name ref — confirm it now resolves cleanly to an active user (or fails fast as "user not found").

🤖 Generated with Claude Code

`tdc users` was listing users who had been removed from the workspace.
Same root cause as twist-cli#245: the Comms API returns both active and
removed members with a `removed: boolean` flag. Comms SDK 0.3.0 adds an
`includeRemoved` option that filters `removed === true` by default; this
change bumps the SDK and threads the option through.

- Bump @doist/comms-sdk 0.2.0 → 0.3.0
- `getWorkspaceUsers` accepts `{ includeRemoved? }`; cache keyed by both
  workspaceId and the flag
- `tdc users --include-removed` opts back into the historical roster and
  renders a red `[removed]` chip
- `removed` added to curated user JSON fields
- `resolveUserRefs` / `resolveNotifyIds` now default to active-only,
  fixing the silent "User N is not part of workspace" 403s on
  channel/group writes that resolve a tombstoned name

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@scottlovegrove scottlovegrove self-assigned this May 28, 2026
@doistbot doistbot requested a review from engfragui May 28, 2026 10:54
@scottlovegrove scottlovegrove added the 👀 Show PR PR must be reviewed before or after merging label May 28, 2026
Copy link
Copy Markdown
Member

@doistbot doistbot left a comment

Choose a reason for hiding this comment

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

Thanks scottlovegrove for your contribution 🤗. The upgrade to Comms SDK 0.3.0 and the new --include-removed flag cleanly solve the 403 errors by properly handling tombstoned users during reference lookups.

Few things worth tightening:

  • Update buildUserNameMap to explicitly fetch removed members (includeRemoved: true), ensuring historical messages from departed users don't fall back to displaying raw IDs.
  • Add a test to verify that the active-only and include-removed cache variants don't collide, confirming two separate API calls are made when both configurations are requested.

Share FeedbackReview Logs

Comment thread src/lib/api.ts Outdated
Comment thread src/lib/api.test.ts
Addresses PR #10 review feedback:

- `buildUserNameMap` now fetches `includeRemoved: true`. Historical
  messages from members who have since been removed need to render the
  author's name, not fall back to `user:123`. The active-only cache
  entry is left alone for ref-resolution callers.
- Add a cache-collision test in `api.test.ts` that calls
  `getWorkspaceUsers` with both default and `includeRemoved: true` to
  prove the cache keys don't collide and each variant is itself cached.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@scottlovegrove scottlovegrove merged commit 31e185c into main May 28, 2026
5 checks passed
@scottlovegrove scottlovegrove deleted the feat/users-include-removed branch May 28, 2026 11:02
doist-release-bot Bot added a commit that referenced this pull request May 28, 2026
## [1.3.1](v1.3.0...v1.3.1) (2026-05-28)

### Bug Fixes

* **users:** filter removed members from `tdc users` by default ([#10](#10)) ([31e185c](31e185c))
@doist-release-bot
Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 1.3.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

released 👀 Show PR PR must be reviewed before or after merging

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants