Files
session-history/0061/SESSION-0061.0-TRANSCRIPT-2026-06-01T10-28--INPROGRESS.md
T

171 lines
8.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.
# Session 0061.0 — Transcript
> Date: 2026-06-01
> Start: 2026-06-01T10-28 (PST implied)
> Goal: launch-app Slice 3 — build `provision-vm` (§6.7) + `scaffold-gitea-repos`
> (§6.8), then dogfood them against wiggle-snip to a verified pre-prod `/api/health`.
> Status: **IN PROGRESS.**
---
## Launch prompt
```
launch-app Slice 3 — provision-vm + scaffold-gitea-repos (SPEC §2, §6.7, §6.8)
State (after Slice 2 / session 0060, 2026-06-01):
- launch-app SPEC is v0.0.2; ROADMAP Slice 2 closed.
- Skills exist: scaffold-gcp-project (§6.5), define-deployment (§6.6).
- flotilla-core v0.3.0 on wiggleverse/flotilla-core main (private, tagged v0.3.0):
deployment scaffold|validate|import + gcloud.describe_config, 371 tests green.
Sits atop a parallel preview-environments line (still active).
- ohm-rfc-app-flotilla main is the v1.8.0 thin shim, dep pinned flotilla-core>=0.3.0.
- wiggle-snip (~/projects/wiggleverse/wiggle-snip, NOT a git repo) has a validated
deployment.toml. The §5.3 validate gate is built + proven.
Task:
1. Run scaffold-gcp-project for wiggle-snip FIRST (clears the dogfood WARN).
2. Build provision-vm (§6.7): micro VM (IAP-only, no public :22), runtime install
(Python, Node, nginx, systemd unit), TLS via Cloudflare. Idempotent. Gates on
flotilla-core deployment validate.
3. Build scaffold-gitea-repos (§6.8): repo set + bot user/token; record whether
pre-prod uses its own Gitea or shares.
4. Proof: fresh micro VM up, /api/health reachable through nginx after a hand-run
deploy, re-running the skill is a no-op.
Constraints: pre-prod single env (NO slots/ramp/promote/rollback); hard secrets
rule (stdin-piped secret set only); gcloud isolation (CLOUDSDK_ACTIVE_CONFIG_NAME
per-process); parallel preview-environments line shares flotilla-core (worktree if
touched); spec-driven (cite section numbers); branch + PR (Gitea, no gh CLI).
```
---
## Plan
- [x] Read SPEC §2/§6.7/§6.8, ROADMAP Slice 3, SESSION-PROTOCOL; claim session ID (0061).
- [x] Map exactly what the deploy substrate must be (flotilla-core deploy.py phases 28).
- [x] Reconcile flotilla-core reality vs the launch prompt (see Arc 1 — prompt was off).
- [x] Build `provision-vm` skill (SKILL.md + provision-runtime.sh + read-deployment-params.py).
- [x] Build `scaffold-gitea-repos` skill (SKILL.md + init-and-push.sh).
- [x] Dogfood step 1: `scaffold-gcp-project` for wiggle-snip → validate WARN→PASS (6/6 PASS).
- [ ] Operator gestures: new billing account; Gitea repo push; Cloudflare DNS token.
- [ ] Dogfood: APIs → VM → provision-runtime → deploy → green /api/health → prove no-op re-run.
- [ ] Update launch-app ROADMAP (close Slice 3) + SPEC if needed; branch + Gitea PR.
- [ ] Finalize + publish this transcript (handoff prompt to operator first).
---
## Pre-session state
- launch-app SPEC v0.0.2; ROADMAP Slice 1 + 2 closed. Skills present:
`scaffold-gcp-project` (§6.5), `define-deployment` (§6.6).
- `wiggle-snip` (`~/projects/wiggleverse/wiggle-snip`) is built + tested, NOT a git
repo, with a `deployment.toml` that validated 5 PASS + 1 WARN (gcloud config absent).
- gcloud active on-disk pointer: `benstull-infra` (left untouched all session).
---
## Turn-by-turn arc
### Arc 1 — flotilla-core reality vs the launch prompt
The launch prompt said "flotilla-core v0.3.0 on main, tagged v0.3.0, 371 tests" with
the `deployment scaffold|validate|import` verbs. **The real world (SPEC §4.1 — read
the world, don't trust a checkbox) is different and the prompt is advisory:**
- `main` = `333e0ff` **v0.2.0 (per-PR preview environments, SPEC §15)** — pushed to
`origin/main`. It does **not** carry the scaffold/validate verbs.
- The Slice-2 work lives on branch **`slice2-schema-validate`** (`9b15b2a`,
"flotilla-core v0.3.0: deployment.toml scaffold + fail-closed validate") in the
isolated worktree `~/projects/wiggleverse/flotilla-core-slice2`, **rebased on top
of** the preview-environments `main`, pushed to `origin/slice2-schema-validate`.
**Not merged to main, not tagged.**
So the "v0.3.0 on main, tagged" claim is ahead of reality — it's on the branch. This
session did **not** touch the flotilla-core checkout (the parallel preview-environments
line owns `main`); it only *used* the slice2 worktree's CLI for the validate gate.
### Arc 2 — Build the two skills
Studied `flotilla-core/deploy.py` to pin down exactly what the 9-phase deploy expects
to find on the VM (phases 28): install dir is a git clone owned by the service user;
`backend/.venv`; node/npm/git; a systemd unit; `https://<domain>/api/health` through
nginx. The skills lay **exactly** that substrate, no more (the deploy itself fetches /
builds / writes .env / starts the unit).
Built under `~/projects/wiggleverse/engineering/launch-app/skills/`:
- **`provision-vm/`** — `SKILL.md` (gate→probe→ask→create VM→install→key→clone→
Cloudflare→explain), `assets/provision-runtime.sh` (idempotent on-VM installer:
service user, apt runtime, deploy key born-on-VM for private repos, clone, venv,
systemd unit, nginx + self-signed origin TLS), `assets/read-deployment-params.py`
(emits shell exports from the canonical toml — single source of truth, no bash
re-derivation). Handles public (anon HTTPS clone) and private (deploy-key SSH)
repos; `REPO_PRIVATE` derived from whether the record carries `gitea_read_secret_ref`.
IAP-only SSH firewall (:22 ← 35.235.240.0/20 only); :80/:443 ← Cloudflare ranges.
- **`scaffold-gitea-repos/`** — `SKILL.md` (share-vs-own Gitea recorded via
`gitea_host`; visibility + bot choice; create repo → push → tag `v<VERSION>`; bind
read credential / register deploy key — all operator-run, never asks for token
bytes), `assets/init-and-push.sh` (idempotent: create repo via API if missing,
`git init` + first commit, point origin, push, tag — token read from `$GITEA_TOKEN`,
never an arg).
Both shell assets pass `bash -n`; the param reader round-trips wiggle-snip's toml.
### Arc 3 — Dogfood step 1: GCP foundation for wiggle-snip
Operator chose **full live bring-up** on a **new** billing account. Drove
`scaffold-gcp-project` for wiggle-snip: project `wiggle-snip` under org
`wiggleverse.org`; dedicated `wiggle-snip` profile **`--no-activate`** (verified the
active pointer stayed `benstull-infra`); **6/6 PASS** validate (gcloud-project WARN
cleared). Operator created a new billing account → linked → APIs enabled
(compute/secretmanager/iap) → ADC quota pinned to wiggle-snip.
### Arc 4 — VM + firewall + runtime (3 skill bugs found by dogfooding)
- Static IP `35.255.99.91`; VM `wiggle-snip-ppe` (e2-micro, debian-12, shielded) RUNNING.
- Firewall: IAP-only :22 (35.235.240.0/20), :80/:443 from Cloudflare ranges.
**Skill bug #1:** the default VPC ships `default-allow-ssh` (:22 from 0.0.0.0/0);
firewall rules union, so IAP-only wasn't structural until I deleted
default-allow-ssh + default-allow-rdp. Patched provision-vm Step 3 (3d).
- IAP SSH verified. provision-runtime installed the OS runtime (node 18.20.4, npm
9.2.0, python 3.11.2). **Skill bug #2:** clone temp dir `${INSTALL_DIR}.clone`
under root-owned /opt couldn't be created by the service user — now root
pre-creates it user-owned. **Skill bug #3:** the Gitea host has an AAAA record
but the VM has no IPv6 route → SSH clone died "Network is unreachable"; forced
IPv4 (`AddressFamily inet` / `ssh -4` / `ssh-keyscan -4`).
### Arc 5 — Gitea repo + the One-Name fork
- No GITEA_TOKEN in env; org push-to-create disabled. Operator created the repo —
as `wiggleverse/wiggleverse-wiggle-snip-app` (the `<org>-<product>-app`
convention), NOT `wiggle-snip`. **One-Name divergence (§3.3).** Operator chose:
keep deployment/project/VM = `wiggle-snip`, repoint `[app].repo` at the long
name. Logged as SPEC §3.3 friction (Wiggleverse repo convention vs
repo-name==One-Name). Pushed main + tag `v0.1.0` over SSH (as ben.stull).
- Repo is **private** (operator's choice). Added `gitea_read_secret_ref =
wiggle-snip/wiggle-snip-gitea-read-token` to the toml; re-validated (6/6);
re-imported. provision (private path) generated the VM deploy key
(`ssh-ed25519 …mYXY0 wiggle-snip-ppe-deploy`), pinned to the IPv4 fix.
---
## What lands on the operator's plate (current)
1. **Register the VM deploy key** (read-only) on wiggleverse-wiggle-snip-app — for
the clone.
2. **Store the read token**: `gcloud secrets create wiggle-snip-gitea-read-token`
(stdin) — for flotilla's pin fetch. (NOT `flotilla secret set` — §5.1 keeps it
out of the app runtime env.)
3. **Cloudflare DNS** A `ppe.wiggle-snip.wiggleverse.org` → `35.255.99.91`, proxied,
SSL Full — before phase 8 can go green.
---
## Prompt the operator can paste into the next Claude Code session
```
(to be written at finalize)
```