Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions skills/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,21 @@ skill 分发内容的变更记录。真源 = `skills/_core/`;交付物 = `skil

---


## [2026-11-07] core@7d01d7fc8d9b —— 默认用户名+密码;邮箱/手机验证后才入库

**内容**(`_core/PROCEDURE.md` + `_core/references/account-recovery.md`,EN/ZH 对称):
- 默认注册改为**用户名 + 密码**;邮箱/手机是可选账号标识,必须通过验证码后才创建/绑定。
- 未验证邮箱/手机不写入 `identities`、不能登录/找回/通知/占唯一性。
- 验证码注册(email-code / phone-code)支持设置密码;OAuth/邀请按 verified 来源处理。
- 找回仍为应用侧恢复码 + 管理员;已验证邮箱/手机 OTP 可选。
- G6:移除 `no-sending`;新增 `verified-registration`;`identifier-contract` 改为“用户名默认”。

**状态**:本地 build/check **6/6 PASS**;**未发布**(等 identity-service + 门户同窗上线);npm 待发布。

---


## [2026-11-07] core@f5e53f2dab16 —— v3.10:JWKS 验签改为「有条件可用」(评审 G13)

**内容**(`_core/PROCEDURE.md` §5.5 + `_core/references/backend-verification.md`,EN/ZH 对称):
Expand Down
12 changes: 6 additions & 6 deletions skills/_core/PROCEDURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ You are an AI agent executing this procedure inside the user's project. Work in

**What the user gets**

- Username + password login (email or phone is required at registration; no code is sent by default), plus optional OAuth / SMS / magic link
- Username + password login by default; email/phone are account identifiers only after verification, plus optional OAuth / SMS / magic link
- Registration, account recovery, profile, device/session management
- Automatic token refresh with multi-tab safety
- Server-side request authentication for your own API
Expand All @@ -71,7 +71,7 @@ Autional 为应用提供身份层。本 Skill 为已有应用建立身份边界

**用户将获得**

- 用户名 + 密码登录(注册需填邮箱或手机号;默认不发验证码),可选 OAuth / 短信 / 魔法链接
- 用户名 + 密码登录(默认);邮箱/手机验证后才作为账号标识,可选 OAuth / 短信 / 魔法链接
- 注册、账号找回、资料、设备/会话管理
- Token 自动刷新 + 多标签页安全
- 自有 API 的服务端请求认证
Expand Down Expand Up @@ -449,7 +449,7 @@ Match the user's scenario against the full matrix in `{{REFS_BASE}}/compliance-m
[D] Custom
```

**Decisions to record**: identifier (register with email or phone; username is a login alias; no code is sent by default) · recovery (app-side recovery code by default; admin reset fallback; email/phone OTP only if the app can send) · registration protection (CAPTCHA + rate limit; email verification is not anti-bot). Option matrix: `{{REFS_BASE}}/account-recovery.md`.
**Decisions to record**: identifier (register with username + password by default; email/phone are account identifiers only after verified code registration) · recovery (app-side recovery code by default; admin reset fallback; verified email/phone OTP optional) · registration protection (CAPTCHA + rate limit; email verification is not anti-bot). Option matrix: `{{REFS_BASE}}/account-recovery.md`.

**TOTP is a second factor, not a recovery channel.** Enable it only after a recovery code exists; SSO users recover at the IdP.

Expand Down Expand Up @@ -477,7 +477,7 @@ After the auth policy is written, re-open the login page and confirm the intende
[D] 自定义
```

**必须记录**:标识符(注册用邮箱或手机号;用户名仅作登录别名;默认不发送验证码)· 找回(默认应用侧恢复码;管理员重置兜底;仅当客户有发送能力时才用邮箱/手机验证码)· 注册防护(CAPTCHA + 限流;邮箱验证不是防机器人)。选项矩阵:`{{REFS_BASE}}/account-recovery.md`。
**必须记录**:标识符(默认用户名+密码;邮箱/手机仅在验证码注册通过后作为账号标识)· 找回(默认应用侧恢复码;管理员重置兜底;已验证邮箱/手机 OTP 可选)· 注册防护(CAPTCHA + 限流;邮箱验证不是防机器人)。选项矩阵:`{{REFS_BASE}}/account-recovery.md`。

