Review
A user can rate and write a short review of any agent they have access to.
Schema (reviews)
| Column | Type | Notes |
|---|---|---|
id | UUID | PK |
agentId | UUID | FK → agents |
userId | UUID | FK → user |
rating | int | 1–5, CHECK (rating BETWEEN 1 AND 5) |
title | text, nullable | Short headline |
body | text, nullable | Long-form text |
createdAt, updatedAt | timestamptz |
Unique on (agentId, userId). Submitting a second review is an upsert that replaces the old content.
Endpoints
| Verb | Path | Guard |
|---|---|---|
| GET | /agents/:agentId/reviews?cursor=&limit= | public, cursor-paginated, newest first |
| POST | /agents/:agentId/reviews | bearer (upsert) |
| DELETE | /reviews/:id | bearer — author or platform_admin |
DTO
type ReviewDto = {
id: string;
rating: number;
title: string | null;
body: string | null;
userDisplayName: string | null;
userAvatarUrl: string | null;
createdAt: string;
updatedAt: string;
};
User display name and avatar are joined from auth.user at read time. Deleting the user does NOT cascade — the review remains but loses the linked profile fields (they go null).
Aggregates on the agent
The agent DTO carries rating (1-decimal mean) and reviewCount. Both are computed at read time from the reviews table. rating is null if reviewCount === 0.
Frontend rendering
The detail page has a Reviews tab fed by useAgentReviews(agentId, { cursor }). Inline review submission uses useUpsertReview() and useDeleteReview().
Moderation
There is no current moderation queue. Reviews are public on insert. Admins can delete via DELETE /reviews/:id. If you need pre-moderation, add a status: 'pending' | 'approved' | 'rejected' column — currently absent.