Skip to content

feat(api): add listing conversations and text messaging - #5

Draft
SKonteye wants to merge 2 commits into
Code-for-Senegal:developfrom
SKonteye:feat/listing-conversations
Draft

SKonteye wants to merge 2 commits into
Code-for-Senegal:developfrom
SKonteye:feat/listing-conversations

Conversation

@SKonteye

@SKonteye SKonteye commented Sep 7, 2026 •

Copy link
Copy Markdown
Contributor

Closes #4

Members can now start a private conversation about an ACTIVE listing and exchange text messages through authenticated REST endpoints. This is the API foundation; web sign-in, messaging UI, attachments, and Socket.IO delivery remain follow-up work.

Behavior

  • Add Conversation, ConversationParticipant (OWNER / INTERESTED), and Message models and a migration. A unique listing/member pair makes concurrent contact requests reuse one conversation.
  • Add endpoints to start/reuse a conversation, list conversations, retrieve a conversation, and list/send messages. Lists use offset pagination with an explicit ID tie-breaker.
  • Check listing eligibility under a database row lock in the creation transaction, preventing concurrent status changes from bypassing the ACTIVE requirement. Existing participants can continue after archival.
  • Return 400 for self-contact, 404 for missing or rejected listings, and 409 for other non-ACTIVE listings. Conversation access by non-participants returns 404.
  • Trim and validate message bodies (1–2000 characters). Persist the message and advance activity atomically; delayed sends cannot move the activity timestamp backwards.
  • Reuse the safe public member shape. Conversation responses omit phone numbers, location data, and listing moderation status.
  • Publish concrete OpenAPI response schemas and regenerate the shared client. Conversation client return types match the shared mutator's direct response-body behavior. Generation cleans stale models and exports.

Validation

  • Passed repository lint and typecheck.
  • Passed 26 unit tests and 23 end-to-end tests against local Docker PostgreSQL and Redis, including concurrent conversation reuse, participant isolation, privacy, response schemas, and monotonic activity.
  • API build and API/client generation passed.
  • Full repository build was attempted; web/admin Turbopack builds are blocked locally by a port-binding permission error. CI must verify the full build for this revision.

The migration preserves the hand-written PostGIS and search indexes.

Members can now contact each other about a listing through the API.

- Conversation, ConversationParticipant and Message models with a migration.
  One conversation per listing and interested member, enforced by a unique
  index so concurrent contact requests converge on one row.
- POST /conversations starts or reuses a conversation; GET /conversations,
  GET /conversations/:id, GET /conversations/:id/messages and
  POST /conversations/:id/messages, all participant-only.
- Opening requires an ACTIVE listing owned by someone else. Participants keep
  reading and writing after the listing is archived.
- Non-participants get 404 so a conversation id never confirms existence.
- Lists are ordered by activity or time, then id, for stable pages.
- Shared safe member shape in users/public-member.ts, also used by the listing
  detail. No phone, location or moderation state in responses.
- Unit spec and end-to-end spec (owner, interested member, stranger).
- OpenAPI document and API client regenerated.

Closes Code-for-Senegal#4

Claude-Session: https://claude.ai/code/session_01VGBQpJZopVVa1AWeVsNaWg
@Denver-sn
Denver-sn changed the base branch from main to develop September 7, 2026 15:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(api): add listing conversations and text messaging

1 participant