**TOTP 是第二因素,不是找回通道。** 先有恢复码再启用;SSO 用户在 IdP 找回。

Expand Down Expand Up @@ -1572,7 +1572,7 @@ Artifacts:
☐ admin password flagged as "shown once"
☐ AUTIONAL_CHANGES.md exists
☐ recovery path answered (app-side recovery code / admin / none recorded)
☐ identifier strategy recorded (email / phone / email+phone; username is a login alias; no code sent)
☐ identifier strategy recorded (username default; email/phone only after verification)
☐ data-isolation gate answered (isolated / downgraded / stopped)
☐ backend request authentication implemented (if the server stores user data)
☐ forged-token test passed (server-backed apps)
Expand Down Expand Up @@ -1615,7 +1615,7 @@ Phase:
☐ 管理员密码已提醒「只显示一次」
☐ AUTIONAL_CHANGES.md 存在
☐ 找回方式已回答(应用侧恢复码 / 管理员 / 不支持并记录)
☐ 标识符策略已记录(邮箱 / 手机号 / 双通道;用户名仅作登录别名;默认不发码)
☐ 标识符策略已记录(默认用户名;邮箱/手机验证后才作为账号标识)
☐ 数据隔离门禁已回答(已隔离 / 降级单用户 / 停止)
☐ 服务端请求认证已实现(服务端保存用户数据时)
☐ 伪造 Token 测试通过(有服务端 API 的应用)
Expand Down
46 changes: 24 additions & 22 deletions skills/_core/references/account-recovery.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<!-- lang:en -->
# Identifier and account recovery

> Registration requires email or phone (platform `RegisterRequest.Validate`); username is only a login alias.
> The app does not send email/SMS codes by default.
> Default registration is username + password.
> Email/phone are account identifiers only after verification; unverified values are never stored.
> Recovery uses an app-side recovery code; admin reset is the fallback.
<!-- /lang:en -->
<!-- lang:zh -->
# 标识符与账号找回

> 注册必须填邮箱或手机号(平台 `RegisterRequest.Validate`);用户名只作登录别名。
> 默认不发送邮件/短信验证码。
> 默认注册是用户名 + 密码。
> 邮箱/手机只有在验证通过后才作为账号标识;未验证值不入库。
> 找回用应用侧恢复码;管理员重置兜底。
<!-- /lang:zh -->

Expand All @@ -18,22 +18,22 @@

| Identifier | Friction | Recovery | Anti-abuse |
|---|---|---|---|
| email + password (default) | low | app-side recovery code / admin | CAPTCHA + rate limit |
| phone + password | medium | app-side recovery code / admin | CAPTCHA + rate limit |
| email + phone (dual) | high | app-side recovery code / admin | both fields |
| username + password (default) | lowest | app-side recovery code / admin | CAPTCHA + rate limit |
| verified email + password | medium | recovery code; verified email OTP optional | CAPTCHA + rate limit |
| verified phone + password | medium | recovery code; verified phone OTP optional | SMS cost + rate limit |
| SSO only | depends on IdP | at the IdP | IdP policy |

Registration without email or phone is rejected (`email or phone is required`).
The email/phone is stored unverified; no code is sent. It is a registration identifier, not a recovery channel by itself.
An optional username (3–32 chars) is the day-to-day login alias.
Registration without a username is rejected. Email/phone are optional account identifiers, but they must pass a verification code before the account is created or the identifier is attached.
An unverified email/phone must not be written to the identity table, used for login, recovery, notifications, or uniqueness checks.
The default login is username + password; email/phone login is allowed only after verification.

## Recovery options

