README.md

February 7, 2026 Β· View on GitHub

Quorum Logo

Collaborative SQL Query Management

Version Control & Peer Review for SQL

Manage, version, and approve SQL queries with your team. Self-hosted or cloud-ready.

License: MIT CI Security React TypeScript Vite PostgreSQL Tailwind CSS

πŸ“– About

Quorum is a team-based SQL query management platform with built-in version control and approval workflows. The name reflects the core featureβ€”configurable approval quotas (a quorum is the minimum needed for a decision).

Unlike shared folders or wikis, Quorum provides:

  • Git-like version history for every query change
  • Mandatory peer review before queries go live
  • Team isolation with database-level security
  • Full audit trail of who changed what and when

Perfect for data teams, analytics engineers, and anyone who needs governance over shared SQL.

✨ Key Features

FeatureDescription
πŸ”’ Team IsolationMulti-tenant architecture with Row-Level Security (RLS). Teams only see their own data.
πŸ“ Version ControlComplete change history with diff views and rollback capability.
βœ… Approval WorkflowsConfigurable approval quotas per team. Require 1, 2, or more reviewers.
πŸ‘₯ Peer ReviewSelf-approval prevented at the database level. Changes require teammates.
πŸ”‘ Role-Based AccessAdmin and member roles with granular permissions.
🏠 Self-Hosted OptionRun on your own infrastructure with Docker. No vendor lock-in.
☁️ Cloud ReadyDeploy to Supabase for managed PostgreSQL and authentication.
πŸ“ Folder OrganizationHierarchical folders to organize queries by project, team, or domain.

πŸš€ Quick Start

git clone https://github.com/montrellcruse/quorum-sql.git
cd quorum-sql
pnpm install
pnpm dev

Visit http://localhost:8080/setup and follow the configuration wizard.

Option 2: Docker (Self-Hosted)

git clone https://github.com/montrellcruse/quorum-sql.git
cd quorum-sql
docker compose up -d db server
pnpm install && pnpm dev

Open http://localhost:8080 to access the application.

πŸ› οΈ Deployment Options

ModeBest ForAuthDatabase
Self-HostedFull control, air-gapped environmentsLocal accountsPostgreSQL via Docker
Supabase CloudQuick start, managed infrastructureSupabase Auth + Google OAuthSupabase PostgreSQL

πŸ’» Tech Stack

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        Frontend                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚   React     β”‚  β”‚  TanStack   β”‚  β”‚   Tailwind CSS      β”‚  β”‚
β”‚  β”‚   Router    β”‚  β”‚   Query     β”‚  β”‚   + shadcn/ui       β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β–Ό                             β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   REST API (Fastify)    β”‚   β”‚   Supabase Client (Cloud)   β”‚
β”‚   - JWT Auth            β”‚   β”‚   - Supabase Auth           β”‚
β”‚   - Rate Limiting       β”‚   β”‚   - Google OAuth            β”‚
β”‚   - CORS                β”‚   β”‚   - Real-time (optional)    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚                                β”‚
            β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                           β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      PostgreSQL                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  8 Tables   β”‚  β”‚  37+ RLS    β”‚  β”‚  Security Definer   β”‚  β”‚
β”‚  β”‚             β”‚  β”‚  Policies   β”‚  β”‚  Functions          β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“Š Database Schema

8 tables with comprehensive Row-Level Security:

TablePurpose
profilesUser information synced with auth
teamsTeam settings + approval quotas
team_membersUser-team relationships with roles
team_invitationsPending invitations by email
foldersHierarchical query organization
sql_queriesVersioned query storage
query_historyComplete change audit trail
query_approvalsApproval tracking per version

See supabase/ERD.md for the full entity relationship diagram.

βš™οΈ Configuration

Environment Variables

Copy .env.example to .env and configure:

# Database Provider: 'rest' (self-hosted) or 'supabase' (cloud)
VITE_DB_PROVIDER=rest

# Self-Hosted Mode
VITE_API_BASE_URL=http://localhost:8787
VITE_AUTH_PROVIDERS=local

# OR Supabase Mode
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_PUBLISHABLE_KEY=your-anon-key

# Common Settings
VITE_ALLOWED_EMAIL_DOMAIN=@yourcompany.com
VITE_APP_NAME=Quorum

Setup Wizard

The setup wizard at /setup guides you through:

  1. Choose Provider β€” Self-Hosted or Supabase Cloud
  2. Configure Settings β€” Email domain restrictions, app name
  3. Generate Config β€” Download your .env file

πŸ“ˆ Observability

Frontend telemetry supports:

  • Sentry error tracking (VITE_SENTRY_DSN, VITE_SENTRY_ENV, VITE_SENTRY_TRACES_SAMPLE_RATE)
  • PostHog product analytics (VITE_POSTHOG_KEY, VITE_POSTHOG_HOST)

Error-to-issue automation (Sentry β†’ GitHub)

Sentry is initialized in src/lib/telemetry.ts, but GitHub issue creation is configured in Sentry, not in this repo. Follow the placeholder runbook to enable or document the integration: runbooks/sentry-github.md.

πŸ“œ Scripts

CommandDescription
pnpm devStart development server on port 8080
pnpm buildBuild for production
pnpm lintRun ESLint
pnpm previewPreview production build
pnpm testRun server unit tests
pnpm test:e2eRun end-to-end tests (Playwright)

πŸ”’ Security

Quorum is built with security as a core principle:

  • 37+ RLS Policies β€” Database-level access control on all tables
  • Team Isolation β€” Users only see their teams' data
  • Peer Review Enforcement β€” Self-approval prevented at database level
  • Domain Restriction β€” Configurable email domain authentication
  • Strong Password Policy β€” Minimum 8 chars with uppercase, lowercase, number, and special character requirements plus common password blocklist
  • SQL Injection Protection β€” Parameterized queries throughout
  • XSS Protection β€” React's automatic escaping + CSP headers (enforced in both dev and production)
  • Security Definer Functions β€” Controlled privilege elevation with SET search_path
  • Rate Limiting β€” Per-route rate limits on all endpoints via @fastify/rate-limit
  • Non-Root Docker β€” Container runs as node user, not root

See SECURITY.md for the complete security policy and audit history.

πŸ“ Project Structure

β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ components/        # React components
β”‚   β”‚   β”œβ”€β”€ setup/         # Setup wizard
β”‚   β”‚   └── ui/            # shadcn/ui components
β”‚   β”œβ”€β”€ contexts/          # Auth & Team React contexts
β”‚   β”œβ”€β”€ pages/             # Route page components
β”‚   β”œβ”€β”€ hooks/             # Custom React hooks
β”‚   └── integrations/      # Supabase client config
β”œβ”€β”€ server/                # Fastify REST API
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ routes/        # API route handlers
β”‚   β”‚   └── middleware/    # Auth, rate limiting
β”‚   └── package.json
β”œβ”€β”€ supabase/
β”‚   β”œβ”€β”€ migrations/        # Squashed baseline migration
β”‚   β”œβ”€β”€ schema.sql         # Schema documentation
β”‚   └── ERD.md             # Entity relationship diagram
β”œβ”€β”€ docker-compose.yml     # Docker services config
└── .env.example           # Environment template

🀝 Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Test your changes (pnpm lint && pnpm build)
  4. Commit with a clear message (git commit -m 'Add amazing feature')
  5. Push to your branch (git push origin feature/amazing-feature)
  6. Open a Pull Request

See CONTRIBUTING.md for detailed guidelines.

πŸ“„ License

This project is licensed under the MIT License β€” see LICENSE for details.

πŸ†˜ Support


Built for teams who care about SQL governance