# leaguelaw — v8 substrate feedback

> Running log of friction hit while building **inside** the v8 conventions.
> **This is feedback about the substrate, not about this project** — it gets
> compiled into `/srv/.logs/planning/server-evolution-2026.md` or the ops queue
> (`/srv/.logs/ideas.md`) once the build settles.
>
> Scope discipline: only entries where the *server framework, standards library,
> or gateway* caused the friction. Bugs in this project's own code belong in
> `handoff.md`, not here.
>
> Each entry: what happened, what it cost, and a candidate fix.

---

## 2026-08-10 — No sanctioned way to snapshot a project database

**What happened.** The build plan gates a destructive content pass on "snapshot
the database first", and there is no gateway command for it. `srv-gw wp --project
<p> -- db export` fails with `env: 'mysqldump': No such file or directory` —
the WordPress image ships wp-cli but not the MySQL client binaries, and `wp db
export` shells out to `mysqldump`. `srv-gw db-query` is deliberately read-only and
returns capped rows, so it cannot produce a restorable dump either.

**What it cost.** Working around it by hand: reading `DB_*` out of the project
`.env`, writing a `--defaults-extra-file` under `umask 077` so the password never
appears in the process list, running host `mysqldump` against `127.0.0.1:3306`,
gzipping, then deleting the temp credentials file. That is a lot of moving parts
for something every WordPress project needs before every risky change — and the
obvious shortcut (password on the command line) leaks it to anyone running `ps`.

**Candidate fix.** A `srv-gw db-snapshot --project <name>` that writes a
timestamped gzip into the project's `.snapshots/` with 640 perms, owned by the
project group, and a matching `db-restore` gated behind `--confirm`. The gateway
already holds the credentials and already brokers `db-query`, so this is the same
trust boundary — it just needs a write-side dump path. Without it, either every
project reinvents this, or people skip the snapshot because it is fiddly, which
is precisely when it is needed.

**Secondary.** Adding the MySQL client to the WordPress image would make
`wp db export` work, but the credentials-and-destination handling still lands on
the caller, so the gateway command is the better fix.

## 2026-08-10 — `new-workspace.sh` creates an instance folder that WordPress projects cannot use

**What happened.** Running the scaffolder on a gateway-managed WordPress project
creates an empty `main/` and writes an `agents.md` Layout section describing
`main/` as "the instance — code only". For WordPress that is wrong: the gateway
bind-mounts `wp-content/` into the container at a fixed path, so the instance is
`wp-content/` and code physically cannot move down a level without breaking the
site. Left alone, `main/` is an empty directory that reads like an instruction —
exactly the kind of thing a later session follows.

**What it cost.** Small, but real: removing the directory, rewriting the Layout
section by hand, and writing a declared-override paragraph so the divergence
reads as deliberate rather than as drift. Every WordPress project migrated to the
shape will pay this same tax, and the ones where nobody notices will end up with
a misleading empty folder.

**Candidate fix.** Have the scaffolder detect project type — `.project.json`
already carries `"type": "wordpress"` — and for WordPress skip `main/`, defaulting
`--instance` to `wp-content` and emitting the override paragraph automatically.
Same shape, correct instance, no hand-editing. The generic path is unchanged for
custom apps.

**Second, smaller note.** The scaffolder's `agents.md` template hardcodes a
deploy-confirmation rule about a visible version string (`/api/meta`, UI footer).
That is a custom-app convention and does not apply to a WordPress site, so it has
to be edited out by hand too. Worth gating on the same type check.
