129 lines
4.9 KiB
Markdown
129 lines
4.9 KiB
Markdown
# Bootstrapping ecomm
|
|
|
|
Bringing an environment from **empty persistence** to "first merchant, first
|
|
storefront" through the product flows alone (SD-0001 BUC-5). Empty is a working state
|
|
(INV-1): the app applies its own schema migrations at startup; there is no seed step.
|
|
|
|
This document grows per environment. SLICE-1 shipped the **localhost** section;
|
|
SLICE-4 adds **pre-production (PPE)**. The production section lands with the prod
|
|
stand-up.
|
|
|
|
## Localhost
|
|
|
|
### Prerequisites
|
|
|
|
- **Docker** (Desktop or Engine) with Compose v2 — the one external prerequisite. The
|
|
dev datastore is a single PostgreSQL container; the app itself runs natively for a
|
|
fast dev loop (D-7).
|
|
- **Python 3.13** and **Node 20+** on your PATH. `scripts/dev.sh` creates the backend
|
|
venv and installs frontend deps on first run.
|
|
|
|
### Bring-up
|
|
|
|
From a clean checkout:
|
|
|
|
```bash
|
|
scripts/dev.sh
|
|
```
|
|
|
|
This:
|
|
|
|
1. starts the dev Postgres container and waits for it to report healthy (the script
|
|
owns the container's lifecycle);
|
|
2. creates the backend virtualenv and installs dependencies (first run only);
|
|
3. installs the frontend's npm dependencies (first run only);
|
|
4. runs the FastAPI backend on **:8000** — which connects to the empty database and
|
|
applies all pending migrations itself (INV-7) — and the Vite dev server on
|
|
**:5173**, proxying `/api` to the backend.
|
|
|
|
Press **Ctrl-C** to stop the backend and Vite. The database container keeps running.
|
|
|
|
### Verify
|
|
|
|
```bash
|
|
curl http://localhost:8000/healthz
|
|
```
|
|
|
|
Expected: `{"status":"ok"}` (HTTP 200) — the process is up, the database is reachable,
|
|
and migrations are current. Open <http://localhost:5173> to see the app shell.
|
|
|
|
### Reset to empty (rehearse the bootstrap)
|
|
|
|
```bash
|
|
docker compose down -v
|
|
```
|
|
|
|
This removes the container and its named volume, returning persistence to empty. The
|
|
next `scripts/dev.sh` re-migrates from scratch — exactly the day-one state every
|
|
environment starts from (BUC-5a).
|
|
|
|
### Configuration
|
|
|
|
`scripts/dev.sh` sets `ECOMM_DATABASE_URL` to the local compose DSN
|
|
(`postgresql://ecomm:ecomm@localhost:5432/ecomm`). No deployment shape is baked into
|
|
the app (INV-8); deployed environments supply this and other config from Secret
|
|
Manager (see PPE below).
|
|
|
|
## Pre-production (PPE)
|
|
|
|
PPE is stood up and deployed through the **launch-app / flotilla-core** suite only
|
|
(handbook §8.5 — provisioning is an operator-run gesture). The app's deployment
|
|
record is `deployment.toml` at this repo's root; flotilla-core consumes it.
|
|
|
|
### One-time provisioning (operator-run, in order)
|
|
|
|
1. **Cloud foundation** — `scaffold-gcp-project`: the GCP project, its dedicated
|
|
`--no-activate` gcloud config, billing, core APIs, ADC quota pin.
|
|
2. **Managed database** — `provision-datastore` (launch-app §6.6a, built for ecomm's
|
|
D-7/D-8): Cloud SQL for PostgreSQL 16, private-IP-only, automated backups +
|
|
point-in-time recovery; writes the full DSN to Secret Manager as
|
|
`<project>/ecomm-ppe-database-url`. Bound on the deployment record as
|
|
`ECOMM_DATABASE_URL`.
|
|
3. **Secrets** (references only — bytes go in via stdin, never through a session):
|
|
`ECOMM_SESSION_SECRET` (fresh random), `ECOMM_SMTP_PASSWORD` (the shared
|
|
Wiggleverse relay credential), and flotilla's own Gitea read token for this
|
|
private repo.
|
|
4. **VM + edge** — `provision-vm`: the e2-micro, IAP-only SSH, nginx + Cloudflare
|
|
origin TLS, the systemd unit, DNS for `ecomm-ppe.wiggleverse.org`.
|
|
5. **Deployment record** — `flotilla-core deployment scaffold ecomm … -o
|
|
deployment.toml`, validate, commit it here, `deployment import --reconcile`.
|
|
|
|
### Deploy
|
|
|
|
Each release is a git tag `v<VERSION>` matching the repo-root `VERSION` file (the
|
|
pin). The one gesture, from the flotilla-core repo's venv:
|
|
|
|
```bash
|
|
CLOUDSDK_ACTIVE_CONFIG_NAME=ecomm .venv/bin/flotilla-core deploy ecomm
|
|
```
|
|
|
|
Nine phases, fail-stop; it ends by polling `https://ecomm-ppe.wiggleverse.org/healthz`
|
|
and requiring `status == "ok"` and `version == <target>`. Watch it yourself the same
|
|
way:
|
|
|
|
```bash
|
|
curl https://ecomm-ppe.wiggleverse.org/healthz
|
|
```
|
|
|
|
### Configuration surface (PPE values)
|
|
|
|
| Env var | Kind | Value |
|
|
| --- | --- | --- |
|
|
| `ECOMM_DATABASE_URL` | secret ref | `<project>/ecomm-ppe-database-url` (from provision-datastore) |
|
|
| `ECOMM_SESSION_SECRET` | secret ref | `<project>/ecomm-ppe-session-secret` |
|
|
| `ECOMM_SMTP_PASSWORD` | secret ref | the shared Wiggleverse relay credential |
|
|
| `ECOMM_MAILER` | overlay | `smtp` |
|
|
| `ECOMM_COOKIE_SECURE` | overlay | `1` |
|
|
| `ECOMM_SMTP_HOST` / `_PORT` / `_USER` / `_FROM` | overlay | the relay coordinates (non-secret) |
|
|
|
|
### The rehearsal (PUC-11)
|
|
|
|
From empty persistence: the deploy migrates the schema at startup (INV-7); then a
|
|
real sign-up → one-time code arriving by **real email** → create storefront → admin,
|
|
through the public flows alone. Record each rehearsal here when it happens.
|
|
|
|
## Production
|
|
|
|
Lands with the prod stand-up — the **identical gesture** on a prod deployment record
|
|
(BUC-5a): same provisioning skills, same deploy, same rehearsal.
|