# 内部 OA 使用度普查与减法路线图:设计说明 ## 1. 设计目标与边界 本任务是一次性生产测量和产品组合裁决,不是监控平台建设,也不是功能精简实施。设计优先保证三件事:查询确实只读、活动归因不把自动化当用户、结论不会由单一数字机械推出。 ```text 仓库事实源建立显式模块目录 -> 本地校验查询合同与输出白名单 -> 生产 identity / runtime SHA / migration PRE -> 单个 READ ONLY 事务读取聚合 -> 脱敏快照 + 去污染分桶 -> 业务必要性裁决 -> 四类矩阵 + 30 天路线图 -> 只读 reviewer ``` 任何阶段失败都停止在证据层,不执行 feature flag、导航、代码、schema 或数据变更。 ## 2. 模块目录 ### 2.1 目录来源 目录由四个来源交叉形成: 1. `workspaceSettings.js`:用户实际可能看到的主、管理、备用和隐藏入口; 2. `featureFlags/index.js`:运行环境 gate 与数据库 override 的组合开关; 3. `schema.prisma`:真实持久化表、时间字段和 actor 关系; 4. 07-30 组合盘点与当前业务事实源:业务必要性、替代品和既有建议。 不以 Prisma model 数量直接代表模块数量。认证 challenge、session、迁移、通知投递、同步 item 等辅助表并入所属模块或列为系统活动,不单独宣称用户价值。 ### 2.2 模块组 | 模块组 | 主记录信号 | 人工活动信号 | 典型系统/辅助信号 | | --- | --- | --- | --- | | 工作台/通知 | notifications、announcements | 公告创建/签收、真人通知阅读 | 通知投递重试 | | 统一审批 | workflow_instances/tasks/history | 提交、审批完成、转交 | 超时提醒、自动撤权 | | 报销/票据/OCR | reimbursement_forms、invoice_pool | 真人提交、附件、财务处理 | OCR/验真 job | | 付款/AP | payment_batches/items/receipts | 创建、复核、执行、回单 | outbox/ERP skip | | 采购 | purchase_requests/items/attachments | 申请、提交、归档 | 通知与工作流辅助 | | 合同 | contract_registry、confidential refs | 创建、维护、终止/导出 | 到期类系统提示 | | 项目 | projects 及里程碑/任务/风险 | 负责人创建更新、成员活动 | 关联索引 | | 资产/盘点 | asset_cards、assignments、inventory_checks | 建档、领用、转移、盘点 | 批量导入 | | 请假/企微留存 | leave_requests、wecom_approval_* | OA/企微发起和真人审批 | callback、compensation、reconcile | | 考勤/团队状态 | attendance/presence、wecom_checkin_* | 真人修正、管理员校正 | 同步 run、日/月摘要 | | 周报/普通待办/公告 | weekly_reports、todo_items、portal_announcements | 提交、完成、创建/签收 | 自动待办/提醒 | | 预算 | budget_pools/ledger/rules | 预算维护与人工调整 | 阈值命中 | | 差旅 | travel_requests/orders/reconciliation | 申请、导入确认、支付 | 卡流水导入/ERP | | 人员生命周期 | employees、lifecycle/checklist、employee contracts/training/certs | 入离职和资料维护 | 企微 HR 同步 | | 薪资/绩效 | salary/payslip/performance_* | 生成、发放、评价 | 批处理生成 | | 系统候选 | feature flags、cutover、integration_* | 管理员明确操作 | 定时同步、迁移期任务 | 实施阶段把该逻辑展开为逐表 allowlist;每个 SQL 标识符必须来自审核后的静态清单,不接受运行时动态拼接。 ## 3. 数据采集合同 ### 3.1 生产身份 - 复用 `production-identity-bootstrap` 解析唯一 trialrun 目标,不把仓库占位符、其他数据库或本地容器当生产。 - 读取并记录实际运行镜像的完整/短 SHA 与 migration 摘要。比较对象是当前运行容器,不要求本地文档提交后的 `HEAD` 等于已部署应用 SHA。 - 不为本任务复制脚本到生产、不发布新候选、不修改远端部署输入。 ### 3.2 事务 审阅后的 task-scoped 查询通过 stdin 送入现有运行环境,不持久化在生产。核心事务合同为: ```sql BEGIN TRANSACTION READ ONLY; SET LOCAL statement_timeout = '30s'; SET LOCAL lock_timeout = '2s'; -- assert current_setting('transaction_read_only') = 'on' -- execute static allowlisted aggregate SELECTs COMMIT; ``` - 禁止 DDL、DML、`SELECT ... FOR UPDATE`、存储过程调用、临时表和动态 SQL。 - 聚合只用 `count`、`max`、条件计数和 `count(distinct ...)`;不返回原始业务行。 - 任一表不存在、字段不一致、超时或 JSON 输出不可解析,整体结果标记 `QUERY_FAILED`,不得把缺失值补成 0。 - 如果连接或输出通道不确定,先以只读证据定性;不得在未知状态下反复 SSH 执行。 ### 3.3 PRE/POST - PRE:生产 identity、运行 SHA、migration pending、数据库事务只读能力均明确。 - POST:事务成功提交、`transaction_read_only=on` 证据存在、输出仅含白名单字段;再次确认运行 SHA/migration 未被本任务改变。 - PRE/POST 间可能有真实用户并发新增记录。若重复只读校验数值变化,记为并发观察,不归因于普查,也不为了“稳定结果”暂停用户。 ## 4. 输出模型与隐私 每个模块只允许输出如下稳定字段: ```text moduleKey totalRows created30d / created90d activity30d / activity90d latestActivityAt humanActors30d / humanActors90d humanEvents30d / humanEvents90d smokeEvents30d / smokeEvents90d systemEvents30d / systemEvents90d unknownEvents30d / unknownEvents90d navigationMode effectiveFlagState queryStatus ``` 时间按生产数据库当前时间计算并统一输出 ISO 时间;最终文档可只保留日期粒度。禁止输出 employee id、姓名、员工编号、邮箱、手机号、IP、user agent、业务编号、金额、正文、附件路径、原始 `extra` 或 payload。 ### 4.1 smoke 识别 复用现有 helper 的 smoke-like 语义:已知 smoke 前缀、受控测试编号及“测试/试运行”标志。匹配只发生在生产事务内,外部只收到 `human/smoke/system/unknown` 聚合计数。规则命中不删除数据,也不改变账号状态。 ### 4.2 system 识别 系统活动由静态 action/表映射识别,例如同步 run、callback/compensation、通知投递、OCR/验真 job、ERP outbox/skip、逾期提醒和自动撤权。管理员手工触发的 job 可以同时具有真人触发者和系统结果;矩阵分别记录“真人触发”和“系统产物”,避免重复解释为两名用户。 ### 4.3 unknown 旧数据没有 actor、actor 已归档、action 语义混合或来源无法证明时进入 `unknown`。unknown 可以证明“存在数据”,不能证明真人持续使用。 ## 5. 有效导航与开关 - 导航以生产 `workspace_settings` 的模块可见性为准,缺记录时才回退当前应用默认配置。 - feature flag 的有效状态同时考虑运行环境 gate、数据库 override、rollout 类型和部门 allowlist;只输出 `on/off/partial/unknown`,不输出环境变量原值或部门标识。 - “隐藏但有真实使用”可能来自直达链接或管理员入口,是需要核实的发现;“显示但无人使用”才构成导航减法候选。 - flag 关闭只能解释当前不可用,不能证明数据无价值或可以物理退役。 ## 6. 分类算法 分类采用证据卡而非硬阈值自动打标。每张卡包含: ```text production usage + people/frequency + exposure + owner + failure cost + substitute historical recommendation + confidence => decision + rationale + trigger ``` 判定顺序: 1. 先看是否存在真实人工活动,而不是总行数; 2. 再看 30/90 天频率、实际 actor 数和最近活动; 3. 再应用小团队决策门,识别低频但必要能力; 4. 最后考虑当前入口是否造成认知负担,以及是否有企微/手工 SOP 等可靠替代; 5. 证据冲突或缺业务确认时,保守落入 `保持冻结` 并列出确认问题。 分类不会自动执行动作: | 分类 | 本任务产物 | 后续动作 | | --- | --- | --- | | 重点优化 | 最多两条真实问题候选 | 另建产品 task,先说明具体用户与问题 | | 保持冻结 | 保持可用、不扩建 | 事件触发或真实问题出现再评估 | | 隐藏入口 | 可逆显隐建议 | 另建 workspace/flag task 并批准生产变更 | | 候选退役 | 调研清单 | 另做数据导出、保留、依赖、回滚审查后再决定 | ## 7. 失败矩阵 | 失败 | 处理 | | --- | --- | | 生产 identity、SHA 或 migration 不明确 | 停止,不查询 | | 事务不是 read-only | 立即回滚并停止 | | allowlist 与 schema 不一致 | 标记合同失败,回本地修正,不推断使用度 | | 查询超时/通道中断/JSON 不可解析 | `QUERY_FAILED`;保留首个失败现场,不连续重跑 | | smoke/system 无法可靠区分 | 进入 unknown,不计入真人活动 | | 导航或 flag 有效状态无法计算 | 标记 unknown,不以代码默认代替生产事实 | | 数据显示零使用但业务必要性未确认 | 保持冻结,登记负责人确认项 | | 发现疑似真实业务缺陷 | 停止产品处置,另建缺陷 task;本任务只记录证据 | ## 8. 证据与复核 任务目录只保存查询合同、脱敏聚合快照、决策矩阵和执行摘要。生产连接信息、原始 SQL 输出、完整账号和 payload 不进入仓库、task 或对话。 由于结论会影响后续模块显隐和退役决策,执行后启动只读 reviewer,重点核对: - 实际查询是否严格等于 allowlist 和只读合同; - 人工/smoke/system/unknown 分桶是否有证据; - 零行、flag off、自动审计量是否被误用; - 四类结论是否符合小团队决策门; - 路线图是否把产品价值置于工具债之前; - 本任务是否未执行任何产品或生产变更。 ## 9. 回滚 本任务没有生产写入,因此没有数据回滚。若聚合、归因或分类错误,撤回相应结论并重新审阅查询合同即可。任何未来隐藏/退役动作的回滚由其独立 task 设计,本任务不预先授权。