# Trust Malawi Backend
Express + PostgreSQL backend for a review and reputation platform built around:
> Publicly anonymous reviews, privately verified experiences.
Authentication is handled by Clerk. PostgreSQL stores product data, aliases, businesses, review targets, reviews, evidence metadata, moderation, claims, invites, audit logs, and outbox events.
## Stack
- Node.js ESM
- Express
- PostgreSQL / Supabase Postgres
- Clerk session JWT verification with `jose`
- Clerk webhook signature verification with `svix`
- Zod validation
- `pg` transactions for multi-table writes
## Setup
```bash
cd "C:\Users\User\Documents\projects\trust malawi\backend"
copy .env.example .env
npm install
npm run db:ping
npm run db:migrate
npm run db:seed
npm run dev
```
Default API URL: `
localhost`
## Supabase Postgres
Set `DATABASE_URL` to a Supabase pooler connection string.
```bash
DATABASE_URL=postgresql://postgres. : @aws-0- .pooler.supabase.com:6543/postgres
DATABASE_SSL_MODE=auto
```
`DATABASE_SSL_MODE=auto` enables TLS for Supabase hosts or URLs with `sslmode=require`. Use `disable` only for local Postgres without TLS.
## Clerk
Required production env vars:
- `CLERK_SECRET_KEY`
- `CLERK_WEBHOOK_SECRET`
- `CLERK_JWT_ISSUER` or `CLERK_JWKS_URL`
- `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` for the frontend
Webhook endpoint:
```text
POST /api/webhooks/clerk
```
Handled events:
- `user.created`
- `user.updated`
- `user.deleted`
- `organization.created`
- `organization.updated`
- `organizationMembership.created`
- `organizationMembership.updated`
- `organizationMembership.deleted`
Webhook events are recorded in `clerk_webhook_events` and processed idempotently.
## Local Auth Bypass
For local API testing only:
```bash
CLERK_AUTH_DEV_BYPASS=true
```
Then send:
```text
x-dev-clerk-user-id: user_reviewer_demo
x-dev-email: reviewer@example.test
```
Never enable this in production.
## Route Summary
System:
- `POST /api/webhooks/clerk`
- `GET /api/me`
- `POST …