feat(auth): last-login audit fields + ADR-0069 status (P1 completion)#2570
Merged
Conversation
…69 D7) Fills the one missing ADR-0069 D7 identity field pair — the rest of P1 (complexity/history/expiry/HIBP/lockout/enforced-MFA) was already implemented (this task was evaluate-first, don't re-develop). - platform-objects: add sys_user.last_login_at (datetime) + last_login_ip (text, 45 = IPv6 max), both readonly/Admin group. - plugin-auth: AuthManager.stampLastLogin stamps them on every successful /sign-in/email via the after-hook, independent of the lockout threshold (which gates recordSignInOutcome). IP from the trusted forwarded headers (x-forwarded-for → cf-connecting-ip → x-real-ip), capped to the column width. Best-effort: never turns a valid login into an error. - 4 unit tests (Date stamp + IP, runs when lockout off, IP cap, never throws on engine failure). - ADR-0069 status Proposed → Accepted (P1/P2 implemented) with an implementation-status matrix documenting what is landed and the remaining P2 gaps (per-org sys_organization.allowed_ip_ranges, shared-store rate limiting for multi-node). Verified: plugin-auth 5 files / platform-objects 2 files green; live showcase run shows last_login_at/ip populated after sign-in (IP from x-forwarded-for), and the pre-existing D1 complexity + D2 lockout enforced end-to-end when enabled via settings. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014y5kiH3aPLWtRRRGcVrXcT
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📓 Docs Drift CheckThis PR changes 2 package(s): 11 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
18 tasks
os-zhuang
marked this pull request as ready for review
July 4, 2026 10:25
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
概述
任务是「评估现有代码,不要重复开发」——评估结论:ADR-0069 P1(密码策略 D1 / 账号锁定 D2 / 强制 MFA D3)+ 大部分 P2 早已实现并合并(auth-manager.ts 里
assertPasswordComplexity/assertPasswordNotReused/HIBP 插件/assertAccountNotLocked/recordSignInOutcome/computeAuthGate→MFA_REQUIRED,settings manifest 字段全齐),只是 ADR 文档还标Proposed。本 PR 不重复开发已有功能,只补上评估中发现的唯一 P1 缺口 + 纠正文档滞后。
变更
D7 唯一缺口:last-login 审计字段
platform-objects:sys_user新增last_login_at(datetime)+last_login_ip(text, 45 = IPv6 最大长度),readonly / Admin 分组。plugin-auth:AuthManager.stampLastLogin在每次成功/sign-in/email的 after-hook 里写入,独立于锁定阈值(recordSignInOutcome在锁定关闭时 no-op,审计不应受此影响)。IP 取自可信转发头(x-forwarded-for→cf-connecting-ip→x-real-ip,与 D5 IP 白名单中间件同优先级),截断到列宽。best-effort:绝不把有效登录变成错误。文档纠偏
Proposed→Accepted — P1 + P2 implemented,新增「实现状态矩阵」逐条标注已落地 vs 剩余 P2 缺口(per-orgsys_organization.allowed_ip_ranges、多节点共享限流 store)。验证
--fresh:39620,Playwright,见 PR 讨论附图):last_login_at登录后落库、last_login_ip从x-forwarded-for取到198.51.100.22(本 PR 改动)PASSWORD_POLICY_VIOLATION拒、强密码通过ACCOUNT_LOCKED剩余(不在本 PR,建议后续)
allowed_ip_ranges记录级字段(现仅全局设置);限流共享 store(现为内存,多节点 gap)。关联
🤖 Generated with Claude Code
https://claude.ai/code/session_014y5kiH3aPLWtRRRGcVrXcT
Generated by Claude Code