# Sojorn - Setup Guide

Quick guide to get Sojorn running locally and deployed.

---

## Prerequisites

- [Supabase CLI](https://supabase.com/docs/guides/cli/getting-started) installed
- [Deno](https://deno.land) installed (for Edge Functions)
- [Git](https://git-scm.com) installed
- A [Supabase account](https://supabase.com) (free tier works)

---

## Step 1: Environment Setup

### 1.1 Create Supabase Project

1. Go to [app.supabase.com](https://app.supabase.com)
2. Click "New Project"
3. Choose a name (e.g., "sojorn-dev")
4. Set a strong database password
5. Select a region close to you
6. Wait for project to initialize (~2 minutes)

### 1.2 Get Your Credentials

Once your project is ready:

1. Go to **Settings → API**
2. Copy these values:
   - **Project URL** (e.g., `https://abcdefgh.supabase.co`)
   - **anon/public key** (starts with `eyJ...`)
   - **service_role key** (starts with `eyJ...`)

3. Go to **Settings → General**
   - Copy your **Project Reference ID** (e.g., `abcdefgh`)

4. Go to **Settings → Database**
   - Copy your **Database Password** (or reset it if you forgot)

### 1.3 Configure .env File

Open `.env` in this project and fill in your values:

```bash
SUPABASE_URL=https://YOUR_PROJECT_REF.supabase.co
SUPABASE_ANON_KEY=eyJ...your_anon_key...
SUPABASE_SERVICE_ROLE_KEY=eyJ...your_service_role_key...
SUPABASE_PROJECT_REF=YOUR_PROJECT_REF
SUPABASE_DB_PASSWORD=your_database_password
CRON_SECRET=generate_with_openssl_rand
NODE_ENV=development
API_BASE_URL=https://YOUR_PROJECT_REF.supabase.co/functions/v1
```

### 1.4 Generate CRON_SECRET

In your terminal:

```bash
# macOS/Linux
openssl rand -base64 32

# Windows (PowerShell)
-join ((48..57) + (65..90) + (97..122) | Get-Random -Count 32 | % {[char]$_})
```

Copy the output and paste it as your `CRON_SECRET` in `.env`.

---

## Step 2: Link to Supabase

```bash
# Login to Supabase
supabase login

# Link your local project to your Supabase project
supabase link --project-ref YOUR_PROJECT_REF

# Enter your database password when prompted
```

---

## Step 3: Deploy Database

### 3.1 Push Migrations

```bash
# Apply all migrations to your Supabase project
supabase db push
```

This will create all tables, functions, and RLS policies.

### 3.2 Seed Categories

Connect to your database and run the seed script:

```bash
# Using psql
psql "postgresql://postgres:YOUR_DB_PASSWORD@db.YOUR_PROJECT_REF.supabase.co:5432/postgres" \
  -f supabase/seed/seed_categories.sql

# Or using Supabase SQL Editor:
# 1. Go to https://app.supabase.com/project/YOUR_PROJECT/editor
# 2. Copy contents of supabase/seed/seed_categories.sql
# 3. Paste and run
```

### 3.3 Verify Database Setup

```bash
# Check that tables were created
supabase db remote commit
```

Or in the Supabase Dashboard:
- Go to **Table Editor** → You should see all 14 tables

---

## Step 4: Deploy Edge Functions

### 4.1 Set Secrets

```bash
# Set the CRON_SECRET for the harmony calculation function
supabase secrets set CRON_SECRET="your_cron_secret_from_env"
```

### 4.2 Deploy All Functions

```bash
# Deploy each function
supabase functions deploy publish-post
supabase functions deploy publish-comment
supabase functions deploy block
supabase functions deploy report
supabase functions deploy feed-personal
supabase functions deploy feed-sojorn
supabase functions deploy trending
supabase functions deploy calculate-harmony
```

Or deploy all at once (if you have a deployment script).

### 4.3 Verify Functions

Go to **Edge Functions** in your Supabase dashboard:
- You should see 8 functions listed
- Check logs to ensure no deployment errors

---

## Step 5: Test the API

### 5.1 Create a Test User

1. Go to **Authentication → Users** in Supabase Dashboard
2. Click "Add User"
3. Enter email and password
4. Copy the User ID (UUID)

### 5.2 Manually Create Profile

In **SQL Editor**, run:

```sql
-- Replace USER_ID with the UUID from step 5.1
INSERT INTO profiles (id, handle, display_name, bio)
VALUES ('USER_ID', 'testuser', 'Test User', 'Testing Sojorn');
```

### 5.3 Get a JWT Token

1. Use the [Supabase Auth API](https://supabase.com/docs/reference/javascript/auth-signinwithpassword):

```bash
curl -X POST "https://YOUR_PROJECT_REF.supabase.co/auth/v1/token?grant_type=password" \
  -H "apikey: YOUR_ANON_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "test@example.com",
    "password": "your_password"
  }'
```

2. Copy the `access_token` from the response

### 5.4 Test Edge Functions

```bash
# Set your token
export TOKEN="your_access_token_here"

# Get a category ID (from seed data)
# Go to Table Editor → categories → Copy the 'general' category UUID

# Test publishing a post
curl -X POST "https://YOUR_PROJECT_REF.supabase.co/functions/v1/publish-post" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "category_id": "CATEGORY_UUID",
    "body": "This is my first friendly post on Sojorn."
  }'

# Test getting personal feed
curl "https://YOUR_PROJECT_REF.supabase.co/functions/v1/feed-personal" \
  -H "Authorization: Bearer $TOKEN"

# Test Sojorn feed
curl "https://YOUR_PROJECT_REF.supabase.co/functions/v1/feed-sojorn?limit=10" \
  -H "Authorization: Bearer $TOKEN"
```

---

## Step 6: Schedule Harmony Calculation

### Option 1: GitHub Actions (Recommended for small projects)

Create `.github/workflows/harmony-cron.yml`:

```yaml
name: Calculate Harmony Daily

on:
  schedule:
    - cron: '0 2 * * *'  # 2 AM UTC daily
  workflow_dispatch:

jobs:
  calculate:
    runs-on: ubuntu-latest
    steps:
      - name: Trigger harmony calculation
        run: |
          curl -X POST \
            https://${{ secrets.SUPABASE_PROJECT_REF }}.supabase.co/functions/v1/calculate-harmony \
            -H "Authorization: Bearer ${{ secrets.CRON_SECRET }}"
```

Add secrets in GitHub:
- `SUPABASE_PROJECT_REF`
- `CRON_SECRET`

### Option 2: Cron-Job.org (External service)

1. Go to [cron-job.org](https://cron-job.org) and create account
2. Create new cron job:
   - URL: `https://YOUR_PROJECT_REF.supabase.co/functions/v1/calculate-harmony`
   - Schedule: Daily at 2 AM
   - Method: POST
   - Header: `Authorization: Bearer YOUR_CRON_SECRET`

---

## Step 7: Verify Everything Works

### 7.1 Check Tables

In **Table Editor**, verify:
- [ ] `profiles` has your test user
- [ ] `categories` has 12 categories
- [ ] `trust_state` has your user (with harmony_score = 50)
- [ ] `posts` has any posts you created

### 7.2 Check RLS Policies

In **SQL Editor**, test block enforcement:

```sql
-- Create a second test user
INSERT INTO auth.users (id, email) VALUES (gen_random_uuid(), 'test2@example.com');
INSERT INTO profiles (id, handle, display_name)
VALUES ((SELECT id FROM auth.users WHERE email = 'test2@example.com'), 'testuser2', 'Test User 2');

-- Block user 2 from user 1
INSERT INTO blocks (blocker_id, blocked_id)
VALUES (
  (SELECT id FROM profiles WHERE handle = 'testuser'),
  (SELECT id FROM profiles WHERE handle = 'testuser2')
);

-- Verify user 1 cannot see user 2's profile
SET request.jwt.claims TO '{"sub": "USER_1_ID"}';
SELECT * FROM profiles WHERE handle = 'testuser2';  -- Should return 0 rows

-- Reset
RESET request.jwt.claims;
```

### 7.3 Test Tone Detection

Try publishing a hostile post:

```bash
curl -X POST "https://YOUR_PROJECT_REF.supabase.co/functions/v1/publish-post" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "category_id": "CATEGORY_UUID",
    "body": "This is fucking bullshit."
  }'
```

Expected response:
```json
{
  "error": "Content rejected",
  "message": "This post contains language that does not fit here.",
  "suggestion": "This space works without profanity. Try rephrasing."
}
```

---

## Troubleshooting

### "Relation does not exist" error
- Run `supabase db push` again
- Check that migrations completed successfully

### "JWT expired" error
- Your auth token expired (tokens last 1 hour)
- Sign in again to get a new token

### "Failed to fetch" error
- Check your `SUPABASE_URL` is correct
- Verify Edge Functions are deployed
- Check function logs: `supabase functions logs FUNCTION_NAME`

### RLS policies blocking everything
- Ensure you're using the correct user ID in JWT
- Check that user exists in `profiles` table
- Verify RLS policies with `\d+ TABLE_NAME` in psql

---

## Next Steps

Now that your backend is running:

1. **Build missing Edge Functions** (signup, follow, like, etc.)
2. **Start Flutter client** (see Flutter setup guide when created)
3. **Write transparency pages** (How Reach Works, Rules)
4. **Add admin tooling** (report review, trending overrides)

---

## Useful Commands

```bash
# View Edge Function logs
supabase functions logs publish-post --tail

# Reset database (WARNING: deletes all data)
supabase db reset

# Check Supabase status
supabase status

# View remote database changes
supabase db remote commit

# Generate TypeScript types from database
supabase gen types typescript --local > types/database.ts
```

---

## Support

- [Supabase Docs](https://supabase.com/docs)
- [Supabase Discord](https://discord.supabase.com)
- [Sojorn Documentation](README.md)