| Option | Requires | If the user loses it | Notes |
|---|---|---|---|
| app-side recovery code (default) | codes generated at signup / in settings | account unrecoverable | 10 single-use codes, hashed, shown once; verify, never reuse |
| admin reset | an operator | requires an operator | audited runbook |
| email/phone OTP (optional) | the app can send email/SMS | unrecoverable unless another channel exists | do not enable without a delivery channel |
| verified email/phone OTP (optional) | the identifier was verified and the app can send | unrecoverable unless another channel exists | do not enable without a delivery channel |
| recovery contact (optional) | the app can send | contact must still be reachable | only with a delivery channel |
| none | — | account unrecoverable | record it in `AUTIONAL_SETUP.md` |

Expand All @@ -45,7 +45,8 @@ Admin resets must be audited.

| Decision | Where to apply | How to verify |
|---|---|---|
| Identifier | registration form (`email` or `phone`) + tenant `login_methods` | submit each chosen identifier; a missing email/phone returns 400 |
| Identifier | registration form (username) / verified code registration for email/phone | username registration returns 201; email/phone without code returns 400 |
| Email/phone verification | identity code endpoints; attach only after code success | verify DB has `verified_at`; no unverified identity row |
| Recovery code | app-side table + settings page | generate once, redeem once, reject reuse |
| Admin reset | operator runbook | reset one test account and check the audit log |
| Registration protection | CAPTCHA + rate limit | 3 failures → challenge; per-IP limit trips |
Expand All @@ -57,22 +58,22 @@ Field names vary by region and version; verify behaviour instead of trusting a 2

| 标识符 | 摩擦 | 找回 | 防滥用 |
|---|---|---|---|
| 邮箱 + 密码(默认) | 低 | 应用侧恢复码 / 管理员 | CAPTCHA + 限流 |
| 手机号 + 密码 | 中 | 应用侧恢复码 / 管理员 | CAPTCHA + 限流 |
| 邮箱 + 手机号(双通道) | 高 | 应用侧恢复码 / 管理员 | 双字段 |
| 用户名 + 密码(默认) | 最低 | 应用侧恢复码 / 管理员 | CAPTCHA + 限流 |
| 已验证邮箱 + 密码 | 中 | 恢复码;已验证邮箱 OTP 可选 | CAPTCHA + 限流 |
| 已验证手机号 + 密码 | 中 | 恢复码;已验证手机 OTP 可选 | 短信成本 + 限流 |
| 仅 SSO | 取决于 IdP | 在 IdP 找回 | IdP 策略 |

注册时邮箱和手机号都没有 → 拒绝(`email or phone is required`)。
邮箱/手机号按未验证保存,**不发送验证码**。它只是注册标识符,本身不是找回通道。
可选用户名(3–32 位)是日常登录别名。
注册必须有用户名。邮箱/手机是可选账号标识,但必须先通过验证码,才能创建账号或绑定标识。
未验证邮箱/手机不得写入身份表,不得用于登录、找回、通知或唯一性判断。
默认登录是用户名 + 密码;邮箱/手机登录只在验证通过后允许。

## 找回方式

| 方式 | 前提 | 用户丢失后 | 说明 |
|---|---|---|---|
| 应用侧恢复码(默认) | 注册时/设置页生成 | 账号不可恢复 | 10 个一次性码,哈希存储,只显示一次;校验后作废,拒绝复用 |
| 管理员重置 | 有运维人员 | 需要人工 | 必须审计 |
| 邮箱/手机验证码(可选) | 客户有邮件/短信发送能力 | 没有其他通道则不可恢复 | 没有投递通道时不要启用 |
| 已验证邮箱/手机验证码(可选) | 标识已验证且客户能发送 | 没有其他通道则不可恢复 | 没有投递通道时不要启用 |
| 恢复联系人(可选) | 客户有发送能力 | 联系人仍须可达 | 仅有投递通道时启用 |
| 不支持找回 | — | 账号不可恢复 | 写进 `AUTIONAL_SETUP.md` |

Expand All @@ -84,7 +85,8 @@ Field names vary by region and version; verify behaviour instead of trusting a 2

