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

vercelBot commented Jul 27, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredJul 27, 2026 1:33pm

Request Review

@github-actionsgithub-actionsBot 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 freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/steststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-zhuang@claude