Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions app/.dev.vars.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copy to .dev.vars for local development
# These are secrets - never commit .dev.vars

# JWT secret for session tokens
JWT_SECRET=your-secret-key-here

# SMS provider (Twilio example)
TWILIO_ACCOUNT_SID=your-account-sid
TWILIO_AUTH_TOKEN=your-auth-token
TWILIO_PHONE_NUMBER=+1234567890

# WebAuthn
WEBAUTHN_RP_ID=localhost
WEBAUTHN_RP_NAME=Mini Chat
WEBAUTHN_ORIGIN=http://localhost:5173
12 changes: 12 additions & 0 deletions app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
.wrangler
.dev.vars
229 changes: 229 additions & 0 deletions app/PERMISSIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
# Permissions System

Rock-solid, fully customizable role-based access control (RBAC) for Mini Chat.

## Overview

The system is built on three core concepts:

1. **Permissions** - Atomic actions (send messages, kick users, edit settings)
2. **Roles** - Named collections of permissions (Owner, Moderator, Member)
3. **Assignments** - Which users have which roles in which rooms

## Design Principles

- **Explicit over implicit** - Every permission is clearly named and documented
- **Fully customizable** - Create custom roles with any combination of permissions
- **Room-scoped** - Each room has its own independent role system
- **Default sensible** - Comes with good defaults, but everything can be changed

## Permission Categories

### Room Permissions
- `room.delete` - Delete the entire room
- `room.transfer_ownership` - Transfer ownership to another user
- `room.archive` - Archive/unarchive the room

