Skip to content

PPT-2536: shared legacy-credential fixtures + refresh-chain test coverage - #11

Merged
camreeves merged 1 commit into
masterfrom
PPT-2536-test-suite
Jul 29, 2026
Merged

PPT-2536: shared legacy-credential fixtures + refresh-chain test coverage#11
camreeves merged 1 commit into
masterfrom
PPT-2536-test-suite

Conversation

@camreeves

Copy link
Copy Markdown
Contributor

First slice of the PPT-2536 test-suite campaign (tasks/PPT-2536/test-matrix.md).

Why

Every auth.cr refresh failure in PPT-2536 was a credential that predated the running code — tokens issued by the Ruby service, or by an earlier auth.cr build. Specs that only exercise freshly-minted tokens structurally cannot see those, which is how the 2026-07-25 dev revert happened with a green suite.

What

spec/spec_helpers/legacy_fixtures.cr — builders for the credential shapes auth.cr did not mint:

  • Ruby/Doorkeeper opaque rows (SHA256-hashed, per hash_token_secrets), shaped to the dev forensics: 7,401 real rows, 100% scopes = 'public'
  • pre-scope-fix auth.cr refresh tokens (user, no scope claim)
  • current-format and ownerless client-grant tokens
  • clear_doorkeeper_rowsclear_tables never touched the Ruby-era table, so seeded rows were outliving spec runs

refresh_hardening_spec.cr now builds from the factory rather than inline lambdas, so the upcoming cutover/session specs share one definition.

New cases

Row Case
RF-04 The literal ts-client request — no client_secret, no scope, via the /auth/oauth/* alias SPAs actually call. Existing specs posted a secret, which real public clients never send
RF-02 The heal survives a 5-hop chain, not one refresh — the revert happened because each hop re-embedded the empty scope
RF-05 A double-submitted refresh token (the ts-client boot race) must not destroy the chain — strict reuse-detection would log out every SPA on startup

RF-05 passing is a positive finding: auth.cr already tolerates the double-submit, so the SPA boot race is safe.

Verification

154 examples, 0 failures (151 + 3 new), no regressions from the refactor.

🤖 Generated with Claude Code

Adds spec/spec_helpers/legacy_fixtures.cr: builders for the credential
shapes auth.cr did NOT mint — Ruby/Doorkeeper opaque rows (SHA256-hashed,
per `hash_token_secrets`), pre-scope-fix auth.cr refresh tokens, current
-format tokens, and ownerless client-grant tokens. Every refresh failure
in PPT-2536 was a credential predating the running code, so specs that
only exercise freshly-minted tokens structurally cannot see them.

refresh_hardening_spec.cr now builds its rows from the factory rather than
inline lambdas, so the cutover/session specs share one definition.

Three new cases from tasks/PPT-2536/test-matrix.md:
  * RF-04 the literal ts-client request — no client_secret, no scope, via
    the /auth/oauth/* alias SPAs actually call. Existing specs posted a
    secret, which real public clients never send.
  * RF-02 the heal survives a 5-hop chain, not just one refresh. The dev
    revert happened because each hop re-embedded the empty scope.
  * RF-05 a double-submitted refresh token (the ts-client boot race) must
    not destroy the chain — strict reuse-detection would log out every SPA
    on startup.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@camreeves
camreeves merged commit 4f6cd52 into master Jul 29, 2026
7 checks passed
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.

1 participant