# SESSION-0010.0 — R03 Locations + flotilla secret-files + config-onboarding spec + wildcard-TLS wiring

**Date:** 2026-06-02
**Driver:** Ben (ben@wiggleverse.org)
**Repos touched:** `wiggleverse-ecomm` (impl, branch `r01-store-settings`),
`flotilla-core` (`main`), `rfc-app` (`main`), `wiggleverse-ecomm-bdd-release-planner-app`
(`main`), plus Claude memory.
**Outcome:** R03 Locations shipped (committed, unmerged); flotilla-core gained a
`secret-file` feature (v0.4.0, pushed) for TLS-cert delivery; config/secret
onboarding UX spec'd (not built); ohm/planner nginx wired to the wildcard cert
(pushed); the git/secrets working model was clarified across memory.

Transcript-honest per the engineering guide — wrong turns included.

---

## What happened (in order)

1. **"Build R03 — Locations (core)."** Read memory + the impl repo, grounded in OHM
   (Location = embodied physical venue of the Commercial Relationship; the
   last-active + set-primary invariants = Duty of Care / Dignity in Commerce).
   GOTCHA: **OHM was unreachable from the sandbox** (`ohm.wiggleverse.org` DNS
   no-answer) — grounded in the concepts already in memory + the SPEC link targets
   instead, and flagged it for re-verification. Built the 4 dependency-free
   scenarios (`13.07.0001/0002/0003/0006`): migration `0004_locations.sql`
   (single-primary as a **partial unique index**), `app/locations.py` (mirrors
   staff.py), seed of one primary "Main location", REST BFF + GraphQL
   (`Store.locations` + add/update/setPrimary/delete), and a Locations admin UI.
   Decision: filed under the existing **`settings`** section (no new section).
   **46 tests** green (38 + 8); all four scenarios browser-verified (the OTC 60s
   cooldown bit again — a curl smoke-test consumed the owner's code, worked around
   by polling for a fresh `dev_code` then verifying via in-page fetch). SPEC → v0.5
   (§9 + §5 rows), README + `/api/health`→R03. Commit `5b3e946` (unmerged).

2. **"I have the *.wiggleverse.org cert — command to load the key into the right
   secret? It'll impact other apps. Huh, bdd.ecomm works fine."** Corrected two
   misconceptions: a single-level wildcard does **NOT** cover the nested
   `bdd.ecomm.wiggleverse.org` (two labels) — bdd works because of its *own* certbot
   cert, grey-cloud; and **no app reads a cert from a secret today** (all use certbot
   on the VM; flotilla had zero TLS code). Gave the safe `gcloud secrets … --data-file`
   gesture but flagged there was no consumer.

3. **"Why not put the cert in a secret and have flotilla deploy it to nginx?"** →
   honest reassessment: good idea, I'd been over-cautious. Walked the build-vs-buy
   shape (renewal ownership turns on Origin-CA-vs-LE; cross-project secret access is
   the real wrinkle; security is a wash). **"Build it into flotilla — go for it."**

