T10.8 - document that a pre-D13 local SQLite database rejects new sign-ins

Found while diagnosing a login failure that turned out to be an account
lockout. The local wpsuite.db has no alembic_version table - it was built by
create_all() before D13 - so users.password_hash is still NOT NULL with no
default while the current model has no such column. Verified on a COPY of the
database rather than reasoned about: provisioning a new account raises

    IntegrityError: NOT NULL constraint failed: users.password_hash

The shape of it is what makes it worth documenting. Accounts already in the file
keep working, so the developer can sign in and nothing looks wrong; it breaks
only when a NEW person signs in, and it surfaces as HTTP 500, which reads as a
server fault rather than a schema one. Nothing anywhere told a developer their
existing database needed migrating.

The note gives the non-destructive fix - stamp a1b8c6d4e2f9 then upgrade head,
which runs only the drop and keeps the data - and says why a plain
`alembic upgrade head` would fail on such a file. Earlier in the session I
suggested deleting the database; stamping is strictly better, since deleting
discards test data for no benefit.

Production is unaffected: Postgres, migrations applied at container start.

Also updated the nested-group done-when to reflect what is now actually known.
The transitive matching rule WAS exercised against the live directory today for
a direct member of a 2,003-member group and returned a match, so the rule and
the filter are right on this estate. A genuinely nested case remains untested
for want of such an account, and the box is marked partial rather than done.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-24 11:44:16 -05:00
parent 25bc5bcd3f
commit c6a100405d
2 changed files with 32 additions and 1 deletions

View File

@@ -138,6 +138,37 @@ previously did not.
## Local dev
> ### A SQLite database created before D13 will reject new sign-ins
>
> `Base.metadata.create_all()` creates missing tables; it never alters existing ones.
> So a `wpsuite.db` built before D13 still has `users.password_hash` declared
> `NOT NULL` with no default, while the current model has no such column — and an
> INSERT that omits it is rejected:
>
> ```
> IntegrityError: NOT NULL constraint failed: users.password_hash
> ```
>
> Accounts already in the file keep working, so **you** can sign in and nothing looks
> wrong. It breaks the moment a *new* person signs in, because provisioning them is an
> INSERT — and it surfaces as an HTTP **500**, not a 401, so it reads as a server fault
> rather than anything to do with the schema.
>
> Such a database also has no `alembic_version` table, so `alembic upgrade head` would
> try to replay the baseline against tables that already exist. Stamp it first:
>
> ```bash
> python -m alembic -c server/alembic.ini stamp a1b8c6d4e2f9 # the revision before the drop
> python -m alembic -c server/alembic.ini upgrade head # runs only the drop
> ```
>
> That keeps whatever is in the file. Deleting the database also works and
> `create_all()` rebuilds a correct schema, but it throws away your test data.
>
> Production is unaffected: it runs Postgres and the container applies migrations at
> start, so the column is dropped properly there.
```bash
cd server
python -m venv .venv && . .venv/bin/activate # Windows: .venv\Scripts\activate