reshape: move OHM transcripts under ohm/ for org-wide multi-app layout; add org-wide root README
This commit is contained in:
@@ -0,0 +1,214 @@
|
||||
# Session 0044.0 — Transcript
|
||||
|
||||
> Date: 2026-05-29
|
||||
> Goal: Isolate this machine's multiple Google Cloud stacks so OHM/flotilla
|
||||
> gestures can never accidentally drive the wrong account/project — first as
|
||||
> operator discipline (a named gcloud config + CLAUDE.md instructions), then
|
||||
> as an enforced guard in flotilla itself.
|
||||
>
|
||||
> Outcome: **Shipped flotilla v1.4.0 (gcloud config guard).** Created an
|
||||
> inactive `wiggleverse` gcloud config; added the `CLOUDSDK_ACTIVE_CONFIG_NAME`
|
||||
> discipline to CLAUDE.md; added a per-deployment `gcloud_config` record field
|
||||
> (migration 006) + `ohm_rfc_app_flotilla/gcloud.py` guard enforced at both
|
||||
> `run_deploy` entry and `ssh.run_remote`; set the live OHM record to
|
||||
> `gcloud_config=wiggleverse`. 214 tests pass. Merged to main, tagged v1.4.0,
|
||||
> pushed. No OHM app redeploy (operator-tool code only).
|
||||
>
|
||||
> Highlights / §19.2 candidates surfaced:
|
||||
> - flotilla relies on env *inheritance* for the config pin — it doesn't set
|
||||
> `CLOUDSDK_ACTIVE_CONFIG_NAME` itself. Candidate: have it assert-or-set.
|
||||
> - `gcloud compute ssh` pins `--project` but not `--account`. Candidate:
|
||||
> store the operator account in the record and pass `--account` too.
|
||||
> - Secret Manager calls use ADC, which `CLOUDSDK_ACTIVE_CONFIG_NAME` does not
|
||||
> select — the guard is scoped to the gcloud-subprocess path by design.
|
||||
>
|
||||
> Timing: the session ran ~30 minutes (start ~07-27, end 07-57 PST). The
|
||||
> exact start minute was not auto-recorded; 07-27 is derived from the
|
||||
> operator-confirmed ~30-minute duration against the real 07-57 end.
|
||||
|
||||
---
|
||||
|
||||
## Pre-session state
|
||||
|
||||
- **flotilla** (`ohm-rfc-app-flotilla`): `main` at `242bb3a` (= `origin/main`),
|
||||
last release tag `v1.3.0` (`fb9bd04`). Working tree clean. 203 tests green.
|
||||
- **OHM live**: unchanged this session — no deploy performed. The local
|
||||
deployment record (`~/.ohm-rfc-app-flotilla`) had one row, `ohm-rfc-app`,
|
||||
`target_vm_project=wiggleverse-ohm`, `gcloud_config=NULL` (column did not
|
||||
exist yet).
|
||||
- **gcloud configs on the machine** at open:
|
||||
- `benstull-infra` (ACTIVE) → `ben.stull@wiggleverse.org` / `wiggleverse-ohm`
|
||||
- `benstullbets` → `ben.stull@benstullbets.com` / `benstullbets`
|
||||
- `default` → `ben@wiggleverse.org` / `wiggleverse-rfc`
|
||||
- **In-flight sessions** per the shared repo at claim time: `0026.0` and
|
||||
`0027.0` (both `--INPROGRESS` from 2026-05-28T13-46, ~18h stale; neither
|
||||
touches flotilla, so the shared checkout was safe to work in directly).
|
||||
|
||||
---
|
||||
|
||||
## Turn-by-turn arc
|
||||
|
||||
### Arc 1 — The original ask: a named config + instruction discipline
|
||||
|
||||
The operator runs more than one Google Cloud stack on this machine and wanted
|
||||
process-scoped isolation: always select the config via
|
||||
`CLOUDSDK_ACTIVE_CONFIG_NAME=xyz` (which never touches the shared on-disk
|
||||
active-config pointer) plus belt-and-suspenders explicit `--project`/`--account`.
|
||||
|
||||
Inspected the existing configs/accounts and how flotilla invokes gcloud:
|
||||
`ssh.py` already passes `--project` from the deployment record; Secret Manager
|
||||
uses ADC; nothing pinned the account or a config. So the env-var discipline was
|
||||
exactly the missing identity pin.
|
||||
|
||||
The two named stacks didn't map cleanly to the existing config names, so I
|
||||
asked the operator (AskUserQuestion) for the account+project mapping per config.
|
||||
Answers: **wiggleverse** → `ben.stull@wiggleverse.org` / `wiggleverse-ohm`;
|
||||
**benstull** → *"don't worry about this one — I'm setting it up in a different
|
||||
session."* So this session created only the `wiggleverse` config.
|
||||
|
||||
Created it inactive and populated it without disturbing the active pointer:
|
||||
```
|
||||
gcloud config configurations create wiggleverse --no-activate
|
||||
CLOUDSDK_ACTIVE_CONFIG_NAME=wiggleverse gcloud config set account ben.stull@wiggleverse.org
|
||||
CLOUDSDK_ACTIVE_CONFIG_NAME=wiggleverse gcloud config set project wiggleverse-ohm
|
||||
CLOUDSDK_ACTIVE_CONFIG_NAME=wiggleverse gcloud config set disable_usage_reporting true
|
||||
```
|
||||
Verified `benstull-infra` stayed `IS_ACTIVE=True`. Added an "Always pin the
|
||||
gcloud config" section to `CLAUDE.md` codifying the discipline (env var on
|
||||
every gcloud call and on `flotilla` invocations so subprocesses inherit it;
|
||||
hard "never mutate the shared active config" rule; read-back + `--no-activate`
|
||||
escape hatches). Did **not** rewrite the operator-guide's many gcloud commands
|
||||
(they already pin `--project`); flagged that as optional.
|
||||
|
||||
### Arc 2 — The operator opted into the enforced guard
|
||||
|
||||
I noted flotilla doesn't *assert* the config, only inherits it, and offered a
|
||||
code-level guard. Operator: **"yes."**
|
||||
|
||||
Key design decision (two-layer rule): the config name `wiggleverse` is an
|
||||
OHM-specific value, so it must live in the §13 deployment record, **not** be
|
||||
hardcoded in the CLI. Implementation:
|
||||
|
||||
- **Migration `006_gcloud_config.sql`** — nullable `gcloud_config TEXT` on
|
||||
`deployments`. `NULL` = guard off (backward compatible; generic /
|
||||
flotilla-core deployments unaffected).
|
||||
- **`ohm_rfc_app_flotilla/gcloud.py`** — `check_active_config(expected, env)`:
|
||||
no-op when `expected` falsy; else raises `GcloudConfigError` (with the exact
|
||||
`CLOUDSDK_ACTIVE_CONFIG_NAME=<name> <command>` remediation) on mismatch *or
|
||||
unset*. Failing on unset is deliberate — forces the explicit per-process pin.
|
||||
- **Two-layer enforcement**: `run_deploy` checks at gesture entry (before a
|
||||
`deploys` row opens → clean refusal, no orphan row) and re-raises as
|
||||
`DeployError`; `ssh.run_remote` re-checks per call (the literal
|
||||
`gcloud compute ssh` chokepoint) via a new `gcloud_config` field on
|
||||
`SshTarget`. `--dry-run` (which goes through `assemble_plan`, not
|
||||
`run_deploy`) stays unguarded.
|
||||
- **registry**: `Deployment.gcloud_config` field, row mapping, `add_deployment`
|
||||
param, `UPDATABLE_FIELDS`. **cli**: `deployment add/update --gcloud-config`
|
||||
(empty string clears to NULL), and `gcloud_config` added to `deployment show`.
|
||||
|
||||
Micro-corrections mid-flight (honest record):
|
||||
- Importing the `gcloud` module into `ssh.py` and `deploy.py` shadowed local
|
||||
variables named `gcloud` (the gcloud *binary* path). Renamed those locals to
|
||||
`gcloud_bin` in both files.
|
||||
- Initially numbered the new SPEC section §11.5 — but §11.5 is already the
|
||||
v1.3.0 webhook-reads boundary. Renumbered the guard to **§11.6** across code
|
||||
comments, the migration, and SPEC; left the genuine webhook §11.5 refs alone.
|
||||
|
||||
Tests: new `tests/test_gcloud.py` (5), plus guard cases in `test_ssh.py`,
|
||||
`test_deployment.py`, and `test_deploy.py` (refuse-before-row-opens +
|
||||
proceed-when-matches). Full suite **214 passed**. CLI smoke test on a fresh
|
||||
temp DB confirmed add/show/update-clear round-trips.
|
||||
|
||||
### Arc 3 — Coherence, live record, release
|
||||
|
||||
- **SPEC**: §5.5 (record field), §11.6 (the guard mechanism + ADC caveat +
|
||||
belt-and-suspenders framing), §13.9 (`gcloud_config: wiggleverse` for OHM),
|
||||
and the §12 verb-surface line.
|
||||
- **CHANGELOG** 1.4.0 with an RFC-2119 upgrade-steps block; **VERSION** +
|
||||
**pyproject** → 1.4.0; **register-ohm.sh** now sets `--gcloud-config
|
||||
wiggleverse` on bring-up; **operator-guide** got a §11.6 callout box.
|
||||
- **Live OHM record**: `deployment update ohm-rfc-app --gcloud-config
|
||||
wiggleverse` (migration 006 applied automatically on the read). The guard is
|
||||
now active for OHM — future deploys MUST be prefixed.
|
||||
- **Release**: branched `session-0044/flotilla-gcloud-config-guard`, committed,
|
||||
fast-forwarded `main`, tagged `v1.4.0`, pushed main + tag + branch to origin.
|
||||
|
||||
---
|
||||
|
||||
## Cut state (end of session)
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| flotilla | `5f1689f` on `main` (= `origin/main`), tag **`v1.4.0`**; branch `session-0044/flotilla-gcloud-config-guard` also pushed |
|
||||
| OHM live | **unchanged** — no deploy this session; still on its prior `deploys.id`/version |
|
||||
| ohm-rfc pin | unchanged |
|
||||
| local deployment record | `ohm-rfc-app` now carries `gcloud_config=wiggleverse` (operator-machine state, not a repo change) |
|
||||
| gcloud configs | added inactive `wiggleverse` (`ben.stull@wiggleverse.org` / `wiggleverse-ohm`); shared active pointer untouched (`benstull-infra`) |
|
||||
|
||||
| Ledger | Status |
|
||||
| --- | --- |
|
||||
| gcloud config isolation — named config + CLAUDE.md discipline | ✅ shipped |
|
||||
| flotilla gcloud-config guard (v1.4.0) | ✅ shipped (merged, tagged, pushed) |
|
||||
| `benstull` gcloud config | ⏸ deferred — operator handling in a separate session |
|
||||
|
||||
---
|
||||
|
||||
## §19.2 candidates surfaced
|
||||
|
||||
1. **flotilla self-asserting vs. self-setting the config.** The guard relies on
|
||||
the *parent* process exporting `CLOUDSDK_ACTIVE_CONFIG_NAME` (gcloud
|
||||
subprocesses inherit it). flotilla could instead *set* it from the record
|
||||
when it shells out — but that would mask the guard's intent (the point is to
|
||||
force the operator/assistant to be explicit). Worth a deliberate call.
|
||||
2. **`--account` pin on `gcloud compute ssh`.** Today only `--project` is
|
||||
passed; the config name carries the account. Storing the operator account in
|
||||
the record and passing `--account` would be true belt-and-suspenders.
|
||||
3. **ADC identity isolation.** `secret set`/`bind` and deploy-time secret reads
|
||||
use ADC, which `CLOUDSDK_ACTIVE_CONFIG_NAME` does not select. If multi-stack
|
||||
ADC ever becomes a real hazard, that needs its own mechanism; for now the
|
||||
project is always passed explicitly on Secret Manager calls.
|
||||
|
||||
---
|
||||
|
||||
## What lands on the operator's plate
|
||||
|
||||
1. **Set up the `benstull` gcloud config** in the other session (deferred here
|
||||
by operator request). Mirror the gesture used for `wiggleverse`:
|
||||
`gcloud config configurations create benstull --no-activate` then populate
|
||||
with env-scoped `gcloud config set …`.
|
||||
2. **Every OHM deploy/ssh gesture now MUST be prefixed**
|
||||
`CLOUDSDK_ACTIVE_CONFIG_NAME=wiggleverse …`, or it refuses fast (no orphan
|
||||
`deploys` row). This is the intended behavior, but it changes the muscle
|
||||
memory.
|
||||
3. (Optional) Wire a Claude Code `SessionStart`/env hook to export the var for
|
||||
OHM sessions automatically, if hand-prefixing proves annoying.
|
||||
|
||||
---
|
||||
|
||||
## Prompt the operator can paste into the next Claude Code session
|
||||
|
||||
```
|
||||
You're an OHM driver session anchored in ohm-rfc-app-flotilla. Claim your own
|
||||
session ID first (~/git/ohm-infra/scripts/claim-session-id.sh --start <now>);
|
||||
the number in this prompt is advisory.
|
||||
|
||||
Context from session 0044: flotilla v1.4.0 shipped a gcloud config guard.
|
||||
The OHM deployment record now carries gcloud_config=wiggleverse, so EVERY
|
||||
deploy/ssh gesture against OHM must be prefixed
|
||||
CLOUDSDK_ACTIVE_CONFIG_NAME=wiggleverse — otherwise flotilla refuses before
|
||||
opening a deploys row. An inactive `wiggleverse` gcloud config
|
||||
(ben.stull@wiggleverse.org / wiggleverse-ohm) exists; the shared on-disk active
|
||||
pointer (benstull-infra) was left untouched. flotilla is at main=5f1689f, tag
|
||||
v1.4.0, pushed to origin. 214 tests green. No OHM app redeploy was needed.
|
||||
|
||||
Open items you might pick up:
|
||||
- The `benstull` gcloud config still needs creating (operator was handling it
|
||||
separately — confirm before assuming it's done).
|
||||
- §19.2 candidates from 0044: (a) should flotilla self-set CLOUDSDK_ACTIVE_
|
||||
CONFIG_NAME rather than only assert it? (b) pin --account on gcloud compute
|
||||
ssh, not just --project? (c) ADC identity isolation for Secret Manager calls.
|
||||
- Otherwise consult /Users/benstull/projects/wiggleverse/ohm-rfc/ROADMAP.md for
|
||||
the next substantive item.
|
||||
|
||||
Don't paste secret bytes into the conversation (SPEC §3 invariant 1 / CLAUDE.md).
|
||||
```
|
||||
Reference in New Issue
Block a user