From 79bf6cff8302d5607e00025acc460a8a45cbeb3e Mon Sep 17 00:00:00 2001 From: shunli Date: Thu, 16 Jul 2026 05:18:59 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B2=89=E6=B7=80=E7=94=9F=E4=BA=A7=E6=94=B6?= =?UTF-8?q?=E5=8F=A3=E8=A7=84=E7=BA=A6=E4=B8=8E=E6=B8=85=E7=90=86=E8=AF=81?= =?UTF-8?q?=E6=8D=AE=EF=BC=8807-15-production-trust-closeout-cleanup?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spec/hyb-oa/backend-fastify-prisma.md | 125 ++++++++++++++ .trellis/spec/hyb-oa/deployment-trialrun.md | 84 +++++++++ .trellis/spec/hyb-oa/docs-and-evidence.md | 17 +- .trellis/spec/hyb-oa/project-governance.md | 64 ++++++- .trellis/spec/hyb-oa/security-privacy.md | 120 +++++++++++++ .../check.jsonl | 1 + .../design.md | 53 ++++++ .../implement.jsonl | 1 + .../prd.md | 160 ++++++++++++++++++ .../research/cleanup-candidate-inventory.md | 60 +++++++ .../research/p0-technical-research.md | 69 ++++++++ .../task.json | 33 ++++ 12 files changed, 784 insertions(+), 3 deletions(-) create mode 100644 .trellis/tasks/07-15-production-trust-closeout-cleanup/check.jsonl create mode 100644 .trellis/tasks/07-15-production-trust-closeout-cleanup/design.md create mode 100644 .trellis/tasks/07-15-production-trust-closeout-cleanup/implement.jsonl create mode 100644 .trellis/tasks/07-15-production-trust-closeout-cleanup/prd.md create mode 100644 .trellis/tasks/07-15-production-trust-closeout-cleanup/research/cleanup-candidate-inventory.md create mode 100644 .trellis/tasks/07-15-production-trust-closeout-cleanup/research/p0-technical-research.md create mode 100644 .trellis/tasks/07-15-production-trust-closeout-cleanup/task.json diff --git a/.trellis/spec/hyb-oa/backend-fastify-prisma.md b/.trellis/spec/hyb-oa/backend-fastify-prisma.md index e0e5c2ae..7afdb8ac 100644 --- a/.trellis/spec/hyb-oa/backend-fastify-prisma.md +++ b/.trellis/spec/hyb-oa/backend-fastify-prisma.md @@ -169,3 +169,128 @@ if (acknowledgementCount > 0) { throw new AppError({ code: "VALID_001", message: "参数校验失败", statusCode: 409 }); } ``` + +## Scenario: Safe Development Seed + +### 1. Scope / Trigger + +- Trigger: changing or running `server/src/scripts/seed-dev.js`, its safety + guard, development account defaults or the `seed:dev` npm command. + +### 2. Signatures + +- Command: `SEED_DEV_ALLOW=1 SEED_DEV_DATABASE_CONFIRM= npm run seed:dev`. +- Optional reset: `SEED_DEV_RESET_PASSWORDS=1`. +- Target: `DATABASE_URL` parsed with the same `pg` semantics used by Prisma's + PostgreSQL adapter. + +### 3. Contracts + +- `NODE_ENV=production` is permanently refused. +- The explicit allow switch and exact database-name confirmation are both + required. +- The effective PostgreSQL host, including query-string overrides, must be + loopback; checking only the URI authority is insufficient. +- Existing passwords are preserved by default. Newly created accounts and + explicitly rotated accounts set `must_change_password=true`. +- The guard and seed logs never print credentials, complete targets or account + passwords. + +### 4. Validation & Error Matrix + +- Production -> `production_forbidden`. +- Missing allow switch -> `explicit_allow_required`. +- Invalid/non-PostgreSQL URL -> `database_url_invalid` or + `database_protocol_invalid`. +- Effective non-loopback host, including `?host=...` -> + `database_host_not_local`. +- Missing/mismatched confirmation -> `database_confirmation_mismatch`. + +### 5. Good/Base/Bad Cases + +- Good: loopback test database, exact confirmation, new accounts require a + password change. +- Base: rerun without reset preserves existing password hashes. +- Bad: accept `postgresql://...@127.0.0.1/db?host=remote.internal` because only + `URL.hostname` was checked. + +### 6. Tests Required + +- Pure guard tests for production, missing allow, remote authority, host-query + override, exact confirmation and redacted errors. +- Unit tests for existing-password preservation, explicit rotation and new + account first-login change. +- Do not validate refusal paths by connecting to a real database. + +### 7. Wrong vs Correct + +#### Wrong + +```js +if (new URL(env.DATABASE_URL).hostname === "127.0.0.1") allowSeed(); +``` + +#### Correct + +```js +const client = new Client({ connectionString: env.DATABASE_URL }); +if (!LOOPBACK_HOSTS.has(client.host)) refuse("database_host_not_local"); +``` + +## Scenario: Database-Free App Contract Tests + +### 1. Scope / Trigger + +- Trigger: unit tests call the production `buildApp()` factory to verify health, + readiness, static serving or other app-level contracts in CI without a DB. + +### 2. Signatures + +- Production: `buildApp()`. +- Test seam: `buildApp({ prismaPlugin, startJobs })`. + +### 3. Contracts + +- Omitted dependencies always use the production Prisma plugin and job starter. +- Unit tests inject a `fastify-plugin`-wrapped Prisma decorator and a no-op job + starter; they must not rely on ESM `vi.mock` intercepting a CJS `require`. +- App-level test doubles expose only methods used by the tested requests. +- `DATABASE_URL='' JWT_SECRET=''` must not make isolated app tests access a + developer `.env` or local PostgreSQL instance. + +### 4. Validation & Error Matrix + +- Production call with missing DB target -> normal startup refusal. +- Test call with injected Prisma plugin -> no production client construction. +- Test double missing a method exercised by the request -> focused unit failure. +- Injected dependencies leaking into `buildApp()` callers without options -> + contract regression. + +### 5. Good/Base/Bad Cases + +- Good: health/static tests inject Prisma and pass with empty DB/JWT process + variables after setting their own test JWT. +- Base: API/Worker call `buildApp()` without options and retain production wiring. +- Bad: a hoisted `vi.mock("../prismaClient")` appears green only because a local + `.env` database is reachable. + +### 6. Tests Required + +- Run health and static tests with `DATABASE_URL='' JWT_SECRET=''`. +- Run the full `scripts/check-minimal.sh` under the same empty environment. +- Keep the production default path covered by normal startup/smoke checks. + +### 7. Wrong vs Correct + +#### Wrong + +```js +vi.mock("../../src/prismaClient", () => ({ createPrismaClient: fake })); +await buildApp(); // CJS plugin may still construct the real client +``` + +#### Correct + +```js +await buildApp({ prismaPlugin: testPrismaPlugin, startJobs: noOpStartJobs }); +``` diff --git a/.trellis/spec/hyb-oa/deployment-trialrun.md b/.trellis/spec/hyb-oa/deployment-trialrun.md index 57f30495..3355202e 100644 --- a/.trellis/spec/hyb-oa/deployment-trialrun.md +++ b/.trellis/spec/hyb-oa/deployment-trialrun.md @@ -263,3 +263,87 @@ const REQUIRED_MAIN_NAV_KEYS = [ const REQUIRED_BACKUP_NAV_KEYS = ["weeklyReports", "announcements"]; const REQUIRED_ADMIN_NAV_KEYS = ["systemSettings"]; ``` + +## Scenario: Immutable Deployment Provenance And Dual Build SHA + +### 1. Scope / Trigger + +- Trigger: changing the trialrun deployment entry, Docker build, Compose + wiring, `/health` or `/ready`, public bundle scanning or live readiness. + +### 2. Signatures + +- Provenance gate: `node deploy/trialrun/check-source-provenance.mjs`. +- Standard release: `SYNC_ENV=0 bash deploy/trialrun/deploy.sh`. +- Build/runtime inputs: `BUILD_SHA=` and + `VITE_BUILD_SHA=<12-char-commit>`. +- Runtime outputs: `/health.data.buildSha`, `/ready.data.buildSha` and the + frontend `html[data-build-sha]` marker. + +### 3. Contracts + +- Deployment rejects tracked and untracked dirty files before synchronization. +- By default HEAD must be contained in its upstream. The explicit unpublished + override is for controlled offline recovery and never relaxes clean-tree. +- Standard deployment refreshes the configured upstream remote before the + ancestor check; a stale local remote-tracking ref is not publication proof. +- Unpublished override requires an allowlisted `DEPLOY_UNPUBLISHED_REASON` and + must emit an `UNPUBLISHED-OVERRIDE` audit line. +- Synchronization comes from `git archive `, not the working + tree. +- Full `BUILD_SHA` is injected at build and runtime; `VITE_BUILD_SHA` is + normalized before bundling so only 12 characters become public. +- Neither build key is persisted in `deploy/trialrun/.env`; direct Compose use + must explicitly provide both and must not publish `unknown`. +- Deployment compares public `/ready` and the public bundle marker with the + verified commit before reporting success. + +### 4. Validation & Error Matrix + +- Dirty tree -> `dirty_worktree`, deployment stops. +- No upstream or commit absent from upstream -> stop unless the explicit + unpublished override is approved. +- Upstream refresh fails -> stop in standard mode; override mode requires an + allowlisted reason and records `remoteVerified=false`. +- Missing runtime/build SHA input -> Compose interpolation fails. +- `/ready` SHA mismatch, bundle marker missing or full SHA exposed -> deployment + fails. +- Standalone readiness missing/mismatching observed SHA -> non-clean finding. + +### 5. Good/Base/Bad Cases + +- Good: clean published commit -> Git archive -> dual-SHA build -> matching + backend and public bundle checks. +- Base: local development build uses `unknown` but is never represented as a + release. +- Bad: rsync the current working tree or let `.env` override the image's SHA + with `unknown`. + +### 6. Tests Required + +- Temp-repo provenance tests for dirty, missing upstream, published and + unpublished-override cases, including a stale remote-tracking ref after a + forced remote update. +- `node deploy/trialrun/validate-env-contract.js` and Compose config with both + SHA inputs. +- Synthetic 40-character build: bundle contains the matching 12-character SHA + and not the full value. +- Local-stub readiness test for expected/observed SHA propagation. +- Public deployment still requires separate approval and post-deploy checks. + +### 7. Wrong vs Correct + +#### Wrong + +```bash +rsync -az --delete ./ remote:/app +docker compose up -d --build server +``` + +#### Correct + +```bash +node deploy/trialrun/check-source-provenance.mjs +BUILD_SHA= VITE_BUILD_SHA= \ + docker compose -f deploy/trialrun/docker-compose.yml build server +``` diff --git a/.trellis/spec/hyb-oa/docs-and-evidence.md b/.trellis/spec/hyb-oa/docs-and-evidence.md index bbe5c1bf..9aa8cf45 100644 --- a/.trellis/spec/hyb-oa/docs-and-evidence.md +++ b/.trellis/spec/hyb-oa/docs-and-evidence.md @@ -36,6 +36,9 @@ Start from `docs/文档索引.md` and `docs/文档事实源状态矩阵.md`. - Use repo-relative `reportRef` / `logRef` when a path is inside the repo. - Do not write absolute local workspace paths into `summary.json`. - Parent summaries must include child report status and child finding counts. +- Live-readiness summaries must distinguish the local `sourceCommit` from the + public `observedBuildSha`; a missing or mismatched public build marker cannot + produce a clean pass. - Parent `findingCount` must become non-zero when any child summary reports `PASS_WITH_FINDINGS`, `SKIP`, `PARTIAL`, `PAUSED`, `MISSING`, blocker-like status or child `findingCount > 0`. @@ -47,6 +50,8 @@ Start from `docs/文档索引.md` and `docs/文档事实源状态矩阵.md`. - 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. +- `check-pending-ocr.mjs` must reuse the adapter-backed Prisma client factory + and close both Prisma and its external PostgreSQL pool. ### 4. Validation & Error Matrix @@ -60,11 +65,15 @@ Start from `docs/文档索引.md` and `docs/文档事实源状态矩阵.md`. summary reflect the failure. - Secret-like field names in generated reports -> privacy finding, even when the value is only a boolean presence flag. +- Public `/ready` has no usable build SHA -> `manual_or_config` finding. +- Expected and observed public SHA differ -> `manual_or_config` finding or a + deployment blocker; never a clean pass attributed to local HEAD. ### 5. Good/Base/Bad Cases - Good: `summary.json` contains `reportRef`, `childReports..status`, - `childReports..findingCount` and no absolute local path. + `childReports..findingCount`, `sourceCommit`, `observedBuildSha` and no + absolute local path. - Base: Missing runtime credentials produce `PASS_WITH_FINDINGS` or `manual_or_config`, not a clean pass. - Bad: Parent command exits 0 for a child `PASS_WITH_FINDINGS` and the parent @@ -81,6 +90,9 @@ Start from `docs/文档索引.md` and `docs/文档事实源状态矩阵.md`. - 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. +- Build a synthetic 40-character SHA and assert the public bundle contains only + its 12-character marker; use a local HTTP stub to assert readiness records and + matches the observed marker. ### 7. Wrong vs Correct @@ -107,6 +119,9 @@ Start from `docs/文档索引.md` and `docs/文档事实源状态矩阵.md`. ```json { "status": "PASS_WITH_FINDINGS", + "sourceCommit": "abcdef1234567890", + "observedBuildSha": "abcdef123456", + "buildShaMatches": true, "reportRef": "artifacts/qa-flow/run", "childReports": { "oaOnlySmokeReadiness": { diff --git a/.trellis/spec/hyb-oa/project-governance.md b/.trellis/spec/hyb-oa/project-governance.md index ff66799f..de8f701f 100644 --- a/.trellis/spec/hyb-oa/project-governance.md +++ b/.trellis/spec/hyb-oa/project-governance.md @@ -13,8 +13,9 @@ tasks after TRELLIS2. - Put goal, scope, out-of-scope, acceptance and test plan in `prd.md`. - Add `design.md` or `implement.md` for complex process, API, migration, permission, deployment or workflow-governance changes. -- Curate `implement.jsonl` and `check.jsonl` with stable spec or research - context only. +- In sub-agent dispatch mode, curate `implement.jsonl` and `check.jsonl` with + stable spec or research context only. In Codex inline mode they may contain + no real entries because the main session reads specs directly. - Give a concrete implementation plan before coding and wait for approval. - Keep edits scoped to the current Trellis task. - Commit in Chinese and include the Trellis task name or task ID. @@ -60,3 +61,62 @@ rollback and future self-maintenance. - Do not delete, bulk rewrite or move historical `issues/*.csv` files. - New work may mention an old Issue CSV for traceability, but must not require a new CSV unless the user explicitly requests legacy/export evidence. + +## Scenario: Codex Inline Context Manifests + +### 1. Scope / Trigger + +- Trigger: creating, validating or finishing a Trellis task while + `.trellis/config.yaml` sets `codex.dispatch_mode: inline`. + +### 2. Signatures + +- Config: `codex.dispatch_mode: inline | sub-agent`. +- Context files: `/implement.jsonl`, `/check.jsonl`. +- Gates: `node scripts/qa/check-trellis-governance.mjs` and + `python3 ./.trellis/scripts/task.py validate `. + +### 3. Contracts + +- Inline mode may keep both JSONL files at zero real entries; the seed + `_example` row does not count as injected context. +- If an inline task contains real entries, each entry must still be valid JSON + with non-empty `file` and `reason`; normal path and context warnings apply. +- Sub-agent mode requires at least one real entry in each manifest. +- Switching dispatch mode changes the validation policy, not historical task + evidence and not the requirement to read specs before implementation. + +### 4. Validation & Error Matrix + +- Inline + zero real entries -> pass with `*_inline_optional`. +- Inline + malformed real entry -> fail. +- Sub-agent + zero real entries -> fail with `*_empty`. +- Either mode + non-spec/non-research context -> warning for review. + +### 5. Good/Base/Bad Cases + +- Good: inline task uses the seed-only files and the main agent reads specs. +- Base: inline task keeps curated entries for audit; they remain validated. +- Bad: governance fabricates placeholder entries only to satisfy a rule meant + for sub-agent context injection. + +### 6. Tests Required + +- Fixture test for inline seed-only pass. +- Fixture test for sub-agent seed-only failure. +- Run both Trellis governance and `task.py validate` for the active task. + +### 7. Wrong vs Correct + +#### Wrong + +```text +dispatch_mode=inline -> require at least one injected JSONL entry +``` + +#### Correct + +```text +dispatch_mode=inline -> allow zero real entries; validate any real entries +dispatch_mode=sub-agent -> require curated real entries +``` diff --git a/.trellis/spec/hyb-oa/security-privacy.md b/.trellis/spec/hyb-oa/security-privacy.md index 53aa1351..990903d9 100644 --- a/.trellis/spec/hyb-oa/security-privacy.md +++ b/.trellis/spec/hyb-oa/security-privacy.md @@ -155,3 +155,123 @@ return reply.send(stream); originals in normal OA attachment areas. - Customer original material, sensitive quotes, contract bodies or signed packages outside authorized business flows. + +## Scenario: External Delivery Error Logging + +### 1. Scope / Trigger + +- Trigger: logging SMTP, webhook, object-storage or other provider delivery + failures whose native error objects may contain recipients or payloads. + +### 2. Signatures + +- Email log metadata: `errorCode`, optional `providerCode`, optional + `smtpCommand`, optional numeric `smtpResponseCode`, request/business IDs and + recipient count. +- Forbidden input: raw provider `Error` objects in structured logs. + +### 3. Contracts + +- Log only explicitly allowlisted scalar metadata. +- Do not log `response`, `rejected`, `rejectedErrors`, `envelope`, addresses, + raw messages, headers, credentials or payloads. +- Provider codes must match a bounded token format; SMTP commands must come + from a fixed safe set; response codes must be bounded integers. +- Delivery failure counts remain observable without exposing recipient data. + +### 4. Validation & Error Matrix + +- Known safe provider code/command/response code -> include normalized fields. +- Unknown or free-form field -> omit it. +- Error with rejected address or SMTP response text -> log generic category and + safe numeric/token fields only. +- Missing logger -> return the delivery result without throwing a logging + error. + +### 5. Good/Base/Bad Cases + +- Good: record `EENVELOPE`, `RCPT TO`, `550`, request ID and failed count. +- Base: plain `Error` becomes only `errorCode=email_delivery_failed`. +- Bad: pass Nodemailer's raw `err` to Pino, which serializes rejected addresses. + +### 6. Tests Required + +- Mock a provider error containing a rejected full address, response and + envelope. +- Assert serialized log context contains none of those values and retains only + allowlisted metadata. +- Cover disabled, configured, success and failure delivery paths. + +### 7. Wrong vs Correct + +#### Wrong + +```js +logger.error({ err: providerError, recipient }, "delivery failed"); +``` + +#### Correct + +```js +logger.error({ ...buildSafeErrorLog(providerError), requestId, failed }, "delivery failed"); +``` + +## Scenario: Current Fact Source Sensitive Gate + +### 1. Scope / Trigger + +- Trigger: adding, registering or changing a CURRENT fact source, README, + deployment entry or environment template. + +### 2. Signatures + +- Gate: `node scripts/qa/check-sensitive-content.mjs`. +- Registry: `docs/文档事实源状态矩阵.md` rows whose status is `CURRENT` and + contract path is under `docs/`. +- Output: `fileRef`, `line`, `category`; never the matched text. + +### 3. Contracts + +- Scan fixed execution/deployment entrypoints plus every CURRENT docs contract + derived from the status matrix; do not maintain a partial duplicate docs list. +- Detect secret assignments, credential URLs, full accounts, personal workspace + paths, private keys and public IPv4 values. +- Allow explicit placeholders, environment interpolation and loopback addresses. +- Missing registry files remain a docs-audit concern; existing scanned files + must not be silently excluded. + +### 4. Validation & Error Matrix + +- Any sensitive match -> `FAIL` with non-zero `findingCount`. +- CURRENT doc added to the matrix -> automatically enters the scan set. +- EVIDENCE/HISTORICAL issue row -> does not enter the CURRENT docs scan set. +- Placeholder such as `` -> pass. + +### 5. Good/Base/Bad Cases + +- Good: all current docs and deploy entrypoints scan clean with metadata-only + output. +- Base: historical evidence stays outside this current-source blocking gate. +- Bad: hard-code six docs while the matrix contains eighteen CURRENT docs. + +### 6. Tests Required + +- Parser fixture with CURRENT doc, historical doc and CURRENT Issue row. +- Assertion that representative current manuals/specs appear in the resolved + default set. +- Repository gate must report `findingCount=0` and the expected expanded file + count after registry changes. + +### 7. Wrong vs Correct + +#### Wrong + +```js +const files = ["docs/文档索引.md", "docs/产品设计规则.md"]; +``` + +#### Correct + +```js +const files = [...fixedEntrypoints, ...extractCurrentDocumentFiles(statusMatrix)]; +``` diff --git a/.trellis/tasks/07-15-production-trust-closeout-cleanup/check.jsonl b/.trellis/tasks/07-15-production-trust-closeout-cleanup/check.jsonl new file mode 100644 index 00000000..9dd3234a --- /dev/null +++ b/.trellis/tasks/07-15-production-trust-closeout-cleanup/check.jsonl @@ -0,0 +1 @@ +{"_example": "Fill with {\"file\": \"\", \"reason\": \"\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."} diff --git a/.trellis/tasks/07-15-production-trust-closeout-cleanup/design.md b/.trellis/tasks/07-15-production-trust-closeout-cleanup/design.md new file mode 100644 index 00000000..35361f11 --- /dev/null +++ b/.trellis/tasks/07-15-production-trust-closeout-cleanup/design.md @@ -0,0 +1,53 @@ +# 生产可信度收口设计 + +## 目标架构 + +本任务不重写业务架构,只在现有入口增加可验证的安全与发布边界。实施按可独立回滚的工作包进行,每个工作包完成后运行聚焦测试,最终再跑全量门禁。 + +## 工作包 + +### WP1:恢复测试基线 + +- 使用 Vitest fake timers 或显式注入当前时间,修复公告测试时间炸弹。 +- 更新导航测试到当前批准名称,不在实现中恢复旧名称。 +- 将 `server npm test` 纳入最小/CI 可信门禁,避免静态绿灯掩盖全量失败。 + +### WP2:运行时与依赖安全 + +- 统一 Node 22。 +- 按研究摘要分三段升级依赖;每段运行认证、回调、邮件、Prisma 和 server 全量测试。 +- 生产依赖审计无 critical;直接可达 high 清零,其余项写明依赖路径和处理结论。 + +### WP3:Readiness 与 Seed 防误操作 + +- 给 readiness 子步骤增加结构化状态和 finding 传播。 +- 新增缺前置条件回归,保证 `SKIP` 不会成为 clean PASS。 +- 抽出可单测的 dev-seed safety guard;默认不覆盖既有密码,日志不输出口令。 + +### WP4:发布追溯与敏感治理 + +- 部署前检查 clean tree、commit/upstream,并把 build SHA 传入构建和版本响应。 +- 扩大当前事实源/README/部署入口的脱敏扫描,输出文件与类别而非匹配原文。 +- 脱敏当前文档中的完整账号、凭据、基础设施信息和绝对路径;不批量重写历史 CSV。 + +### WP5:第一批生成物清理与第二批候选 + +- 删除可重建且无跟踪引用的 build/test 临时目录。 +- 保留根级 `output/`、`artifacts/`,提交第二批候选清单,不删除 Git 跟踪兼容代码。 + +## 验证矩阵 + +- 后端:Prisma validate/generate check、全量 `npm test`、触达文件 `node --check`、认证/企微回调/邮件聚焦测试、生产依赖审计。 +- 前端:typecheck、build、Router 聚焦 smoke。 +- QA:readiness 四类状态场景、process/Trellis/docs gates、部署环境契约、shell syntax。 +- 治理:task validate、敏感扫描、`git diff --check`、只读 reviewer。 + +## 回滚 + +- 依赖段按 package/lockfile 和相关适配代码分别回滚,不使用 amend 或重写迁移。 +- readiness/seed/deploy 入口均保留旧业务行为之外的 fail-closed 变化;若验证失败,回滚对应工作包,不放宽安全边界。 +- 删除仅限可再生忽略目录;必要时由 build/test 命令重建。 + +## 部署边界 + +本任务完成只代表本地可信基线。公网部署、远端配置和带凭据复核需另行明确批准。 diff --git a/.trellis/tasks/07-15-production-trust-closeout-cleanup/implement.jsonl b/.trellis/tasks/07-15-production-trust-closeout-cleanup/implement.jsonl new file mode 100644 index 00000000..9dd3234a --- /dev/null +++ b/.trellis/tasks/07-15-production-trust-closeout-cleanup/implement.jsonl @@ -0,0 +1 @@ +{"_example": "Fill with {\"file\": \"\", \"reason\": \"\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."} diff --git a/.trellis/tasks/07-15-production-trust-closeout-cleanup/prd.md b/.trellis/tasks/07-15-production-trust-closeout-cleanup/prd.md new file mode 100644 index 00000000..33609f8d --- /dev/null +++ b/.trellis/tasks/07-15-production-trust-closeout-cleanup/prd.md @@ -0,0 +1,160 @@ +# 生产可信度收口与兼容清理 + +## Goal + +将项目从“功能完整但发布可信度不足的内部试运行态”收口到可验证、可追溯、可安全继续试运行的工程基线:先修复安全依赖、全量测试、readiness 假绿、开发 seed 防误操作和发布追溯等 P0 问题,再以引用、运行时和验证证据为依据清理本地生成物、兼容层及确认不需要的内容,降低单人维护成本。 + +## Scope + +- 后端测试、Node 运行时、生产依赖、认证、企微回调和邮件发送适配。 +- QA readiness 状态、报告聚合、敏感扫描和最小/CI 门禁。 +- 开发 seed 防误操作、部署 clean-tree 与 commit/build 追溯。 +- 当前事实源、运行手册和开发说明的必要脱敏。 +- 可重建本地生成物清理,以及第二批 Git 跟踪兼容/冗余候选清单。 +- Trellis inline 模式与项目治理门禁的一致性修正。 + +## What I Already Know + +- 仓库最小门禁、Prisma schema、前端 typecheck/build、Trellis 治理和 `git diff --check` 当前通过。 +- 后端全量测试为 733/738 通过,5 个失败来自固定日期样例和旧菜单名断言;当前不是全绿发布基线。 +- 后端生产依赖审计报告 3 个 critical、18 个 high、37 个 moderate;认证 JWT 和企业微信 XML 解析链存在直接可达风险。 +- `run-live-smoke-readiness.sh` 会把部分 `SKIP` 子项聚合成 clean `PASS`,历史 Day 1-Day 4 的零 finding 不能直接作为最终启用证据。 +- `seed:dev` 没有 production fail-closed、显式允许开关或目标数据库保护,且会覆盖既有开发账号凭据并输出口令。 +- 部署脚本直接同步当前工作树,没有 clean-tree 校验和不可变提交标识;当前公网 bundle 不能可靠映射到唯一已记录提交。 +- OA 7 天真实试运行只有 Day 1-Day 4 证据,缺 Day 5-Day 7、人工闭环和 Day 7 Go/No-Go。 +- 当前有 3 个 `in_progress` Trellis task,其中一个已部署完成但未归档,一个已提交代码但验收项未勾选。 +- `docs/` 有 24 个未登记文档,现有敏感扫描未完整覆盖账号、内部标识、基础设施信息和完整路径。 +- 本地忽略目录中约有 151 MB `output/` 和 17 MB `artifacts/`;Git 当前没有跟踪这些生成物。 +- 用户已同意按审查建议开展,并允许删除部分兼容或确认不需要的内容。 + +## Assumptions (Temporary) + +- 第一批以 P0 可信度修复为主,不同时扩大业务能力。 +- 删除必须分为两类:无争议本地生成物可按保留策略清理;Git 跟踪内容必须先形成候选清单和证据,再按批准批次删除。 +- 数据库 migration、历史 `issues/*.csv`、已归档 Trellis task 属于审计材料,除非项目规则另行调整,否则不删除或改写。 +- 冻结功能不等于可直接删代码;只有确认不再使用、无运行时入口、无数据/迁移依赖且回归通过时,才进入删除候选。 +- 本任务不自动部署、不 push、不写生产数据、不重置数据库、不执行企业微信或真实付款写入。 + +## Requirements (Evolving) + +### P0 可信度修复 + +- 修复或升级认证、XML 解析、Fastify 及其关键运行时依赖,更新 lockfile,并对认证和企业微信回调做聚焦回归。 +- 修复 5 个后端测试漂移;固定时间语义并同步已批准的新菜单契约。 +- 让 readiness 父子报告正确传播 `SKIP/PARTIAL/MISSING/PASS_WITH_FINDINGS` 和 findingCount;补缺数据库、缺凭据、缺 OCR 样票回归。 +- 为 `seed:dev` 增加 production fail-closed、显式允许开关、数据库目标保护、一次性口令和日志脱敏。 +- 为部署增加 clean-tree 检查、提交 SHA/构建标识和不可变产物边界;不得在本任务内未经批准部署。 +- 扩大敏感信息扫描范围并脱敏当前事实源、运行手册和开发说明中的完整标识、凭据及路径。 + +### 安全清理 + +- 第一批只清理可重建且没有任务/事实源证据依赖的本地生成物;`output/`、`artifacts/` 等存在历史证据引用的目录先盘点、后决定,不整目录直接删除。 +- 对 Git 跟踪的兼容层、旧入口、占位资源、未使用模块和重复事实源只建立候选清单,记录引用、运行时、数据和回滚影响,本轮不直接删除。 +- 第二批删除必须基于候选清单另行批准;删除后同步修复测试、文档、CI、路由和配置引用,不保留静默断链。 +- 迁移、历史审计材料和仍承担回滚/兼容职责的内容默认保留。 + +### 后续收口 + +- 整理 3 个活动 task 的真实状态,但不补造历史证据。 +- P0 修复后另行决定是否启动新的连续 7 天真实试运行 task。 + +## Acceptance Criteria (Evolving) + +- [x] `cd server && npm test` 为 738/738 或更新后的完整用例全绿。 +- [x] `npm audit --omit=dev` 无 critical;直接可达 high 清零,其余 high 有可复核的不可达/接受说明。 +- [x] readiness 缺前置条件时输出非 clean PASS,并在父报告中产生非零 findingCount。 +- [x] `seed:dev` 在 production、未显式允许或非允许数据库上拒绝执行,日志不输出口令。 +- [x] 部署入口拒绝脏工作树并生成可核对的提交/构建标识。 +- [x] 前端 typecheck/build、Prisma validate、全量后端测试、项目治理门禁和文档审计通过。 +- [x] CI、Dockerfile、开发 compose 和 package engines 统一到 Node 22 基线。 +- [x] `check-trellis-governance` 不再要求 inline planning task 维护仅供子代理注入的 JSONL,但仍校验非 inline/有条目时的内容合法性。 +- [x] 每个 Git 跟踪删除项都有“无引用/无运行时依赖/无数据破坏/验证通过”证据(本批未删除 Git 跟踪项,第二批仅形成候选清单)。 +- [x] 生成物清理不删除当前任务或事实源引用的必要脱敏摘要。 +- [x] 工作树最终只包含本任务预期变更,不包含敏感原始材料。 + +## Definition of Done + +- 代码、测试、lockfile、QA runner、治理和必要文档在同一任务内保持一致。 +- 权限、认证、workflow、migration 和删除类高风险变更完成只读 reviewer 复核。 +- 完成项目规定的最小门禁、全量测试、依赖审计和 `git diff --check`。 +- 所有删除均可从 Git 历史或明确重建步骤恢复,并记录回滚方式。 +- 不把本地验证误报成公网已部署或正式启用完成。 + +## Test Plan + +```bash +cd server && npm run prisma:validate +cd server && npm run prisma:check-generated +cd server && npm test +cd server && npm audit --omit=dev +cd client && npm run typecheck +cd client && npm run build +cd client && npm audit --omit=dev +bash -n scripts/qa/run-live-smoke-readiness.sh +bash -n deploy/trialrun/deploy.sh +node deploy/trialrun/validate-env-contract.js +node scripts/qa/check-process-contract.mjs --baseline --json +node scripts/qa/audit-docs.mjs +node scripts/qa/check-trellis-governance.mjs +python3 ./.trellis/scripts/task.py validate 07-15-production-trust-closeout-cleanup +git diff --check +``` + +- 另运行新增的 readiness 缺数据库/缺凭据/缺样票单元或隔离脚本测试。 +- 另运行认证、企微回调、邮件和公告/导航聚焦 Vitest。 +- 本任务不运行公网带凭据 smoke、真实 OCR、部署、seed 或任何数据库写入命令。 + +## Verification Results + +- `DATABASE_URL='' JWT_SECRET='' bash scripts/check-minimal.sh` 全绿:Prisma validate、静态检查、后端 153 个测试文件 / 786 个用例、前端 typecheck/build 和特性矩阵均通过,证明 ci-minimal 不依赖本机数据库或 `.env`。 +- `npm run prisma:check-generated` 通过;部署环境契约、Compose config、process/docs/Trellis/task/sensitive gates 和 `git diff --check` 通过。 +- 服务端生产依赖审计为 0 critical、0 high、6 moderate;剩余项来自 Prisma CLI 的静态服务链,以及 ExcelJS/Tencent SDK 的 UUID v3/v5/v6 传递链,当前无直接可达 high。客户端生产依赖为 0 漏洞。 +- 完整开发依赖快照仍有工具链风险:server 16 项、client 16 项;与生产运行依赖分开登记,后续单独升级构建/测试工具链。 +- 合成 40 位 SHA 构建验证:公网 bundle 只包含 12 位标识,不包含完整 SHA;readiness 记录并比较本地来源提交与公网观察 SHA。 +- 发布来源检查会先刷新 upstream remote-tracking ref;离线 override 必须提供 allowlist 原因码并在日志中醒目标记。 +- 敏感门禁由状态矩阵派生全部 CURRENT docs,当前扫描 28 个入口/事实源且 findingCount=0。 +- 第一批生成物已在最终构建后再次删除;第二批 Git 跟踪候选未删除,仍需另行批准。 +- 未执行部署、push、真实 OCR、seed、数据库写入、企业微信写入或付款操作。 + +## Technical Approach + +- 先修复现有 5 个测试漂移,建立可比较的全绿基线,再升级依赖;任何升级导致的新失败都可明确归因。 +- 运行时统一到 Node 22 LTS;Node 20 已结束支持,Node 24 暂不引入以减少跨版本变量。 +- 依赖按三段升级:兼容补丁/小版本、OTel 0.x 版本族、Nodemailer 主版本;每段独立执行聚焦测试和生产依赖审计,不使用 `npm audit fix --force`。 +- readiness 采用结构化 step JSON 和父子状态聚合,不依赖日志字符串或仅依赖退出码判断 `SKIP`。 +- `seed:dev` 采用 production 永久拒绝、显式允许、目标数据库确认和本机数据库限制;默认不覆盖既有密码,只有额外显式重置开关才允许旋转开发账号密码,任何模式都不打印口令。 +- 部署入口在同步前校验 clean tree、当前 commit 和 upstream 状态,并把 commit/build 标识传入构建;本任务只实现和验证入口,不实际部署。 +- 文档敏感扫描只阻断当前事实源、运行手册、开发说明和部署入口;历史 Issue CSV 保持审计只读,不因新规则被批量改写。 +- 第一批只删除 `client/dist`、测试报告、coverage、CLI 临时快照等可重建且零跟踪引用的生成物;根级 `output/`、`artifacts/` 先保留并登记第二批候选。 + +## Decision (ADR-lite) + +**Context**:P0 可信度修复已经跨越安全依赖、测试、QA runner、开发 seed、部署和文档治理;同时删除 Git 跟踪兼容代码会扩大回归面,并可能触及历史证据、运行时入口和数据迁移。 + +**Decision**:采用两批策略。第一批完成 P0 修复和无争议本地生成物清理,并产出 Git 跟踪兼容/冗余候选清单;第二批在候选清单经用户批准后另行实施删除。 + +**Consequences**:第一批风险更可控、验证链更清晰,不会因清理动作掩盖安全修复问题;代价是部分已识别冗余会暂时保留到第二批。 + +## Out of Scope + +- 未经单独批准的公网部署、生产配置修改、远端同步、真实数据写入或数据库重置。 +- 在本任务中补造缺失的 Day 5-Day 7、人工业务或历史 Go/No-Go 证据。 +- 删除 Prisma migrations、历史 Issue CSV、归档 Trellis task 或仍被生产数据依赖的 schema。 +- 一次性重写全部超大页面、路由或业务架构。 +- 未经候选清单确认就删除低频但仍可能使用的业务模块。 + +## Technical Notes + +- 工作流:`.trellis/workflow.md` +- 治理规约:`.trellis/spec/hyb-oa/project-governance.md` +- 证据规约:`.trellis/spec/hyb-oa/docs-and-evidence.md` +- 安全隐私:`.trellis/spec/hyb-oa/security-privacy.md` +- 后端规约:`.trellis/spec/hyb-oa/backend-fastify-prisma.md` +- 部署规约:`.trellis/spec/hyb-oa/deployment-trialrun.md` +- 关键入口:`scripts/qa/run-live-smoke-readiness.sh`、`scripts/qa/run-oa-real-use-daily.sh`、`server/src/scripts/seed-dev.js`、`deploy/trialrun/deploy.sh` +- 删除验证使用项目实际命令,不照搬通用 skill 中与本仓库技术栈不匹配的脚本名。 + +## Research References + +- `research/p0-technical-research.md`:Node/依赖升级、readiness、seed 和发布追溯的最小风险方案。 +- `research/cleanup-candidate-inventory.md`:生成物与第二批兼容/冗余候选的保护边界。 diff --git a/.trellis/tasks/07-15-production-trust-closeout-cleanup/research/cleanup-candidate-inventory.md b/.trellis/tasks/07-15-production-trust-closeout-cleanup/research/cleanup-candidate-inventory.md new file mode 100644 index 00000000..cfc116c4 --- /dev/null +++ b/.trellis/tasks/07-15-production-trust-closeout-cleanup/research/cleanup-candidate-inventory.md @@ -0,0 +1,60 @@ +# 清理候选与保护边界 + +## 第一批可清理生成物 + +以下目录均未被 Git 跟踪,可从现有命令重建;在验证结束后清理: + +- `client/dist/` +- `client/playwright-report/` +- `client/test-results/` +- `client/output/` +- `server/coverage/` +- `.playwright-cli/` + +`node_modules/` 本轮保留,避免在多段依赖验证中反复安装。 + +### 2026-07-15 执行结果 + +- 已删除:`.playwright-cli/`、`client/dist/`、`client/output/`、`client/playwright-report/`、`client/test-results/`、`server/coverage/`。 +- 删除前合计约 7.4 MB;六个目录的 Git 跟踪文件数均为 0。 +- 重建入口:`cd client && npm run build`、Playwright 对应用例、`cd server && npm run test:coverage`。 +- 未删除:`node_modules/`、`server/generated/storage/`、`deploy/trialrun/screenshots/`、根级 `output/` 和 `artifacts/`。 +- 最终全量门禁曾重建 `client/dist/`,只读前端复核曾产生 `client/playwright-report/`;两者均在取证完成后再次删除,其余第一批目录也再次确认不存在。 + +## 第一批明确保护 + +- 根级 `output/`:约 151 MB、1754 个文件。 +- 根级 `artifacts/`:约 17 MB、1786 个文件。 +- 跟踪文件中约有 430 处 `output/` 或 `artifacts/` 引用;其中可能含部署、视觉、试运行或敏感材料证据。 +- 在完成“引用映射、摘要留存、敏感材料处置、保留周期”前,不整目录删除。 + +## 第二批 Git 跟踪候选(本轮只盘点) + +| 候选 | 当前信号 | 删除前置 | +| --- | --- | --- | +| 旧 `Portal` 导航兼容 | 运行时代码已使用当前命名;旧词仍存在于 1 个视觉 E2E 和部署规约的 mock 兼容示例 | 更新视觉 fixture 与部署规约后跑导航、live smoke 和视觉回归 | +| `client/src/design/tokens.ts` | Git 跟踪;除文件自身外未发现静态引用;颜色/间距已由 CSS/Tailwind 承担 | 再确认没有生成器或外部同步脚本消费;删除后 typecheck/build | +| 1x1 PWA 占位图标 | 3 个文件均仅 68 bytes,实际尺寸 1x1;manifest 却声明 192/512/maskable | 推荐替换为真实图标;若选择删除,必须同步移除 manifest 安装声明并做 PWA 验证 | +| Postman 开发环境文件 | 仅 `server/README.md` 引用 collection/environment;环境模板含固定开发凭据模式 | 确认不再使用 Postman;可选“删除两文件和 README 章节”或“保留 collection、把 environment 改为空占位模板” | +| ERP 入口、路由与集成代码 | `client/src`、`server/src`、`scripts`、`deploy`、CI 中仍有约 79 个含 ERP 的文件,远非孤立死代码 | 单独做 schema/outbox/审计/feature flag/历史数据审计;不得在普通清理批次删除 | +| 冻结的预算、差旅、薪酬、绩效等模块 | 部分隐藏或冻结,但代码/数据仍完整存在 | 逐模块确认真实使用、数据保留、权限、路由和迁移影响 | +| 历史 Issue-first 流程兼容 | 新任务已 Trellis-only,但旧 QA gate 仍消费 Issue CSV | 先迁移 gate 与历史引用;历史 CSV 本身保持审计只读 | + +## 永久保护项 + +- Prisma migrations 和迁移历史。 +- 历史 `issues/*.csv` 审计材料,除非另有治理任务改变项目规则。 +- 已归档 Trellis task。 +- 仍被事实源、回滚、生产数据、部署或外部系统消费的兼容代码。 + +## 第二批删除准入 + +每个候选必须同时满足:无静态引用、无动态注册/配置引用、无生产数据依赖、无迁移破坏、回滚方式明确、聚焦与全量验证通过,并再次获得用户批准。 + +## 第二批建议决策顺序 + +1. `client/src/design/tokens.ts`:最接近可直接删除,但仍需第二批批准。 +2. 旧 `Portal` fixture/spec 兼容:先统一测试契约,再删除旧词兼容。 +3. Postman:在“空模板保留”与“整套删除”之间二选一。 +4. PWA 图标:优先替换,不建议直接删除。 +5. ERP 与冻结业务模块:另建专项 task,不纳入轻量清理。 diff --git a/.trellis/tasks/07-15-production-trust-closeout-cleanup/research/p0-technical-research.md b/.trellis/tasks/07-15-production-trust-closeout-cleanup/research/p0-technical-research.md new file mode 100644 index 00000000..0c9b74f3 --- /dev/null +++ b/.trellis/tasks/07-15-production-trust-closeout-cleanup/research/p0-technical-research.md @@ -0,0 +1,69 @@ +# P0 技术研究摘要 + +## 运行时基线 + +- Node 官方 release schedule 显示 Node 20 已于 2026-04-30 结束支持;Node 22 支持至 2027-04-30,Node 24 支持至 2028-04-30。 +- 当前本机使用 Node 22,前端 build、Prisma validate 和后端绝大多数测试已在该版本运行;CI、开发 compose 和试运行 Dockerfile 仍为 Node 20。 +- 推荐统一 Node 22,更新 CI、Dockerfile、开发 compose、package engines 和版本文件;Node 24 延后单独评估。 + +## 依赖升级分段 + +### A. 兼容补丁/小版本 + +- `@fastify/jwt` 10.0 -> 10.2;最新版依赖修复后的 `fast-jwt` 6.2.4。 +- Fastify 5.7 -> 5.10。 +- `fast-xml-parser` 5.3.4 -> 5.10。 +- Prisma / Prisma Client 7.3 -> 7.8。 +- AWS S3 SDK 更新到同一 v3 最新兼容线,以消除旧 XML 解析传递依赖。 +- React Router DOM 仅升 6.30.3 -> 6.30.4,不跨到 7.x。 + +### B. OTel 0.x 版本族 + +- SDK 0.213 -> 0.220,auto-instrumentations 0.71 -> 0.78。 +- 0.x 次版本可能包含破坏性变化,需单独验证 server bootstrap、traces disabled/enabled、metrics 和优雅退出。 +- 该升级用于消除 protobuf/grpc 等传递严重公告;不在第一批删除 OTel 代码。 + +### C. Nodemailer 主版本 + +- 当前 6.x,安全修复线为 9.x;项目只使用 `createTransport` 和文本 `sendMail` 基础接口。 +- 单独升级并补 transporter 配置、发送成功、发送异常和禁用邮件测试;不得用真实 SMTP 做自动验证。 + +## Readiness 状态设计 + +- `check-pending-ocr.mjs` 应输出机器可读 `PASS/SKIP/FAIL`,缺数据库时为 `SKIP` 且 findingCount 非零。 +- `run-live-smoke-readiness.sh` 为 `/ready`、public bundle、pending OCR、live smoke、live OCR 分别写 step JSON。 +- 缺凭据、缺样票或缺数据库属于 `manual_or_config`,最终为 `PASS_WITH_FINDINGS`;required step 失败才为 `FAIL/BLOCKED`。 +- `summary.json` 必须包含 child/step status、findingCount、repo-relative reportRef 和 commit,且不得含原始凭据名或完整路径。 +- 回归必须覆盖缺数据库、缺登录凭据、缺 OCR 样票和全前置条件就绪四类场景。 + +## Dev Seed 安全设计 + +- `NODE_ENV=production` 无条件拒绝。 +- 必须同时设置显式允许开关和目标数据库确认值;数据库必须为本机地址,确认值必须匹配 URL 中实际数据库名。 +- 默认创建缺失开发账号,但不覆盖已有账号密码;密码重置需要额外显式开关。 +- 继续支持本地/CI 可重复测试,但不在控制台、报告或文档输出任何口令。 +- 对 guard 做纯函数单元测试;禁止用真实数据库验证拒绝路径。 + +## 发布追溯设计 + +- 部署脚本在 rsync 前拒绝 dirty/untracked 工作树,记录完整 commit SHA 和分支。 +- 默认要求 HEAD 已包含在 upstream;如确有离线灾备场景,必须使用单独显式 override,不能静默部署未同步提交。 +- 构建接收 commit/build 参数,健康或版本元数据返回脱敏短 SHA;部署报告据此核对公网版本。 +- 本任务不执行公网部署,完成后另行获得批准。 + +## 结论 + +采用“基线测试 -> Node/兼容升级 -> OTel -> 邮件 -> readiness/seed -> 发布追溯”的顺序。每段可独立回滚 lockfile 和对应代码,避免安全升级与历史清理互相掩盖。 + +## 2026-07-15 实施与风险处置结果 + +- 统一 Node 22,关键生产依赖升级后全量后端为 153 个测试文件、786 个用例全绿;客户端 typecheck/build 全绿。空 `DATABASE_URL/JWT_SECRET` 的 CI 等价最小门禁同样通过。 +- 生产依赖审计:server 为 0 critical / 0 high / 6 moderate,client 为 0 漏洞。server 剩余中危分别位于 Prisma CLI 的 Hono 静态服务依赖,以及 ExcelJS/Tencent SDK 的 UUID v3/v5/v6 传递链;不采用会把 Prisma 回退到 6.x 或 SDK 回退版本的 `audit fix --force`。 +- 完整开发依赖审计 server/client 各 16 项,属于后续构建与测试工具链升级范围,不与本轮生产运行风险混报。 +- Pending OCR 改为复用 Prisma 7 adapter 工厂并关闭外部 pool;缺数据库仍为非 clean `SKIP`。 +- Readiness 现在同时记录 `sourceCommit`、`expectedBuildSha`、`observedBuildSha` 和匹配结论;缺失或不匹配不再 clean PASS。 +- Seed guard 使用 node-postgres 的实际解析结果校验目标,阻断 `?host=` 绕过;新建和显式轮换账号均强制首次改密。 +- 邮件失败日志只保留白名单化错误分类、provider code、SMTP command 和数字响应码,不再序列化 Nodemailer 原始错误对象。 +- 部署使用 clean/published Git archive,并在判断 published 前刷新 upstream;离线 override 需要 allowlist 原因码且输出醒目审计。完整 SHA 仅用于后端构建与运行时,前端在 Vite 构建期截断为 12 位,直接 Compose 缺任一 SHA 时拒绝解析。 +- 敏感扫描从状态矩阵派生全部 CURRENT docs,扫描范围由 16 个文件扩展到 28 个;遗漏的两处完整本地路径已脱敏。 +- 本任务只完成本地可信基线,未据此声称公网版本已更新或可测试。 diff --git a/.trellis/tasks/07-15-production-trust-closeout-cleanup/task.json b/.trellis/tasks/07-15-production-trust-closeout-cleanup/task.json new file mode 100644 index 00000000..25607f04 --- /dev/null +++ b/.trellis/tasks/07-15-production-trust-closeout-cleanup/task.json @@ -0,0 +1,33 @@ +{ + "id": "production-trust-closeout-cleanup", + "name": "production-trust-closeout-cleanup", + "title": "生产可信度收口与兼容清理", + "description": "修复生产可信度阻断项,收口测试、安全依赖、readiness、开发 seed 与发布追溯,并以证据驱动方式清理生成物、兼容层和确认不需要的内容。", + "status": "in_progress", + "dev_type": null, + "scope": "server, client, scripts/qa, deploy/trialrun, docs, Trellis governance and workspace hygiene", + "package": null, + "priority": "P0", + "creator": "shunli", + "assignee": "shunli", + "createdAt": "2026-07-15", + "completedAt": null, + "branch": null, + "base_branch": "main", + "worktree_path": null, + "commit": null, + "pr_url": null, + "subtasks": [], + "children": [], + "parent": null, + "relatedFiles": [ + "server/package.json", + "server/src/scripts/seed-dev.js", + "scripts/qa/run-live-smoke-readiness.sh", + "scripts/check-minimal.sh", + "deploy/trialrun/deploy.sh", + "docs/文档事实源状态矩阵.md" + ], + "notes": "用户已批准两阶段方案;P0 实施与本地门禁完成,等待最终只读复核和提交计划确认。第二阶段 Git 跟踪候选仍未获删除批准。", + "meta": {} +}