Skip to content

chore(db): drop the vestigial user challenge columns - #226

Merged
Bccorb merged 1 commit into
mainfrom
chore/drop-vestigial-challenge-columns
Aug 31, 2026
Merged

chore(db): drop the vestigial user challenge columns#226
Bccorb merged 1 commit into
mainfrom
chore/drop-vestigial-challenge-columns

Conversation

@Bccorb

@Bccorb Bccorb commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Closes #209.

On the precondition

The issue asks to "confirm #164 has been running in production long enough that a
rollback to before it is no longer plausible". Strictly it has not: the package is
still 0.7.4 with 25 pending changesets, so the webauthn_challenges migration
has never been released.

That resolves the concern rather than blocking on it. Because neither has shipped,
both land in the same release, so a deployment moves from "challenges on the
user row" to "challenges in their own table with the old columns gone" in one
step. There is no window in which a rollback lands on code that expects the
columns to still be there and populated.

The residual risk is the data, and it is not material: a challenge lives 300
seconds (CHALLENGE_TTL_SECONDS), so anything a rollback could have carried
across has already expired. The worst case is an in-flight ceremony that the user
starts again.

What changed

Both columns are dropped, along with their declarations in
src/models/users.ts. Nothing has read or written either since #164; left in
place they read as live state to the next person opening the model.

The down restores both nullable, which is the shape they had.

On the deleted assertions

Several tests asserted that challenge and challengeContext never appear in an
admin or user response. Those are dropped rather than rewritten. They were
guarding an allowlist in serializeApiUser, and the same tests still assert it
for emailVerificationToken and phoneVerificationToken, which are real and
sensitive, so the guard keeps its teeth.

Verified against a real database

Mocks would not have caught a schema mismatch here, so this was run against a
throwaway PostgreSQL 17 rather than asserted:

  • db:migrate removes both columns
  • db:migrate:undo restores them as character varying and jsonb, both
    nullable
  • re-applying removes them again
  • the User model reads and writes against the new schema (findAll and
    create both succeed), which is what would fail if a declaration had been left
    behind

npm run typecheck, npm run lint, npm run format:check, npm run build,
npm run test:run (1173 passing) and npm run coverage (98.78% statements) all
pass.

WebAuthn challenges moved to the webauthn_challenges table, which gave them a
purpose, an expiry and one-time use. users.challenge and users.challenge_context
were left behind so that release could be rolled back without losing challenge
state, and nothing has read or written either since. Left in place they read as
live state to anyone opening src/models/users.ts, and the next person to touch a
WebAuthn flow has to work out that they are dead.

Both columns and their model declarations are gone. The down restores them
nullable, which is the shape they had. It does not restore data and does not need
to: a challenge lives 300 seconds, so anything a rollback could carry across has
already expired, and the worst case is an in-flight ceremony the user starts
again.

The table move has not shipped either, so both land in the same release and a
deployment sees one step rather than two.

Tests that asserted the columns never leak through a response are dropped rather
than rewritten. They were guarding an allowlist, and the same tests still assert
it for emailVerificationToken and phoneVerificationToken, which are real.

Verified against a throwaway PostgreSQL 17 rather than mocks: the up removes both
columns, the down restores them as nullable varchar and jsonb, re-applying removes
them again, and the User model reads and writes against the new schema.

Closes #209
@Bccorb
Bccorb merged commit 9e420c8 into main Aug 31, 2026
4 checks passed
@Bccorb
Bccorb deleted the chore/drop-vestigial-challenge-columns branch August 31, 2026 01:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Drop the vestigial users.challenge and users.challengeContext columns

1 participant