22 KiB
22 KiB
CaiWuXiTong 团队通用规则
适用范围:本仓库所有成员、所有分支,以及使用 Codex 等 AI 编程工具完成的工作。
1. 核心原则
- 本项目是财务系统。金额、权限、审批、数据导入、数据库迁移和生产配置均属于高风险内容。
- AI 是协作工具,不是审批人。AI 生成的代码、命令和结论必须由提交人检查并完成实际验证。
- 不确定当前环境、分支、命令作用或数据范围时,停止操作并向负责人或 Codex 说明现场,不要猜。
- 一次只完成一个明确任务;不顺手重构、升级依赖或修改无关模块。
1.1 前端视觉规范
- 仓库根目录
DESIGN.md是本项目唯一正式视觉规范;.impeccable/design.json是供 Codex、设计工具和自动检查读取的同源机器规范。所有前端任务在分析或修改代码前必须先完整阅读DESIGN.md。 - 项目正式主题固定为 VIP 黑金:最左侧工具轨道使用深黑,功能导航栏使用稍浅的黑;深色区域使用浅金或米白文字,浅色内容区使用黑色正文和深金交互色。旧有紫色、靛蓝色和高饱和亮蓝色不得继续作为主题色扩散。
- 新增或修改页面必须复用全局设计令牌和共享组件,不得另写一套黑色、金色、字号、圆角、阴影或状态样式。成功、警告、错误、信息等语义色只用于对应状态,不得代替主题色。
- 页面标题、侧边栏层级、图标、标签页、表格、滚动条、加载状态、选中状态和局部导航行为均按
DESIGN.md执行;不得用整页刷新代替标签页或局部内容切换,也不得叠加两套选中标识。 - 截图、浏览器批注和
design-qa.md只属于验收证据或临时问题记录,不能覆盖正式视觉规范。需要改变视觉方向时,必须先得到项目负责人确认,并同步更新DESIGN.md与.impeccable/design.json,再修改业务页面。 - 前端 PR 必须说明是否符合
DESIGN.md、是否存在经批准的偏差,并用实际页面完成最小视觉与交互验证;“AI 已修改”或单看代码不能作为验收结果。
2. 分支与提交
main是稳定主线,默认禁止直接推送、禁止强推、禁止直接修改。项目负责人WuYongJie,以及得到其明确授权的 Codex,可以直接合并 PR 或直接推送main;任何身份仍禁止强推。- 每次开工必须先核对当前目录、远程仓库、Git 身份和当前分支:项目目录必须是
CaiWuXiTong,origin必须指向WuYongJie/CaiWuXiTong,分支用户名必须属于当前任务的实际开发者。发现其他项目名、其他项目开发者名或无法解释的旧分支时立即停止,不得继续提交。 - 每项任务都必须从最新
main新建分支;不得长期共用或复用旧任务分支。 - 分支命名:新功能用
feature/用户名-任务名,修复用fix/用户名-问题名,紧急修复用hotfix/用户名-问题名。 - 示例:
feature/dodo-login、fix/wangshu-amount-rounding。 - 一个分支只做一个任务。任务完成并合并后,删除本地和远程任务分支;任何人不得在已合并分支继续提交,下一项任务必须重新从最新
main新建。 - AI 开工前必须执行并核对
git rev-parse --show-toplevel、git status --short --branch、git remote get-url origin和git config user.name。分支名与实际任务负责人不一致时,AI 必须先报告现场,不得自行沿用该分支。 - 提交前必须查看
git status和git diff,确认没有把别人的改动、日志、构建产物、.env或敏感文件带进去。 - 禁止使用
git push --force、git reset --hard、git clean -fd,除非负责人明确给出目标和操作步骤。
3. 新人使用 AI 的固定流程
- 先确认任务目标、验收方式、影响范围和不能触碰的模块。
- 进入正确项目和分支,先执行
git status;看到陌生改动,先停止并说明情况。 - 向 AI 提供:任务目标、当前分支、报错或现象、相关文件、不可修改的范围。
- 要求 AI 先说明改动计划、涉及文件、风险和验证步骤;确认后再修改。
- 修改后查看 diff,并要求 AI 用普通语言解释“改了什么、为什么、怎样测试”。
- 在本地或测试环境完成最小有效验证,记录实际结果。
- 推送任务分支并发起 PR;新人不得自行绕过 PR 合并到
main。项目负责人和其明确授权的 Codex 按上面的例外执行。
推荐向 AI 提问的模板:
项目:CaiWuXiTong(Laravel/PHP 财务系统)。
任务:<要实现的功能或要修复的问题>。
当前分支:<分支名>。
现场:<报错、复现步骤、相关文件>。
边界:不要修改 <模块/表/配置>;不要执行删除、部署、生产数据库操作。
要求:先列出改动计划、风险和验证步骤,等我确认后再改。
4. PR 与合并
- 新人和普通协作者的任务分支必须通过 PR 合并到
main;项目负责人和其明确授权的 Codex 可以作为例外直接合并或推送。 - PR 作者必须填写:做了什么、Codex 改了哪些文件、怎样测试、是否涉及金额/权限/数据库/配置。
- 新人提交的 PR 至少由另一位成员检查后才能批准;作者不得把“AI 已完成”当作测试结果。项目负责人和其明确授权的 Codex 不受这条审核人数限制,但仍必须完成实际验证并如实记录结果。
- 涉及金额计算、权限、导入、数据库迁移、账户或系统配置时,必须在 PR 中明确标注,并由负责人最终确认。
- 使用仓库默认的 Squash merge(压缩合并)。合并由负责人或指定合并人执行。
- PR 合并后分支自动删除;不要把已合并分支继续用于新任务。
5. 测试与问题处理
- 修改完成不等于可用。至少验证正常流程、错误输入/无权限场景和本次改动影响的旧功能。
- 出现冲突、测试失败或 PR 显示落后
main时,不要自行猜命令。先让 AI 只分析同步方案,禁止强推和 rebase;必要时找负责人处理。 - 提交问题时必须写清:环境、账号角色、复现步骤、实际结果、期望结果和报错截图/日志(脱敏后)。
6. 数据与安全红线
- 不得提交
.env、密码、Token、SSH 私钥、数据库连接串、真实财务数据、客户数据或生产日志。 - 不得把上述内容粘贴到 AI 对话、工单、PR、聊天群或截图中。
- 不得在不确认环境和影响范围时执行数据库写入、迁移、删除、导入、部署或服务器命令。
- 任何包含金额、账户、登录凭据、权限或数据库连接的信息都按敏感数据处理。
- 发现误提交、泄露或错误操作,立即告知负责人;不要自行删除记录掩盖问题。
7. 本仓库的最小验证要求
- 前端改动:至少检查目标页面、正常交互和错误提示。
- 后端改动:至少执行相关测试或启动后走一次目标接口/页面。
- 数据库迁移:新人不得自行在共享环境执行;先在 PR 说明影响、验证方式和回滚思路。
- 未完成验证时,PR 必须明确写“未验证”及原因,不能写“应该没问题”。
8. 固定构建与部署规则
8.1 职责边界
- 项目负责人只负责产品方向、验收标准和高风险授权,不负责日常构建、上传、部署命令和服务器维护操作。
- 新人负责描述任务、检查结果和发起 PR;Codex 负责按本节流程完成环境检查、构建、部署、验证和收口,不得把一串命令丢给项目负责人执行。
- 正式发布只允许使用已合并的
main。非main只能用于明确授权的测试发布。 - 生产数据库迁移、数据修复、删除、覆盖配置等高风险动作,仍需项目负责人明确授权。
8.2 服务器红线
- 当前服务器只有 2GB 内存,只负责运行容器、健康检查和镜像切换。
- 严禁在服务器执行
docker build、docker compose build、npm install、npm run production、composer install或其他源码构建命令。 compose.jiangling.yml不得出现build:;服务器只能运行开发机已经构建并上传的caiwu_akaunting:<commit>镜像。- 生产访问地址固定为
https://118.196.84.79(不附加端口);宿主机 Nginx 监听80/443,HTTP 自动跳转 HTTPS,应用容器仅绑定127.0.0.1:18088。 - HTTPS 使用 Let’s Encrypt 短期 IP 证书,服务器定时器每 8 小时检查续期;证书、私钥和 ACME 账户不得进入 Git 或应用镜像。
mariadb:11.4运行镜像由开发机缓存并仅随首次初始化全量包上传,服务器不得在发布时临时访问 Docker Hub。- 日常发布必须通过只监听
127.0.0.1的服务器本机 Registry 和 SSH 隧道传输,仅上传 Registry 中不存在的镜像层;禁止每次上传完整docker save压缩包。 - 日常增量包必须由 BuildKit 直接导出 OCI 分层格式;禁止用
docker save作为日常增量源,因为其未压缩层在重复导入时会产生不同压缩摘要、破坏跨版本层复用。 - 服务器保留当前镜像和上一个可回滚镜像,其他本项目旧镜像在发布成功后清理。
- 服务器发布必须使用互斥锁;同一时间只允许一个人切换版本,禁止并发覆盖。
8.3 开发机固定流程
- Windows 开发机统一使用
scripts/deploy-from-workstation.ps1,不得手工拼接构建、打包、上传和启动命令。 - 镜像标签使用 Git 提交 SHA;工作区有未提交的受控文件时,脚本必须拒绝发布。
- 使用项目专属 BuildKit 构建器
caiwu-builder。禁止日常使用--no-cache、--pull或删除全部 Docker 数据。 - Dockerfile 必须先复制锁文件再安装依赖:只有
composer.lock、package-lock.json或基础镜像定义变化时,才允许对应依赖层失效。 - 前端资源必须由开发机宿主系统运行
scripts/build-frontend.ps1构建;脚本固定并复用项目专用 Node 20,不得在 Docker 虚拟机或服务器内执行前端打包。 - 基础镜像、Composer 下载缓存、npm 下载缓存和未变化的构建层应直接复用,不得每次全量下载。
-BootstrapServer仅用于新服务器首次全量初始化;已有服务器的日常发布自动走增量镜像层传输。-ConfigureHttps仅用于首次配置或修复宿主机 Nginx、IP 证书和自动续期;日常发布不得重复添加。
8.4 磁盘和缓存上限
- Docker Desktop 虚拟磁盘上限建议设为 60GB;宿主机至少保留 15GB 可用空间。前端打包使用宿主机内存,不要求为了本项目调高 Docker 虚拟机内存。
- 发布脚本使用独立缓存并将 BuildKit 缓存控制在 3GB 内,只清理 7 天前的本项目缓存。
- 前端 Node 堆内存默认上限为 4GB,JavaScript 压缩默认最多使用 2 个工作线程;不得为了追求构建速度取消限制。
package-lock.json和 Node 版本未变化时复用node_modules;页面模板变化只重建 Tailwind CSS,只有 JavaScript 源码或依赖变化才重新打包 JavaScript。- 开发机、服务器 Docker 和服务器本机 Registry 默认各保留 2 个本项目版本;上传用临时
image.tar无论成功失败都必须删除。 - 禁止脚本自动执行全局
docker system prune -a、删除其他项目镜像、删除卷或重置 Docker Desktop。 - Docker 虚拟磁盘文件不会因为普通清理立即缩小;日常目标是控制已用空间不再增长,不得让新人自行删除或重建虚拟磁盘。
8.5 发布安全与验收
- SSH 私钥、
runtime/.env、镜像临时包、数据库密码不得进入 Git 或 Docker 构建上下文。 - 首次服务器初始化由脚本生成数据库密码和
APP_KEY,不在终端、聊天或文档中输出。 - 数据库迁移默认关闭;检测到新增迁移时发布必须停止,获得负责人授权后才可显式开启。
- 新镜像必须先通过本机后端健康检查,再通过公网 HTTPS 页面验收;失败时自动恢复上一个镜像,并保留日志用于排查。
- 发布完成必须报告:分支、提交 SHA、镜像标签、服务器容器状态、真实页面结果、是否执行迁移、清理结果。
- 容器内所有
php artisan、初始化、测试和后台刷新命令必须以www-data运行;手工命令统一使用docker compose exec -u www-data ...或docker exec -u www-data ...。禁止默认root执行后在storage、bootstrap/cache或.env留下网页进程不可写的文件。入口脚本启动时必须修复旧属主,app:ready必须以www-data验证数据库连接和运行目录写权限,不得把角色或权限映射作为容器健康条件。
8.6 上游数据库读取规则
- 本系统按 3 个以上上游来源设计;来源统一登记在
config/upstreams.php,每个来源必须拥有独立配置、适配器、缓存命名空间、并发预算、熔断状态和后台刷新任务。一个来源故障不得清空或阻塞其他来源的快照。 - 上游是长期运行且不可修改的旧系统,统一按只读黑盒处理;不得要求修改其账号、表结构、索引、字段或启用 Change Tracking 等功能。
- 本地开发环境(
APP_ENV=local)直接执行UpstreamQueryCacheresolver 中已经写入代码的只读查询,不等待生产刷新节点、共享快照或allowed_scopes。两套连接资料仍从共享系统数据库自动解析,开发者只填写一次系统数据库密码,不再配置上游环境变量。 - 生产环境(
APP_ENV=production)继续通过UpstreamQueryCache读取持久化在共享系统数据库upstream_query_cache中的按需查询快照;页面冷查询只登记需求,首份数据和后续刷新由upstream:snapshots:refresh-all生成。 - 两套上游的表、视图和字段结构由命令
upstream:schema:sync低频读取INFORMATION_SCHEMA,保存到共享系统数据库upstream_schema_columns。任何能够直连的开发环境或生产刷新节点都可以生成目录;同步失败必须保留最近一次完整目录。 - 新来源适配器必须通过
UpstreamReadOnlyQuery执行固定、参数化的只读查询,禁止把原始 PDO 连接暴露给控制器或页面。即使现有数据库账号本身有写权限,应用代码也不得执行写入、高风险语句或存储过程。 - 系统数据库只保存活跃查询登记、参数、访问范围和共享结果,不执行 SQL。禁止把任意 SQL、DSN 或凭据写入任务表让后台解释执行;生产后台进程只能运行已经合并到
main并在UpstreamSnapshotRefresher中登记的固定查询代码。 - 开发者需要尚未缓存的新表或字段时,必须在任务说明和 PR 中列出来源标识、业务目的、表/视图、字段、筛选与排序、最大返回量、公司/权限范围、缓存时间和失败表现;未说明边界的“把整张表接进来”不得合并。
- 新查询在任务分支中必须同时完成 Repository/适配器、稳定
scope、UpstreamQueryCache调用、对应刷新器映射和测试。自动测试使用脱敏 fixture 或测试替身;能够直连的开发机可执行少量真实只读验收,但不得输出凭据、敏感业务行或提交本机覆盖配置。 - 新查询在本地开发环境可以直接读取验证,不需要先开放
allowed_scopes。合并并部署到生产前,仍需登记刷新器和生产精确范围,生产页面继续复用共享快照。 - 快照复用按“来源 + 数据范围 + 查询条件 + 公司/权限范围”判断,与账户数量和开发机数量无关;权限或数据范围不同的结果不得错误共用。
- 生产列表和汇总快照默认 2 分钟,选项类数据默认 60 分钟。生产页面命中过期快照时立即返回共享旧值并排入后台刷新。
- 生产相同查询使用共享系统数据库中的独立单飞锁;每个来源的不同冷查询默认最多占用 2 个上游槽位、每分钟最多 6 个查询组、每轮最多刷新 2 个近期活跃查询。上述限制不作用于本地开发直连。
- 生产刷新必须设置连接超时、查询超时、慢查询冷却和连接失败熔断;本地开发直连只保留连接与查询超时,错误立即脱敏返回,不进入共享冷却。
- 上游 API 必须保留
X-Caiwu-Data-Status和X-Caiwu-Data-Synced-At响应头;验收同时检查数据状态和同步时间,不能只看 HTTP 200。 - 每个来源的连接开关统一保存在系统数据库。
allowed_scopes只控制生产快照刷新,不阻挡本地开发直连;生产范围仍需使用精确前缀,禁止用*放开核心大表。 - 跨来源报表不得在页面请求中实时连接多个上游做 JOIN;需要组合的数据先分别受控读取并物化到共享标准表或查询快照,再从共享数据生成报表。物化记录必须保留来源标识、上游业务键和同步时间,金额仍以本地财务规则校验。
- 当前方案是近实时查询快照,不得冒充完整行级增量复制。没有可靠变更标记时,禁止定时全表扫描;历史一致性只能采用低频、小批量、可中止的核对。
- 首次全量历史数据同步必须单独评估行数、时间窗口和上游低峰期,不得在日常发布时自动执行。
- 生产服务器不能直接访问某个上游时,只允许通过专用低权限 SSH 账户建立受限反向隧道;每个来源使用独立
SourceKey、私有配置、计划任务和 Docker 私网端口,禁止监听公网地址,隧道账户禁止 Shell、TTY、本地转发和任意端口转发。 - 隧道由
scripts/keep-upstream-tunnel.ps1自动重连,并通过scripts/install-upstream-tunnel-task.ps1 -SourceKey <来源标识>安装。数据库凭据不得作为隧道参数;每台候选中继开发机使用独立 SSH 私钥,不得多人共享私钥。 - 每个来源最多安排 1 台主中继和 1 台备用中继;同一来源同一时刻只允许一个远端监听成功,备用机低频重试。隧道中断时页面继续读取该来源旧快照,禁止绕过缓存直接重试上游。
- 系统数据库的启动连接只允许存在于服务器私有
runtime/.env;超级管理员和普通管理员可在“数据库管理”中连接。新人接入只验证密码能够解锁固定资料、数据库能够连接、TLS 已自动建立且基础系统表存在,并在持久化storage中生成私有备份。迁移版本、管理员权限映射、公司映射和云数据库配置不再作为切换前置条件;super_admin和admin角色不受缺失的权限关联表记录阻塞。 - 云数据库连接与系统数据库配置必须分开。显式开启
UPSTREAM_STORED_CONFIG_ENABLED后,云数据库密码在system_database_connections中同时保留旧版APP_KEY密文用于紧急回滚,并使用系统数据库登录密码派生的密钥写入shared_password供受信任开发机共享;真实值仍不得进入代码、提交、PR、共享文档或日志。系统数据库固定主机、端口、库名和账号以密文团队资料保存在代码中,不含数据库密码;新人页面只允许填写系统数据库密码,由它解锁固定资料并自动启用 TLS。禁止恢复主机、端口、账号、TLS、证书或 CA 路径等新人表单。系统数据库密码轮换前必须先完成共享云数据库密文重加密、数据库备份和团队连接资料密文更新。只有隔离排错或尚未迁移的旧环境才允许显式开启本机覆盖,并通过私有DB_<来源>_*环境变量提供完整连接。中继开发机只保留已收紧 ACL 的隧道端点配置,不保存数据库密码。 - 本地开发的标准入口只有“系统设置 → 数据库管理 → 系统数据库”。开发者只填写并验证同一套系统数据库密码,其他连接参数由项目自动设置;成功后系统用户、侧边栏、系统设置和云数据库登记必须继续使用该系统数据库。不得再把主业务连接的
DB_HOST改回本机 MySQL 容器,否则会形成一套互不相干的本地数据,导致用户、配置、来源映射和业务结果与团队不一致。 - 两个现有来源的标识和数据库映射固定为:
jiansun对应JianSun旧业务库,operations_replica对应JSReportReplica的rpt只读视图。不得把shujuku、本机测试库名或历史截图中的临时名称写回共享记录,也不得交换两个来源的账号或数据库名。 - 开发者拉取包含本规则的最新代码后,必须确保
docker-compose.local.yml已挂载./modules:/var/www/html/modules,并至少重建一次应用容器、清除 Laravel 配置缓存。禁止只重启旧镜像后根据旧模块结果判断共享配置无效。 - 本机临时引导库的新增迁移由
deploy/local-init.sh和新版容器入口自动补齐;该逻辑只允许在SYSTEM_DATABASE_MODE=bootstrap、MySQL 驱动且主机为固定容器服务名mysql时运行。连接共享系统数据库后必须自动跳过,普通开发者不需要也不得自行执行php artisan migrate;看到本机迁移Pending时应重新运行标准初始化脚本,而不是操作共享数据库。 - Codex 排查开发机连接时,必须先确认当前主业务库仍是共享系统数据库,再确认
UPSTREAM_STORED_CONFIG_ENABLED=true、UPSTREAM_LOCAL_CONFIG_ENABLED=false,随后通过UpstreamSourceRegistry验证完整连接来自system_database_connections。不得通过填写本机DB_JIANSUN_*、DB_OPERATIONS_REPLICA_*、复制他人.env或统一APP_KEY来掩盖共享配置读取错误。 - 系统数据库统一保存应用数据、云数据库配置、上游数据字典和生产共享快照,但不是 SQL Server 网络代理。本地开发应用直接使用系统数据库中的连接资料访问两套上游;前提是该开发机网络本身能够到达数据库端点。
- 开发验收分别验证两套来源的共享配置解析、
SELECT 1和至少一个真实只读查询;生产验收还需验证共享快照。所有输出不得包含地址、账号、密码或完整 DSN。页面和 Repository 仍必须通过UpstreamReadOnlyQuery执行固定、参数化的SELECT,禁止写操作和任意 SQL 输入。
详细 SOP 见 docs/开发与部署SOP.md。