Skip to main content

conversation_participants

Overview

The conversation_participants table tracks which users belong to which conversations. It includes step-away tracking fields that record when a user has temporarily stepped away from a conversation, supporting the "absence is first-class" design principle.

Relevant Invariants

  • Invariant #15: "Non-Interaction Is Valid" -- Step-away tracking normalizes absence
  • Invariant #13: "Absence Is First-Class" -- Stepped-away state is an explicit, respected state

Schema

-- From 20260131_messaging_system.sql + 20260201_stepped_away_tracking.sql
CREATE TABLE conversation_participants (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
conversation_id UUID NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
joined_at TIMESTAMPTZ DEFAULT NOW(),
-- Step-away tracking (20260201_stepped_away_tracking.sql)
stepped_away_at TIMESTAMPTZ,
step_away_prompted BOOLEAN DEFAULT FALSE,
UNIQUE(conversation_id, user_id)
);

Columns

ColumnTypeNullableDefaultDescription
iduuidNogen_random_uuid()Primary key
conversation_iduuidNo--Conversation reference
user_iduuidNo--Participant user
joined_attimestamptzNoNOW()When user joined the conversation
stepped_away_attimestamptzYes--When user stepped away (null = active)
step_away_promptedbooleanNoFALSEWhether user was prompted about stepping away

RLS Policies

-- SELECT: Conversation participants can see other participants
CREATE POLICY "Participants can view other participants"
ON conversation_participants FOR SELECT
USING (EXISTS (
SELECT 1 FROM conversation_participants cp
WHERE cp.conversation_id = conversation_participants.conversation_id
AND cp.user_id = auth.uid()
));

-- UPDATE: Users can update their own participation (step away/return)
CREATE POLICY "Users can update own participation"
ON conversation_participants FOR UPDATE
USING (auth.uid() = user_id);

Last updated: 2026-02-07