docs: fix the examples that fail if you paste them

Six procedures that could not be followed as written.

Eighty-nine curl examples single-quoted `Authorization: Bearer $TOKEN`, so the
shell never expanded it and the server answered 422 "Not enough segments". Nine
more did the same with X-API-Key. The other 129 examples in the same file
already used double quotes, so this was drift rather than a convention, and the
spec regenerated from it carried the fault onward.

The GE-Enforce report example put a `//` comment inside a JSON body. The server
parses with silent=True, so it saw `{}` and answered "hostname is required"
about a body that plainly has one - the worst kind of error message, one that
sends the reader to the wrong field entirely.

The IIS install ran `flask db upgrade` and a per-plugin install loop but never
`flask plugin upgrade-all`, leaving every plugin's own chain unapplied. That is
precisely the 1054 "Unknown column" a deploy then hits somewhere else, days
later, on the page that uses the new column.

The pilot runbook looped `flask plugin enable` over plugins that were not yet
installed; enable refuses those, so on a fresh database it exited 1 on every
iteration and enabled nothing. ADR-013 had already recorded that defect.
`apply-profile` installs and enables in dependency order, which is what the step
was reaching for.

DEPLOY-WINDOWS-IIS named a profile file that does not exist; the shipped ones do.

And PLUGIN-EXTERNAL-REPO never mentioned PLUGIN_TABLE_OWNERS, while the
migration engine raises for any plugin missing from it - so the guide's own
step 5 fails for any external plugin that owns a table. That the registry lives
in the framework repo is deliberate, so the guide now says so, and says what it
costs: a table-owning external plugin is a two-repository change, and a plugin
that owns no tables avoids it entirely.
This commit is contained in:
cproudlock
2026-08-14 15:43:27 -04:00
parent d1ba3a1a02
commit 05be4c4489
7 changed files with 242 additions and 202 deletions

View File

@@ -102,6 +102,35 @@ venv/bin/python -m pytest ../wjsf-shipping/tests
Edits in `../wjsf-shipping` are picked up on the next framework restart, because
the symlink points back at your working tree.
### If your plugin owns tables, step 5 needs a change to the framework
This is the one place an external plugin is not self-contained, and it is better
said plainly than discovered at the first migration.
`flask plugin upgrade-all` builds each plugin's metadata from
`PLUGIN_TABLE_OWNERS` in `shopdb/plugins/alembic_template.py`, and raises rather
than guessing when a plugin has no entry:
```
RuntimeError: PLUGIN_TABLE_OWNERS has no entry for plugin 'shipping'.
Update shopdb/plugins/alembic_template.py.
```
So a plugin that owns tables needs its table names registered in that dictionary
in the framework repository. It is deliberate - the registry is what stops one
plugin's migration touching another's tables, and `tests/test_plugin_migrations.py`
tests it - but it does mean a table-owning external plugin is a two-repository
change: yours, plus a one-line addition upstream.
Two ways to live with it:
- **Send the entry upstream.** One line in `PLUGIN_TABLE_OWNERS` plus one in
`EXPECTED_HEAD_REVISION`, and your plugin is a normal citizen from then on.
- **Own no tables.** A plugin that stores nothing of its own - a report, a
dashboard card, a settings page over existing models - has nothing to
register and stays entirely in your repository. More plugins fit this than
expect to.
## core_version pinning for sister sites
The framework is pre-1.0. Under semver, any 0.x minor bump is allowed to break