| 决策 | 落地位置 | 怎么验证 |
|---|---|---|
| 标识符 | 注册表单(`email` 或 `phone`)+ 租户 `login_methods` | 分别提交每种标识符;缺邮箱/手机应返回 400 |
| 标识符 | 注册表单(用户名);邮箱/手机走验证码注册 | 用户名注册返回 201;邮箱/手机无验证码返回 400 |
| 邮箱/手机验证 | identity 验证码接口;通过后才绑定 | 查库确认 `verified_at`;不存在未验证身份行 |
| 恢复码 | 应用侧表 + 设置页 | 生成一次、兑换一次、拒绝复用 |
| 管理员重置 | 运维手册 | 重置一个测试账号并查审计日志 |
| 注册防护 | CAPTCHA + 限流 | 3 次失败出挑战;同 IP 限流生效 |
Expand All @@ -111,7 +113,7 @@ SSO 用户没有本应用密码,找回在身份提供方完成。
Copy this into `AUTIONAL_SETUP.md`:

```
Identifier: email | phone | email+phone | SSO only (username is a login alias)
Identifier: username (default) | verified email | verified phone | SSO only
Recovery: app-side recovery code | admin | none
If none: account is unrecoverable (accepted by <user> on <date>)
```
Expand All @@ -122,7 +124,7 @@ If none: account is unrecoverable (accepted by <user> on <date>)
复制到 `AUTIONAL_SETUP.md`:

