feat(backend): add standalone data plane

Replace the Supabase application data plane with the Node/PostgreSQL API, migrate mobile, admin, web, and MCP callers, add controlled cutover tooling, and define hardened Dokploy infrastructure.
This commit is contained in:
jjbrunton committed 2026-08-28 14:42:11 +01:00
1 parent 01bb8225ae
commit 006761d3b0
294 files changed
+16259 -6138

No files matched your search

+55 -14
View File
@@ -1,30 +1,71 @@
# Local full-stack development
Use `scripts/dev-local.sh`; do not start a mixture of local and production-backed
services manually.
Use `scripts/dev-local.sh`; do not start a mixture of local and production data
services manually. The default stack uses conventional PostgreSQL and the Sauci
Node API. It does **not** start local Supabase. Supabase remains the hosted
identity provider, so local application processes need the public Auth settings
described by their environment examples.
| Service | Owner | Port |
|---|---|---:|
| Supabase API / functions | Supabase CLI | 54321 |
| Supabase database | Supabase CLI | 54322 |
| Supabase Studio | Supabase CLI | 54323 |
| PostgreSQL | Docker Compose | 54320 |
| Sauci API | Node / Hono | 3003 |
| Operations worker | Node / Hono domain modules | none |
| Web | Next.js | 3000 |
| Admin | Vite | 3001 |
| MCP | Hono | 3002 |
| Expo Metro | Expo | 8081 |
PostgreSQL is bound to `127.0.0.1`, is healthchecked before application startup,
and stores data in a named Docker volume. The local connection string is:
```text
postgresql://sauci:sauci_local_only@127.0.0.1:54320/sauci
```
Those credentials are for local development only. Deployed environments must
inject unique secrets; they must never consume `infra/backend/.env.example`.
## First run
1. Use Node from `.nvmrc` and run `npm ci`.
2. Install Docker Desktop or Rancher Desktop, tmux, and the Supabase CLI.
3. Copy committed environment examples. Local helpers derive local Supabase
values; they never print or overwrite production credentials.
4. Run `scripts/dev-local.sh reset` to apply migrations and create E2E fixtures.
2. Install Docker Desktop or Rancher Desktop and tmux.
3. Configure the hosted Supabase Auth public URL/key for the mobile application
and the hosted Auth issuer/JWKS settings for the API. Do not configure any
local command with production credentials. Authenticated mobile E2E requires
the designated hosted non-production Auth project and a disposable,
onboarding-complete user whose subject has a matching local profile. Pass
its credentials as `E2E_EMAIL` and `E2E_PASSWORD` only to the Maestro process;
do not store them in an Expo environment file.
To exercise MCP tools, also set a local `ADMIN_API_SERVICE_TOKEN`, its
fixture `ADMIN_API_SERVICE_USER_ID`, and a separate `SAUCI_MCP_API_KEY`.
`scripts/dev-local.sh` passes the service token to MCP as
`SAUCI_ADMIN_API_TOKEN`; MCP never receives a database or Supabase service
credential.
4. Run `scripts/dev-local.sh reset` to recreate only the dedicated local Docker
volume, apply API migrations, and create configured fixtures.
5. Run `scripts/dev-local.sh up`.
`up` is idempotent. `down` stops tmux services and leaves Supabase available;
`down --all` also stops Supabase. Use `status`, `logs <service>`, `restart
<service>`, and `attach` for diagnosis.
`up` is idempotent. `down` stops tmux application processes and leaves the
database available. `down --all` also stops PostgreSQL but retains its volume.
Use `status`, `logs <service>`, `restart <service>`, and `attach` for diagnosis.
`logs postgres` reads Compose logs; other names read their tmux panes.
The `worker` pane owns scheduled jobs, notifications, moderation classification,
and filesystem cleanup; local development disables external AI classification.
The Expo window defaults to Metro. Use `scripts/dev-local.sh ios` or `android` to
launch the native app against the same backend.
`reset` is destructive but fails closed unless the database is the dedicated
loopback instance on port 54320. It removes only the `sauci-local` Compose
volume, starts a fresh healthy database, then runs the API's `db:migrate` and
`db:seed` scripts. `seed` retains the volume and reapplies those two scripts.
The API seed is a no-op unless its documented local fixture identity is set.
The Expo window defaults to Metro with
`EXPO_PUBLIC_API_URL=http://127.0.0.1:3003`. Use `scripts/dev-local.sh ios` or
`android` to launch the native application against the same API. Physical
devices require a reachable host URL rather than loopback.
`e2e/maestro/login-screen-smoke.yaml` verifies the native build and Auth shell
without credentials. `e2e/maestro/login-smoke.yaml` is the authenticated
standalone-API flow and must fail closed unless the non-production fixture above
is explicitly supplied. Neither local nor E2E runs may use the production Auth
project, production subscriber, or production application database.