修复巡检报告隐私字段并记录 Wave4-5 公网验证(05-29-frontend-ux-wave4-5-finance-admin-refresh)

这个提交包含在:
2026-05-29 09:37:57 +08:00
父节点 bfb1cb6e65
当前提交 41b9c2236e
共修改 40 个文件,包含 1919 行新增和 20 行删除
+23
查看文件
@@ -44,6 +44,9 @@ Start from `docs/文档索引.md` and `docs/文档事实源状态矩阵.md`.
- Machine-readable reports must not include amounts, prices, costs, balances, - Machine-readable reports must not include amounts, prices, costs, balances,
bank details, invoice values, full accounts, tokens, secrets, raw payloads, bank details, invoice values, full accounts, tokens, secrets, raw payloads,
raw form values or full local paths. raw form values or full local paths.
- Credential/readiness presence reports must use safe business labels, not raw
env key names. For example, emit `adminCredentialReady: true` instead of a
field named after a credential-value environment variable.
### 4. Validation & Error Matrix ### 4. Validation & Error Matrix
@@ -55,6 +58,8 @@ Start from `docs/文档索引.md` and `docs/文档事实源状态矩阵.md`.
according to whether the parent step is required. according to whether the parent step is required.
- Privacy smoke match -> write redacted finding metadata and make final - Privacy smoke match -> write redacted finding metadata and make final
summary reflect the failure. summary reflect the failure.
- Secret-like field names in generated reports -> privacy finding, even when
the value is only a boolean presence flag.
### 5. Good/Base/Bad Cases ### 5. Good/Base/Bad Cases
@@ -73,6 +78,8 @@ Start from `docs/文档索引.md` and `docs/文档事实源状态矩阵.md`.
- child finding count is visible in parent summary; - child finding count is visible in parent summary;
- privacy step is present in parent summary; - privacy step is present in parent summary;
- `summary.json` has no full workspace path or business amount fields. - `summary.json` has no full workspace path or business amount fields.
- For live/readiness env reports, assert the JSON contains safe readiness
labels and does not contain raw secret-like env key names.
- Run the matching launch/readiness aggregator when it consumes the report. - Run the matching launch/readiness aggregator when it consumes the report.
### 7. Wrong vs Correct ### 7. Wrong vs Correct
@@ -87,6 +94,14 @@ Start from `docs/文档索引.md` and `docs/文档事实源状态矩阵.md`.
} }
``` ```
```json
{
"liveSmoke": {
"RAW_CREDENTIAL_ENV_KEY": true
}
}
```
#### Correct #### Correct
```json ```json
@@ -102,3 +117,11 @@ Start from `docs/文档索引.md` and `docs/文档事实源状态矩阵.md`.
} }
} }
``` ```
```json
{
"liveSmoke": {
"adminCredentialReady": true
}
}
```
@@ -91,6 +91,47 @@ OAOPS1_REPORT_DIR=.trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh
LIVE_SMOKE_BASE_URL=https://oa.hyinda.com bash scripts/qa/run-oa-real-use-daily.sh LIVE_SMOKE_BASE_URL=https://oa.hyinda.com bash scripts/qa/run-oa-real-use-daily.sh
``` ```
## Deployment Result
2026-05-29 user-approved public deployment completed.
- Deployed commit: `bfb1cb6 完成 Wave4-5 财务与管理页刷新(05-29-frontend-ux-wave4-5-finance-admin-refresh)`.
- Deploy command used `SYNC_ENV=0`, so the remote `.env` was not overwritten.
- Deploy script passed env contract, remote build, seed/config, seed/trialrun, `/ready`, external dependency smoke, runtime smoke and public bundle copy scan.
- Remote migrations had no pending migration.
- Deploy rsync reported a non-fatal warning for an old non-empty artifacts directory; deployment continued and runtime checks passed.
- Automatic deploy-time live smoke was skipped because the deploy shell did not include the full live smoke variables; manual postdeploy checks below covered it.
## Postdeploy Verification Result
Final passing evidence is stored under:
`research/postdeploy-20260529-wave4-5-public-rerun/`
- `run-live-smoke-readiness.sh`: `PASS`.
- `/ready` passed.
- Public bundle copy scan passed with 0 findings.
- Live smoke Playwright passed: 3 tests.
- Live OCR sample passed: 1 test. The sample produced the expected duplicate/same-invoice style OCR outcome for the already-used sample file.
- Pending OCR scan skipped because the local command environment did not include `DATABASE_URL`.
- `run-oa-real-use-daily.sh`: `PASS_OA_REAL_USE_DAILY_READY`, `findingCount=0`.
- `public-ready`: PASS.
- `live-smoke-env`: PASS.
- `live-readiness`: PASS.
- `oa-only-smoke-readiness`: PASS.
- `live-feature-flags`: PASS.
- `authenticated-readonly-probe`: PASS.
- `mobile-entry-matrix`: PASS.
- `wecom-rendering-matrix`: PASS.
- `wecom-entry`: PASS.
- `report-privacy-smoke`: PASS.
## Report Privacy Fix
The first OAOPS1 run failed only at `report-privacy-smoke` because the live smoke env report emitted secret-looking env key names as boolean presence fields. It did not expose actual secret values.
`scripts/qa/check-live-smoke-env.mjs` now emits safe readiness labels such as `adminCredentialReady`, `employeeCredentialReady`, `managerCredentialReady` and `financeCredentialReady` instead of raw env key names containing password-like words. The rerun passed privacy smoke.
## Spec Update Expectation ## Spec Update Expectation
Only update `.trellis/spec/` if implementation introduces a reusable frontend convention beyond the existing finance/admin surfaces. If the task only applies existing conventions, record that no spec update is needed. Only update `.trellis/spec/` if implementation introduces a reusable frontend convention beyond the existing finance/admin surfaces. If the task only applies existing conventions, record that no spec update is needed.
@@ -99,7 +99,7 @@
- [x] `node scripts/qa/check-ui-design-rules.mjs --strict` 通过。 - [x] `node scripts/qa/check-ui-design-rules.mjs --strict` 通过。
- [x] `python3 ./.trellis/scripts/task.py validate 05-29-frontend-ux-wave4-5-finance-admin-refresh` 通过。 - [x] `python3 ./.trellis/scripts/task.py validate 05-29-frontend-ux-wave4-5-finance-admin-refresh` 通过。
- [x] `node scripts/qa/check-trellis-governance.mjs` 和 `git diff --check` 通过。 - [x] `node scripts/qa/check-trellis-governance.mjs` 和 `git diff --check` 通过。
- [ ] 若部署给用户测试,已完成公网部署与公网检查并记录证据。 - [x] 若部署给用户测试,已完成公网部署与公网检查并记录证据。
## Implementation Result ## Implementation Result
@@ -114,6 +114,17 @@
- Focused Playwright 扩展到 Wave4-5 页面:付款批次、AP、票据池、审批规则、人员、组织、工作区、用户、主数据、通知渠道、系统设置、功能开关、流程定义、审计日志。 - Focused Playwright 扩展到 Wave4-5 页面:付款批次、AP、票据池、审批规则、人员、组织、工作区、用户、主数据、通知渠道、系统设置、功能开关、流程定义、审计日志。
- 本轮没有改后端、数据库、权限、审批规则语义、付款状态机、企业微信配置、SMTP 或生产配置。 - 本轮没有改后端、数据库、权限、审批规则语义、付款状态机、企业微信配置、SMTP 或生产配置。
2026-05-29 公网部署与只读巡检完成:
- 部署代码:`bfb1cb6 完成 Wave4-5 财务与管理页刷新(05-29-frontend-ux-wave4-5-finance-admin-refresh)`。
- 部署方式:`SYNC_ENV=0 LIVE_SMOKE_BASE_URL=https://oa.hyinda.com bash deploy/trialrun/deploy.sh`,未同步覆盖远端 `.env`。
- 部署脚本完成 `/ready`、外部依赖 smoke、runtime smoke、公网 bundle 文案扫描;远端迁移无待执行项。
- 首次 OAOPS1 发现报告隐私巡检误报,原因是环境检查报告输出了含凭据含义的原始 env key 名作为“字段名存在=true”标签,不含真实密钥或密码。
- 已将 `scripts/qa/check-live-smoke-env.mjs` 的报告输出改为业务安全标签,如 `adminCredentialReady`、`employeeCredentialReady`,不再把敏感 env key 名写入证据报告。
- 复跑公网 readiness:`PASS`;`/ready`、公网 bundle 文案扫描、live smoke 3 项、真实 OCR 样本复核通过;pending OCR 因本地命令未带 `DATABASE_URL` 按设计跳过。
- 复跑 OAOPS1:`PASS_OA_REAL_USE_DAILY_READY`,`findingCount=0`;public-ready、live-smoke-env、live-readiness、oa-only-smoke-readiness、feature flags、authenticated readonly probe、mobile entry、WeCom rendering、WeCom entry、report privacy smoke 全部通过。
- 证据目录:`research/postdeploy-20260529-wave4-5-public-rerun/`。
## Test Plan ## Test Plan
```bash ```bash
@@ -0,0 +1,46 @@
{
"checkedAt": "2026-05-29T01:27:15.005Z",
"baseUrl": "https://oa.hyinda.com",
"liveSmokeReady": true,
"liveSmoke": {
"adminCredentialReady": true,
"employeeCredentialReady": true
},
"liveSmokeOptional": {
"expectedWecomStatusReady": true,
"managerCredentialReady": true,
"financeCredentialReady": true
},
"liveOcrReady": true,
"liveOcr": {
"userReady": true,
"invoiceSampleReady": true,
"invoiceFileProvided": true,
"invoiceFileReady": true,
"invoiceBatchDirProvided": false,
"invoiceBatchDirReady": false,
"allowDuplicate": true
},
"missing": [],
"publicReady": {
"ok": true,
"status": 200
},
"wecomConfig": {
"ok": true,
"status": 200,
"statusText": "ready",
"entryEnabled": true,
"oauthEnabled": true,
"defaultReturnTo": "/mobile",
"loginUrl": "/api/auth/wecom/login?returnTo=%2Fmobile"
},
"authCapabilities": {
"ok": true,
"status": 200,
"emailDeliveryReady": true,
"emailDeliveryReasons": [],
"emailLoginCodeEnabled": true,
"passwordResetEnabled": true
}
}
@@ -0,0 +1,7 @@
Running 1 test using 1 worker
[live-ocr] {"alias":"SAMPLE-PDF-001","status":"ocr_failed","durationMs":922,"transport":"ui","timings":{"uploadMs":922,"terminalWaitMs":0},"reasonCategory":"duplicate_or_same_invoice","fieldHits":{"invoiceId":false,"invoiceCodeOrNumber":false,"sellerName":false,"totalAmount":false,"invoiceDate":false}}
✓ 1 tests/e2e/manual/live-invoice-ocr.spec.ts:8:1 › 手工 live 腾讯 OCR 辅助复核:真实 VAT 发票上传后进入可处理状态 (6.8s)
1 passed (11.0s)
@@ -0,0 +1,14 @@
>>> 探活 live /ready: https://oa.hyinda.com/ready
>>> 执行 live smoke Playwright
> [email protected] test:e2e:live
> playwright test tests/e2e/live-smoke.spec.ts
Running 3 tests using 1 worker
✓ 1 tests/e2e/live-smoke.spec.ts:43:3 › live smoke › 公网基础探活与企微配置状态 (2.9s)
✓ 2 tests/e2e/live-smoke.spec.ts:64:3 › live smoke › 管理员只读网页 smoke (11.7s)
✓ 3 tests/e2e/live-smoke.spec.ts:106:3 › live smoke › 员工只读网页 smoke (10.8s)
3 passed (29.4s)
@@ -0,0 +1 @@
[public-bundle-copy] base=https://oa.hyinda.com scanned=91 focused=2 findings=0
@@ -0,0 +1,12 @@
{
"issueId": null,
"baseURL": "https://oa.hyinda.com",
"commit": "bfb1cb6",
"checkedAt": "2026-05-29T01:28:07.869Z",
"status": "PASS",
"mode": "live-smoke-readiness",
"reportDir": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/live-smoke-readiness",
"reportRef": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/live-smoke-readiness",
"groups": null,
"notes": "公网 /ready、public bundle、pending OCR、live smoke 和真实 OCR 可用性检查;缺少凭据或样票时按脚本规则记录 SKIP。"
}
@@ -0,0 +1,129 @@
{
"mode": "oaops1-authenticated-readonly-probe",
"status": "PASS",
"baseUrl": "https://oa.hyinda.com",
"checkedAt": "2026-05-29T01:31:32.486Z",
"readOnly": true,
"duplicateRoleChecks": "employee/finance/payment/AP are covered by oa-only-smoke-readiness to avoid repeated login throttling",
"roles": {
"admin": {
"status": "PASS",
"reason": null,
"maskedIdentifier": "sm***om"
}
},
"checks": [
{
"id": "portal",
"role": "admin",
"path": "/api/portal/home",
"domain": "portal",
"status": "PASS",
"httpStatus": 200,
"summary": {}
},
{
"id": "workflow-tasks",
"role": "admin",
"path": "/api/workflow/tasks?page=1&pageSize=5",
"domain": "approval",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 0,
"total": 0
}
},
{
"id": "reimbursements",
"role": "admin",
"path": "/api/reimbursements?page=1&pageSize=5",
"domain": "reimbursement",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 5,
"total": 33
}
},
{
"id": "reimbursement-summary",
"role": "admin",
"path": "/api/reimbursements/stats/summary",
"domain": "reimbursement",
"status": "PASS",
"httpStatus": 200,
"summary": {
"totalCount": 33,
"avgProcessingDays": 0
}
},
{
"id": "invoice-pool",
"role": "admin",
"path": "/api/invoice-pool?page=1&pageSize=5",
"domain": "invoice_ocr",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 5,
"total": 46
}
},
{
"id": "purchase-requests",
"role": "admin",
"path": "/api/purchase-requests?page=1&pageSize=5",
"domain": "procurement",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 0,
"total": 0
}
},
{
"id": "contracts-registry",
"role": "admin",
"path": "/api/contracts-registry",
"domain": "contracts",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 6,
"total": null
}
},
{
"id": "projects",
"role": "admin",
"path": "/api/projects?page=1&pageSize=5",
"domain": "projects",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 4,
"total": null
}
},
{
"id": "audit-logs",
"role": "admin",
"path": "/api/audit-logs?page=1&pageSize=5",
"domain": "audit",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 5,
"total": 2235
}
}
],
"boundaries": {
"noBusinessWrites": true,
"noExportsByDefault": true,
"noFileUploads": true,
"noWeComWrites": true,
"noRealPaymentExecution": true
}
}
@@ -0,0 +1,129 @@
{
"mode": "oaops1-authenticated-readonly-probe",
"status": "PASS",
"baseUrl": "https://oa.hyinda.com",
"checkedAt": "2026-05-29T01:31:32.486Z",
"readOnly": true,
"duplicateRoleChecks": "employee/finance/payment/AP are covered by oa-only-smoke-readiness to avoid repeated login throttling",
"roles": {
"admin": {
"status": "PASS",
"reason": null,
"maskedIdentifier": "sm***om"
}
},
"checks": [
{
"id": "portal",
"role": "admin",
"path": "/api/portal/home",
"domain": "portal",
"status": "PASS",
"httpStatus": 200,
"summary": {}
},
{
"id": "workflow-tasks",
"role": "admin",
"path": "/api/workflow/tasks?page=1&pageSize=5",
"domain": "approval",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 0,
"total": 0
}
},
{
"id": "reimbursements",
"role": "admin",
"path": "/api/reimbursements?page=1&pageSize=5",
"domain": "reimbursement",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 5,
"total": 33
}
},
{
"id": "reimbursement-summary",
"role": "admin",
"path": "/api/reimbursements/stats/summary",
"domain": "reimbursement",
"status": "PASS",
"httpStatus": 200,
"summary": {
"totalCount": 33,
"avgProcessingDays": 0
}
},
{
"id": "invoice-pool",
"role": "admin",
"path": "/api/invoice-pool?page=1&pageSize=5",
"domain": "invoice_ocr",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 5,
"total": 46
}
},
{
"id": "purchase-requests",
"role": "admin",
"path": "/api/purchase-requests?page=1&pageSize=5",
"domain": "procurement",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 0,
"total": 0
}
},
{
"id": "contracts-registry",
"role": "admin",
"path": "/api/contracts-registry",
"domain": "contracts",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 6,
"total": null
}
},
{
"id": "projects",
"role": "admin",
"path": "/api/projects?page=1&pageSize=5",
"domain": "projects",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 4,
"total": null
}
},
{
"id": "audit-logs",
"role": "admin",
"path": "/api/audit-logs?page=1&pageSize=5",
"domain": "audit",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 5,
"total": 2235
}
}
],
"boundaries": {
"noBusinessWrites": true,
"noExportsByDefault": true,
"noFileUploads": true,
"noWeComWrites": true,
"noRealPaymentExecution": true
}
}
@@ -0,0 +1,9 @@
{
"name": "authenticated-readonly-probe",
"status": "PASS",
"kind": "finding_allowed",
"code": 0,
"detail": "ok",
"logRef": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/authenticated-readonly-probe.log",
"checkedAt": "2026-05-29T01:31:32.564Z"
}
@@ -0,0 +1,64 @@
{
"checkedAt": "2026-05-29T01:30:25.816Z",
"baseUrl": "https://oa.hyinda.com",
"status": "PASS",
"readOnly": true,
"results": [
{
"flagKey": "payment_batch_v1",
"expectedState": "force_on",
"status": "PASS",
"item": {
"flagKey": "payment_batch_v1",
"overrideMode": "force_on",
"rolloutType": "global",
"version": 17,
"envEnabled": true,
"effectiveEnabled": true,
"effectiveReason": "flag_force_on_global"
}
},
{
"flagKey": "erp_sync",
"expectedState": "force_off",
"status": "PASS",
"item": {
"flagKey": "erp_sync",
"overrideMode": "force_off",
"rolloutType": "global",
"version": 2,
"envEnabled": true,
"effectiveEnabled": false,
"effectiveReason": "flag_force_off"
}
},
{
"flagKey": "attendance_v1",
"expectedState": "disabled",
"status": "PASS",
"item": {
"flagKey": "attendance_v1",
"overrideMode": "force_on",
"rolloutType": "global",
"version": 86,
"envEnabled": false,
"effectiveEnabled": false,
"effectiveReason": "env_hard_off"
}
},
{
"flagKey": "attendance_unified_v1",
"expectedState": "enabled",
"status": "PASS",
"item": {
"flagKey": "attendance_unified_v1",
"overrideMode": "force_on",
"rolloutType": "global",
"version": 84,
"envEnabled": true,
"effectiveEnabled": true,
"effectiveReason": "flag_force_on_global"
}
}
]
}
@@ -0,0 +1,9 @@
{
"name": "live-feature-flags",
"status": "PASS",
"kind": "finding_allowed",
"code": 0,
"detail": "ok",
"logRef": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/live-feature-flags.log",
"checkedAt": "2026-05-29T01:30:25.887Z"
}
@@ -0,0 +1,45 @@
>>> [live-readiness] 环境与公网入口检查
[live-smoke-env] base=https://oa.hyinda.com
[live-smoke-env] publicReady=true status=200
[live-smoke-env] wecom=ready entry=true oauth=true
[live-smoke-env] authCapabilities=true emailDelivery=true
[live-smoke-env] liveSmokeReady=true
[live-smoke-env] liveOcrReady=true
>>> [live-readiness] /ready: https://oa.hyinda.com
>>> [live-readiness] 公网资源文案扫描
[public-bundle-copy] base=https://oa.hyinda.com scanned=91 focused=2 findings=0
>>> [live-readiness] pending OCR 扫描
[pending-ocr][SKIP] missing DATABASE_URL
>>> [live-readiness] 执行公网 live smoke
>>> 探活 live /ready: https://oa.hyinda.com/ready
>>> 执行 live smoke Playwright
> [email protected] test:e2e:live
> playwright test tests/e2e/live-smoke.spec.ts
Running 3 tests using 1 worker
(node:81586) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set.
(Use `node --trace-warnings ...` to show where the warning was created)
(node:81586) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set.
(Use `node --trace-warnings ...` to show where the warning was created)
✓ 1 tests/e2e/live-smoke.spec.ts:43:3 › live smoke › 公网基础探活与企微配置状态 (2.6s)
✓ 2 tests/e2e/live-smoke.spec.ts:64:3 › live smoke › 管理员只读网页 smoke (11.7s)
✓ 3 tests/e2e/live-smoke.spec.ts:106:3 › live smoke › 员工只读网页 smoke (10.4s)
3 passed (28.3s)
>>> [live-readiness] 执行真实 OCR 样本复核
Running 1 test using 1 worker
(node:82388) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set.
(Use `node --trace-warnings ...` to show where the warning was created)
(node:82388) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set.
(Use `node --trace-warnings ...` to show where the warning was created)
[live-ocr] {"alias":"SAMPLE-PDF-001","status":"ocr_failed","durationMs":657,"transport":"ui","timings":{"uploadMs":658,"terminalWaitMs":0},"reasonCategory":"duplicate_or_same_invoice","fieldHits":{"invoiceId":false,"invoiceCodeOrNumber":false,"sellerName":false,"totalAmount":false,"invoiceDate":false}}
✓ 1 tests/e2e/manual/live-invoice-ocr.spec.ts:8:1 › 手工 live 腾讯 OCR 辅助复核:真实 VAT 发票上传后进入可处理状态 (6.6s)
1 passed (10.2s)
[live-readiness][PASS] readiness 检查完成
[live-readiness] report=.trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/live-smoke-readiness
@@ -0,0 +1,9 @@
{
"name": "live-readiness",
"status": "PASS",
"kind": "finding_allowed",
"code": 0,
"detail": "ok",
"logRef": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/live-readiness.log",
"checkedAt": "2026-05-29T01:29:14.867Z"
}
@@ -0,0 +1,46 @@
{
"checkedAt": "2026-05-29T01:28:22.362Z",
"baseUrl": "https://oa.hyinda.com",
"liveSmokeReady": true,
"liveSmoke": {
"adminCredentialReady": true,
"employeeCredentialReady": true
},
"liveSmokeOptional": {
"expectedWecomStatusReady": true,
"managerCredentialReady": true,
"financeCredentialReady": true
},
"liveOcrReady": true,
"liveOcr": {
"userReady": true,
"invoiceSampleReady": true,
"invoiceFileProvided": true,
"invoiceFileReady": true,
"invoiceBatchDirProvided": false,
"invoiceBatchDirReady": false,
"allowDuplicate": true
},
"missing": [],
"publicReady": {
"ok": true,
"status": 200
},
"wecomConfig": {
"ok": true,
"status": 200,
"statusText": "ready",
"entryEnabled": true,
"oauthEnabled": true,
"defaultReturnTo": "/mobile",
"loginUrl": "/api/auth/wecom/login?returnTo=%2Fmobile"
},
"authCapabilities": {
"ok": true,
"status": 200,
"emailDeliveryReady": true,
"emailDeliveryReasons": [],
"emailLoginCodeEnabled": true,
"passwordResetEnabled": true
}
}
@@ -0,0 +1,9 @@
{
"name": "live-smoke-env",
"status": "PASS",
"kind": "finding_allowed",
"code": 0,
"detail": "ok",
"logRef": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/live-smoke-env.log",
"checkedAt": "2026-05-29T01:28:22.439Z"
}
@@ -0,0 +1,46 @@
{
"checkedAt": "2026-05-29T01:28:22.930Z",
"baseUrl": "https://oa.hyinda.com",
"liveSmokeReady": true,
"liveSmoke": {
"adminCredentialReady": true,
"employeeCredentialReady": true
},
"liveSmokeOptional": {
"expectedWecomStatusReady": true,
"managerCredentialReady": true,
"financeCredentialReady": true
},
"liveOcrReady": true,
"liveOcr": {
"userReady": true,
"invoiceSampleReady": true,
"invoiceFileProvided": true,
"invoiceFileReady": true,
"invoiceBatchDirProvided": false,
"invoiceBatchDirReady": false,
"allowDuplicate": true
},
"missing": [],
"publicReady": {
"ok": true,
"status": 200
},
"wecomConfig": {
"ok": true,
"status": 200,
"statusText": "ready",
"entryEnabled": true,
"oauthEnabled": true,
"defaultReturnTo": "/mobile",
"loginUrl": "/api/auth/wecom/login?returnTo=%2Fmobile"
},
"authCapabilities": {
"ok": true,
"status": 200,
"emailDeliveryReady": true,
"emailDeliveryReasons": [],
"emailLoginCodeEnabled": true,
"passwordResetEnabled": true
}
}
@@ -0,0 +1,7 @@
Running 1 test using 1 worker
[live-ocr] {"alias":"SAMPLE-PDF-001","status":"ocr_failed","durationMs":657,"transport":"ui","timings":{"uploadMs":658,"terminalWaitMs":0},"reasonCategory":"duplicate_or_same_invoice","fieldHits":{"invoiceId":false,"invoiceCodeOrNumber":false,"sellerName":false,"totalAmount":false,"invoiceDate":false}}
✓ 1 tests/e2e/manual/live-invoice-ocr.spec.ts:8:1 › 手工 live 腾讯 OCR 辅助复核:真实 VAT 发票上传后进入可处理状态 (6.6s)
1 passed (10.2s)
@@ -0,0 +1,14 @@
>>> 探活 live /ready: https://oa.hyinda.com/ready
>>> 执行 live smoke Playwright
> [email protected] test:e2e:live
> playwright test tests/e2e/live-smoke.spec.ts
Running 3 tests using 1 worker
✓ 1 tests/e2e/live-smoke.spec.ts:43:3 › live smoke › 公网基础探活与企微配置状态 (2.6s)
✓ 2 tests/e2e/live-smoke.spec.ts:64:3 › live smoke › 管理员只读网页 smoke (11.7s)
✓ 3 tests/e2e/live-smoke.spec.ts:106:3 › live smoke › 员工只读网页 smoke (10.4s)
3 passed (28.3s)
@@ -0,0 +1 @@
[public-bundle-copy] base=https://oa.hyinda.com scanned=91 focused=2 findings=0
@@ -0,0 +1,12 @@
{
"issueId": "OAOPS1",
"baseURL": "https://oa.hyinda.com",
"commit": "bfb1cb6",
"checkedAt": "2026-05-29T01:29:14.797Z",
"status": "PASS",
"mode": "live-smoke-readiness",
"reportDir": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/live-smoke-readiness",
"reportRef": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/live-smoke-readiness",
"groups": null,
"notes": "公网 /ready、public bundle、pending OCR、live smoke 和真实 OCR 可用性检查;缺少凭据或样票时按脚本规则记录 SKIP。"
}
@@ -0,0 +1,20 @@
# OAOPS1 每日人工收口清单
## 员工
- 真实报销:上传 PDF 发票,补充必要附件,提交 OA 审批。
- 采购/费用:在 OA 创建申请,关联项目;如涉及合同,关联或补录合同台账。
- 合同:只录入合同摘要、编号、负责人、项目、金额、线下归档位置;涉密合同正文、敏感报价和成本细节不上传公网 OA。
## 审批人
- 从 OA 待办进入详情,确认报销、采购、合同或项目上下文后再审批。
- 退回时写清需要补充的材料,避免线下口头说明替代系统记录。
## 出纳/财务
- 审批通过后创建付款批次,线下银行渠道付款。
- 上传银行回单附件后再在 OA 标记已付款。
- 每日抽查 AP 台账、报销导出、票据状态和付款批次状态。
## 管理员
- 查看本报告 summary.json 和人工问题登记。
- 阻断项当天建修复 Issue CSV 或暂停对应流程;非阻断体验问题进入反馈池。
- 确认 payment_batch_v1=force_on,erp_sync=force_off;图片 OCR、预算、ERP、银行流水导入、真实支付直连继续冻结。
@@ -0,0 +1,10 @@
Running 1 test using 1 worker
(node:86699) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set.
(Use `node --trace-warnings ...` to show where the warning was created)
(node:86699) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set.
(Use `node --trace-warnings ...` to show where the warning was created)
✓ 1 tests/e2e/r124-mobile-entry-matrix.spec.ts:486:3 › R124 企业微信移动入口矩阵 › 底部入口、我的二级入口、PDF 上传和草稿删除不回退到 PC 体验 (14.1s)
1 passed (17.8s)
@@ -0,0 +1,9 @@
{
"name": "mobile-entry-matrix",
"status": "PASS",
"kind": "finding_allowed",
"code": 0,
"detail": "ok",
"logRef": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/mobile-entry-matrix.log",
"checkedAt": "2026-05-29T01:31:56.368Z"
}
@@ -0,0 +1,392 @@
{
"issueId": "OSMOKE1",
"mode": "oa-only-smoke-readiness",
"status": "PASS_OA_ONLY_SMOKE_READY",
"conclusion": "PASS_OA_ONLY_SMOKE_READY",
"baseUrl": "https://oa.hyinda.com",
"checkedAt": "2026-05-29T01:29:19.810Z",
"businessReadOnly": true,
"readOnlyNote": "performs login/readiness probes only; no business data writes and no WeCom writes",
"privacy": "role/masked identifier/status/counts only; no password/token/secret/full email/full phone",
"targets": [
{
"key": "admin",
"expectedRoles": [
"admin",
"employee"
],
"maskedIdentifier": "sm***@***.com",
"login": {
"status": "PASS",
"reason": null,
"code": null
},
"roleMatch": "PASS",
"probes": [
{
"id": "me",
"status": "PASS",
"httpStatus": 200,
"summary": {
"status": "active",
"notificationPushEnabled": true,
"roleCodes": [
"admin",
"employee"
]
}
},
{
"id": "portal",
"status": "PASS",
"httpStatus": 200,
"summary": {}
},
{
"id": "assets",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 7,
"total": null
}
},
{
"id": "users",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 1,
"total": 13
}
}
],
"actualRoles": [
"admin",
"employee"
],
"missingRoles": []
},
{
"key": "employee",
"expectedRoles": [
"employee"
],
"maskedIdentifier": "sm***@***.com",
"login": {
"status": "PASS",
"reason": null,
"code": null
},
"roleMatch": "PASS",
"probes": [
{
"id": "me",
"status": "PASS",
"httpStatus": 200,
"summary": {
"status": "active",
"notificationPushEnabled": true,
"roleCodes": [
"employee"
]
}
},
{
"id": "portal",
"status": "PASS",
"httpStatus": 200,
"summary": {}
},
{
"id": "my-assets",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 0,
"total": null
}
}
],
"actualRoles": [
"employee"
],
"missingRoles": []
},
{
"key": "manager",
"expectedRoles": [
"manager",
"employee"
],
"maskedIdentifier": "sm***@***.com",
"login": {
"status": "PASS",
"reason": null,
"code": null
},
"roleMatch": "PASS",
"probes": [
{
"id": "me",
"status": "PASS",
"httpStatus": 200,
"summary": {
"status": "active",
"notificationPushEnabled": true,
"roleCodes": [
"employee",
"manager"
]
}
},
{
"id": "portal",
"status": "PASS",
"httpStatus": 200,
"summary": {}
},
{
"id": "workflow",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 1,
"total": 1
}
}
],
"actualRoles": [
"employee",
"manager"
],
"missingRoles": []
},
{
"key": "ceo",
"expectedRoles": [
"ceo",
"employee"
],
"maskedIdentifier": "sm***@***.com",
"login": {
"status": "PASS",
"reason": null,
"code": null
},
"roleMatch": "PASS",
"probes": [
{
"id": "me",
"status": "PASS",
"httpStatus": 200,
"summary": {
"status": "active",
"notificationPushEnabled": true,
"roleCodes": [
"ceo",
"employee"
]
}
},
{
"id": "portal",
"status": "PASS",
"httpStatus": 200,
"summary": {}
},
{
"id": "dashboard",
"status": "PASS",
"httpStatus": 200,
"summary": {
"totalCount": 33,
"paidCount": 8,
"reviewingCount": 3
}
}
],
"actualRoles": [
"ceo",
"employee"
],
"missingRoles": []
},
{
"key": "finance",
"expectedRoles": [
"finance",
"employee"
],
"maskedIdentifier": "sm***@***.com",
"login": {
"status": "PASS",
"reason": null,
"code": null
},
"roleMatch": "PASS",
"probes": [
{
"id": "me",
"status": "PASS",
"httpStatus": 200,
"summary": {
"status": "active",
"notificationPushEnabled": true,
"roleCodes": [
"employee",
"finance"
]
}
},
{
"id": "portal",
"status": "PASS",
"httpStatus": 200,
"summary": {}
},
{
"id": "payment-batches",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 9,
"total": null
}
},
{
"id": "ap-ledger",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 1,
"total": 33
}
}
],
"actualRoles": [
"employee",
"finance"
],
"missingRoles": []
},
{
"key": "finance_mgr",
"expectedRoles": [
"finance",
"finance_mgr",
"employee"
],
"maskedIdentifier": "sm***@***.com",
"login": {
"status": "PASS",
"reason": null,
"code": null
},
"roleMatch": "PASS",
"probes": [
{
"id": "me",
"status": "PASS",
"httpStatus": 200,
"summary": {
"status": "active",
"notificationPushEnabled": true,
"roleCodes": [
"employee",
"finance",
"finance_mgr"
]
}
},
{
"id": "portal",
"status": "PASS",
"httpStatus": 200,
"summary": {}
},
{
"id": "payment-batches",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 9,
"total": null
}
},
{
"id": "ap-ledger",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 1,
"total": 33
}
}
],
"actualRoles": [
"employee",
"finance",
"finance_mgr"
],
"missingRoles": []
},
{
"key": "hr",
"expectedRoles": [
"hr",
"employee"
],
"maskedIdentifier": "sm***@***.com",
"login": {
"status": "PASS",
"reason": null,
"code": null
},
"roleMatch": "PASS",
"probes": [
{
"id": "me",
"status": "PASS",
"httpStatus": 200,
"summary": {
"status": "active",
"notificationPushEnabled": true,
"roleCodes": [
"employee",
"hr"
]
}
},
{
"id": "portal",
"status": "PASS",
"httpStatus": 200,
"summary": {}
},
{
"id": "wecom-archive",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 1,
"total": 9
}
}
],
"actualRoles": [
"employee",
"hr"
],
"missingRoles": []
}
],
"findings": [],
"boundaries": {
"noBusinessWrites": true,
"noWeComWrites": true,
"noPasswordOutput": true,
"noRealEmployeeIdentifiers": true
}
}
[oa-only-smoke-readiness] report=.trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/oa-only-smoke-readiness/summary.json
@@ -0,0 +1,9 @@
{
"name": "oa-only-smoke-readiness",
"status": "PASS",
"kind": "finding_allowed",
"code": 0,
"detail": "ok",
"logRef": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/oa-only-smoke-readiness.log",
"checkedAt": "2026-05-29T01:29:19.941Z"
}
@@ -0,0 +1,391 @@
{
"issueId": "OSMOKE1",
"mode": "oa-only-smoke-readiness",
"status": "PASS_OA_ONLY_SMOKE_READY",
"conclusion": "PASS_OA_ONLY_SMOKE_READY",
"baseUrl": "https://oa.hyinda.com",
"checkedAt": "2026-05-29T01:29:19.810Z",
"businessReadOnly": true,
"readOnlyNote": "performs login/readiness probes only; no business data writes and no WeCom writes",
"privacy": "role/masked identifier/status/counts only; no password/token/secret/full email/full phone",
"targets": [
{
"key": "admin",
"expectedRoles": [
"admin",
"employee"
],
"maskedIdentifier": "sm***@***.com",
"login": {
"status": "PASS",
"reason": null,
"code": null
},
"roleMatch": "PASS",
"probes": [
{
"id": "me",
"status": "PASS",
"httpStatus": 200,
"summary": {
"status": "active",
"notificationPushEnabled": true,
"roleCodes": [
"admin",
"employee"
]
}
},
{
"id": "portal",
"status": "PASS",
"httpStatus": 200,
"summary": {}
},
{
"id": "assets",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 7,
"total": null
}
},
{
"id": "users",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 1,
"total": 13
}
}
],
"actualRoles": [
"admin",
"employee"
],
"missingRoles": []
},
{
"key": "employee",
"expectedRoles": [
"employee"
],
"maskedIdentifier": "sm***@***.com",
"login": {
"status": "PASS",
"reason": null,
"code": null
},
"roleMatch": "PASS",
"probes": [
{
"id": "me",
"status": "PASS",
"httpStatus": 200,
"summary": {
"status": "active",
"notificationPushEnabled": true,
"roleCodes": [
"employee"
]
}
},
{
"id": "portal",
"status": "PASS",
"httpStatus": 200,
"summary": {}
},
{
"id": "my-assets",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 0,
"total": null
}
}
],
"actualRoles": [
"employee"
],
"missingRoles": []
},
{
"key": "manager",
"expectedRoles": [
"manager",
"employee"
],
"maskedIdentifier": "sm***@***.com",
"login": {
"status": "PASS",
"reason": null,
"code": null
},
"roleMatch": "PASS",
"probes": [
{
"id": "me",
"status": "PASS",
"httpStatus": 200,
"summary": {
"status": "active",
"notificationPushEnabled": true,
"roleCodes": [
"employee",
"manager"
]
}
},
{
"id": "portal",
"status": "PASS",
"httpStatus": 200,
"summary": {}
},
{
"id": "workflow",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 1,
"total": 1
}
}
],
"actualRoles": [
"employee",
"manager"
],
"missingRoles": []
},
{
"key": "ceo",
"expectedRoles": [
"ceo",
"employee"
],
"maskedIdentifier": "sm***@***.com",
"login": {
"status": "PASS",
"reason": null,
"code": null
},
"roleMatch": "PASS",
"probes": [
{
"id": "me",
"status": "PASS",
"httpStatus": 200,
"summary": {
"status": "active",
"notificationPushEnabled": true,
"roleCodes": [
"ceo",
"employee"
]
}
},
{
"id": "portal",
"status": "PASS",
"httpStatus": 200,
"summary": {}
},
{
"id": "dashboard",
"status": "PASS",
"httpStatus": 200,
"summary": {
"totalCount": 33,
"paidCount": 8,
"reviewingCount": 3
}
}
],
"actualRoles": [
"ceo",
"employee"
],
"missingRoles": []
},
{
"key": "finance",
"expectedRoles": [
"finance",
"employee"
],
"maskedIdentifier": "sm***@***.com",
"login": {
"status": "PASS",
"reason": null,
"code": null
},
"roleMatch": "PASS",
"probes": [
{
"id": "me",
"status": "PASS",
"httpStatus": 200,
"summary": {
"status": "active",
"notificationPushEnabled": true,
"roleCodes": [
"employee",
"finance"
]
}
},
{
"id": "portal",
"status": "PASS",
"httpStatus": 200,
"summary": {}
},
{
"id": "payment-batches",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 9,
"total": null
}
},
{
"id": "ap-ledger",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 1,
"total": 33
}
}
],
"actualRoles": [
"employee",
"finance"
],
"missingRoles": []
},
{
"key": "finance_mgr",
"expectedRoles": [
"finance",
"finance_mgr",
"employee"
],
"maskedIdentifier": "sm***@***.com",
"login": {
"status": "PASS",
"reason": null,
"code": null
},
"roleMatch": "PASS",
"probes": [
{
"id": "me",
"status": "PASS",
"httpStatus": 200,
"summary": {
"status": "active",
"notificationPushEnabled": true,
"roleCodes": [
"employee",
"finance",
"finance_mgr"
]
}
},
{
"id": "portal",
"status": "PASS",
"httpStatus": 200,
"summary": {}
},
{
"id": "payment-batches",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 9,
"total": null
}
},
{
"id": "ap-ledger",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 1,
"total": 33
}
}
],
"actualRoles": [
"employee",
"finance",
"finance_mgr"
],
"missingRoles": []
},
{
"key": "hr",
"expectedRoles": [
"hr",
"employee"
],
"maskedIdentifier": "sm***@***.com",
"login": {
"status": "PASS",
"reason": null,
"code": null
},
"roleMatch": "PASS",
"probes": [
{
"id": "me",
"status": "PASS",
"httpStatus": 200,
"summary": {
"status": "active",
"notificationPushEnabled": true,
"roleCodes": [
"employee",
"hr"
]
}
},
{
"id": "portal",
"status": "PASS",
"httpStatus": 200,
"summary": {}
},
{
"id": "wecom-archive",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 1,
"total": 9
}
}
],
"actualRoles": [
"employee",
"hr"
],
"missingRoles": []
}
],
"findings": [],
"boundaries": {
"noBusinessWrites": true,
"noWeComWrites": true,
"noPasswordOutput": true,
"noRealEmployeeIdentifiers": true
}
}
@@ -0,0 +1 @@
{"requestId":"983ef37c-e6ec-4907-af6e-d31449e08e29","data":{"ok":true}}
@@ -0,0 +1,9 @@
{
"name": "public-ready",
"status": "PASS",
"kind": "required",
"code": 0,
"detail": "ok",
"logRef": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/public-ready.log",
"checkedAt": "2026-05-29T01:28:21.869Z"
}
@@ -0,0 +1,9 @@
{
"name": "report-privacy-smoke",
"status": "PASS",
"kind": "required",
"code": 0,
"detail": "ok",
"logRef": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/report-privacy-smoke.log",
"checkedAt": "2026-05-29T01:33:22.341Z"
}
@@ -0,0 +1,294 @@
{
"issueId": "OAOPS1",
"mode": "oa-real-use-daily",
"status": "PASS_OA_REAL_USE_DAILY_READY",
"conclusion": "PASS_OA_REAL_USE_DAILY_READY",
"baseURL": "https://oa.hyinda.com",
"commit": "bfb1cb6",
"checkedAt": "2026-05-29T01:33:22.264Z",
"reportRef": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily",
"window": {
"durationDays": 7,
"scope": "small-team-all-employees",
"realBusinessDataAllowed": true,
"fixPolicy": "blocking_same_day_issue_contract_nonblocking_feedback_pool"
},
"oaPrimaryDomains": [
"reimbursement_pdf_ocr",
"approval_tasks",
"procurement_expense",
"contracts_registry",
"projects",
"payment_batches",
"bank_receipt_attachments",
"ap_accounting_handoff",
"mobile_wecom_entry",
"audit"
],
"frozenItems": [
"image_ocr",
"complex_bpm",
"budget_control",
"erp_write",
"bank_statement_import",
"real_payment_provider",
"wecom_hr_deep_mirror",
"emergency_takeover",
"recovery_writeback",
"ruleops"
],
"boundaries": {
"defaultReadOnlyAutomation": true,
"manualRealBusinessWritesOnly": true,
"paymentBatchExpected": "force_on",
"erpExpected": "force_off",
"actualPaymentChannel": "offline_bank_channel",
"contractSensitiveFiles": "do_not_upload_confidential_body_sensitive_quote_cost_detail_to_public_oa"
},
"childReports": {
"liveReadiness": {
"status": "PASS",
"reportRef": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/live-smoke-readiness/summary.json",
"findingCount": 0,
"openCount": 0
},
"oaOnlySmokeReadiness": {
"status": "PASS_OA_ONLY_SMOKE_READY",
"reportRef": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/oa-only-smoke-readiness/summary.json",
"findingCount": 0,
"openCount": 0
}
},
"steps": {
"public-ready": {
"name": "public-ready",
"status": "PASS",
"kind": "required",
"code": 0,
"detail": "ok",
"logRef": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/public-ready.log",
"checkedAt": "2026-05-29T01:28:21.869Z"
},
"live-smoke-env": {
"name": "live-smoke-env",
"status": "PASS",
"kind": "finding_allowed",
"code": 0,
"detail": "ok",
"logRef": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/live-smoke-env.log",
"checkedAt": "2026-05-29T01:28:22.439Z"
},
"live-readiness": {
"name": "live-readiness",
"status": "PASS",
"kind": "finding_allowed",
"code": 0,
"detail": "ok",
"logRef": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/live-readiness.log",
"checkedAt": "2026-05-29T01:29:14.867Z"
},
"oa-only-smoke-readiness": {
"name": "oa-only-smoke-readiness",
"status": "PASS",
"kind": "finding_allowed",
"code": 0,
"detail": "ok",
"logRef": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/oa-only-smoke-readiness.log",
"checkedAt": "2026-05-29T01:29:19.941Z"
},
"live-feature-flags": {
"name": "live-feature-flags",
"status": "PASS",
"kind": "finding_allowed",
"code": 0,
"detail": "ok",
"logRef": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/live-feature-flags.log",
"checkedAt": "2026-05-29T01:30:25.887Z"
},
"authenticated-readonly-probe": {
"name": "authenticated-readonly-probe",
"status": "PASS",
"kind": "finding_allowed",
"code": 0,
"detail": "ok",
"logRef": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/authenticated-readonly-probe.log",
"checkedAt": "2026-05-29T01:31:32.564Z"
},
"mobile-entry-matrix": {
"name": "mobile-entry-matrix",
"status": "PASS",
"kind": "finding_allowed",
"code": 0,
"detail": "ok",
"logRef": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/mobile-entry-matrix.log",
"checkedAt": "2026-05-29T01:31:56.368Z"
},
"wecom-rendering-matrix": {
"name": "wecom-rendering-matrix",
"status": "PASS",
"kind": "finding_allowed",
"code": 0,
"detail": "ok",
"logRef": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/wecom-rendering-matrix.log",
"checkedAt": "2026-05-29T01:33:07.280Z"
},
"wecom-entry": {
"name": "wecom-entry",
"status": "PASS",
"kind": "finding_allowed",
"code": 0,
"detail": "ok",
"logRef": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/wecom-entry.log",
"checkedAt": "2026-05-29T01:33:22.015Z"
},
"report-privacy-smoke": {
"name": "report-privacy-smoke",
"status": "PASS",
"kind": "required",
"code": 0,
"detail": "ok",
"logRef": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/report-privacy-smoke.log",
"checkedAt": "2026-05-29T01:33:22.191Z"
}
},
"readonlyProbe": {
"mode": "oaops1-authenticated-readonly-probe",
"status": "PASS",
"baseUrl": "https://oa.hyinda.com",
"checkedAt": "2026-05-29T01:31:32.486Z",
"readOnly": true,
"duplicateRoleChecks": "employee/finance/payment/AP are covered by oa-only-smoke-readiness to avoid repeated login throttling",
"roles": {
"admin": {
"status": "PASS",
"reason": null,
"maskedIdentifier": "sm***om"
}
},
"checks": [
{
"id": "portal",
"role": "admin",
"path": "/api/portal/home",
"domain": "portal",
"status": "PASS",
"httpStatus": 200,
"summary": {}
},
{
"id": "workflow-tasks",
"role": "admin",
"path": "/api/workflow/tasks?page=1&pageSize=5",
"domain": "approval",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 0,
"total": 0
}
},
{
"id": "reimbursements",
"role": "admin",
"path": "/api/reimbursements?page=1&pageSize=5",
"domain": "reimbursement",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 5,
"total": 33
}
},
{
"id": "reimbursement-summary",
"role": "admin",
"path": "/api/reimbursements/stats/summary",
"domain": "reimbursement",
"status": "PASS",
"httpStatus": 200,
"summary": {
"totalCount": 33,
"avgProcessingDays": 0
}
},
{
"id": "invoice-pool",
"role": "admin",
"path": "/api/invoice-pool?page=1&pageSize=5",
"domain": "invoice_ocr",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 5,
"total": 46
}
},
{
"id": "purchase-requests",
"role": "admin",
"path": "/api/purchase-requests?page=1&pageSize=5",
"domain": "procurement",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 0,
"total": 0
}
},
{
"id": "contracts-registry",
"role": "admin",
"path": "/api/contracts-registry",
"domain": "contracts",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 6,
"total": null
}
},
{
"id": "projects",
"role": "admin",
"path": "/api/projects?page=1&pageSize=5",
"domain": "projects",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 4,
"total": null
}
},
{
"id": "audit-logs",
"role": "admin",
"path": "/api/audit-logs?page=1&pageSize=5",
"domain": "audit",
"status": "PASS",
"httpStatus": 200,
"summary": {
"itemCount": 5,
"total": 2235
}
}
],
"boundaries": {
"noBusinessWrites": true,
"noExportsByDefault": true,
"noFileUploads": true,
"noWeComWrites": true,
"noRealPaymentExecution": true
}
},
"findingCount": 0,
"findings": [],
"manualGates": {
"dailyCloseout": "管理员每日查看 summary.json 和 manual-gates.md,阻断即修,非阻断入反馈池。",
"day7Closeout": [
"A:接受 PASS_OA_REAL_USE_READY,进入下一轮体验/效率优化。",
"B:接受 PASS_WITH_FINDINGS,但先处理指定 finding。",
"C:暂停真实使用扩展,先做整改。"
]
},
"privacy": "status/count/report-path summaries only; no phone/email/token/Secret/EncodingAESKey/full external ids/full invoice image/full bank receipt/full contract body/raw payload"
}
@@ -0,0 +1,24 @@
[oaops1] loaded masked live smoke env file
>>> [oaops1] public-ready
[oaops1][PASS] public-ready
>>> [oaops1] live-smoke-env
[oaops1][PASS] live-smoke-env
>>> [oaops1] live-readiness
[oaops1][PASS] live-readiness
>>> [oaops1] oa-only-smoke-readiness
[oaops1][PASS] oa-only-smoke-readiness
[oaops1] login cooldown 65s before live-feature-flags
>>> [oaops1] live-feature-flags
[oaops1][PASS] live-feature-flags
[oaops1] login cooldown 65s before authenticated-readonly-probe
>>> [oaops1] authenticated-readonly-probe
[oaops1][PASS] authenticated-readonly-probe
>>> [oaops1] mobile-entry-matrix
[oaops1][PASS] mobile-entry-matrix
>>> [oaops1] wecom-rendering-matrix
[oaops1][PASS] wecom-rendering-matrix
>>> [oaops1] wecom-entry
[oaops1][PASS] wecom-entry
[oaops1][PASS] report-privacy-smoke
[oaops1][PASS] report-privacy-smoke
[oaops1] report=.trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily
@@ -0,0 +1,11 @@
Running 2 tests using 1 worker
(node:89063) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set.
(Use `node --trace-warnings ...` to show where the warning was created)
(node:89063) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set.
(Use `node --trace-warnings ...` to show where the warning was created)
✓ 1 tests/e2e/wecom-entry.spec.ts:56:1 › E2E 企微入口:普通浏览器下只提示企业微信工作台打开 (2.9s)
✓ 2 tests/e2e/wecom-entry.spec.ts:66:1 › E2E 企微入口:企业微信场景优先显示企微 CTA,并展示未绑定提示 (2.5s)
2 passed (9.1s)
@@ -0,0 +1,9 @@
{
"name": "wecom-entry",
"status": "PASS",
"kind": "finding_allowed",
"code": 0,
"detail": "ok",
"logRef": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/wecom-entry.log",
"checkedAt": "2026-05-29T01:33:22.015Z"
}
@@ -0,0 +1,17 @@
Running 8 tests using 1 worker
(node:87388) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set.
(Use `node --trace-warnings ...` to show where the warning was created)
(node:87388) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set.
(Use `node --trace-warnings ...` to show where the warning was created)
✓ 1 tests/e2e/r6-wecom-mobile-rendering-hardening.spec.ts:588:7 › WCM6 企业微信多手机移动渲染稳定化 › 320 iPhone 企业微信 › 核心移动入口使用 SVG 图标且跨视口不挤压 (7.9s)
✓ 2 tests/e2e/r6-wecom-mobile-rendering-hardening.spec.ts:588:7 › WCM6 企业微信多手机移动渲染稳定化 › 360 Android 企业微信 › 核心移动入口使用 SVG 图标且跨视口不挤压 (7.5s)
✓ 3 tests/e2e/r6-wecom-mobile-rendering-hardening.spec.ts:588:7 › WCM6 企业微信多手机移动渲染稳定化 › 375 iPhone 企业微信 › 核心移动入口使用 SVG 图标且跨视口不挤压 (7.5s)
✓ 4 tests/e2e/r6-wecom-mobile-rendering-hardening.spec.ts:588:7 › WCM6 企业微信多手机移动渲染稳定化 › 390 iPhone12 企业微信 › 核心移动入口使用 SVG 图标且跨视口不挤压 (7.7s)
✓ 5 tests/e2e/r6-wecom-mobile-rendering-hardening.spec.ts:588:7 › WCM6 企业微信多手机移动渲染稳定化 › 393 Android 企业微信 › 核心移动入口使用 SVG 图标且跨视口不挤压 (7.5s)
✓ 6 tests/e2e/r6-wecom-mobile-rendering-hardening.spec.ts:588:7 › WCM6 企业微信多手机移动渲染稳定化 › 414 iPhone 企业微信 › 核心移动入口使用 SVG 图标且跨视口不挤压 (7.5s)
✓ 7 tests/e2e/r6-wecom-mobile-rendering-hardening.spec.ts:588:7 › WCM6 企业微信多手机移动渲染稳定化 › 430 iPhone 企业微信 › 核心移动入口使用 SVG 图标且跨视口不挤压 (8.0s)
✓ 8 tests/e2e/r6-wecom-mobile-rendering-hardening.spec.ts:604:5 › WCM6 企业微信多手机移动渲染稳定化 › 390 iPhone12 企业微信 字体失败 › Material Symbols 字体失败时核心移动入口仍稳定 (7.1s)
8 passed (1.1m)
@@ -0,0 +1,9 @@
{
"name": "wecom-rendering-matrix",
"status": "PASS",
"kind": "finding_allowed",
"code": 0,
"detail": "ok",
"logRef": ".trellis/tasks/05-29-frontend-ux-wave4-5-finance-admin-refresh/research/postdeploy-20260529-wave4-5-public-rerun/oa-real-use-daily/wecom-rendering-matrix.log",
"checkedAt": "2026-05-29T01:33:07.280Z"
}
+18 -19
查看文件
@@ -8,8 +8,8 @@ function present(key) {
return Boolean(process.env[key]?.trim()); return Boolean(process.env[key]?.trim());
} }
function maskedPresence(keys) { function readinessMap(entries) {
return Object.fromEntries(keys.map((key) => [key, present(key)])); return Object.fromEntries(entries.map(([label, isReady]) => [label, Boolean(isReady)]));
} }
function existingFileFrom(keys) { function existingFileFrom(keys) {
@@ -56,13 +56,11 @@ async function fetchJson(url) {
} }
function buildStaticChecks() { function buildStaticChecks() {
const liveSmokeKeys = [ const adminCredentialReady = present("LIVE_SMOKE_ADMIN_IDENTIFIER") && present("LIVE_SMOKE_ADMIN_PASSWORD");
"LIVE_SMOKE_ADMIN_IDENTIFIER", const employeeCredentialReady = present("LIVE_SMOKE_EMPLOYEE_IDENTIFIER") && present("LIVE_SMOKE_EMPLOYEE_PASSWORD");
"LIVE_SMOKE_ADMIN_PASSWORD", const managerCredentialReady = present("LIVE_SMOKE_MANAGER_IDENTIFIER") && present("LIVE_SMOKE_MANAGER_PASSWORD");
"LIVE_SMOKE_EMPLOYEE_IDENTIFIER", const financeCredentialReady = present("LIVE_SMOKE_FINANCE_IDENTIFIER") && present("LIVE_SMOKE_FINANCE_PASSWORD");
"LIVE_SMOKE_EMPLOYEE_PASSWORD", const liveSmokeReady = adminCredentialReady && employeeCredentialReady;
];
const liveSmokeReady = liveSmokeKeys.every(present);
const ocrUserReady = ( const ocrUserReady = (
(present("PLAYWRIGHT_OCR_LIVE_IDENTIFIER") && present("PLAYWRIGHT_OCR_LIVE_PASSWORD")) || (present("PLAYWRIGHT_OCR_LIVE_IDENTIFIER") && present("PLAYWRIGHT_OCR_LIVE_PASSWORD")) ||
(present("LIVE_SMOKE_EMPLOYEE_IDENTIFIER") && present("LIVE_SMOKE_EMPLOYEE_PASSWORD")) (present("LIVE_SMOKE_EMPLOYEE_IDENTIFIER") && present("LIVE_SMOKE_EMPLOYEE_PASSWORD"))
@@ -76,13 +74,14 @@ function buildStaticChecks() {
return { return {
baseUrl, baseUrl,
liveSmokeReady, liveSmokeReady,
liveSmoke: maskedPresence(liveSmokeKeys), liveSmoke: readinessMap([
liveSmokeOptional: maskedPresence([ ["adminCredentialReady", adminCredentialReady],
"LIVE_EXPECT_WECOM_STATUS", ["employeeCredentialReady", employeeCredentialReady],
"LIVE_SMOKE_MANAGER_IDENTIFIER", ]),
"LIVE_SMOKE_MANAGER_PASSWORD", liveSmokeOptional: readinessMap([
"LIVE_SMOKE_FINANCE_IDENTIFIER", ["expectedWecomStatusReady", present("LIVE_EXPECT_WECOM_STATUS")],
"LIVE_SMOKE_FINANCE_PASSWORD", ["managerCredentialReady", managerCredentialReady],
["financeCredentialReady", financeCredentialReady],
]), ]),
liveOcrReady: ocrUserReady && invoiceSampleReady, liveOcrReady: ocrUserReady && invoiceSampleReady,
liveOcr: { liveOcr: {
@@ -100,13 +99,13 @@ function buildStaticChecks() {
function addMissing(checks) { function addMissing(checks) {
if (!checks.liveSmokeReady) { if (!checks.liveSmokeReady) {
for (const [key, value] of Object.entries(checks.liveSmoke)) { for (const [label, value] of Object.entries(checks.liveSmoke)) {
if (!value) checks.missing.push(key); if (!value) checks.missing.push(label);
} }
} }
if (!checks.liveOcr.userReady) { if (!checks.liveOcr.userReady) {
checks.missing.push("PLAYWRIGHT_OCR_LIVE_IDENTIFIER/PASSWORD 或 LIVE_SMOKE_EMPLOYEE_*"); checks.missing.push("ocrOrEmployeeCredentialReady");
} }
if (!checks.liveOcr.invoiceSampleReady) { if (!checks.liveOcr.invoiceSampleReady) {
checks.missing.push("PLAYWRIGHT_OCR_LIVE_FILE 或 PLAYWRIGHT_OCR_LIVE_DIR 中的 PDF 样票"); checks.missing.push("PLAYWRIGHT_OCR_LIVE_FILE 或 PLAYWRIGHT_OCR_LIVE_DIR 中的 PDF 样票");