```
Identifier: email | phone | email+phone | SSO only (username is a login alias)
Identifier: username (default) | verified email | verified phone | SSO only
Recovery: app-side recovery code | admin | none
If none: account is unrecoverable (accepted by <user> on <date>)
```
Expand Down
10 changes: 5 additions & 5 deletions skills/_gen/check-skills.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -344,14 +344,14 @@ const GATES = [
why: '账号找回默认必须是应用侧恢复码(客户无邮件/短信发送能力)',
},
{
id: 'no-sending',
re: /(默认不发送验证码|no code is sent by default)/i,
why: '必须写明默认不发送验证码,避免依赖客户的邮件/短信能力',
id: 'verified-registration',
re: /(验证码注册|verified code registration|验证后才|after verification)/i,
why: '邮箱/手机必须验证通过后才作为账号标识',
},
{
id: 'identifier-contract',
re: /(注册用邮箱或手机号|register with email or phone)/i,
why: '注册标识符必须写明 email/phone(用户名仅登录别名)',
re: /(默认用户名|username \+ password|用户名\+密码|username-only|仅用户名)/i,
why: '默认必须是用户名+密码;email/phone 验证后才作为标识',
},
{
id: 'isolation-gate',
Expand Down
8 changes: 4 additions & 4 deletions skills/autional-cn/SKILL.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: "Add Autional login, sessions and account lifecycle to an existing
region: cn
lang: en
canonical: https://www.autional.cn/ai/skill.en.md
generated: core@f5e53f2dab16
generated: core@1229279235b2
---

<!-- Generated by skills/_gen/build-skills.mjs from skills/_core — do not edit directly. -->
Expand Down Expand Up @@ -32,7 +32,7 @@ You are an AI agent executing this procedure inside the user's project. Work in

**What the user gets**

- Username + password login (email or phone is required at registration; no code is sent by default), plus optional OAuth / SMS / magic link
- Username + password login by default; email/phone are account identifiers only after verification, plus optional OAuth / SMS / magic link
- Registration, account recovery, profile, device/session management
- Automatic token refresh with multi-tab safety
- Server-side request authentication for your own API
Expand Down Expand Up @@ -224,7 +224,7 @@ Match the user's scenario against the full matrix in `https://www.autional.cn/ai
[D] Custom
```

**Decisions to record**: identifier (register with email or phone; username is a login alias; no code is sent by default) · recovery (app-side recovery code by default; admin reset fallback; email/phone OTP only if the app can send) · registration protection (CAPTCHA + rate limit; email verification is not anti-bot). Option matrix: `https://www.autional.cn/ai/references/account-recovery.md`.
**Decisions to record**: identifier (register with username + password by default; email/phone are account identifiers only after verified code registration) · recovery (app-side recovery code by default; admin reset fallback; verified email/phone OTP optional) · registration protection (CAPTCHA + rate limit; email verification is not anti-bot). Option matrix: `https://www.autional.cn/ai/references/account-recovery.md`.

**TOTP is a second factor, not a recovery channel.** Enable it only after a recovery code exists; SSO users recover at the IdP.

Expand Down Expand Up @@ -761,7 +761,7 @@ Artifacts:
☐ admin password flagged as "shown once"
☐ AUTIONAL_CHANGES.md exists
☐ recovery path answered (app-side recovery code / admin / none recorded)
☐ identifier strategy recorded (email / phone / email+phone; username is a login alias; no code sent)
☐ identifier strategy recorded (username default; email/phone only after verification)
☐ data-isolation gate answered (isolated / downgraded / stopped)
☐ backend request authentication implemented (if the server stores user data)
☐ forged-token test passed (server-backed apps)
Expand Down
8 changes: 4 additions & 4 deletions skills/autional-cn/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: "为现有应用接入 Autional 登录、会话与账号生命周
region: cn
lang: zh
canonical: https://www.autional.cn/ai/skill.md
generated: core@f5e53f2dab16
generated: core@1229279235b2
---

<!-- Generated by skills/_gen/build-skills.mjs from skills/_core — do not edit directly. -->
Expand Down Expand Up @@ -32,7 +32,7 @@ Autional 为应用提供身份层。本 Skill 为已有应用建立身份边界

**用户将获得**

- 用户名 + 密码登录(注册需填邮箱或手机号;默认不发验证码),可选 OAuth / 短信 / 魔法链接
- 用户名 + 密码登录(默认);邮箱/手机验证后才作为账号标识,可选 OAuth / 短信 / 魔法链接
- 注册、账号找回、资料、设备/会话管理
- Token 自动刷新 + 多标签页安全
- 自有 API 的服务端请求认证
Expand Down Expand Up @@ -222,7 +222,7 @@ core + 框架包 增加约 15 KB(gzip 后约 5 KB);首屏 +约 50 ms(OID
[D] 自定义
```

**必须记录**:标识符(注册用邮箱或手机号;用户名仅作登录别名;默认不发送验证码)· 找回(默认应用侧恢复码;管理员重置兜底;仅当客户有发送能力时才用邮箱/手机验证码)· 注册防护(CAPTCHA + 限流;邮箱验证不是防机器人)。选项矩阵:`https://www.autional.cn/ai/references/account-recovery.md`。
**必须记录**:标识符(默认用户名+密码;邮箱/手机仅在验证码注册通过后作为账号标识)· 找回(默认应用侧恢复码;管理员重置兜底;已验证邮箱/手机 OTP 可选)· 注册防护(CAPTCHA + 限流;邮箱验证不是防机器人)。选项矩阵:`https://www.autional.cn/ai/references/account-recovery.md`。

**TOTP 是第二因素,不是找回通道。** 先有恢复码再启用;SSO 用户在 IdP 找回。

Expand Down Expand Up @@ -760,7 +760,7 @@ Phase:
☐ 管理员密码已提醒「只显示一次」
☐ AUTIONAL_CHANGES.md 存在
☐ 找回方式已回答(应用侧恢复码 / 管理员 / 不支持并记录)
☐ 标识符策略已记录(邮箱 / 手机号 / 双通道;用户名仅作登录别名;默认不发码)
☐ 标识符策略已记录(默认用户名;邮箱/手机验证后才作为账号标识)
☐ 数据隔离门禁已回答(已隔离 / 降级单用户 / 停止)
☐ 服务端请求认证已实现(服务端保存用户数据时)
☐ 伪造 Token 测试通过(有服务端 API 的应用)
Expand Down
2 changes: 1 addition & 1 deletion skills/autional-cn/references/account-lifecycle.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- generated: core@f5e53f2dab16 · region: cn · lang: zh — do not edit directly -->
<!-- generated: core@1229279235b2 · region: cn · lang: zh — do not edit directly -->

# 账号生命周期:加入、绑定、找回

Expand Down
Loading
Loading