Skip to content

test(auth): cover the lock itself and its expiry, not just the counter (#3624 follow-up) - #3667

Merged
os-zhuang merged 1 commit into
mainfrom
claude/org-creation-http-500-teams-gocypm
Jul 27, 2026
Merged

test(auth): cover the lock itself and its expiry, not just the counter (#3624 follow-up)#3667
os-zhuang merged 1 commit into
mainfrom
claude/org-creation-http-500-teams-gocypm

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

#3659。那个 PR 钉住了 2FA 失败预算的两端 —— 输错会被计数、输对会清零 —— 但停在了让它成为锁定而非单纯计数器的那几步转移上,而那才是真正保护账户的部分。

补三条断言:

1. 锁真的会落。 预算耗尽后 locked_until 被戳上一个未来时间。

走到这一步要同时尊重两个叠在一起的预算:better-auth 每个 two-factor cookie 只允许 5 次验证(beginAttempt(5)),每个账户允许 10 次连续失败(accountLockout.maxFailedAttempts)。只有后者碰得到本次要测的两个列,所以循环每 5 次就得换一个新 challenge。计数器在每一次失败后都断言,不是只在最后看一眼。

2. 锁在验码之前就生效。 已锁定的账户连正确的 TOTP 也拒(429)。没有这条,所谓"锁定"不过是一个慢一点的爆破循环。

3. 过期的锁会自己清掉。 better-auth 清锁走的是一个带 guard 的 incrementOne —— where locked_until <= now,set { failedVerificationCount: 0, lockedUntil: null }

这是整个适配器里唯一需要处理 lte 对 datetime 的地方,所以这条断言覆盖的不只是列,还有那个操作符:驱动一旦处理错,用户会被永久锁死,而且任何地方都不会报错。测试通过数据引擎把锁提前到过期(默认时长 900 秒,没有端点能加速它)—— 这是全文件唯一一处伸手绕过 API 的地方,已在注释里写明原因。

测试

two-factor-lockout.dogfood.test.ts 4 passed;连同 org-create-default-team.dogfood.test.ts 一起 5 passed。

纯测试改动,且 @objectstack/dogfood 是 private 包,所以配的是空 changeset(仓库认可的"本 PR 不发布任何东西"声明)。

Refs #3624, #3647, #3659


Generated by Claude Code

#3624 follow-up)

#3659 pinned the two ends of the 2FA failure budget — a wrong code is counted,
a correct one resets it. It stopped short of the transitions that make it a
LOCKOUT rather than a counter, which is the part that actually protects the
account. Three more assertions:

1. **The lock engages.** Spending the budget stamps `locked_until` in the
   future. Reaching it means respecting two stacked budgets: better-auth allows
   5 verifications per two-factor cookie (`beginAttempt(5)`) and 10 consecutive
   failures per ACCOUNT (`accountLockout.maxFailedAttempts`). Only the second
   touches the columns under test, so the loop takes a fresh challenge every 5
   tries. The counter is asserted after every single failure, not just at the
   end.

2. **The lock bites before the code is checked.** A locked account refuses even
   a VALID TOTP with 429. Without this the "lockout" would just be a slower
   guess loop.

3. **An expired lock clears itself.** better-auth clears it through a GUARDED
   `incrementOne` — `where locked_until <= now`, `set { failedVerificationCount:
   0, lockedUntil: null }`. That is the only place the ObjectQL adapter has to
   handle `lte` against a datetime, so this covers the operator as much as the
   columns: a driver mishandling it would leave the user locked out forever with
   no error anywhere. The test ages the lock through the data engine because no
   endpoint can — the default duration is 900s.

Test-only, and `@objectstack/dogfood` is private, hence the empty changeset.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UYLC8TfjzHGwatNxZKdX7H
@vercel

vercel Bot commented Jul 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Jul 27, 2026 1:33pm

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling size/s labels Jul 27, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): packages/qa.

2 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/permissions/authorization.mdx (via packages/qa)
  • content/docs/permissions/delegated-administration.mdx (via packages/qa)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/s tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants