Conversation
…tion - Add users table (id, displayName, isAdmin, isAgent, avatarUrl, timestamps) - Apply DB migration: CREATE TABLE + GRANT to team_user - Seed initial users: chris, clio, domingo, zumie, gonzo - auth.ts: remove hardcoded validMailboxes set, load from users table at startup - auth.ts: export listUsers() for admin use - register.post.ts: auto-upsert users row on invite redemption - Add GET /api/admin/users — list users with presence enrichment - Add PATCH /api/admin/users/:id — update user profile/status - api.ts: add listUsers() and updateUser() client helpers
- Add GET /api/users — authenticated endpoint returning all active users - Add useUsers() / useUserIds() React hook with 5-min module-level cache - Replace ALL_USERS/KNOWN_USERS/KNOWN_RECIPIENTS constants in: - src/components/nav.tsx (presence avatar bar) - src/routes/presence.tsx (team list, group chat dialog) - src/routes/swarm.tsx (task assignee pickers, project lead pickers) - src/routes/admin.tsx (recurring task assignee picker) - src/components/compose-dialog.tsx (recipient quick-pick) - Any new user added to the users table now automatically appears everywhere
…view - Add archived_at column to chat_members (per-member, others unaffected) - DB migration applied - chat.ts: filter archived channels from default list; add archiveChannel/unarchiveChannel - GET /api/chat/channels: support ?archived=true to fetch archived chats - POST /api/chat/channels/:id/archive + /unarchive endpoints - api.ts: archiveChat() / unarchiveChat() / listChatChannels(archived) client helpers - presence.tsx: hover on chat row shows Archive icon (replaces timestamp) Archive button: removes from active list instantly Archived view: Archive icon in header toggles between active/archived ArchiveRestore icon in archived view to unarchive
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e42740a9aa
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
P1: user-select.tsx was spreading data.users (now HiveUser[]) directly into a string[] — map to ids before merging with value set P2: Boolean() coercion in admin PATCH endpoint would accept any non-empty string as true for isAdmin/isAgent flags — now requires strict boolean type, returns 400 on anything else
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 144f1b3ac9
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
P1 (auth.ts): archived users stay in validMailboxes until restart - Add deregisterMailbox() to auth.ts - PATCH /api/admin/users/:id now calls deregister/registerMailbox immediately when archivedAt is set/cleared — no restart needed P2 (presence.tsx): hover-only archive button unreachable on touch - Remove hoveredChannel state and mouse enter/leave handlers - Archive icon always visible (text-muted-foreground/30, tap target) with hover:text-muted-foreground for desktop polish - Timestamp shown alongside archive button at all times
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d2edc0175a
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
P1 (users.get.ts): env-token users missing from /api/users - Export getEnvIdentities() from auth.ts - /api/users merges DB users + env-only identities as minimal objects so all authenticated users appear in UI selectors regardless of whether they have a users table row P1 (patch.ts): archived users kept working tokens - On archive: revoke all mailboxTokens rows for that identity + clear DB auth cache — existing tokens immediately stop working - On restore: re-add to validMailboxes + clear cache (revoked tokens stay revoked; admin must issue new tokens)
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c22f9f11f5
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| .update(mailboxTokens) | ||
| .set({ revokedAt: new Date() }) | ||
| .where(eq(mailboxTokens.identity, id)); |
There was a problem hiding this comment.
Block archived users with env-backed tokens
Archiving currently revokes only mailbox_tokens rows, but auth still accepts identities from envTokens (HIVE_TOKEN_*, MAILBOX_TOKEN_*, UI_MAILBOX_KEYS) and sender routes do not re-check sender validity against mailbox status, so an archived user with an env-configured token can continue authenticating and calling protected APIs after archival. To make deactivation effective, archival needs to block env-token auth for that identity (or auth must check users.archived_at before returning a context).
Useful? React with 👍 / 👎.
| .filter((id) => !dbIds.has(id)) | ||
| .map((id) => ({ |
There was a problem hiding this comment.
Exclude archived env identities from
/api/users
The env fallback compares against dbIds built from listUsers() (non-archived only), so if an identity is archived in users but still present in env tokens, it is reintroduced as an active user object here. That makes archived accounts reappear in user pickers and causes downstream send/archive UX inconsistencies because those accounts were intentionally deactivated. The merge should exclude any identity that exists in users at all, not just currently active ones.
Useful? React with 👍 / 👎.
| export const users = pgTable("users", { | ||
| id: varchar("id", { length: 50 }).primaryKey(), // = identity slug ("gonzo", "chris") | ||
| displayName: varchar("display_name", { length: 100 }).notNull(), | ||
| isAdmin: boolean("is_admin").notNull().default(false), | ||
| isAgent: boolean("is_agent").notNull().default(false), // true for AI agents |
There was a problem hiding this comment.
Add a Drizzle migration for new user/chat schema
This change introduces new DB schema (users table and chat_members.archived_at) and immediately depends on it in runtime code, but no migration file was added under drizzle/ in this commit. Deployments that follow the documented db:migrate upgrade flow will keep the old schema and encounter runtime SQL failures when these queries run. A tracked migration is needed so upgrades apply the required DDL consistently.
Useful? React with 👍 / 👎.
What's new in v1.0.3
🧑🤝🧑 Central users table
userstable as canonical user registry (id, displayName, isAdmin, isAgent, avatarUrl)auth.ts: removed hardcodedvalidMailboxesset — loads from DB at startupusersrow for new membersGET /api/admin/users,PATCH /api/admin/users/:id🔄 Dynamic user lists
GET /api/users— authenticated endpoint (non-admin) for fetching active usersuseUsers()/useUserIds()React hook with 5-min module-level cacheALL_USERS/KNOWN_USERS/KNOWN_RECIPIENTSconstants across: nav avatar bar, presence team list, presence group chat dialog, swarm assignee pickers, admin recurring task picker, compose dialog recipient quick-pickuserstable now appears everywhere automatically🗄️ Chat archive (soft delete)
archived_atcolumn onchat_members(per-member — archiving only affects your view)GET /api/chat/channels— supports?archived=trueto fetch archived chatsPOST /api/chat/channels/:id/archiveand/unarchiveendpointsDB migrations applied