Skip to content

Commit 9aa5510

Browse files
os-zhuangclaude
andauthored
test(auth): cover the better-auth 2FA lockout path; regenerate object translation bundles (#3624 follow-up) (#3659)
* test(auth): cover the better-auth 2FA lockout path; regenerate object translation bundles (#3624 follow-up) Follow-up to #3647, which provisioned four better-auth 1.7 columns that no platform object had. Two loose ends from that PR. ## The 2FA lockout path had no test at all `sys_two_factor.failed_verification_count` / `locked_until` were added blind alongside the team fix — found by the new parity gate, not by anything exercising the behavior. That is why they went missing in the first place: the whole path was untested, so a column better-auth writes on every wrong code could vanish without a single failure. The new dogfood test pins the behavior, not just the schema: a wrong code is COUNTED (the counter advances in the database), and a correct code RESETS the count — which is what makes the budget track *consecutive* failures. It has to go through the mid-sign-in two-factor cookie, not a bearer token: better-auth only runs `assertTwoFactorNotLocked` / `recordTwoFactorFailure` when `isSignIn` is true, and deliberately skips both when the same endpoint is called with a live session. A bearer-token test would have passed while the lockout path stayed entirely unexercised — the exact blind spot that let the columns through. Reverting the `AUTH_TWO_FACTOR_SCHEMA` mapping makes it fail, and shows the breakage was wider than the wrong-code path: `two-factor/enable` itself 500s with `table sys_two_factor has no column named failedVerificationCount`, so enrollment was broken too. TOTP is generated in-test from the otpauth:// secret via RFC 6238 over node:crypto rather than importing `@better-auth/utils/otp` — that is a transitive dependency, and taking a direct one on it to produce six digits would tie the test to an internal package's resolution. ## Translation bundles `os i18n extract` regenerated for the four new fields, which were absent from every locale bundle. Also picks up `sys_organization.parent_organization_id` / `sort_order` from the earlier ADR-0105 D6 work, which had the same gap. The `*.metadata-forms.generated.ts` bundles are deliberately NOT included: the same run rewrites them with unrelated spec drift (agent `visibility` and `capabilities.trash`/`mru` removed, `summaryOperations.*` added). Those are DELETIONS of curated translations for a spec change this branch has nothing to do with, so they are left for whoever owns that change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UYLC8TfjzHGwatNxZKdX7H * chore(changeset): declare the object-translation bundle update (#3624 follow-up) The regenerated bundles ship inside @objectstack/platform-objects, so the change is consumer-visible and takes a real patch changeset rather than an empty one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UYLC8TfjzHGwatNxZKdX7H --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent aa8b847 commit 9aa5510

6 files changed

Lines changed: 331 additions & 0 deletions

File tree

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
"@objectstack/platform-objects": patch
3+
---
4+
5+
fix(i18n): ship the missing object-translation keys for the better-auth 1.7 and ADR-0105 D6 fields (#3624 follow-up)
6+
7+
The generated object-translation bundles predate two rounds of field additions,
8+
so six fields had no entry in **any** locale and fell back to their raw schema
9+
labels in every UI surface that reads the bundle:
10+
11+
- `sys_team.member_count`, `sys_team_member.membership_key`,
12+
`sys_two_factor.failed_verification_count` / `locked_until` — the better-auth
13+
1.7 columns provisioned in #3647.
14+
- `sys_organization.parent_organization_id` / `sort_order` — the same gap left
15+
by the earlier ADR-0105 D6 group-structure work.
16+
17+
Regenerated with `os i18n extract` (merge mode, so every existing translation is
18+
preserved — the diff is purely additive). No API or schema change; the fields
19+
themselves already shipped.

packages/platform-objects/src/apps/translations/en.objects.generated.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,14 @@ export const enObjects: NonNullable<TranslationData['objects']> = {
507507
label: "Require Multi-Factor Auth",
508508
help: "When true, every member of this organization must enroll an authenticator app to access data."
509509
},
510+
parent_organization_id: {
511+
label: "Parent Organization",
512+
help: "Reporting/grouping parent. Grants NOTHING — visibility across organizations comes from membership, never from this reference (ADR-0105 D6)."
513+
},
514+
sort_order: {
515+
label: "Sort Order",
516+
help: "Display order among sibling organizations. Presentation only."
517+
},
510518
id: {
511519
label: "Organization ID"
512520
},
@@ -709,6 +717,10 @@ export const enObjects: NonNullable<TranslationData['objects']> = {
709717
label: "Organization",
710718
help: "Parent organization for this team"
711719
},
720+
member_count: {
721+
label: "Member Count",
722+
help: "Seat counter maintained by better-auth; do not write directly."
723+
},
712724
id: {
713725
label: "Team ID"
714726
},
@@ -759,6 +771,10 @@ export const enObjects: NonNullable<TranslationData['objects']> = {
759771
},
760772
user_id: {
761773
label: "User"
774+
},
775+
membership_key: {
776+
label: "Membership Key",
777+
help: "Derived membership digest maintained by better-auth; do not write directly."
762778
}
763779
},
764780
_actions: {
@@ -993,6 +1009,14 @@ export const enObjects: NonNullable<TranslationData['objects']> = {
9931009
verified: {
9941010
label: "Verified",
9951011
help: "Whether the enrollment was confirmed with a valid TOTP code (managed by better-auth)"
1012+
},
1013+
failed_verification_count: {
1014+
label: "Failed Verification Count",
1015+
help: "Consecutive failed 2FA verifications; reset on success. Maintained by better-auth."
1016+
},
1017+
locked_until: {
1018+
label: "Locked Until",
1019+
help: "Set when failed 2FA verifications cross the lockout threshold. Maintained by better-auth."
9961020
}
9971021
},
9981022
_views: {

packages/platform-objects/src/apps/translations/es-ES.objects.generated.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,14 @@ export const esESObjects: NonNullable<TranslationData['objects']> = {
507507
label: "Exigir autenticación multifactor",
508508
help: "Si es true, todos los miembros de esta organización deben registrar una aplicación de autenticación para acceder a los datos."
509509
},
510+
parent_organization_id: {
511+
label: "Parent Organization",
512+
help: "Reporting/grouping parent. Grants NOTHING — visibility across organizations comes from membership, never from this reference (ADR-0105 D6)."
513+
},
514+
sort_order: {
515+
label: "Sort Order",
516+
help: "Display order among sibling organizations. Presentation only."
517+
},
510518
id: {
511519
label: "ID de organización"
512520
},
@@ -709,6 +717,10 @@ export const esESObjects: NonNullable<TranslationData['objects']> = {
709717
label: "Organización",
710718
help: "Organización principal de este equipo."
711719
},
720+
member_count: {
721+
label: "Member Count",
722+
help: "Seat counter maintained by better-auth; do not write directly."
723+
},
712724
id: {
713725
label: "ID de equipo"
714726
},
@@ -759,6 +771,10 @@ export const esESObjects: NonNullable<TranslationData['objects']> = {
759771
},
760772
user_id: {
761773
label: "Usuario"
774+
},
775+
membership_key: {
776+
label: "Membership Key",
777+
help: "Derived membership digest maintained by better-auth; do not write directly."
762778
}
763779
},
764780
_actions: {
@@ -993,6 +1009,14 @@ export const esESObjects: NonNullable<TranslationData['objects']> = {
9931009
verified: {
9941010
label: "Verified",
9951011
help: "Whether the enrollment was confirmed with a valid TOTP code (managed by better-auth)"
1012+
},
1013+
failed_verification_count: {
1014+
label: "Failed Verification Count",
1015+
help: "Consecutive failed 2FA verifications; reset on success. Maintained by better-auth."
1016+
},
1017+
locked_until: {
1018+
label: "Locked Until",
1019+
help: "Set when failed 2FA verifications cross the lockout threshold. Maintained by better-auth."
9961020
}
9971021
},
9981022
_views: {

packages/platform-objects/src/apps/translations/ja-JP.objects.generated.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,14 @@ export const jaJPObjects: NonNullable<TranslationData['objects']> = {
507507
label: "多要素認証を必須化",
508508
help: "true の場合、この組織のすべてのメンバーはデータにアクセスするために認証アプリの登録が必要になります。"
509509
},
510+
parent_organization_id: {
511+
label: "Parent Organization",
512+
help: "Reporting/grouping parent. Grants NOTHING — visibility across organizations comes from membership, never from this reference (ADR-0105 D6)."
513+
},
514+
sort_order: {
515+
label: "Sort Order",
516+
help: "Display order among sibling organizations. Presentation only."
517+
},
510518
id: {
511519
label: "組織 ID"
512520
},
@@ -709,6 +717,10 @@ export const jaJPObjects: NonNullable<TranslationData['objects']> = {
709717
label: "組織",
710718
help: "このチームの親組織"
711719
},
720+
member_count: {
721+
label: "Member Count",
722+
help: "Seat counter maintained by better-auth; do not write directly."
723+
},
712724
id: {
713725
label: "チーム ID"
714726
},
@@ -759,6 +771,10 @@ export const jaJPObjects: NonNullable<TranslationData['objects']> = {
759771
},
760772
user_id: {
761773
label: "ユーザー"
774+
},
775+
membership_key: {
776+
label: "Membership Key",
777+
help: "Derived membership digest maintained by better-auth; do not write directly."
762778
}
763779
},
764780
_actions: {
@@ -993,6 +1009,14 @@ export const jaJPObjects: NonNullable<TranslationData['objects']> = {
9931009
verified: {
9941010
label: "Verified",
9951011
help: "Whether the enrollment was confirmed with a valid TOTP code (managed by better-auth)"
1012+
},
1013+
failed_verification_count: {
1014+
label: "Failed Verification Count",
1015+
help: "Consecutive failed 2FA verifications; reset on success. Maintained by better-auth."
1016+
},
1017+
locked_until: {
1018+
label: "Locked Until",
1019+
help: "Set when failed 2FA verifications cross the lockout threshold. Maintained by better-auth."
9961020
}
9971021
},
9981022
_views: {

packages/platform-objects/src/apps/translations/zh-CN.objects.generated.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,14 @@ export const zhCNObjects: NonNullable<TranslationData['objects']> = {
507507
label: "强制多因素认证",
508508
help: "为 true 时,该组织的每位成员都必须注册身份验证器 App 才能访问数据。"
509509
},
510+
parent_organization_id: {
511+
label: "Parent Organization",
512+
help: "Reporting/grouping parent. Grants NOTHING — visibility across organizations comes from membership, never from this reference (ADR-0105 D6)."
513+
},
514+
sort_order: {
515+
label: "Sort Order",
516+
help: "Display order among sibling organizations. Presentation only."
517+
},
510518
id: {
511519
label: "组织 ID"
512520
},
@@ -709,6 +717,10 @@ export const zhCNObjects: NonNullable<TranslationData['objects']> = {
709717
label: "组织",
710718
help: "该团队所属的上级组织"
711719
},
720+
member_count: {
721+
label: "Member Count",
722+
help: "Seat counter maintained by better-auth; do not write directly."
723+
},
712724
id: {
713725
label: "团队 ID"
714726
},
@@ -759,6 +771,10 @@ export const zhCNObjects: NonNullable<TranslationData['objects']> = {
759771
},
760772
user_id: {
761773
label: "用户"
774+
},
775+
membership_key: {
776+
label: "Membership Key",
777+
help: "Derived membership digest maintained by better-auth; do not write directly."
762778
}
763779
},
764780
_actions: {
@@ -993,6 +1009,14 @@ export const zhCNObjects: NonNullable<TranslationData['objects']> = {
9931009
verified: {
9941010
label: "Verified",
9951011
help: "Whether the enrollment was confirmed with a valid TOTP code (managed by better-auth)"
1012+
},
1013+
failed_verification_count: {
1014+
label: "Failed Verification Count",
1015+
help: "Consecutive failed 2FA verifications; reset on success. Maintained by better-auth."
1016+
},
1017+
locked_until: {
1018+
label: "Locked Until",
1019+
help: "Set when failed 2FA verifications cross the lockout threshold. Maintained by better-auth."
9961020
}
9971021
},
9981022
_views: {

0 commit comments

Comments
 (0)