oa-email-code-login 记录部署公网验证

这个提交包含在:
2026-05-27 08:07:35 +08:00
父节点 7f96cc0379
当前提交 76df8b6636
共修改 4 个文件,包含 112 行新增和 8 行删除
@@ -9,9 +9,79 @@ operations require explicit approval and evidence.
- Use `SYNC_ENV=0 bash deploy/trialrun/deploy.sh` only when deployment is - Use `SYNC_ENV=0 bash deploy/trialrun/deploy.sh` only when deployment is
approved; do not overwrite remote `.env`. approved; do not overwrite remote `.env`.
- When `server/src/config.js` reads a new environment key, add the same key to
`deploy/trialrun/.env.example` before deployment; `deploy/trialrun/deploy.sh`
runs `node deploy/trialrun/validate-env-contract.js` at step 0 and must fail
if the example contract drifts.
- After deployment, report commit hash, `/ready`, public smoke results and - After deployment, report commit hash, `/ready`, public smoke results and
whether the user can test. whether the user can test.
- Real business writes are manual unless an Issue explicitly authorizes a - Real business writes are manual unless an Issue explicitly authorizes a
controlled test write. controlled test write.
- Do not execute real payments, import bank statements, connect payment - Do not execute real payments, import bank statements, connect payment
providers or write ERP without a separate approved Issue. providers or write ERP without a separate approved Issue.
## Scenario: Deployment Env Contract
### 1. Scope / Trigger
- Trigger: any backend config, deployment compose, or trialrun env wiring change.
- Purpose: prevent deploy-time surprises where local code compiles but the
deployment contract rejects the release or silently misses a runtime default.
### 2. Signatures
- Command: `node deploy/trialrun/validate-env-contract.js`
- Deployment entry: `SYNC_ENV=0 bash deploy/trialrun/deploy.sh`
- Contract sources:
- `server/src/config.js`
- `deploy/trialrun/.env.example`
- `deploy/trialrun/docker-compose.yml`
### 3. Contracts
- Every `process.env.KEY` or `requiredEnv("KEY")` in `server/src/config.js`
must be present in `deploy/trialrun/.env.example`.
- `server`, `worker`, and `init` services must load `./.env` through
`env_file`.
- Compose service-level `environment` overrides are limited to the explicit
allowlist in `validate-env-contract.js`.
- `SYNC_ENV=0` is the default public deploy mode; it does not overwrite remote
`.env`.
### 4. Validation & Error Matrix
- Missing key in `.env.example` -> `validate-env-contract.js` exits non-zero.
- Service omits `env_file: ./.env` -> contract exits non-zero.
- Unauthorized compose override -> contract exits non-zero.
- Remote `.env` missing -> deploy step 4 exits before migration.
### 5. Good/Base/Bad Cases
- Good: add `EMAIL_LOGIN_CODE_TTL_SECONDS` to `config.js`, document it in
`.env.example`, then run contract validation before deploy.
- Base: code-only feature without env changes still runs the contract gate.
- Bad: add a config key only in `config.js`; deploy fails at step 0.
### 6. Tests Required
- Always run `node deploy/trialrun/validate-env-contract.js` after env-related
changes and before public deployment.
- For public deploys, also run or verify `/ready`, runtime smoke, external deps
smoke, public bundle copy scan, and live smoke when credentials exist.
### 7. Wrong vs Correct
#### Wrong
```bash
# Config key exists only in server/src/config.js.
SYNC_ENV=0 bash deploy/trialrun/deploy.sh
```
#### Correct
```bash
# Add the key to deploy/trialrun/.env.example first.
node deploy/trialrun/validate-env-contract.js
SYNC_ENV=0 bash deploy/trialrun/deploy.sh
```
@@ -55,3 +55,31 @@
- Trellis governance 对历史任务 `05-26-oa-auth-layout-wecom-login-ux` 的 jsonl 仍保留 `docs/产品设计规则.md` context warning;这是已提交历史任务的上下文提醒,不影响本任务通过。 - Trellis governance 对历史任务 `05-26-oa-auth-layout-wecom-login-ux` 的 jsonl 仍保留 `docs/产品设计规则.md` context warning;这是已提交历史任务的上下文提醒,不影响本任务通过。
- 公网部署和 live smoke 需要本地提交后另行确认。 - 公网部署和 live smoke 需要本地提交后另行确认。
## Deployment And Public Smoke Log
- 用户已批准执行部署与公网验证。
- 部署前已完成远端备份:
- DB 备份:`hyb-oa-db-20260527_075800.dump`
- 文件存储备份:`hyb-oa-storage-20260527_075801.tar.gz`
- 远端环境配置副本:`hyb-oa-env-20260527_075800.env`
- 部署命令采用 `SYNC_ENV=0`,未覆盖远端 `.env`。
- 部署脚本已通过:
- 部署环境契约校验。
- Docker 前端 production build。
- Prisma migration deploy,已应用 `20260526211500_email_code_login`。
- Prisma migration status:schema up to date。
- `/ready`、external deps smoke、runtime smoke。
- 公网 live smoke:3 passed。
- 公网前端资源文案扫描:`findings=0`。
- 补充公网验证已通过:
- `check-live-smoke-env.mjs --strict`:public ready、企微 ready、live smoke 与 OCR 条件均 ready。
- 邮箱验证码公网后端探测:不存在账号请求验证码返回通用成功;伪造验证码校验被拒绝,未暴露账号存在性。
- 公网前端 focused E2E:登录页找回密码/PWA 输入保护、邮箱验证码登录、找回密码流程,3 passed。
- 公网企业微信入口 E2E:普通浏览器次级入口、企业微信场景主 CTA,2 passed。
- 公网登录页截图与溢出检查:PC 密码登录、PC 邮箱验证码、移动企微入口均通过。
- 视觉截图:
- `output/playwright/oa-email-code-login-live/desktop-password-login.png`
- `output/playwright/oa-email-code-login-live/desktop-email-code-login.png`
- `output/playwright/oa-email-code-login-live/mobile-wecom-login.png`
- 远端近期 server 日志摘要:近 5 分钟 error-like 行数为 0。
@@ -57,14 +57,14 @@
## Acceptance Criteria ## Acceptance Criteria
- [ ] 普通浏览器登录页可切换密码登录和邮箱验证码登录。 - [x] 普通浏览器登录页可切换密码登录和邮箱验证码登录。
- [ ] 邮箱验证码请求成功时显示通用提示,不暴露账号是否存在。 - [x] 邮箱验证码请求成功时显示通用提示,不暴露账号是否存在。
- [ ] 正确验证码可完成登录并进入原 redirect 目标。 - [x] 正确验证码可完成登录并进入原 redirect 目标。
- [ ] 错误、过期或已使用验证码不能登录,并有可理解错误提示。 - [x] 错误、过期或已使用验证码不能登录,并有可理解错误提示。
- [ ] 企业微信 WebView 登录层级不回退,企微一键进入仍为主入口。 - [x] 企业微信 WebView 登录层级不回退,企微一键进入仍为主入口。
- [ ] 找回密码验证码和登录验证码数据、接口、审计语义隔离。 - [x] 找回密码验证码和登录验证码数据、接口、审计语义隔离。
- [ ] 前端不持久化验证码、密码或 token。 - [x] 前端不持久化验证码、密码或 token。
- [ ] 后端单测、前端 typecheck/build、关键 E2E 和设计规则检查通过。 - [x] 后端单测、前端 typecheck/build、关键 E2E 和设计规则检查通过。
## Definition of Done ## Definition of Done
@@ -85,6 +85,10 @@
- 不执行真实账号重置、真实业务写入或公网部署。 - 不执行真实账号重置、真实业务写入或公网部署。
- 不改变密码找回流程。 - 不改变密码找回流程。
## Post-Approval Scope Extension
- 用户后续明确批准部署和公网测试;已按 `SYNC_ENV=0` 执行公网部署,不覆盖远端 `.env`,并完成 live smoke、登录专项 E2E、邮箱验证码公网后端探测和视觉截图验证。
## Proposed Implementation ## Proposed Implementation
1. Backend schema: 1. Backend schema:
+2
查看文件
@@ -37,6 +37,8 @@ FIELD_ENCRYPTION_KEY=
# ===== 密码 / 登录安全 ===== # ===== 密码 / 登录安全 =====
PASSWORD_RESET_CODE_TTL_SECONDS=600 PASSWORD_RESET_CODE_TTL_SECONDS=600
DEV_SHOW_PASSWORD_RESET_CODE=false DEV_SHOW_PASSWORD_RESET_CODE=false
EMAIL_LOGIN_CODE_TTL_SECONDS=600
EMAIL_LOGIN_CODE_MAX_ATTEMPTS=5
AUTH_LOGIN_FAIL_WINDOW_SECONDS=900 AUTH_LOGIN_FAIL_WINDOW_SECONDS=900
AUTH_LOGIN_FAIL_MAX_ATTEMPTS=5 AUTH_LOGIN_FAIL_MAX_ATTEMPTS=5
AUTH_LOGIN_LOCK_SECONDS=1800 AUTH_LOGIN_LOCK_SECONDS=1800