Skip to main content

Share with Everyone

Date: 2026-03-03
Status: Implemented
Type: Feature Addition

Summary

Added a "Share with everyone" option to conversation sharing, completing the three-tier sharing model: individual users, teams, and everyone. Owners can toggle a conversation's visibility to make it accessible to all authenticated users in the organization with full read and write access (same access level as user/team sharing).

Problem Statement

Conversation sharing was limited to specific users (by email) or teams (by team ID). There was no way to make a conversation broadly visible to the entire organization. The is_public field existed in the sharing schema but was not wired through the API or UI, leaving it permanently false.

Common use cases that required this:

  • Sharing best practices and solutions organization-wide
  • Incident post-mortem conversations
  • Onboarding materials and reference conversations
  • Cross-team knowledge sharing without managing individual access

Decision

Activate the existing is_public boolean field end-to-end rather than introducing a new sharing mechanism. This approach:

  • Requires zero schema migration (field already exists with default false)
  • Maintains backward compatibility
  • Follows the same API pattern as user/team sharing
AlternativeProsConsDecision
Activate is_public fieldNo migration, simple, consistentBinary (all or nothing)Chosen
"Organization" pseudo-teamReuses team modelRequires special team management, confusing UXRejected
Separate public endpointClean separationAPI duplication, extra routes to maintainRejected

Access Level Decision

Public access grants the same full access (read + write) as user/team sharing. Users who access a public conversation can both view messages and send new ones. Read-only enforcement for public viewers was considered but deferred — the current design matches the existing shared conversation behavior where all shared users can participate.

Solution Architecture

Access Check Flow

requireConversationAccess(conversationId, userId)

├─ Owner? ──────────────── ✅ GRANT

├─ is_public? ─────────── ✅ GRANT (new)

├─ shared_with user? ──── ✅ GRANT

├─ shared_with_teams? ─── ✅ GRANT (if member)

├─ sharing_access? ────── ✅ GRANT (if record exists)

└─ ────────────────────── ❌ DENY

API Changes

POST /api/chat/conversations/[id]/share

New: accepts is_public as a standalone sharing action:

{ "is_public": true }

Previously required user_emails or team_ids with permission. Now accepts any combination of:

  • is_public (standalone toggle)
  • user_emails + permission
  • team_ids + permission

Query Changes

Both conversation listing and shared listing endpoints add a public condition:

// GET /api/chat/conversations
const ownershipConditions = [
{ owner_id: user.email },
{ 'sharing.shared_with': user.email },
{ 'sharing.is_public': true }, // ← new
// + team conditions if applicable
];

// GET /api/chat/shared
const sharedConditions = [
{ 'sharing.shared_with': user.email },
{ 'sharing.is_public': true }, // ← new
// + team conditions if applicable
];

UI Changes

ShareDialog — New toggle switch between the copy-link section and the people/teams search:

┌─────────────────────────────────────────┐
│ Share Conversation │
│ My Conversation Title │
├─────────────────────────────────────────┤
│ Share Link [https://...] [Copy] │
├─────────────────────────────────────────┤
│ 🌐 Share with everyone [━━●] │ ← new toggle
│ Anyone in the organization... │
├─────────────────────────────────────────┤
│ People, Teams │
│ [Search by email or team name...] │
├─────────────────────────────────────────┤
│ Access (Everyone) │
│ 🌐 Everyone — All org members Can view│ ← new entry
│ 👤 user@example.com [🗑] │
│ 👥 Platform Engineering [🗑] │
└─────────────────────────────────────────┘

Sidebar — Differentiated sharing indicator:

  • Public: Green Globe icon with "Shared with everyone" tooltip
  • Private share: Blue Users icon with "Shared conversation" tooltip

Components Changed

FileChange
ui/src/types/mongodb.tsAdded is_public?: boolean to ShareConversationRequest
ui/src/lib/api-middleware.tsrequireConversationAccess checks is_public after owner check
ui/src/app/api/chat/conversations/[id]/share/route.tsHandles is_public toggle; relaxed validation for standalone toggle
ui/src/app/api/chat/conversations/route.tsAdded { 'sharing.is_public': true } to $or conditions
ui/src/app/api/chat/shared/route.tsAdded { 'sharing.is_public': true } to $or conditions
ui/src/components/chat/ShareDialog.tsxToggle switch, handleTogglePublic, "Everyone" access entry
ui/src/components/layout/Sidebar.tsxGlobe icon (green) for public, Users icon (blue) for private sharing
ui/src/app/api/__tests__/chat-sharing-teams.test.tsUpdated expectations for new is_public query condition
ui/src/app/api/__tests__/chat-sharing-public.test.tsNew — 19 tests for public sharing

Testing

  • 19 new tests in chat-sharing-public.test.ts:
    • Access control: public grant, deny, owner bypass, skip-teams optimization (5 tests)
    • API POST: toggle on/off, standalone, combined with users, validation, owner-only, response, auth (9 tests)
    • API GET: returns is_public state true/false (2 tests)
    • Query inclusion: conversations listing, shared listing with exclusions (3 tests)
  • 2 updated tests in existing chat-sharing-teams.test.ts for new query conditions

Migration Notes

  • No migration requiredis_public already exists in the schema with default false
  • Backward compatible — existing sharing with users and teams is unchanged
  • Gradual adoption — public sharing is opt-in per conversation by the owner
  • Spec: .specify/specs/share-with-everyone.md
  • Related ADR: docs/docs/changes/2026-01-30-admin-dashboard-teams-management.md
  • Branch: prebuild/feat/share-with-everyone