docs(slice-4): BOOTSTRAP.md PPE runbook, version 0.4.0, README status
ci / check (pull_request) Has been cancelled
ci / check (push) Has been cancelled

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-10 23:36:24 -07:00
parent 22d738fc74
commit acff7ac588
4 changed files with 127 additions and 6 deletions
+67 -3
View File
@@ -4,8 +4,9 @@ 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 ships the **localhost** section; the
pre-production and production sections land with SLICE-4.
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
@@ -61,4 +62,67 @@ environment starts from (BUC-5a).
`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 (SLICE-4).
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.