Skip to main content

friendships

Overview

The friendships table manages bidirectional friend relationships. CommonPlace only supports mutual friendships -- there are no one-way "follows." A friendship begins as a request (status = 'pending') and becomes active when accepted. The requester/addressee distinction tracks who initiated.

Relevant Invariants

  • Invariant #1: "Participation Is Always Voluntary" -- Friend requests can be declined or ignored without consequence
  • Invariant #7: "Human-Scale Social Contexts" -- Mutual friendships enforce small, intentional networks

Schema

-- Pre-existing table (inferred from frontend code)
CREATE TABLE friendships (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
requester_id UUID REFERENCES auth.users(id) NOT NULL,
addressee_id UUID REFERENCES auth.users(id) NOT NULL,
status TEXT DEFAULT 'pending' CHECK (status IN ('pending', 'accepted', 'declined')),
responded_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW(),
stepped_back_by UUID REFERENCES auth.users(id),
stepped_back_at TIMESTAMPTZ,
stepped_back_until TIMESTAMPTZ,
stepped_back_reason TEXT,
UNIQUE(requester_id, addressee_id)
);

Columns

ColumnTypeNullableDefaultDescription
iduuidNouuid_generate_v4()Primary key
requester_iduuidNo--User who sent the friend request
addressee_iduuidNo--User who received the request
statustextNo'pending'Request state: pending, accepted, declined
responded_attimestamptzYes--When request was accepted/declined
created_attimestamptzNoNOW()When request was sent
stepped_back_byuuidYes--Which user initiated the step-back (null = not stepped back)
stepped_back_attimestamptzYes--When the step-back was initiated
stepped_back_untiltimestamptzYes--Optional auto-restore date (null = indefinite)
stepped_back_reasontextYes--Private note visible only to the stepper

RLS Policies

-- SELECT: Users can see their own friendships
CREATE POLICY "Users can view own friendships"
ON friendships FOR SELECT
USING (auth.uid() = requester_id OR auth.uid() = addressee_id);

-- INSERT: Users can send friend requests
CREATE POLICY "Users can send friend requests"
ON friendships FOR INSERT
WITH CHECK (auth.uid() = requester_id);

-- UPDATE: Addressee can accept/decline requests
CREATE POLICY "Users can respond to friend requests"
ON friendships FOR UPDATE
USING (auth.uid() = addressee_id);

-- DELETE: Either party can remove friendship
CREATE POLICY "Users can remove friendships"
ON friendships FOR DELETE
USING (auth.uid() = requester_id OR auth.uid() = addressee_id);

Step-Back Feature

The stepped_back_* columns enable a private, temporary break from seeing a friend's posts without blocking them. Key properties:

  • Private: The other party is never notified
  • Reversible: Clearing the columns restores normal visibility
  • Optional expiration: stepped_back_until allows auto-restore after a set time
  • Feed filtering: The posts SELECT RLS policy excludes posts from stepped-back friends

The frontend hook useSteppedBack (in src/hooks/useSteppedBack.js) manages this state and auto-checks for expired step-backs every hour.

  • profiles -- Both parties in the friendship
  • blocks -- Blocking removes friendships
  • circles -- Friends can be organized into circles
  • relationship_edges -- Custom relationship labels between friends

Last updated: 2026-02-08