diff --git a/openspec/changes/force-password-change/.openspec.yaml b/openspec/changes/archive/2026-10-11-force-password-change/.openspec.yaml similarity index 100% rename from openspec/changes/force-password-change/.openspec.yaml rename to openspec/changes/archive/2026-10-11-force-password-change/.openspec.yaml diff --git a/openspec/changes/force-password-change/design.md b/openspec/changes/archive/2026-10-11-force-password-change/design.md similarity index 100% rename from openspec/changes/force-password-change/design.md rename to openspec/changes/archive/2026-10-11-force-password-change/design.md diff --git a/openspec/changes/force-password-change/proposal.md b/openspec/changes/archive/2026-10-11-force-password-change/proposal.md similarity index 100% rename from openspec/changes/force-password-change/proposal.md rename to openspec/changes/archive/2026-10-11-force-password-change/proposal.md diff --git a/openspec/changes/force-password-change/specs/backend/auth/spec.md b/openspec/changes/archive/2026-10-11-force-password-change/specs/backend/auth/spec.md similarity index 100% rename from openspec/changes/force-password-change/specs/backend/auth/spec.md rename to openspec/changes/archive/2026-10-11-force-password-change/specs/backend/auth/spec.md diff --git a/openspec/changes/force-password-change/specs/frontend/AD/force-password-change/spec.md b/openspec/changes/archive/2026-10-11-force-password-change/specs/frontend/AD/force-password-change/spec.md similarity index 100% rename from openspec/changes/force-password-change/specs/frontend/AD/force-password-change/spec.md rename to openspec/changes/archive/2026-10-11-force-password-change/specs/frontend/AD/force-password-change/spec.md diff --git a/openspec/changes/force-password-change/specs/frontend/AD/user/spec.md b/openspec/changes/archive/2026-10-11-force-password-change/specs/frontend/AD/user/spec.md similarity index 100% rename from openspec/changes/force-password-change/specs/frontend/AD/user/spec.md rename to openspec/changes/archive/2026-10-11-force-password-change/specs/frontend/AD/user/spec.md diff --git a/openspec/changes/force-password-change/specs/shared/api-contract/spec.md b/openspec/changes/archive/2026-10-11-force-password-change/specs/shared/api-contract/spec.md similarity index 100% rename from openspec/changes/force-password-change/specs/shared/api-contract/spec.md rename to openspec/changes/archive/2026-10-11-force-password-change/specs/shared/api-contract/spec.md diff --git a/openspec/changes/force-password-change/specs/shared/data-model/spec.md b/openspec/changes/archive/2026-10-11-force-password-change/specs/shared/data-model/spec.md similarity index 100% rename from openspec/changes/force-password-change/specs/shared/data-model/spec.md rename to openspec/changes/archive/2026-10-11-force-password-change/specs/shared/data-model/spec.md diff --git a/openspec/changes/force-password-change/tasks.md b/openspec/changes/archive/2026-10-11-force-password-change/tasks.md similarity index 100% rename from openspec/changes/force-password-change/tasks.md rename to openspec/changes/archive/2026-10-11-force-password-change/tasks.md diff --git a/openspec/specs/backend/auth/spec.md b/openspec/specs/backend/auth/spec.md index dd2d886..9e8850f 100644 --- a/openspec/specs/backend/auth/spec.md +++ b/openspec/specs/backend/auth/spec.md @@ -42,3 +42,28 @@ #### Scenario: 超管查看全量数据 - **WHEN** 超管执行列表查询 - **THEN** 系统不做 data_scope 部门过滤,返回全量数据 + +### Requirement: 待改密门禁 +系统 SHALL 对 `must_change_password=true` 的用户实施门禁:除「修改本人密码」与「登出」接口外,其余接口返回 403(提示需先修改密码)。 + +#### Scenario: 待改密访问受保护接口 +- **WHEN** 待改密用户请求除改密/登出外的任意接口 +- **THEN** 系统返回 403 并提示需先修改密码 + +#### Scenario: 待改密改密与登出放行 +- **WHEN** 待改密用户请求修改密码或登出接口 +- **THEN** 系统放行 + +### Requirement: 登录返回待改密标志 +登录成功 SHALL 在响应中返回 mustChangePassword,值为该用户是否待改密。 + +#### Scenario: 待改密登录 +- **WHEN** 待改密用户登录成功 +- **THEN** 响应含 mustChangePassword=true + +### Requirement: 改密清除待改密 +用户修改本人密码成功 SHALL 清除其待改密标记。 + +#### Scenario: 改密后清除 +- **WHEN** 待改密用户修改密码成功 +- **THEN** 其 must_change_password 置为 false diff --git a/openspec/specs/frontend/AD/force-password-change/spec.md b/openspec/specs/frontend/AD/force-password-change/spec.md new file mode 100644 index 0000000..e620e54 --- /dev/null +++ b/openspec/specs/frontend/AD/force-password-change/spec.md @@ -0,0 +1,21 @@ +# Force Password Change Specification + +## Purpose + +定义首登强制改密页面的行为:登录后对待改密用户强制跳转改密页,改密成功后重新登录。 + +## Requirements + +### Requirement: 强制跳转改密页 +登录后若 mustChangePassword=true,前端 SHALL 强制跳转改密页并禁止进入其它页面(路由守卫拦截)。 + +#### Scenario: 待改密强制跳转 +- **WHEN** 用户登录成功且 mustChangePassword=true +- **THEN** 前端跳转到改密页,访问其它路由被重定向回改密页 + +### Requirement: 改密后重新登录 +改密页 SHALL 提供修改密码表单(新密码);提交成功后清空会话并跳转登录页重新登录。 + +#### Scenario: 改密成功 +- **WHEN** 用户在改密页提交新密码成功 +- **THEN** 前端清空会话并跳转登录页,用户用新密码重新登录 diff --git a/openspec/specs/frontend/AD/user/spec.md b/openspec/specs/frontend/AD/user/spec.md index ffb287d..c7efe14 100644 --- a/openspec/specs/frontend/AD/user/spec.md +++ b/openspec/specs/frontend/AD/user/spec.md @@ -69,3 +69,14 @@ #### Scenario: 解锁用户 - **WHEN** 管理员对某锁定用户执行解锁 - **THEN** 系统解锁该用户并刷新列表 + +### Requirement: 创建用户指定强制改密 +新增用户表单 SHALL 提供「首登强制改密」配置项(默认勾选);提交时将其作为 mustChangePassword 传入。 + +#### Scenario: 默认强制改密 +- **WHEN** 管理员新增用户保持「首登强制改密」勾选并提交 +- **THEN** 创建的该用户 mustChangePassword=true + +#### Scenario: 关闭强制改密 +- **WHEN** 管理员新增用户取消勾选「首登强制改密」 +- **THEN** 创建的该用户 mustChangePassword=false diff --git a/openspec/specs/shared/api-contract/spec.md b/openspec/specs/shared/api-contract/spec.md index ff06b4f..af456c5 100644 --- a/openspec/specs/shared/api-contract/spec.md +++ b/openspec/specs/shared/api-contract/spec.md @@ -43,11 +43,11 @@ - **THEN** 系统返回 403 ### Requirement: 认证接口 -系统 SHALL 提供登录、刷新令牌、登出接口;登录需 tenantCode+username+password,返回 access token 与 refresh token。 +系统 SHALL 提供登录、刷新令牌、登出接口;登录需 tenantCode+username+password,返回 access token、refresh token 与 mustChangePassword(待改密标志)。 #### Scenario: 登录成功 - **WHEN** 用户提供正确的租户、账号与密码 -- **THEN** 返回 access token(2h 过期)与 refresh token(7d 过期) +- **THEN** 返回 access token(2h 过期)、refresh token(7d 过期)与 mustChangePassword(待改密为 true,否则 false) #### Scenario: 刷新令牌 - **WHEN** access 过期后客户端携带 refresh token 请求刷新 diff --git a/openspec/specs/shared/data-model/spec.md b/openspec/specs/shared/data-model/spec.md index 7802e5b..e4483ed 100644 --- a/openspec/specs/shared/data-model/spec.md +++ b/openspec/specs/shared/data-model/spec.md @@ -63,6 +63,21 @@ user 实体 SHALL 通过 `status` 字段支持启用/停用(管理员手动启 - **WHEN** 停用用户(status=disabled)尝试登录 - **THEN** 系统拒绝登录并提示账号已停用 +### Requirement: 待改密标记 +user 实体 SHALL 通过 `must_change_password`(布尔,默认 false)标记待改密状态:管理员重置密码、租户初始化下发随机密码、创建用户(默认)时置 true;创建用户时管理员可显式关闭;用户自行改密成功后置 false。 + +#### Scenario: 临时密码置标记 +- **WHEN** 管理员重置密码或初始化租户下发临时密码 +- **THEN** 该用户 must_change_password 为 true + +#### Scenario: 创建用户默认强制改密 +- **WHEN** 管理员创建用户(未显式关闭「首登强制改密」) +- **THEN** 该用户 must_change_password 为 true;显式关闭则为 false + +#### Scenario: 改密清除标记 +- **WHEN** 用户修改本人密码成功 +- **THEN** 该用户 must_change_password 置为 false + ### Requirement: 字典实体扩展 dict_type 实体 SHALL 新增 built_in 字段(布尔,标记内置字典类型);dict_item 实体 SHALL 新增 built_in(布尔,标记内置字典项)与 color_type(字符串,取值 primary/success/warning/danger/info,可空)字段,用于前端标签渲染与内置保护。