### Settings Permissions
- `settings.edit_topic` - Change room topic
- `settings.edit_description` - Change room description
- `settings.make_durable` - Make room persistent (won't expire)
- `settings.make_private` - Make room invite-only
- `settings.manage_roles` - Create, edit, delete custom roles

### Member Permissions
- `members.invite` - Invite users to the room
- `members.kick` - Remove users from the room
- `members.ban` - Ban users permanently or temporarily
- `members.mute` - Mute users (read-only mode)
- `members.assign_roles` - Assign roles to members
- `members.view_list` - View member list

### Message Permissions
- `messages.send` - Send messages to the room
- `messages.edit_own` - Edit your own messages
- `messages.delete_own` - Delete your own messages
- `messages.edit_any` - Edit any message (moderation)
- `messages.delete_any` - Delete any message (moderation)
- `messages.pin` - Pin important messages
- `messages.search` - Search message history

## Default Roles

When a room is created, these roles are automatically set up:

### Owner (System Role)
- **Cannot be deleted or edited**
- **Color:** `#FFD700` (gold)
- **Permissions:** ALL
- **Assignment:** Automatically assigned to room creator
- **Position:** 1000 (highest)

### Moderator
- **Color:** `#3B3BBB` (purple-blue)
- **Permissions:**
- All member permissions (invite, kick, ban, mute, assign roles)
- All message moderation (edit any, delete any, pin)
- Some settings (edit topic, edit description)
- **Position:** 900

### Member (Default Role)
- **Color:** `#888888` (gray)
- **Permissions:**
- Send messages
- Edit own messages
- Delete own messages
- View member list
- Search messages
- **Position:** 100
- **Note:** Automatically assigned to new members

### Everyone (System Role)
- **Cannot be deleted**
- **Color:** `#CCCCCC` (light gray)
- **Permissions:**
- View member list
- Search messages (if room is not private)
- **Position:** 0 (lowest)
- **Note:** Applied to ALL users in the room, regardless of other roles

## Custom Roles

Room owners and moderators (with `settings.manage_roles`) can:

1. **Create new roles**
```
POST /api/rooms/{room}/roles
{
"name": "VIP",
"description": "Trusted members",
"color": "#FF69B4",
"permissions": ["messages.send", "messages.pin", "members.invite"]
}
```

2. **Edit existing roles**
- Change name, description, color
- Add/remove permissions
- Cannot edit system roles (Owner, Everyone)

3. **Delete roles**
- Can delete any custom role
- Cannot delete system roles
- Users with that role lose it automatically

4. **Set default role**
- Choose which role new members get
- Can only have one default role

## Permission Hierarchy

Roles have a `position` field that determines priority:

- Higher position = more important
- Used for display order (Owner at top, Everyone at bottom)
- Used for "can manage" logic (can only manage roles below you)

## Permission Checks

The system checks permissions in this order:

1. **Is user banned?** → Deny everything
2. **Is user muted?** → Deny `messages.send` (allow read)
3. **Is user owner?** → Allow everything
4. **Check user's roles** → Union of all permissions from all roles
5. **Check "Everyone" role** → Base permissions for all users

## Database Schema

### Tables

**permissions** - All available permissions (seeded)
- `id`, `name`, `description`, `category`

**roles** - Roles per room
- `id`, `room_id`, `name`, `description`, `color`, `is_default`, `is_system`, `position`

**role_permissions** - Which permissions each role has
- `role_id`, `permission_id`

**user_roles** - Which users have which roles
- `user_id`, `room_id`, `role_id`, `assigned_by`, `assigned_at`

**room_bans** - Banned users
- `room_id`, `user_id`, `banned_by`, `reason`, `expires_at`

**room_mutes** - Muted users
- `room_id`, `user_id`, `muted_by`, `reason`, `expires_at`

**room_invites** - Invite codes for private rooms
- `room_id`, `code`, `invited_user_id`, `max_uses`, `expires_at`

## API Endpoints

### Role Management
- `GET /api/rooms/{room}/roles` - List all roles
- `POST /api/rooms/{room}/roles` - Create custom role
- `PATCH /api/rooms/{room}/roles/{role}` - Edit role
- `DELETE /api/rooms/{room}/roles/{role}` - Delete role
- `GET /api/rooms/{room}/roles/{role}/permissions` - List role permissions
- `PUT /api/rooms/{room}/roles/{role}/permissions` - Update role permissions

### Member Management
- `GET /api/rooms/{room}/members` - List members with roles
- `POST /api/rooms/{room}/members/{user}/roles` - Assign role
- `DELETE /api/rooms/{room}/members/{user}/roles/{role}` - Remove role
- `POST /api/rooms/{room}/members/{user}/ban` - Ban user
- `DELETE /api/rooms/{room}/members/{user}/ban` - Unban user
- `POST /api/rooms/{room}/members/{user}/mute` - Mute user
- `DELETE /api/rooms/{room}/members/{user}/mute` - Unmute user

### Invites (for private rooms)
- `POST /api/rooms/{room}/invites` - Create invite
- `GET /api/rooms/{room}/invites` - List invites
- `DELETE /api/rooms/{room}/invites/{invite}` - Revoke invite
- `POST /api/invites/{code}/accept` - Join via invite code

### Permission Checks
- `GET /api/rooms/{room}/permissions/me` - Get my permissions
- `GET /api/rooms/{room}/permissions/{user}` - Get user's permissions (if allowed)

## Usage Examples

### Check if user can kick someone
```typescript
const canKick = await hasPermission(userId, roomId, 'members.kick');
if (!canKick) {
throw error(403, 'You do not have permission to kick members');
}
```

### Create a "Read-Only" role
```typescript
await createRole(roomId, {
name: 'Read-Only',
description: 'Can view but not participate',
permissions: ['members.view_list', 'messages.search'],
color: '#AAAAAA'
});
```

### Make user a moderator
```typescript
await assignRole(userId, roomId, moderatorRoleId, assignedBy);
```

## Migration Path

Existing rooms will get:
- Default roles created automatically
- Room creator assigned Owner role
- All other current members assigned Member role

## Future Enhancements

Possible additions:
- Permission overrides per user (grant/deny specific permissions)
- Role hierarchies (inherit from parent roles)
- Time-based roles (temporary moderator for 7 days)
- Audit log for permission changes
129 changes: 129 additions & 0 deletions app/QUICKSTART.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# Quick Start Guide

Get up and running with Mini Chat v2 in 5 minutes.

## Option 1: Cloudflare (Full Features)

### 1. Install Wrangler
```bash
npm install -g wrangler
wrangler login
```

### 2. Create D1 Database
```bash
cd app
wrangler d1 create mini-chat
```

Copy the `database_id` from the output and update `wrangler.toml`:
```toml
[[d1_databases]]
binding = "DB"
database_name = "mini-chat"
database_id = "YOUR_DATABASE_ID_HERE" # Replace this
```

### 3. Initialize Schema
```bash
wrangler d1 execute mini-chat --local --file=schema.sql
```

### 4. Set Up Environment
```bash
cp .dev.vars.example .dev.vars
# Edit .dev.vars with your secrets
```

### 5. Run Dev Server
```bash
npm install
npm run dev
```

Visit http://localhost:5173

## Option 2: Local Only (Limited Features)

For quick testing without Cloudflare setup:

```bash
cd app
npm install

# Use Wrangler's local mode (includes local D1)
npx wrangler d1 execute mini-chat --local --file=schema.sql
npm run dev
```

Note: This uses Wrangler's local D1 emulation. Some Cloudflare-specific features may not work.

## What's Working

✅ SvelteKit app structure
✅ CSS design system ported
✅ Database schema (D1/SQLite)
✅ Storage abstraction layer
✅ API routes for rooms & messages
✅ Durable Object for WebSocket (structure ready)

## What's Next

The foundation is solid! Next steps:

1. **Finish WebSocket UI** - Connect frontend to Durable Objects
2. **Add Auth** - WebAuthn + SMS verification
3. **Build MCP Server** - AI agent integration
4. **Add Cleanup Jobs** - Expire old ephemeral rooms

## Architecture Highlights

### Abstraction Layers

The app uses clean interfaces so you can swap technologies:

- **Storage**: `StorageAdapter` interface
- Current: D1 (Cloudflare SQLite)
- Easy swap to: PostgreSQL, MySQL, MongoDB

- **Messaging**: `MessagingAdapter` interface
- Current: Durable Objects
- Easy swap to: Redis, Socket.io, SSE

See `src/lib/server/README.md` for details.

### Project Structure

```
app/
├── src/
│ ├── lib/server/ # Backend abstractions
│ │ ├── storage/ # DB layer (swappable)
│ │ ├── messaging/ # Real-time layer (swappable)
│ │ └── ChatRoom.ts # Durable Object
│ ├── routes/
│ │ ├── api/ # REST endpoints
│ │ └── +page.svelte # Main UI
│ └── app.css # Polished design system
├── schema.sql # Database schema
└── wrangler.toml # Cloudflare config
```

## Troubleshooting

### "Database not initialized"
- Make sure you've run `wrangler d1 execute mini-chat --local --file=schema.sql`
- Check `wrangler.toml` has correct `database_id`

### Port already in use
- Change port in `package.json`: `"dev": "vite dev --port 3000"`

### TypeScript errors
- Run `npm run check` to see detailed errors
- The app is set up for strict TypeScript

## Next: Try it out!

The UI is basic but functional. Open http://localhost:5173 and you should see the chat interface with your ported CSS design.

Ready to add WebSockets, auth, or MCP? Let's keep building!
Loading