4. **flotilla-core `secret-file` feature.** Discovered the two apps run *different*
   flotilla generations (ohm = thin shim over flotilla-core; planner = bespoke
   `planner_flotilla`) → built into **flotilla-core** (shared, future-facing).
   Migration `010`, `registry.bind/list/unbind_secret_file`, `[[secret_file]]` in
   `deployment.toml`, **phase 6 extended** (atomic root write via sudo, bytes over
   stdin, zeroed + redacted, dedup'd reload, fail-stop), plan + a `secret-file` CLI
   group (`bind`/`set`/`unbind`/`list`). 366 tests; ohm shim inherits the verb free.

5. **"How is it set up for other apps?"** Confirmed from code: secrets → `.env` only;
   TLS entirely out-of-band (certbot). So secret-files is genuinely new flotilla
   surface, not a switch-flip.

6. **"Add a UX to manage config + secrets, per app type, with provider instructions.
   Stop using a Claude skill — make it deterministic. Spotify open-sourced something
   — build or buy?"** Researched (web worked; only internal hosts fail DNS):
   Spotify = **Backstage** (IDP framework, Scaffolder; secrets weak, 2–4 FTEs / 6–12
   mo — too heavy); Infisical/Doppler solve *storage* (GCP SM already covers).
   Verdict: **build** — the app-type-aware required-config + provider instructions is
   bespoke. **"Spec the manifest schema and two verbs."** Wrote
   `flotilla-core/docs/config-onboarding-spec.md` (manifest + `init` + `config
   doctor` + seed `cloudflare-proxied-vm`/`wildcard-tls` manifests). Locked
   decisions: PEM via **local file path**; `deploy` **gates on doctor by default**
   with `--skip-config-check`, doctor also standalone.

7. **nginx wiring.** Rewired ohm (`ohm.wiggleverse.org.conf` — was the pre-certbot
   template; now an explicit 80→443 vhost) and planner (`planner.conf` for
   `rfc.wiggleverse.org`) to the wildcard at `/etc/ssl/{certs,private}/`. Committed
   `34a65e0` (rfc-app) + `ddb27eb` (planner).

8. **/finalize → commit + push.** Committed the flotilla feature (`014c0f3`) + spec
   (`cd729f1`). Ben: **"push the unpushed commits."** rfc-app + planner pushed
   clean. **flotilla-core push REJECTED** — a parallel **PR #1** had merged a
   *different* "v0.3.0" (deployment.toml scaffold + fail-closed `validate`) and
   **tagged v0.3.0**.

   - ⚠️ **Wrong turn:** rebased onto it; resolved the top-of-file `deployment_toml.py`
     conflicts but **missed a third conflict region** (in `sync_to_registry`) and
     `git add`+`--continue` committed it **with conflict markers** (broken code).
     Caught it immediately (not pushed). Resolved properly (merged my secret-file
     binding into their reconciling sync + extended the prune logic), **renumbered my
     release 0.3.0 → 0.4.0** (0.3.0 was taken+tagged), back-filled a CHANGELOG stub
     for their release, and **rebuilt clean linear history** (`git reset --soft` —
     no force, no broken intermediate). **394 tests** green (mine + theirs). Pushed
     `b77dd7a`. No force-push anywhere; their PR untouched.

9. **"I don't want to push/merge myself — remove that guidance."** Found the rule
   was **self-contradictory** in memory (engineering-pattern already said merge was
   mine; ecomm files still called it "operator-only for Ben"). Fixed all of them.
   Then **"remove that from working-preferences"** (don't duplicate the git rule
   there) — removed it; canonical home is `wiggleverse-engineering-pattern`. Then
   **"update engineering-pattern to match: operator only wants secrets; otherwise
   Claude can do everything but lays out a plan and gets approval."** Settled model
   recorded: **operator owns secrets only; everything else is Claude's to do, gated
   by plan + approval for consequential actions; local/reversible work needs none.**

10. **"What's next?"** → recommended the **ohm wildcard-TLS cutover** (highest value
    + first real dogfood of secret-files). **"Go with it, but in a new session —
    finalize this one."** Verified all repos clean/in-sync; set the ▶NEXT pointer in
    memory. Wrote this transcript.

---

## State at wrap

| Repo | Branch | State |
|---|---|---|
| `wiggleverse-ecomm` | `r01-store-settings` | R03 committed `5b3e946`; unmerged (R01+auth+R02+GraphQL+R03 ride together) |
| `flotilla-core` | `main` | `b77dd7a` pushed — **v0.4.0** secret-files + onboarding spec |
| `rfc-app` | `main` | `34a65e0` pushed (ohm nginx → wildcard) |
| `…-bdd-release-planner-app` | `main` | `ddb27eb` pushed (rfc.wiggleverse.org nginx → wildcard) |

## Next session — the ohm wildcard-TLS cutover

1. **Decide cross-project secret access first** — one shared `*.wiggleverse.org`
   secret + `secretAccessor` grants to each VM's SA, vs one copy per project.
2. Ben runs `flotilla secret-file set` with the cert key + fullchain (NO SECRETS:
   his gesture; bytes never transit Claude).
3. Claude lays out the cutover step plan for approval, then deploys ohm.
4. Ben flips Cloudflare → Full(strict) + orange-cloud on `ohm` (Origin-CA cert only
   validates behind the proxy — do cert+proxy together).
5. `certbot delete --cert-name ohm.wiggleverse.org`.

Then back to **R04 — Product create & lifecycle** (next ecomm release).

**Open follow-ups:** teach flotilla `validate` about `[[secret_file]]` refs;
migrate the planner off bespoke `planner_flotilla` onto flotilla-core; re-verify
R03 OHM citations when `ohm.wiggleverse.org` is reachable.
