From f8d74a1933fcbb8a658bf3333fe607e06b950003 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 1 Dec 2025 15:53:56 +0000 Subject: [PATCH 1/5] feat: Add BSL 1.1 licensing and update pricing model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add BSL 1.1 LICENSE file (source available, commercial hosting restricted) - Update README with new pricing tiers and self-hosting info - Update MyPlan.tsx with correct hosted tier limits: - Free: 100 jobs, 1K parts/mo, 5GB - Pro: 1K jobs/mo, 10K parts/mo, 50GB (€97/mo) - Enterprise: Unlimited, SSO, dedicated (€497/mo) - Update Pricing.tsx with self-hosted option callout - Add comprehensive SELF_HOSTING_GUIDE.md documentation Self-hosted (BSL 1.1) is unlimited and free, separate from hosted tiers. Upgrades via email request (no Stripe integration yet). --- LICENSE | 116 ++++++++++++ README.md | 95 +++++----- docs/SELF_HOSTING_GUIDE.md | 361 ++++++++++++++++++++++++++++++++++++ src/pages/Pricing.tsx | 40 +++- src/pages/common/MyPlan.tsx | 27 ++- 5 files changed, 569 insertions(+), 70 deletions(-) create mode 100644 LICENSE create mode 100644 docs/SELF_HOSTING_GUIDE.md diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..053fba24 --- /dev/null +++ b/LICENSE @@ -0,0 +1,116 @@ +Business Source License 1.1 + +License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved. +"Business Source License" is a trademark of MariaDB Corporation Ab. + +----------------------------------------------------------------------------- + +Parameters + +Licensor: Sheet Metal Connect e.U. +Licensed Work: Eryxon Flow + The Licensed Work is (c) 2025 Sheet Metal Connect e.U. +Additional Use Grant: You may make use of the Licensed Work, provided that + you do not use the Licensed Work for a Production Use + that is Competing with any offering of the Licensor. + + A Production Use is Competing if it offers to third + parties access to the Licensed Work in a manner that + competes with or substitutes for the Licensor's own + commercial hosting offering of the Licensed Work. + + For clarity, the following uses are expressly permitted: + + 1. Self-hosting the Licensed Work for your own internal + business operations, regardless of organization size + + 2. Using the Licensed Work for development, testing, + evaluation, and educational purposes + + 3. Offering consulting, integration, or customization + services built around the Licensed Work + + 4. Creating derivative works for your own internal use + +Change Date: Four years from the date the Licensed Work is published + +Change License: Apache License, Version 2.0 + +----------------------------------------------------------------------------- + +Terms + +The Licensor hereby grants you the right to copy, modify, create derivative +works, redistribute, and make non-production use of the Licensed Work. The +Licensor may make an Additional Use Grant, above, permitting limited +production use. + +Effective on the Change Date, or the fourth anniversary of the first publicly +available distribution of a specific version of the Licensed Work under this +License, whichever comes first, the Licensor hereby grants you rights under +the terms of the Change License, and the rights granted in the paragraph +above terminate. + +If your use of the Licensed Work does not comply with the requirements +currently in effect as described in this License, you must purchase a +commercial license from the Licensor, its affiliated entities, or authorized +resellers, or you must refrain from using the Licensed Work. + +All copies of the original and modified Licensed Work, and derivative works +of the Licensed Work, are subject to this License. This License applies +separately for each version of the Licensed Work and the Change Date may vary +for each version of the Licensed Work released by Licensor. + +You must conspicuously display this License on each original or modified copy +of the Licensed Work. If you receive the Licensed Work in original or +modified form from a third party, the terms and conditions set forth in this +License apply to your use of that work. + +Any use of the Licensed Work in violation of this License will automatically +terminate your rights under this License for the current and all other +versions of the Licensed Work. + +This License does not grant you any right in any trademark or logo of +Licensor or its affiliates (provided that you may use a trademark or logo of +Licensor as expressly required by this License). + +TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON +AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, +EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND +TITLE. + +MariaDB hereby grants you permission to use this License's text to license +your works, and to refer to it using the trademark "Business Source License", +as long as you comply with the Covenants of Licensor below. + +----------------------------------------------------------------------------- + +Covenants of Licensor + +In consideration of the right to use this License's text and the "Business +Source License" name and trademark, Licensor covenants to MariaDB, and to all +other recipients of the licensed work to be provided by Licensor: + +1. To specify as the Change License the GPL Version 2.0 or any later version, + or a license that is compatible with GPL Version 2.0 or a later version, + where "compatible" means that software provided under the Change License can + be included in a program with software provided under GPL Version 2.0 or a + later version. Licensor may specify additional Change Licenses without + limitation. + +2. To either: (a) specify an additional grant of rights to use that does not + impose any additional restriction on the right granted in this License, as + the Additional Use Grant; or (b) insert the text "None". + +3. To specify a Change Date. + +4. Not to modify this License in any other way. + +----------------------------------------------------------------------------- + +Notice + +The Business Source License (this document, or the "License") is not an Open +Source license. However, the Licensed Work will eventually be made available +under an Open Source License, as stated in this License. diff --git a/README.md b/README.md index 7ee2af8a..f5f50b34 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,27 @@ -# Eryxon Flow - Manufacturing Execution System +# Eryxon MES -**Internal Project - Proprietary** +**The simple, elegant and powerful manufacturing execution system that your people will love to use. Made for SMB metal fabrication.**
+[![License: BSL 1.1](https://img.shields.io/badge/License-BSL_1.1-blue?style=for-the-badge)](LICENSE) [![React](https://img.shields.io/badge/React-18.3.1-61DAFB?style=for-the-badge&logo=react&logoColor=black)](https://reactjs.org/) [![TypeScript](https://img.shields.io/badge/TypeScript-5.8.3-3178C6?style=for-the-badge&logo=typescript&logoColor=white)](https://www.typescriptlang.org/) -[![Vite](https://img.shields.io/badge/Vite-5.4.19-646CFF?style=for-the-badge&logo=vite&logoColor=white)](https://vitejs.dev/) [![Supabase](https://img.shields.io/badge/Supabase-2.80.0-3ECF8E?style=for-the-badge&logo=supabase&logoColor=white)](https://supabase.com/) -[![TailwindCSS](https://img.shields.io/badge/Tailwind-3.4.17-06B6D4?style=for-the-badge&logo=tailwindcss&logoColor=white)](https://tailwindcss.com/) - -
- -
- -![React Query](https://img.shields.io/badge/React_Query-5.83.0-FF4154?style=flat-square&logo=react-query&logoColor=white) -![React Router](https://img.shields.io/badge/React_Router-6.30.1-CA4245?style=flat-square&logo=react-router&logoColor=white) -![MUI](https://img.shields.io/badge/Material_UI-7.3.5-007FFF?style=flat-square&logo=mui&logoColor=white) -![Three.js](https://img.shields.io/badge/Three.js-0.180.0-000000?style=flat-square&logo=three.js&logoColor=white) -![Zod](https://img.shields.io/badge/Zod-3.25.76-3E67B1?style=flat-square&logo=zod&logoColor=white) -![i18next](https://img.shields.io/badge/i18next-25.6.2-26A69A?style=flat-square&logo=i18next&logoColor=white)
--- -
- -![Commits](https://img.shields.io/badge/commits-557-blue) -![Inception](https://img.shields.io/badge/inception-2025-11-09-lightgrey) -![Velocity](https://img.shields.io/badge/last_30d-557_commits-orange) +## What Makes This Different -
- ---- +- **MCP Server** - AI/automation ready out of the box +- **API-first** - Send data from any system +- **Webhooks** - Link to any other system +- **Event-driven, real-time** - Industry 4.0 ready +- **Modern UI** - Operators actually want to use it -A modern, production-ready MES (Manufacturing Execution System) for sheet metal manufacturing with real-time tracking, QRM capacity management, and comprehensive API integration. +It's opinionated. Built for sheet metal manufacturing. Not for everyone. ## ✨ Key Features @@ -116,39 +102,60 @@ Additional documentation: - **API Security**: Bearer token auth with bcrypt-hashed keys - **Webhooks**: HMAC-SHA256 signatures for verification -## 📦 Deployment +## Pricing (Hosted) -| Environment | Platform | Details | -|-------------|----------|---------| -| **Development** | [Lovable](https://lovable.dev/projects/aaa3208a-70fb-4eb6-a5eb-5823f025e734) | Auto-syncs with GitHub | -| **Production** | Docker on Hetzner | EU-hosted, fixed costs | -| **Local/On-Premise** | Docker | Same image, custom Supabase | +| Tier | Limits | Support | Price | +|------|--------|---------|-------| +| **Free** | 100 jobs/mo, 1K parts | Docs only | €0 | +| **Pro** | 1K jobs/mo, 10K parts | Email | €97/mo | +| **Enterprise** | Unlimited | Dedicated + SSO | €497/mo | -### CI/CD Pipeline +- **Free** = Try it without installing anything +- **Enterprise** = Hand-holding tier (your infra or ours) -- **PRs**: Automated lint, type-check, build, test -- **Releases**: Manual workflow with migrations and Edge Functions deployment -- **Docker Images**: Published to GitHub Container Registry (GHCR) +Want to self-host? See the [Self-Hosting Guide](docs/SELF_HOSTING_GUIDE.md) - unlimited, free, you manage it. -See **[docs/CICD_DEPLOYMENT_PLAN.md](docs/CICD_DEPLOYMENT_PLAN.md)** for full setup instructions. +Need integration work or custom forks? [Contact us](mailto:office@sheetmetalconnect.com). -### Quick Docker Run +## Deployment + +### Self-Hosted (Free) + +```bash +# Clone and configure +git clone https://github.com/SheetMetalConnect/eryxon-flow.git +cd eryxon-flow +cp .env.example .env +# Edit .env with your Supabase credentials + +# Run with Docker +docker-compose up -d +``` + +See **[docs/SELF_HOSTING_GUIDE.md](docs/SELF_HOSTING_GUIDE.md)** for complete setup instructions. + +### Docker Quick Start ```bash docker pull ghcr.io/sheetmetalconnect/eryxon-flow:latest -docker run -p 8080:80 ghcr.io/sheetmetalconnect/eryxon-flow:latest +docker run -p 8080:80 \ + -e VITE_SUPABASE_URL=your-url \ + -e VITE_SUPABASE_PUBLISHABLE_KEY=your-key \ + ghcr.io/sheetmetalconnect/eryxon-flow:latest ``` -## 📄 License +## License + +**Business Source License 1.1 (BSL 1.1)** -**Proprietary - Internal Use Only** +- You can view, modify, and self-host the code for your own use - free, unlimited +- You cannot offer commercial hosted versions that compete with our SaaS +- After 4 years, converts to Apache 2.0 -Copyright © 2025 Sheet Metal Connect e.U. All rights reserved. +See [LICENSE](LICENSE) for full terms. -This software is for internal use only and may not be distributed, copied, or modified without explicit permission. +Copyright © 2025 Sheet Metal Connect e.U. --- -**Built with** React 18 + TypeScript + Supabase -**Status**: Production -**Version**: 1.2 +**Built with** React + TypeScript + Supabase | **Region**: EU (Netherlands) diff --git a/docs/SELF_HOSTING_GUIDE.md b/docs/SELF_HOSTING_GUIDE.md new file mode 100644 index 00000000..bdd78287 --- /dev/null +++ b/docs/SELF_HOSTING_GUIDE.md @@ -0,0 +1,361 @@ +# Self-Hosting Guide + +This guide covers how to self-host Eryxon Flow on your own infrastructure. Self-hosting is free, unlimited, and you manage everything yourself. + +**License:** BSL 1.1 - You can self-host for your own use. You cannot offer commercial hosting to third parties. + +--- + +## Deployment Options + +| Option | Complexity | Best For | +|--------|------------|----------| +| **Supabase Cloud + Docker** | Easy | Most users, quick setup | +| **Self-Hosted Supabase** | Advanced | Full control, air-gapped environments | + +--- + +## Option 1: Supabase Cloud (Recommended) + +The fastest way to get started. Supabase offers a free tier that works for evaluation and small deployments. + +### Prerequisites + +- Node.js 18+ and npm (or Docker) +- A Supabase account ([supabase.com](https://supabase.com)) +- Git + +### Step 1: Create Supabase Project + +1. Go to [supabase.com](https://supabase.com) and sign in +2. Click **New Project** +3. Choose your organization +4. Enter project details: + - **Name:** `eryxon-flow` (or your preference) + - **Database Password:** Generate a strong password (save it!) + - **Region:** Choose closest to your users +5. Click **Create new project** +6. Wait for project to be ready (~2 minutes) + +### Step 2: Get Your Credentials + +From your Supabase project dashboard: + +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** (for edge functions - keep this secret!) + +### Step 3: Apply Database Schema + +Using Supabase CLI: +```bash +# Install Supabase CLI +npm install -g supabase + +# Clone the repo +git clone https://github.com/SheetMetalConnect/eryxon-flow.git +cd eryxon-flow + +# Link to your project +supabase link --project-ref your-project-id + +# Push schema +supabase db push +``` + +Or manually: +1. Go to **SQL Editor** in your Supabase dashboard +2. Run the migrations from `supabase/migrations/` in order + +### Step 4: Deploy Edge Functions + +```bash +cd eryxon-flow + +# Login to Supabase +supabase login + +# Deploy all functions +supabase functions deploy +``` + +### Step 5: Configure Storage Buckets + +Verify in **Storage** that these buckets exist: +- `parts-images` - For CAD files and part photos +- `issues` - For issue attachments + +If missing, create them with: +- **Public:** No +- **File size limit:** 50MB +- **Allowed MIME types:** `image/*`, `application/pdf`, `model/step` + +### Step 6: Run the Application + +**Option A: Docker (Recommended)** +```bash +# Create .env file +cat > .env << EOF +VITE_SUPABASE_URL=https://your-project-id.supabase.co +VITE_SUPABASE_PUBLISHABLE_KEY=your-anon-key +EOF + +# Run with Docker Compose +docker-compose up -d +``` + +**Option B: Development mode** +```bash +cp .env.example .env +# Edit .env with your credentials + +npm install +npm run dev +# Open http://localhost:8080 +``` + +**Option C: Production build** +```bash +npm run build +# Serve the 'dist' folder with nginx, Apache, or any static file server +``` + +### Step 7: Create Your First User + +1. Open the application in your browser +2. Click **Sign Up** +3. Enter your email and password +4. Check your email for verification link +5. First user automatically becomes admin + +--- + +## Option 2: Fully Self-Hosted (Air-Gapped) + +For organizations requiring complete control over all infrastructure. + +### Prerequisites + +- Docker and Docker Compose +- 4GB+ RAM +- 20GB+ disk space +- Domain name (for production) +- SSL certificates + +### Architecture + +``` ++----------------------------------------------------------+ +| Your Server | ++----------------------------------------------------------+ +| +---------+ +---------+ +----------+ +----------+ | +| | Postgres| | GoTrue | |PostgREST | | Realtime | | +| | DB | | Auth | | API | | WS | | +| +---------+ +---------+ +----------+ +----------+ | +| +---------+ +---------+ +----------+ | +| | Storage | | Kong | | Studio | | +| | API | | Gateway | | (Admin) | | +| +---------+ +---------+ +----------+ | ++----------------------------------------------------------+ +| +------------------------------------------------------+| +| | Eryxon Flow (Frontend) || +| +------------------------------------------------------+| ++----------------------------------------------------------+ +``` + +### Step 1: Clone Supabase Docker Setup + +```bash +git clone --depth 1 https://github.com/supabase/supabase +cd supabase/docker +cp .env.example .env +``` + +### Step 2: Configure Environment + +Edit `.env`: +```env +# Generate with: openssl rand -base64 32 +POSTGRES_PASSWORD=your-secure-password +JWT_SECRET=your-jwt-secret-min-32-chars + +# Generate using Supabase docs +ANON_KEY=your-anon-key +SERVICE_ROLE_KEY=your-service-role-key + +# Your domain +SITE_URL=https://your-domain.com +API_EXTERNAL_URL=https://your-domain.com + +# SMTP for auth emails +SMTP_HOST=smtp.your-provider.com +SMTP_PORT=587 +SMTP_USER=your-smtp-user +SMTP_PASS=your-smtp-password +SMTP_SENDER_NAME=Eryxon Flow +``` + +### Step 3: Start Supabase Services + +```bash +docker compose up -d +docker compose ps # Verify all services running +``` + +### Step 4: Apply Schema and Deploy App + +```bash +# Apply migrations via Studio UI or psql +# Then deploy Eryxon Flow pointing to your self-hosted instance + +cd /path/to/eryxon-flow +cat > .env << EOF +VITE_SUPABASE_URL=https://your-domain.com +VITE_SUPABASE_PUBLISHABLE_KEY=your-anon-key +EOF + +docker build -t eryxon-flow . +docker run -p 3000:80 --env-file .env eryxon-flow +``` + +### Production Checklist + +- [ ] SSL/TLS configured (Let's Encrypt) +- [ ] PostgreSQL backups scheduled +- [ ] Monitoring set up +- [ ] Email delivery configured +- [ ] Security review completed + +--- + +## Docker Quick Reference + +### docker-compose.yml + +```yaml +version: '3.8' + +services: + eryxon-flow: + build: . + ports: + - "8080:80" + environment: + - VITE_SUPABASE_URL=${SUPABASE_URL} + - VITE_SUPABASE_PUBLISHABLE_KEY=${SUPABASE_ANON_KEY} + restart: unless-stopped +``` + +### Quick Start + +```bash +# Set credentials +export SUPABASE_URL=https://your-project.supabase.co +export SUPABASE_ANON_KEY=your-anon-key + +# Run +docker-compose up -d + +# Access at http://localhost:8080 +``` + +--- + +## MCP Server Setup + +Enable AI assistants to interact with your manufacturing data. + +### Installation + +```bash +cd mcp-server +npm install +npm run build +``` + +### Configuration + +Create `mcp-server/.env`: +```env +SUPABASE_URL=https://your-project.supabase.co +SUPABASE_SERVICE_KEY=your-service-role-key +``` + +### Claude Desktop Integration + +Add to `~/.claude/config.json`: +```json +{ + "mcpServers": { + "eryxon-flow": { + "command": "node", + "args": ["/path/to/eryxon-flow/mcp-server/dist/index.js"], + "env": { + "SUPABASE_URL": "https://your-project.supabase.co", + "SUPABASE_SERVICE_KEY": "your-service-role-key" + } + } + } +} +``` + +--- + +## Troubleshooting + +### Common Issues + +**"Invalid API key" error** +- Verify `VITE_SUPABASE_PUBLISHABLE_KEY` is correct +- Use the `anon` key, not the `service_role` key + +**"Permission denied" on queries** +- Check RLS policies are applied +- Verify user is authenticated +- Check tenant_id matches + +**Edge functions not working** +- Verify deployment: `supabase functions list` +- Check logs: `supabase functions logs function-name` + +**Storage uploads failing** +- Verify buckets exist with correct names +- Check bucket policies allow authenticated uploads + +--- + +## Updates + +```bash +# Pull latest +git pull origin main + +# Rebuild +npm install +npm run build + +# If using Docker +docker-compose build +docker-compose up -d +``` + +For database schema updates: +```bash +supabase db push +``` + +--- + +## Support + +Self-hosting is community-supported only: +- **GitHub Issues:** Bug reports +- **Documentation:** `/docs` folder + +Need help with complex deployments? Contact [office@sheetmetalconnect.com](mailto:office@sheetmetalconnect.com) for consulting services. + +--- + +*Licensed under BSL 1.1 - See [LICENSE](../LICENSE) for terms* diff --git a/src/pages/Pricing.tsx b/src/pages/Pricing.tsx index 0c8d7486..ce8e6d9c 100644 --- a/src/pages/Pricing.tsx +++ b/src/pages/Pricing.tsx @@ -98,9 +98,29 @@ Thank you!`; Free & Pro: Multi-tenant architecture with complete data isolation per tenant. Row-level security enforces separation at the database level. {" "} - Premium: Single-tenant deployment with dedicated infrastructure, completely air-gapped. + Enterprise: Single-tenant deployment - your infrastructure or dedicated hosted. {" "} - All tiers include HTTPS traffic only, hashed passwords, encrypted API keys, and time-limited file access via signed URLs. + All tiers include HTTPS, hashed passwords, encrypted API keys, and signed URLs for file access. +

+ + + + + + {/* Self-Hosted Option */} + + +
+ +
+

Self-Hosted Option (Free, Unlimited)

+

+ Want to run it yourself? The source code is available under BSL 1.1. + Self-host on your own infrastructure with unlimited jobs, parts, and storage. + Community support via docs only. See the{" "} + + GitHub repository + for setup instructions.

@@ -202,29 +222,29 @@ Thank you!`;
-

Self-Service Only

+

Self-Service

- No onboarding calls. No consultants. No phone support. Sign up, configure your stages - and materials, connect your API, and go. Documentation and email support only. + No onboarding calls. No consultants. Sign up, configure your stages + and materials, connect your API, and go. Documentation and email support (Pro+) only.

How to Upgrade

- Ready to upgrade? Click the "Request Upgrade" or "Contact Sales" button above to send - an email to + Ready to upgrade? Click "Request Upgrade" above to email{' '} + office@sheetmetalconnect.com . We'll get back to you with next steps.

-

Usage Tracking & Plan Management

+

Usage & Limits

- Monitor your usage, track jobs and parts count, and manage your subscription from your{' '} + Monitor your usage from your{' '} My Plan page. - You'll see real-time usage statistics and receive alerts when approaching tier limits. + You'll see real-time statistics and alerts when approaching limits.

diff --git a/src/pages/common/MyPlan.tsx b/src/pages/common/MyPlan.tsx index 375837cc..08e00c40 100644 --- a/src/pages/common/MyPlan.tsx +++ b/src/pages/common/MyPlan.tsx @@ -28,15 +28,14 @@ const pricingTiers = [ id: "free", name: "Free", price: "€0", - description: "Perfect for small shops getting started", + description: "Try the hosted version with limits", features: [ - "100 jobs per month", + "100 jobs", "1,000 parts per month", "5 GB file storage", "Limited API access", - "Multi-tenant architecture", "Community support (docs only)", - "Basic workflow tracking", + "Multi-tenant hosted", ], }, { @@ -44,36 +43,32 @@ const pricingTiers = [ name: "Pro", price: "€97", popular: true, - description: "For growing shops with higher volume", + description: "We run it for you, multi-tenant", features: [ "Unlimited users", "1,000 jobs per month", "10,000 parts per month", "50 GB file storage", "Full API access", - "Multi-tenant architecture", - "Priority email support", - "Advanced analytics", "Webhook integrations", + "Email support", + "EU-hosted (Hetzner)", ], }, { id: "premium", name: "Enterprise", price: "€497", - description: "Custom, bespoke solution", + description: "Hand-holding tier, your infra or ours", features: [ - "Everything in Pro", "Unlimited jobs & parts", "Unlimited storage", - "Unlimited usage", - "Self-hosted (on-premises)", "Single-tenant architecture", + "Your infrastructure OR dedicated hosted", + "Email support + SLA", "SSO/SAML authentication", - "Dedicated support channel", - "Custom SLA", - "White-label options", - "Advanced security controls", + "Custom integrations", + "Onboarding assistance", ], }, ]; From 2c476b0c2d5d777f9012ab9ec5c2847b70fc5ceb Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 1 Dec 2025 16:01:15 +0000 Subject: [PATCH 2/5] fix: Update pricing tiers to accurate model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Free tier (hosted): - 25 jobs/mo, 250 parts/mo, 500MB storage - Limited API, NO webhooks, NO MCP server - Docs only support Pro tier (€97/mo): - 500 jobs/mo, 5K parts/mo, 10GB storage - Full API, webhooks, MCP server - Email support (no SLA) Enterprise tier (€497/mo): - Unlimited, their infrastructure - SSO/SAML, white-label, dedicated support Self-hosted (free): - Unlimited everything, they manage it - Community/docs support only --- README.md | 33 ++++++++++++++++++----------- src/pages/Pricing.tsx | 10 ++++----- src/pages/common/MyPlan.tsx | 42 ++++++++++++++++++------------------- 3 files changed, 47 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index f5f50b34..1763e193 100644 --- a/README.md +++ b/README.md @@ -102,18 +102,27 @@ Additional documentation: - **API Security**: Bearer token auth with bcrypt-hashed keys - **Webhooks**: HMAC-SHA256 signatures for verification -## Pricing (Hosted) - -| Tier | Limits | Support | Price | -|------|--------|---------|-------| -| **Free** | 100 jobs/mo, 1K parts | Docs only | €0 | -| **Pro** | 1K jobs/mo, 10K parts | Email | €97/mo | -| **Enterprise** | Unlimited | Dedicated + SSO | €497/mo | - -- **Free** = Try it without installing anything -- **Enterprise** = Hand-holding tier (your infra or ours) - -Want to self-host? See the [Self-Hosting Guide](docs/SELF_HOSTING_GUIDE.md) - unlimited, free, you manage it. +## Pricing + +| | Free | Pro | Enterprise | Self-hosted | +|---|---|---|---|---| +| **Price** | €0 | €97/mo | €497/mo | €0 | +| **Where** | My infra | My infra | Your infra | Your infra | +| **Jobs/mo** | 25 | 500 | Unlimited | Unlimited | +| **Parts/mo** | 250 | 5,000 | Unlimited | Unlimited | +| **Storage** | 500MB | 10GB | Your cost | Your cost | +| **API** | Limited | Full | Full | Full | +| **Webhooks** | No | Yes | Yes | Yes | +| **MCP Server** | No | Yes | Yes | Yes | +| **SSO/SAML** | No | No | Yes | DIY | +| **Support** | Docs | Email | Dedicated | Community | + +- **Free** — Try it. Limited. No support. +- **Pro** — I run it. Real usage. Email support. +- **Enterprise** — Your network, your Supabase, I deploy and support it. +- **Self-hosted** — Download it, run it yourself, unlimited, you're on your own. + +Want to self-host? See the [Self-Hosting Guide](docs/SELF_HOSTING_GUIDE.md). Need integration work or custom forks? [Contact us](mailto:office@sheetmetalconnect.com). diff --git a/src/pages/Pricing.tsx b/src/pages/Pricing.tsx index ce8e6d9c..e9d44539 100644 --- a/src/pages/Pricing.tsx +++ b/src/pages/Pricing.tsx @@ -113,14 +113,14 @@ Thank you!`;
-

Self-Hosted Option (Free, Unlimited)

+

Self-Hosted (Free, Unlimited)

- Want to run it yourself? The source code is available under BSL 1.1. - Self-host on your own infrastructure with unlimited jobs, parts, and storage. - Community support via docs only. See the{" "} + Download it, run it yourself, you're on your own. Source code available under BSL 1.1. + Unlimited jobs, parts, storage. Full API, webhooks, MCP server. + Community support via docs and GitHub Discussions only. See the{" "} GitHub repository - for setup instructions. + .

diff --git a/src/pages/common/MyPlan.tsx b/src/pages/common/MyPlan.tsx index 08e00c40..7024905a 100644 --- a/src/pages/common/MyPlan.tsx +++ b/src/pages/common/MyPlan.tsx @@ -28,14 +28,15 @@ const pricingTiers = [ id: "free", name: "Free", price: "€0", - description: "Try the hosted version with limits", + description: "Try it. Limited. No support.", features: [ - "100 jobs", - "1,000 parts per month", - "5 GB file storage", + "25 jobs per month", + "250 parts per month", + "500 MB storage", "Limited API access", - "Community support (docs only)", - "Multi-tenant hosted", + "No webhooks", + "No MCP server", + "Docs only", ], }, { @@ -43,32 +44,31 @@ const pricingTiers = [ name: "Pro", price: "€97", popular: true, - description: "We run it for you, multi-tenant", + description: "We run it. Real usage. Email support.", features: [ - "Unlimited users", - "1,000 jobs per month", - "10,000 parts per month", - "50 GB file storage", + "500 jobs per month", + "5,000 parts per month", + "10 GB storage", "Full API access", - "Webhook integrations", - "Email support", - "EU-hosted (Hetzner)", + "Webhooks included", + "MCP server access", + "Email support (no SLA)", + "Extra storage on request", ], }, { id: "premium", name: "Enterprise", price: "€497", - description: "Hand-holding tier, your infra or ours", + description: "Your network, we deploy and support it.", features: [ "Unlimited jobs & parts", - "Unlimited storage", - "Single-tenant architecture", - "Your infrastructure OR dedicated hosted", - "Email support + SLA", + "Your infrastructure", + "Your Supabase instance", "SSO/SAML authentication", - "Custom integrations", - "Onboarding assistance", + "White-label options", + "Dedicated support channel", + "Custom SLA available", ], }, ]; From 3fc5a37825d22047e98a7f99ab54c479e5907bf4 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 1 Dec 2025 16:04:33 +0000 Subject: [PATCH 3/5] feat: Add plan limits migration and .env.example for BSL 1.1 - Add migration to update plan limits: - Free: 25 jobs/mo, 250 parts/mo, 1GB storage - Pro: 500 jobs/mo, 5000 parts/mo, 10GB storage - Enterprise: Unlimited (NULL) - Update handle_new_tenant() with new free tier defaults - Add get_plan_limits() function for plan info - Update plan-limits.ts comments to reflect BSL 1.1 model - Add .env.example for self-hosters with setup instructions --- .env.example | 42 +++++++ supabase/functions/_shared/plan-limits.ts | 9 +- .../20251201000000_update_plan_limits_bsl.sql | 114 ++++++++++++++++++ 3 files changed, 161 insertions(+), 4 deletions(-) create mode 100644 .env.example create mode 100644 supabase/migrations/20251201000000_update_plan_limits_bsl.sql diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..f996e373 --- /dev/null +++ b/.env.example @@ -0,0 +1,42 @@ +# Eryxon Flow - Environment Configuration +# Copy this file to .env and fill in your values + +# ============================================================================= +# SUPABASE CONFIGURATION (Required) +# ============================================================================= +# Get these from your Supabase project dashboard: Settings -> API + +# Your Supabase project URL +VITE_SUPABASE_URL="https://your-project-id.supabase.co" + +# Supabase anon/public key (safe to expose in frontend) +VITE_SUPABASE_PUBLISHABLE_KEY="your-anon-key-here" + +# Supabase project ID (the part before .supabase.co) +VITE_SUPABASE_PROJECT_ID="your-project-id" + +# ============================================================================= +# OPTIONAL CONFIGURATION +# ============================================================================= + +# App title (shown in browser tab) +# VITE_APP_TITLE="Eryxon Flow" + +# Default language (en, nl, de) +# VITE_DEFAULT_LANGUAGE="en" + +# ============================================================================= +# SELF-HOSTED NOTES +# ============================================================================= +# +# For self-hosted deployments: +# 1. Create a Supabase project (cloud or self-hosted) +# 2. Apply the database schema from supabase/migrations/ +# 3. Deploy edge functions: supabase functions deploy +# 4. Configure storage buckets: parts-images, issues +# 5. Set these environment variables +# +# See docs/SELF_HOSTING_GUIDE.md for complete instructions. +# +# License: BSL 1.1 - Self-hosting is free and unlimited. +# You cannot offer commercial hosted versions that compete with eryxon.eu diff --git a/supabase/functions/_shared/plan-limits.ts b/supabase/functions/_shared/plan-limits.ts index 64382323..8fbc7270 100644 --- a/supabase/functions/_shared/plan-limits.ts +++ b/supabase/functions/_shared/plan-limits.ts @@ -4,10 +4,11 @@ * This module provides utilities for enforcing subscription plan limits * across all API endpoints. * - * Plan Limits: - * - Free: 100 jobs, 1000 parts/month, 5GB storage, limited API access - * - Pro: 1000 jobs, 10000 parts/month, 50GB storage, full API access - * - Enterprise: Unlimited everything (premium tier in DB) + * Plan Limits (BSL 1.1 Model): + * - Free: 25 jobs/mo, 250 parts/mo, 1GB storage, limited API (no webhooks, no MCP) + * - Pro: 500 jobs/mo, 5000 parts/mo, 10GB storage, full API + webhooks + MCP + * - Enterprise: Unlimited everything, SSO/SAML (premium tier in DB) + * - Self-hosted: Unlimited (configured via env, not enforced) */ import { SupabaseClient } from "https://esm.sh/@supabase/supabase-js@2"; diff --git a/supabase/migrations/20251201000000_update_plan_limits_bsl.sql b/supabase/migrations/20251201000000_update_plan_limits_bsl.sql new file mode 100644 index 00000000..a70e6570 --- /dev/null +++ b/supabase/migrations/20251201000000_update_plan_limits_bsl.sql @@ -0,0 +1,114 @@ +-- Update plan limits for BSL 1.1 pricing model +-- Free: 25 jobs/mo, 250 parts/mo, 500MB storage +-- Pro: 500 jobs/mo, 5000 parts/mo, 10GB storage +-- Premium/Enterprise: Unlimited (NULL) + +-- Update existing tenants by plan +UPDATE public.tenants +SET + max_jobs = 25, + max_parts_per_month = 250, + max_storage_gb = 1 -- 500MB rounded to 1GB for simplicity +WHERE plan = 'free'; + +UPDATE public.tenants +SET + max_jobs = 500, + max_parts_per_month = 5000, + max_storage_gb = 10 +WHERE plan = 'pro'; + +UPDATE public.tenants +SET + max_jobs = NULL, + max_parts_per_month = NULL, + max_storage_gb = NULL +WHERE plan = 'premium'; + +-- Update the handle_new_tenant function with new free tier defaults +CREATE OR REPLACE FUNCTION public.handle_new_tenant() +RETURNS TRIGGER +LANGUAGE plpgsql +SECURITY DEFINER +SET search_path = public +AS $$ +BEGIN + -- Check if tenant exists + IF NOT EXISTS (SELECT 1 FROM public.tenants WHERE id = NEW.tenant_id) THEN + -- Create new tenant with free plan defaults (BSL 1.1 model) + INSERT INTO public.tenants ( + id, + name, + plan, + status, + max_jobs, + max_parts_per_month, + max_storage_gb, + contact_email + ) VALUES ( + NEW.tenant_id, + COALESCE(NEW.full_name || '''s Organization', 'New Organization'), + 'free', + 'active', + 25, -- Free tier: 25 jobs/mo + 250, -- Free tier: 250 parts/mo + 1, -- Free tier: ~500MB (1GB for simplicity) + NEW.email + ); + END IF; + + RETURN NEW; +END; +$$; + +-- Create or replace function to get plan limits by plan type +-- Used for documentation and plan upgrades +CREATE OR REPLACE FUNCTION public.get_plan_limits(p_plan subscription_plan) +RETURNS TABLE ( + plan_name TEXT, + max_jobs INTEGER, + max_parts_per_month INTEGER, + max_storage_gb INTEGER, + has_webhooks BOOLEAN, + has_mcp_server BOOLEAN, + has_sso BOOLEAN +) +LANGUAGE SQL +STABLE +AS $$ + SELECT + p_plan::TEXT, + CASE p_plan + WHEN 'free' THEN 25 + WHEN 'pro' THEN 500 + WHEN 'premium' THEN NULL -- unlimited + END, + CASE p_plan + WHEN 'free' THEN 250 + WHEN 'pro' THEN 5000 + WHEN 'premium' THEN NULL -- unlimited + END, + CASE p_plan + WHEN 'free' THEN 1 + WHEN 'pro' THEN 10 + WHEN 'premium' THEN NULL -- unlimited + END, + CASE p_plan + WHEN 'free' THEN FALSE + WHEN 'pro' THEN TRUE + WHEN 'premium' THEN TRUE + END, + CASE p_plan + WHEN 'free' THEN FALSE + WHEN 'pro' THEN TRUE + WHEN 'premium' THEN TRUE + END, + CASE p_plan + WHEN 'free' THEN FALSE + WHEN 'pro' THEN FALSE + WHEN 'premium' THEN TRUE + END; +$$; + +-- Add comment for documentation +COMMENT ON FUNCTION public.get_plan_limits IS 'Returns plan limits for BSL 1.1 pricing model. Free: 25 jobs, 250 parts, 1GB. Pro: 500 jobs, 5000 parts, 10GB. Premium: unlimited.'; From d92327834ac044cf8caae42f03b8d11deb507250 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 1 Dec 2025 16:08:33 +0000 Subject: [PATCH 4/5] feat: Add 4-tier pricing model (Free, Pro, Premium, Enterprise) Pricing tiers (BSL 1.1): - Free: 25 jobs/mo, 250 parts/mo, 1GB, limited API - Pro: 500 jobs/mo, 5K parts/mo, 10GB, full API + webhooks + MCP - Premium: 2K jobs/mo (fair use), 20K parts/mo, 100GB, SSO, priority - Enterprise: Unlimited, their infra, custom scope, by request - Self-hosted: Unlimited, free forever Changes: - Add 'enterprise' to subscription_plan enum - Update migration with new limits - Update plan-limits.ts with 4 tiers - Update useSubscription.ts types - Update MyPlan.tsx with all 4 tiers - Update README pricing table --- README.md | 36 ++++++++-------- src/hooks/useSubscription.ts | 10 +++-- src/pages/common/MyPlan.tsx | 34 ++++++++++----- supabase/functions/_shared/plan-limits.ts | 24 +++++++---- .../20251201000000_update_plan_limits_bsl.sql | 43 ++++++++++++++++--- 5 files changed, 101 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index 1763e193..e33a433c 100644 --- a/README.md +++ b/README.md @@ -104,23 +104,25 @@ Additional documentation: ## Pricing -| | Free | Pro | Enterprise | Self-hosted | -|---|---|---|---|---| -| **Price** | €0 | €97/mo | €497/mo | €0 | -| **Where** | My infra | My infra | Your infra | Your infra | -| **Jobs/mo** | 25 | 500 | Unlimited | Unlimited | -| **Parts/mo** | 250 | 5,000 | Unlimited | Unlimited | -| **Storage** | 500MB | 10GB | Your cost | Your cost | -| **API** | Limited | Full | Full | Full | -| **Webhooks** | No | Yes | Yes | Yes | -| **MCP Server** | No | Yes | Yes | Yes | -| **SSO/SAML** | No | No | Yes | DIY | -| **Support** | Docs | Email | Dedicated | Community | - -- **Free** — Try it. Limited. No support. -- **Pro** — I run it. Real usage. Email support. -- **Enterprise** — Your network, your Supabase, I deploy and support it. -- **Self-hosted** — Download it, run it yourself, unlimited, you're on your own. +| | Free | Pro | Premium | Enterprise | Self-hosted | +|---|---|---|---|---|---| +| **Price** | €0 | €97/mo | €497/mo | By request | €0 | +| **Where** | My infra | My infra | My infra | Your infra | Your infra | +| **Jobs/mo** | 25 | 500 | Fair use | Unlimited | Unlimited | +| **Parts/mo** | 250 | 5,000 | Fair use | Unlimited | Unlimited | +| **Storage** | 500MB | 10GB | 100GB | Your cost | Your cost | +| **API** | Limited | Full | Full | Full | Full | +| **Webhooks** | No | Yes | Yes | Yes | Yes | +| **MCP Server** | No | Yes | Yes | Yes | Yes | +| **SSO/SAML** | No | No | Yes | Yes | DIY | +| **White-label** | No | No | Optional | Yes | DIY | +| **Support** | Docs | Email | Priority | Dedicated | Community | + +- **Free** — Try it. Very limited. +- **Pro** — Real usage, my infra, email support. +- **Premium** — High limits, SSO, priority support. Still my infra. +- **Enterprise** — Your network, I deploy, custom scope. Contact me. +- **Self-hosted** — On your own. Free forever. Want to self-host? See the [Self-Hosting Guide](docs/SELF_HOSTING_GUIDE.md). diff --git a/src/hooks/useSubscription.ts b/src/hooks/useSubscription.ts index 80807a3d..cbcbd23d 100644 --- a/src/hooks/useSubscription.ts +++ b/src/hooks/useSubscription.ts @@ -2,7 +2,7 @@ import { useState, useEffect } from 'react'; import { supabase } from '../integrations/supabase/client'; import { useAuth } from '../contexts/AuthContext'; -export type SubscriptionPlan = 'free' | 'pro' | 'premium'; +export type SubscriptionPlan = 'free' | 'pro' | 'premium' | 'enterprise'; export type SubscriptionStatus = 'active' | 'cancelled' | 'suspended' | 'trial'; export interface TenantSubscription { @@ -76,19 +76,21 @@ export const useSubscription = () => { }, [profile?.tenant_id]); const getPlanDisplayName = (plan: SubscriptionPlan): string => { - const planNames = { + const planNames: Record = { free: 'Free Plan', pro: 'Pro Plan', premium: 'Premium Plan', + enterprise: 'Enterprise Plan', }; return planNames[plan] || 'Unknown Plan'; }; const getPlanColor = (plan: SubscriptionPlan): string => { - const planColors = { + const planColors: Record = { free: '#64748b', // slate pro: '#8b5cf6', // purple - premium: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', // gradient + premium: '#f59e0b', // amber + enterprise: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', // gradient }; return planColors[plan] || '#64748b'; }; diff --git a/src/pages/common/MyPlan.tsx b/src/pages/common/MyPlan.tsx index 7024905a..329f552b 100644 --- a/src/pages/common/MyPlan.tsx +++ b/src/pages/common/MyPlan.tsx @@ -28,7 +28,7 @@ const pricingTiers = [ id: "free", name: "Free", price: "€0", - description: "Try it. Limited. No support.", + description: "Try it. Very limited.", features: [ "25 jobs per month", "250 parts per month", @@ -44,7 +44,7 @@ const pricingTiers = [ name: "Pro", price: "€97", popular: true, - description: "We run it. Real usage. Email support.", + description: "Real usage, my infra, email support.", features: [ "500 jobs per month", "5,000 parts per month", @@ -52,23 +52,37 @@ const pricingTiers = [ "Full API access", "Webhooks included", "MCP server access", - "Email support (no SLA)", - "Extra storage on request", + "Email support", ], }, { id: "premium", - name: "Enterprise", + name: "Premium", price: "€497", - description: "Your network, we deploy and support it.", + description: "High limits, SSO, priority support. Still my infra.", + features: [ + "Fair use (high limits)", + "100 GB storage", + "Full API access", + "Webhooks + MCP server", + "SSO/SAML authentication", + "White-label (optional)", + "Priority email support", + ], + }, + { + id: "enterprise", + name: "Enterprise", + price: "Contact", + description: "Your network, I deploy, custom scope.", features: [ "Unlimited jobs & parts", "Your infrastructure", "Your Supabase instance", - "SSO/SAML authentication", - "White-label options", - "Dedicated support channel", - "Custom SLA available", + "SSO/SAML included", + "White-label included", + "Dedicated support", + "Custom SLA", ], }, ]; diff --git a/supabase/functions/_shared/plan-limits.ts b/supabase/functions/_shared/plan-limits.ts index 8fbc7270..a24086b6 100644 --- a/supabase/functions/_shared/plan-limits.ts +++ b/supabase/functions/_shared/plan-limits.ts @@ -4,17 +4,18 @@ * This module provides utilities for enforcing subscription plan limits * across all API endpoints. * - * Plan Limits (BSL 1.1 Model): + * Plan Limits (BSL 1.1 Model - 4 hosted tiers + self-hosted): * - Free: 25 jobs/mo, 250 parts/mo, 1GB storage, limited API (no webhooks, no MCP) * - Pro: 500 jobs/mo, 5000 parts/mo, 10GB storage, full API + webhooks + MCP - * - Enterprise: Unlimited everything, SSO/SAML (premium tier in DB) + * - Premium: 2000 jobs/mo, 20000 parts/mo, 100GB storage, SSO/SAML, priority support + * - Enterprise: Unlimited, their infrastructure, custom scope * - Self-hosted: Unlimited (configured via env, not enforced) */ import { SupabaseClient } from "https://esm.sh/@supabase/supabase-js@2"; export interface PlanLimits { - plan: 'free' | 'pro' | 'premium'; + plan: 'free' | 'pro' | 'premium' | 'enterprise'; max_jobs: number | null; max_parts_per_month: number | null; max_storage_gb: number | null; @@ -149,16 +150,16 @@ export async function canCreateParts( /** * Check if a tenant has API access * Free plan has limited API access (rate limited more aggressively) - * Pro and Enterprise have full API access + * Pro, Premium, and Enterprise have full API access */ -export function getApiAccessLevel(plan: 'free' | 'pro' | 'premium'): 'limited' | 'full' { +export function getApiAccessLevel(plan: 'free' | 'pro' | 'premium' | 'enterprise'): 'limited' | 'full' { return plan === 'free' ? 'limited' : 'full'; } /** * Get rate limit configuration based on plan */ -export function getRateLimitConfig(plan: 'free' | 'pro' | 'premium'): { +export function getRateLimitConfig(plan: 'free' | 'pro' | 'premium' | 'enterprise'): { maxRequests: number; windowMs: number; } { @@ -175,7 +176,12 @@ export function getRateLimitConfig(plan: 'free' | 'pro' | 'premium'): { }; case 'premium': return { - maxRequests: 10000, // 10000 requests per hour + maxRequests: 5000, // 5000 requests per hour (priority) + windowMs: 60 * 60 * 1000, + }; + case 'enterprise': + return { + maxRequests: 10000, // 10000 requests per hour (dedicated) windowMs: 60 * 60 * 1000, }; default: @@ -275,13 +281,15 @@ export async function canUploadFile( /** * Get a user-friendly plan name */ -export function getPlanDisplayName(plan: 'free' | 'pro' | 'premium'): string { +export function getPlanDisplayName(plan: 'free' | 'pro' | 'premium' | 'enterprise'): string { switch (plan) { case 'free': return 'Free'; case 'pro': return 'Pro'; case 'premium': + return 'Premium'; + case 'enterprise': return 'Enterprise'; default: return 'Unknown'; diff --git a/supabase/migrations/20251201000000_update_plan_limits_bsl.sql b/supabase/migrations/20251201000000_update_plan_limits_bsl.sql index a70e6570..f52abb08 100644 --- a/supabase/migrations/20251201000000_update_plan_limits_bsl.sql +++ b/supabase/migrations/20251201000000_update_plan_limits_bsl.sql @@ -1,7 +1,20 @@ --- Update plan limits for BSL 1.1 pricing model +-- Update plan limits for BSL 1.1 pricing model (4 hosted tiers + self-hosted) -- Free: 25 jobs/mo, 250 parts/mo, 500MB storage -- Pro: 500 jobs/mo, 5000 parts/mo, 10GB storage --- Premium/Enterprise: Unlimited (NULL) +-- Premium: Fair use (2000 jobs/mo, 20000 parts/mo, 100GB storage) +-- Enterprise: Unlimited (NULL) - their infrastructure + +-- Add 'enterprise' to the subscription_plan enum if not exists +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM pg_enum + WHERE enumlabel = 'enterprise' + AND enumtypid = (SELECT oid FROM pg_type WHERE typname = 'subscription_plan') + ) THEN + ALTER TYPE subscription_plan ADD VALUE 'enterprise'; + END IF; +END $$; -- Update existing tenants by plan UPDATE public.tenants @@ -18,12 +31,22 @@ SET max_storage_gb = 10 WHERE plan = 'pro'; +-- Premium now has fair use limits (high but not unlimited) +UPDATE public.tenants +SET + max_jobs = 2000, + max_parts_per_month = 20000, + max_storage_gb = 100 +WHERE plan = 'premium'; + +-- Enterprise has unlimited (NULL) +-- Note: Existing 'premium' tenants that should be enterprise need manual migration UPDATE public.tenants SET max_jobs = NULL, max_parts_per_month = NULL, max_storage_gb = NULL -WHERE plan = 'premium'; +WHERE plan = 'enterprise'; -- Update the handle_new_tenant function with new free tier defaults CREATE OR REPLACE FUNCTION public.handle_new_tenant() @@ -81,34 +104,40 @@ AS $$ CASE p_plan WHEN 'free' THEN 25 WHEN 'pro' THEN 500 - WHEN 'premium' THEN NULL -- unlimited + WHEN 'premium' THEN 2000 -- Fair use + WHEN 'enterprise' THEN NULL -- Unlimited END, CASE p_plan WHEN 'free' THEN 250 WHEN 'pro' THEN 5000 - WHEN 'premium' THEN NULL -- unlimited + WHEN 'premium' THEN 20000 -- Fair use + WHEN 'enterprise' THEN NULL -- Unlimited END, CASE p_plan WHEN 'free' THEN 1 WHEN 'pro' THEN 10 - WHEN 'premium' THEN NULL -- unlimited + WHEN 'premium' THEN 100 + WHEN 'enterprise' THEN NULL -- Unlimited END, CASE p_plan WHEN 'free' THEN FALSE WHEN 'pro' THEN TRUE WHEN 'premium' THEN TRUE + WHEN 'enterprise' THEN TRUE END, CASE p_plan WHEN 'free' THEN FALSE WHEN 'pro' THEN TRUE WHEN 'premium' THEN TRUE + WHEN 'enterprise' THEN TRUE END, CASE p_plan WHEN 'free' THEN FALSE WHEN 'pro' THEN FALSE WHEN 'premium' THEN TRUE + WHEN 'enterprise' THEN TRUE END; $$; -- Add comment for documentation -COMMENT ON FUNCTION public.get_plan_limits IS 'Returns plan limits for BSL 1.1 pricing model. Free: 25 jobs, 250 parts, 1GB. Pro: 500 jobs, 5000 parts, 10GB. Premium: unlimited.'; +COMMENT ON FUNCTION public.get_plan_limits IS 'Returns plan limits for BSL 1.1 pricing model. Free: 25/250/1GB. Pro: 500/5K/10GB. Premium: 2K/20K/100GB (fair use). Enterprise: unlimited.'; From 195965563c675cd9392b482bf9afd31465529657 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 1 Dec 2025 16:10:16 +0000 Subject: [PATCH 5/5] docs: Add yearly billing note to README pricing --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e33a433c..4c7de92e 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ Additional documentation: - **Enterprise** — Your network, I deploy, custom scope. Contact me. - **Self-hosted** — On your own. Free forever. -Want to self-host? See the [Self-Hosting Guide](docs/SELF_HOSTING_GUIDE.md). +Paid plans billed yearly. Want to self-host? See the [Self-Hosting Guide](docs/SELF_HOSTING_GUIDE.md). Need integration work or custom forks? [Contact us](mailto:office@sheetmetalconnect.com).