Skip to main content
PATCH
Note: This endpoint was previously documented as GET /api/threads/{id}/share but the actual backend implementation is PATCH /api/threads/{id}/visibility (Lines 338-420 in ThreadsController.cs). The /share endpoint does NOT exist in the current backend.

Authentication

Required: JWT Bearer token JWT Claims Extraction (Lines 346-350):

Path Parameters

string
required
Thread UUIDFormat: Valid GUIDValidation: Route constraint :guid (Line 339)

Request Body

string
required
New visibility levelValidation (Lines 381-400):
Allowed Values:
  • "private": Owner-only access
  • "public": Public access when public_sharing feature enabled
  • "unlisted": Accessible via direct link when public_sharing feature enabled
Case-Insensitive: Automatically lowercased (Line 392)

Authorization

Ownership Verification (Lines 358-378):
Permission Rules:
  • ONLY thread owner can change visibility (Line 369)
  • Explicit message: “Only the thread owner can change visibility” (Line 375)
  • No delegation or admin override

Side Effects

Database Mutations (Line 402):
Tables Written:
  • UPDATE threads SET visibility = {request.Visibility}, updated_at = NOW() WHERE thread_id = {threadId}
Access Control Changes:
  • Changing TO "private": Thread becomes owner-only
  • Changing TO "public": Thread becomes publicly accessible (if public_sharing feature enabled)
  • Changing TO "unlisted": Thread accessible via direct link (if public_sharing feature enabled)
Cascade Effects: None
  • Existing messages/comparisons/votes unaffected
  • Thread remains in owner’s thread list
  • Share URLs become invalid/valid based on new visibility

Permissions

Who Can Modify Visibility:
  • Thread owner only
Who Cannot Modify:
  • Other authenticated users
  • Public thread viewers
  • Admins (not documented as exception)

Visibility Semantics

private

  • Access: Owner only, always
  • Feature Flag: Irrelevant (owner-only regardless)
  • Sharing: Cannot be shared

public

  • Access: Anyone if public_sharing = true, owner only if false
  • Discovery: May be listed in public directories (implementation-dependent)
  • Indexing: May be indexed by search engines

unlisted

  • Access: Anyone with link if public_sharing = true, owner only if false
  • Discovery: Not listed publicly
  • Indexing: Implementation-dependent

Edge Cases

  1. Thread doesn’t exist: 404 (Lines 359-367)
  2. User is not owner: 403 (Lines 369-378)
  3. Visibility is null: 400 (Lines 381-389)
  4. Visibility is empty: 400 (Lines 381-389)
  5. Invalid visibility value: 400 (Lines 391-400)
  6. Case variations ("Public", "PUBLIC"): Accepted, lowercased (Line 392)
  7. Same visibility as current: Update proceeds (no change detection)
  8. Thread currently has public viewers: Changing to private immediately denies access

Error Conditions

Exception Handling (Lines 411-419):

Behavioral Guarantees

Atomicity: Single UPDATE query (atomic) Idempotency: NOT idempotent
  • updated_at timestamp changes on every call
  • Even if visibility unchanged
Immediate Effect: Visibility change takes effect immediately
  • Next GET request reflects new visibility
  • Access control updated instantly

Validation Order

  1. User ID from JWT (401 if missing)
  2. Thread existence (404 if not found)
  3. Ownership (403 if not owner)
  4. Visibility value validation (400 if invalid)
  5. Update execution (500 if fails)
Note: Validation happens AFTER ownership check

Security Implications

Public Exposure Risk:
  • Changing private → public exposes thread to world (if feature enabled)
  • No confirmation required
  • No warning for sensitive content
Privacy Downgrade:
  • Private → public/unlisted is one-way exposure
  • Changing back to private doesn’t “un-share” (content may be cached elsewhere)
Access Revocation:
  • Changing public → private immediately denies access to non-owners
  • No grace period

Feature Flag Dependency

Depends on: public_sharing feature flag Behavior Matrix: Note: Setting visibility to public/unlisted has NO EFFECT if public_sharing = false

Response Format

Success Response (Lines 404-409):
  • Includes visibility field echoing normalized value (lowercased)
  • Example: Request "PUBLIC" → Response "public"