Files
mc_cars_gmbh_infraestructure/README.md
T
Lago 61517879e1 feat: Add Supabase configuration and migrations for MC Cars application
- Create Kong declarative configuration for routing and authentication.
- Implement initialization script to set up the database.
- Add SQL migration for initializing roles, schemas, and seeding vehicle data.
- Create leads and customers tables with appropriate policies and functions for CRM.
- Seed admin user and configure storage bucket with RLS policies.
2026-04-17 17:50:57 +02:00

115 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MC Cars Dockerized Supabase CRM
Self-hosted Supabase stack + bilingual (DE/EN) public website + lead-management admin panel. Everything lives under this folder. Copying the folder to another machine and running `docker compose up -d` reproduces the stack bit-for-bit — all runtime state is under `./data/` bind mounts, no named volumes.
## What's inside
| Service | Image | Purpose |
| ------------- | ------------------------------------ | ----------------------------------------- |
| `db` | `postgres:15-alpine` | Postgres with `wal_level=logical` |
| `auth` | `supabase/gotrue:v2.158.1` | Email+password auth (signup disabled) |
| `rest` | `postgrest/postgrest:v12.2.0` | Auto-generated REST API |
| `storage` | `supabase/storage-api:v1.11.13` | S3-like bucket API (backed by `./data/storage`) |
| `imgproxy` | `darthsim/imgproxy:v3.8.0` | On-the-fly image transforms |
| `realtime` | `supabase/realtime:v2.30.23` | Live `postgres_changes` subscriptions |
| `meta` | `supabase/postgres-meta:v0.84.2` | Schema introspection for Studio |
| `post-init` | `postgres:15-alpine` | Idempotent bootstrap: seed admin + migrations |
| `kong` | `kong:2.8.1` | Single API gateway at `:54321` |
| `studio` | `supabase/studio` | Supabase dashboard (`:3000`) |
| `web` | local `nginx:alpine` build | Public site + admin panel (`:8080`) |
## Requirements
- Docker Desktop / Docker Engine with Compose v2
- Free ports: `3000`, `5432`, `8080`, `54321`, `54443`
## Run
```powershell
cd 'c:\Coding\MC Cars GmbH'
docker compose up -d
```
First boot pulls ~1.5 GB of images and runs migrations (`01-init.sql`, `post-boot.sql`, `02-leads.sql`). Give it 3060 s to settle.
### Stop / reset
```powershell
docker compose down # stop, keep data
docker compose down -v # stop + delete named volumes (there are none anymore)
Remove-Item -Recurse -Force .\data # FULL wipe (needed to re-run first-boot migrations)
```
## URLs
| Purpose | URL |
| ------------------------------- | -------------------------------- |
| Public website | http://localhost:8080 |
| Admin panel | http://localhost:8080/admin.html |
| Supabase Studio | http://localhost:3000 |
| API gateway (Kong) | http://localhost:54321 |
| Postgres | `localhost:5432` |
> Admin access is deliberately **not** linked from the public site. Bookmark it.
## Credentials (dev defaults rotate before any deployment)
| Account | Value |
| -------------------- | ---------------------------------------- |
| Admin bootstrap user | `admin@mccars.local` / `mc-cars-admin` |
| Postgres superuser | `postgres` / see `POSTGRES_PASSWORD` |
The admin is seeded with `must_change_password = true` in `raw_user_meta_data`. On first login the UI **forces** a rotation and refuses to reuse the bootstrap password. The real working password never equals `.env`.
## Data model
- `public.vehicles` — fleet, public-readable where `is_active`.
- `public.leads` — booking form submissions. `anon` may `INSERT` only; `authenticated` has full CRUD. Status: `new | qualified | disqualified`.
- `public.customers` — created **only** by qualifying a lead. Hard FK `lead_id` preserves the audit link to the originating lead.
- RPCs: `qualify_lead(uuid, text)`, `disqualify_lead(uuid, text)`, `reopen_lead(uuid)` — transactional, `SECURITY INVOKER`, `authenticated` only.
- Realtime: `supabase_realtime` publication broadcasts inserts/updates on leads, customers, vehicles.
## Portability
Runtime state under `./data/`:
```
data/
├── db/ # Postgres cluster (bind mount)
└── storage/ # vehicle-photos bucket content
```
Everything else (config, migrations, frontend) is in the repo. Zip the folder, scp it, `docker compose up -d` — you have the same stack.
## Project layout
```
MC Cars/
├── docker-compose.yml # full stack, bind-mount portability
├── .env # dev secrets / tunables
├── data/ # runtime state (git-ignored)
├── supabase/
│ ├── kong.yml # gateway routes (/auth, /rest, /realtime, /storage, /pg)
│ └── migrations/
│ ├── 00-run-init.sh # creates supabase service roles
│ ├── 01-init.sql # vehicles + bucket + seed cars
│ ├── post-boot.sql # admin user (must_change_password) + bucket row
│ └── 02-leads.sql # leads, customers, RPCs, realtime publication
├── frontend/
│ ├── Dockerfile # nginx + runtime anon-key injection
│ ├── nginx.conf
│ ├── index.html # public DE/EN site, booking form -> leads
│ ├── admin.html # auth-gated CRM
│ ├── app.js
│ ├── admin.js # realtime + qualify/disqualify + password change
│ ├── config.js # anon-only runtime config
│ ├── i18n.js
│ ├── styles.css
│ ├── impressum.html
│ └── datenschutz.html
├── AGENT.md # findings, conventions, traps
└── ARQUITECTURE.md # architecture deep-dive
```
See [AGENT.md](AGENT.md) and [ARQUITECTURE.md](ARQUITECTURE.md) for everything deeper.