Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 27 additions & 9 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,51 @@ hotsrm 是基于 [ObjectStack](https://github.com/objectstack-ai/objectstack)
管理(SRM)应用,由三层组成:

- **通用核心**:设计在 `docs/design/`,源码在 `src/core/`(`type: app`);
- **行业扩展包**:设计在 `docs/packs/`,源码在 `src/bulk/`、`src/hazmat/`、`src/soe/`
(`type: module`),构建时与核心合成一个应用([ADR-0002](./docs/adr/0002-packs-composed-into-one-app.md));
- **客户配置**:参数取值、组织、物资目录、样式等,放在客户的私有仓库,**不进本仓库**。
- **行业扩展包**:设计在 `docs/packs/`,源码将放在 `src/bulk/`、`src/hazmat/`、`src/soe/`
(`type: module`),构建时与核心合成一个应用([ADR-0002](./docs/adr/0002-packs-composed-into-one-app.md))。
**现阶段只做核心包**,三个扩展包保留为设计、未排期([ADR-0009](./docs/adr/0009-core-first-pack-criteria-and-customer-layer.md));
- **客户配置**:参数取值、组织、物资目录、样式、Studio 覆盖层、客户私有包,放在客户的
私有仓库和客户环境,**不进本仓库**(ADR-0009)。

核心做什么、不做什么:供应商生命周期、合同、质量、绩效、风险、门户、寻源在核心;
采购订单、收货、对账、发票、付款留在 ERP,SRM 只记结论、不记过程
([ADR-0008](./docs/adr/0008-order-to-pay-stays-in-erp.md))。路线:内部核心 → 门户 → 寻源,
见 [docs/design/07](./docs/design/07-delivery-plan.md)。

文档地图见 [docs/README.md](./docs/README.md),关键决定见 [docs/adr/](./docs/adr/README.md)。

## 2. 红线(违反即退回)

1. **只用元数据**([ADR-0001](./docs/adr/0001-declarative-only.md)):业务规则不得依赖生命周期
钩子、插件或服务端函数。托管云不执行应用包代码,依赖它们的规则会静默失效。
钩子、插件或服务端函数。平台本身有沙箱钩子,但本仓库不用:托管云可以关闭应用包
代码,依赖它们的规则会静默失效。例外只能按包写新的 ADR。
2. **供应商之间零可见**([ADR-0003](./docs/adr/0003-portal-isolation-by-supplier-position.md)):
- 新增面向供应商的顶层对象,必须同时有 `portal_position` 字段、前缀校验规则、门户 RLS
和隔离测试;
- 内部权限集一律不设 `isDefault`;
- 不得删除或跳过隔离测试。
3. **封标**([ADR-0004](./docs/adr/0004-sealed-bid.md)):任何能读到报价的权限集、报表、视图
都必须受 `bid_opened == true` 约束;不得给任何角色报价对象的全量读取权限。
4. **扩展包不改核心**:扩展包只能用 `objectExtensions`、`picklistExtensions`、导航贡献三种
方式接入核心,不修改 `src/core/` 下的文件;扩展包之间不互相引用,联动放
`src/bridges/<A>-<B>/`。
4. **扩展包不改核心**([ADR-0009](./docs/adr/0009-core-first-pack-criteria-and-customer-layer.md)):
扩展包只能用 `objectExtensions`、`picklistExtensions`、导航贡献三种方式接入核心,不修改
`src/core/` 下的文件;包主要新增自己的对象并用 `lookup` 关联核心,对核心对象的
`objectExtensions` 每包不超过 2–3 个字段;扩展包之间不互相引用,桥接模块现阶段不做。
新包必须满足准入标准(受法规约束 / 三家以上复用 / 保护测试资产)之一才立项。
5. **不写客户信息**:本仓库是公开仓库。不写客户名称,也不写能认出客户的组合(某客户的
物料清单、组织形态、合同条款);参数只用标明「示例」的行业常见值。
6. **不提交密钥**:连接串、令牌、密码、证书私钥一律不进仓库、提交信息、PR 和文档。
7. **核心 API 名冻结**(ADR-0009):对象名、字段名、字段类型一旦合入主干不再改;改必须附
ADR,门槛 2(v0.7 结束)之后还要附迁移说明。客户个性化放客户层,核心字段只能隐藏,
不能删除。

## 3. 元数据约定

- `@objectstack/spec` 是唯一契约。元数据跑不通时改元数据,不去放宽运行时;不确定某个
写法是否合法时,查框架源码中的规范定义,不要猜。
- 命名:核心对象 `srm_*`;扩展包对象 `srm_bulk_*`、`srm_hz_*`、`srm_soe_*`;字段名和选项值
用 snake_case,不以数字开头。
用 snake_case,不以数字开头;字段名不含 `role`(平台保留词,联系人角色叫 `contact_function`)。
- 字段谓词(`requiredWhen`、`readonlyWhen`、`visibleWhen`)只能读本记录;关联记录只在
`script` 校验规则里经一跳读取。其余建模规则见 [docs/engineering/](./docs/engineering/README.md)。
- 建模原则见[核心 02 §1](./docs/design/02-domain-model.md#1-建模原则),要点:
- 状态是主对象上的 `select` 字段,作为 `stageField`,每个选项带 `kind`;
`state_machine` 校验同时声明 `transitions` 和 `initialStates`;
Expand All @@ -56,7 +71,10 @@ hotsrm 是基于 [ObjectStack](https://github.com/objectstack-ai/objectstack)

- 正文用简体中文,机器名用英文。
- 先改设计再改元数据:行为变化先更新 `docs/design/` 或 `docs/packs/` 的对应章节,再改源码。
- 新的关键决定写 ADR;改变已有决定时写新的 ADR 取代旧的,不改写旧记录的「决定」部分。
- 新的关键决定写 ADR;改变已有决定时写新的 ADR 取代旧的,不改写旧记录的「决定」部分;
「待验证」有结论后在该条下追加「结果(日期)」。
- 版本出口时同步 `docs/design/07` 的路线表和根 README 的对象数;模板里不写死会进系统的
数字,一律引用 `params/`。
- `docs/reference/` 由脚本从元数据生成,禁止手改。
- 体系文件条款与系统控制点同步修改:改了一边,检查另一边([ADR-0005](./docs/adr/0005-governance-and-system-share-parameters.md))。
- 体系文件模板只写通用表述,不写【待确认】和任何客户信息;客户的取值、标注和专属段落放
Expand Down
55 changes: 35 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@

基于 [ObjectStack](https://github.com/objectstack-ai/objectstack) 的通用供应商关系管理(SRM)应用。

hotsrm 管企业**与供应商协同**的那一半:供应商全生命周期、寻源定价、合同、订单与送货协同、
质量整改、绩效、对账开票、风险,以及面向供应商的门户。物料、库存、应付凭证和付款仍由
ERP 记账,hotsrm 不做第二套账。
hotsrm 管企业**与供应商协同**的那一半:供应商全生命周期、合同、质量整改、绩效、风险、
寻源定价,以及面向供应商的门户。采购订单、收货、对账、发票、付款留在 ERP,hotsrm 只记
结论、不做第二套账([ADR-0008](./docs/adr/0008-order-to-pay-stays-in-erp.md))。

## 三层结构

| 层 | 内容 | 设计 | 源码 |
|---|---|---|---|
| 通用核心 | 所有企业都需要的功能与管理制度 | [`docs/design/`](./docs/design/README.md) | `src/core/`(`type: app`) |
| 行业扩展包 | 同类企业共有的做法,按需组合:[大宗物料包](./docs/packs/bulk-materials.md)、[危化品包](./docs/packs/hazmat.md)、[国企采购合规包](./docs/packs/soe-procurement.md) | [`docs/packs/`](./docs/packs/README.md) | `src/bulk/`、`src/hazmat/`、`src/soe/`(`type: module`) |
| 客户配置 | 某个客户的参数取值、组织结构、物资目录、审批权限、文件样式 | — | 客户的私有仓库,不在本仓库 |
| 行业扩展包 | 同类企业共有的做法,按需组合:[大宗物料包](./docs/packs/bulk-materials.md)、[危化品包](./docs/packs/hazmat.md)、[国企采购合规包](./docs/packs/soe-procurement.md)。**设计保留,未排期**([ADR-0009](./docs/adr/0009-core-first-pack-criteria-and-customer-layer.md)) | [`docs/packs/`](./docs/packs/README.md) | 将来放 `src/bulk/`、`src/hazmat/`、`src/soe/`(`type: module`) |
| 客户配置 | 某个客户的参数取值、组织结构、物资目录、审批权限、文件样式、Studio 覆盖层、客户私有包 | — | 客户的私有仓库与客户环境,不在本仓库 |

客户需求按「通用核心 → 扩展包 → 参数 → 定制」的顺序归位,定制尽量少(见
[扩展包总览](./docs/packs/README.md#1-三层结构))。
客户需求按「通用核心 → 扩展包 → 参数 → 定制」的顺序归位;现阶段只做核心包,客户个性化
放客户层,核心 API 名冻结(见 [扩展包总览](./docs/packs/README.md#1-三层结构) 与 ADR-0009)。

## 扩展包怎么组合与安装

Expand All @@ -27,8 +27,8 @@ ObjectStack 中客户能安装的只有应用(`type: app`)。扩展包是模
| 标准版 | 核心 | 本仓库 | 公开应用市场 |
| 客户版 | 核心 + 客户选定的扩展包 + 客户初始化数据 | 客户的私有仓库 | 只发布到该客户的组织 |

扩展包只通过对象扩展、选项列表扩展和导航贡献接入核心,不修改核心;两个扩展包之间的
联动放在桥接模块里。客户后来要加扩展包,发布同一个应用的新版本并升级即可(见
扩展包只通过对象扩展、选项列表扩展和导航贡献接入核心,不修改核心;桥接模块等第二个
包出现再做。客户后来要加扩展包,发布同一个应用的新版本并升级即可(见
[扩展包总览 §3](./docs/packs/README.md#3-扩展包怎么组合与安装))。

## 管理制度与系统同源
Expand All @@ -42,6 +42,8 @@ hotsrm 附带一套供应商管理体系文件模板(程序文件、管理办

- **只用元数据实现**:对象、校验规则、行级权限、flow、审批全部用平台元数据表达,在托管云
上无需应用代码即可运行([ADR-0001](./docs/adr/0001-declarative-only.md))。
- **记结论、不记过程**:订单到付款留在 ERP,SRM 用导入的交付记录算绩效,预留集成点
([ADR-0008](./docs/adr/0008-order-to-pay-stays-in-erp.md))。
- **供应商之间零可见**:门户按供应商隔离,取不到隔离依据时一行也不放行
([ADR-0003](./docs/adr/0003-portal-isolation-by-supplier-position.md))。
- **封标**:开标前,内部任何角色(包括 AI 助手)都读不到报价
Expand All @@ -57,17 +59,17 @@ hotsrm/
├── CLAUDE.md 指向 AGENTS.md
├── docs/ 文档,地图见 docs/README.md
│ ├── design/ 核心设计
│ ├── packs/ 扩展包设计
│ ├── packs/ 扩展包设计(设计保留,未排期)
│ ├── engineering/ 建模规范、CI 门禁、测试与版本策略
│ └── adr/ 决策记录
├── governance/ 体系文件模板与生成脚本
├── params/ 参数定义与示例默认值(制度与系统共用)
├── src/
│ ├── core/ 核心(type: app)
│ ├── bulk/ hazmat/ soe/ 三个扩展包(type: module) 〔待建〕
│ └── bridges/ 扩展包之间的联动(type: module) 〔待建〕
├── test/ 启动测试;门户隔离、封标、组合构建、flow 测试随功能补齐
├── objectstack.composition.ts 按开关选出要组合的模块
├── objectstack.config.ts 合成一个发布制品
│ └── core/ 核心(type: app);v0.1 已合入(PR #5)
│ (扩展包 bulk/ hazmat/ soe/ 与桥接模块等有客户要求时再建,ADR-0009)
├── test/ 启动测试与 flow 测试;门户隔离(v0.6 起)、封标(v0.7 起)
├── objectstack.composition.ts 按开关选出要组合的模块(现只有核心)
├── objectstack.config.ts 发布制品
└── objectstack.manifest.json 标准版的应用标识(市场展示信息)
```

Expand All @@ -86,7 +88,20 @@ pnpm validate # 每次改元数据后跑;其余检查见 AGENTS.md §6

## 当前状态

v0.1 开发中:工程骨架、CI 和核心应用外壳(`srm_workbench` 工作台、采购品类)已就位。
建议的 v0.1 范围是内部工作台上的供应商主数据、准入审批和资质到期预警,门户、寻源和 ERP 集成
放在后续版本。设计文档目录见 [docs/README.md](./docs/README.md);参与开发前先读
[AGENTS.md](./AGENTS.md)。
2026-10-23:范围与路线重定(ADR-0008、ADR-0009)。核心收到 **27 个对象**,按版本交付:

| 版本 | 内容 | 累计对象 |
|---|---|---|
| v0.1(已合入,PR #5) | 内部工作台:主数据、两级准入审批、资质到期扫描 | 7 |
| v0.2 | 物料只读副本、银行账户、存量导入、信息变更单 | 10 |
| v0.3 | 合同与协议、供应商处置 | 13 |
| v0.4 | 交付记录导入、质量问题 / SCAR、供应商审核 | 16 |
| v0.5 | 绩效、风险事件、管理报表 = 内部版 MVP,试运行 | 20 |
| v0.6 | 供应商门户(依赖 objectstack#25233) | 21 |
| v0.7 | 寻源与封标、价格库;核心对象冻结 | 27 |

已完成:核心设计、三个扩展包设计(保留)、ADR-0001~0009、参数文件首版、体系文件生成脚本
和 12 份模板、v0.1 内部工作台(PR #5)。文档目录见 [docs/README.md](./docs/README.md);
参与开发前先读 [AGENTS.md](./AGENTS.md)。

下一步:v0.2 主数据补齐——物料只读副本、银行账户、存量导入、信息变更单([07 §1](./docs/design/07-delivery-plan.md#1-分期路线图))。
10 changes: 5 additions & 5 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@

| 目录 / 文件 | 内容 | 读者 |
|---|---|---|
| [design/](./design/README.md) | 核心设计:需求、领域模型、流程与自动化、权限与门户、界面与分析、集成与 AI、交付计划 | 产品、开发、实施 |
| [packs/](./packs/README.md) | 行业扩展包:大宗物料包、危化品包、国企采购合规包,以及扩展包的组合与接入方式 | 产品、开发、实施 |
| [design/](./design/README.md) | 核心设计:需求、领域模型、流程与自动化、权限与门户、界面与分析、预留集成点与 AI、交付计划 | 产品、开发、实施 |
| [packs/](./packs/README.md) | 行业扩展包(设计保留,未排期):大宗物料包、危化品包、国企采购合规包,以及扩展包的组合与接入方式 | 产品、开发、实施 |
| [engineering/](./engineering/README.md) | 建模规范、分支与 PR、CI 门禁、测试策略、版本与升级 | 开发者、AI agent |
| [adr/](./adr/README.md) | 决策记录 | 全体 |
| [../governance/](../governance/README.md) | 体系文件(管理制度)模板的结构、参数与生成方式 | 实施顾问、客户体系工程师 |
| [../AGENTS.md](../AGENTS.md) | 开发规则与红线 | 开发者、AI agent |
Expand All @@ -15,9 +16,8 @@
| 目录 | 内容 | 时机 |
|---|---|---|
| `requirements/` | 需求记录 `NNNN-*.md`:客户需求提炼成通用表述后登记,写明落在核心、扩展包还是参数 | 收到第一个新需求时 |
| `engineering/` | 元数据建模规范、测试策略、版本与升级策略 | 开始写代码前 |
| `integration/` | ERP 等外部系统的接口规格,每个数据流一份(I1–I15) | 第一期开发前(先写 I1–I6) |
| `implementation/` | 实施手册、数据导入模板、上线检查清单 | 第一个客户项目启动时 |
| `integration/` | ERP 等外部系统的接口规格,每个数据流一份(I1–I15) | ERP 集成立项时([ADR-0008](./adr/0008-order-to-pay-stays-in-erp.md)) |
| `implementation/` | 实施手册(含客户层四种定制方式的边界)、数据导入模板、上线检查清单 | v0.5 试运行前 |
| `reference/` | 由元数据自动生成的对象、字段、选项、权限清单(禁止手改) | 有代码之后 |
| `../content/docs/` | 对外的产品文档、用户手册、供应商操作指南 | 临近上线 |

Expand Down
13 changes: 13 additions & 0 deletions docs/adr/0001-declarative-only.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,16 @@ hotsrm 的所有业务规则都用元数据表达,不依赖任何应用代码
- 一些规则要换一种写法:冗余判断依据到本记录再校验、用 screen flow 做受控写入口、
用追赶式扫描代替精确定时(见[核心 03 §2](../design/03-processes-and-automation.md#2-平台机制与本设计的用法))。
- 代码评审时,任何新增的钩子、插件或函数都要说明它为什么不是业务规则的唯一保障。

## 补充说明(2026-10-23)

- 平台本身支持应用代码:钩子在 QuickJS 沙箱里运行,默认 CPU 预算 250 毫秒(动作 5 秒),
嵌套的跨对象写入加入同一事务(objectstack ADR-0034、0102、0119);记录变更型 flow
则不能否决触发它的写入(ADR-0077)。所以「纯元数据」是本仓库自己的选择,不是平台
的限制:理由仍是托管云与自托管行为一致、规则不会静默失效。
- 「托管云不执行应用包代码」对应运行时开关 `OS_DISABLE_AUTHORED_HOOKS` /
`OS_DISABLE_AUTHORED_ACTIONS`;「安装时提示」来自实测而非平台文档,上生产前在目标
环境再验证一次(07 §6 V7)。
- 核心 27 个对象([ADR-0008](./0008-order-to-pay-stays-in-erp.md))没有一个需要钩子。
将来某个扩展包出现「一起成功或一起失败」的跨对象动作时,按包写新的 ADR 给本记录
加例外,不在本记录里放宽。
10 changes: 10 additions & 0 deletions docs/adr/0002-packs-composed-into-one-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,13 @@ ObjectStack 的规定后发现这条路走不通:
- 同一个应用升级到新版本时新增一批对象(加入一个扩展包),在托管云上的升级是否顺畅。
- 客户版用托管安装(定义锁定,可升级)还是模板安装(复制一份,完全可改,但以后不能升级)。
倾向托管安装,保住升级能力。
- 结果(2026-10-23):objectstack ADR-0131 D6 已裁定托管安装 = 定义封存,客户按
ADR-0126 的三种方式(参数、Studio 覆盖层、私有包)定制;模板安装在共库多租户上
被拒绝。托管云只能托管安装,结论定下。

## 补充说明(2026-10-23)

[ADR-0009](./0009-core-first-pack-criteria-and-customer-layer.md) 收窄了本记录的扩展包
接入规则:现阶段只做核心包,三个扩展包保留为设计;包主要新增自己的对象,对核心的
`objectExtensions` 每包不超过 2–3 个字段;桥接模块和组合测试矩阵推迟到第二个包出现。
构建时组合、「只加不减」和三种接入方式不变。
8 changes: 8 additions & 0 deletions docs/adr/0003-portal-isolation-by-supplier-position.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,12 @@
## 待验证

- flow 能否以系统身份写岗位任命;不能时由管理员手工任命。
- 结果(2026-10-23):岗位本身是元数据定义,flow 不能创建,由管理员新建(objectstack
ADR-0090 修订);用户 ↔ 岗位任命 `sys_user_position` 是数据行,但受委托管理范围
约束,系统身份的 flow 写入是否放行平台源码没有明确答案(objectstack#25251)。已向
平台提交「按外部方在运行时建岗位并任命」的需求(objectstack#25443)。门户在 v0.6
开工前按 07 §6 的 V2、V3 实测;不放行时「开通门户」screen flow 只做回填,任命由
管理员在成员页完成。
- 门户用户能否列出全组织用户:实测可以(objectstack#25233,P1),与本记录的
「用户目录可见范围不在控制范围内」一致;平台修复前不开门户。
- 平台以后若支持在元数据里声明成员集合,可以改用成员集合的写法,取消逐家建岗位。
Loading
Loading