diff --git a/AGENTS.md b/AGENTS.md index 01fe955..7d47df6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,7 +11,7 @@ ## Project context An **ObjectStack** application: contract lifecycle management (intake → review → approval → signing -and sealing → obligations and payments → renewal and archive) defined as typed metadata. A sellable +and execution formalities → obligations and payments → renewal and archive) defined as typed metadata. A sellable standard product, not a starter: every customer-specific need goes through `docs/requirements/` triage (A already supported · B standard enhancement · C customer overlay · D decline) before it touches `src/`. @@ -48,7 +48,10 @@ Paste the three green tails into the PR body. | Exports | `PascalCase`, barrel via `Object.values()` | `export { Contract } from './contract.object.js'` | - **Industry-neutral, always.** No vertical vocabulary in any object, field, option value or label. - Contract types, approval thresholds, seal kinds, payment terms and signing entities live in seed data. + Contract types, approval thresholds, execution formalities, currencies, payment terms and signing entities live in seed data. +- **Global by default.** English is the default locale and the source of every label; `zh-CN` is a full second bundle. + Nothing in schema, option values or defaults assumes one country: a region-specific requirement is an + execution formality, a seed row or a connector, never a hard-coded path. - **Reserved platform words — never as field names:** `role`, `position`, `permission_set`, `business_unit` (ADR-0090 D3; `validate` refuses them as `security-role-word`). Use a domain word. - **Never set `namespace` or `tableName` on an object.** Prefix lives in `name`. @@ -72,7 +75,7 @@ src/objects/ clm_*.object.ts + *.hook.ts src/profiles/ src/sharing src/views/ src/pages/ *.view.ts / *.page.ts src/flows/ F1–F15 (DESIGN.md §06) src/apps/ one App, five audience groups src/skills/ S1–S4 (DESIGN.md §07) src/datasets/ src/dashboards/ analytics src/mappings/ import projections -src/translations/ zh-CN (default), en src/data/ demo-zh/ · demo-en/ +src/translations/ en (default), zh-CN src/data/ demo-en/ · demo-zh/ docs/backlog/ work cards docs/requirements/ customer requirement triage ``` diff --git a/DESIGN.md b/DESIGN.md index db89820..df0269a 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -32,9 +32,21 @@ 2. **合同类型即流程。** NDA、采购、销售、劳务各自一条流程定义:发起字段、审批矩阵、签署方式、归档属性。新增一种合同 = 加一条配置,不是加一段代码。 3. **合同是数据,不是文件。** 关键属性结构化存储,文件只是附件;到期、义务、收付款都是可查询、可提醒、可看板的记录。 +### 全球优先(维护者裁定,2026-09-07) + +产品面向全球客户,区域需求以配置和区域包承载,绝不进 schema 的硬路径: + +- **语言**:英文为默认与源语言,`zh-CN` 为完整第二语言包;对象、字段、选项的 label 先写英文。 +- **主体与币种**:签约主体多个(集团多法人),币种在合同上(`currency_code`,组织级默认是设置不是 schema,出厂 `USD`)。 +- **法域**:每份合同带 `governing_law`、`jurisdiction`、`contract_language`;相对方带 `country_code`。 +- **执行**:电子签是默认执行方式(DocuSign 首发,Adobe Acrobat Sign、Dropbox Sign 随后,ESIGN / eIDAS 框架下的法律效力由提供商承担);公司印章、公证、见证、回签副本是类型上可配置的**执行形式**(`execution_formalities`),不是模块。 +- **相对方筛查**:制裁名单与公司登记核验走连接器(OFAC / EU / UK 名单,OpenCorporates、Dun & Bradstreet),区域包接本地登记库。 +- **数据保护**:类型级保留年限与处置,满足 GDPR 的存储限制;导出与删除按平台数据主体流程。 +- **区域包**:中国(契约锁 / 法大大 / e签宝、本地登记库、印章形式的种子)等区域差异以扩展包装配(§13 Q7),标准品零区域词汇。 + ### 范围 -**范围内**:发起与受理 · 法务审查 · 条款库与偏离 · 审批矩阵 · 谈判轮次与版本 · 签署与用印 · 履约义务 · 收付款计划核对 · 变更补充与续签 · 到期与归档 · 台账与看板 · 存量合同导入。 +**范围内**:发起与受理 · 法务审查 · 条款库与偏离 · 审批矩阵 · 谈判轮次与版本 · 签署与执行形式 · 履约义务 · 收付款计划核对 · 变更补充与续签 · 到期与归档 · 台账与看板 · 存量合同导入。 **范围外**:在线起草与红线编辑器(v2)· 电子签引擎(只集成,不自建)· 供应商准入与评价(SRM)· 应收应付账(财务系统)· 商机与报价(HotCRM)· 法律案件与诉讼。 @@ -50,7 +62,7 @@ ### 命名纪律 -对象名、字段名、选项值一律通用,**零行业词汇**。合同类型、审批阈值、用印种类、付款条件、签约主体全部是种子数据或配置 —— 换一套种子就是另一个行业的版本。 +对象名、字段名、选项值一律通用,**零行业词汇**。合同类型、审批阈值、执行形式、币种、付款条件、签约主体全部是种子数据或配置 —— 换一套种子就是另一个行业的版本。 平台保留词(`role` · `position` · `permission_set` · `business_unit`)不得作字段名(ADR-0090 D3)。 ## 02 Ironclad 概念 → 平台落法 @@ -64,7 +76,7 @@ | Editor / Redlining | 在线红线 | v1 版本文件加 `kind` 标记(`clm_contract_version`);v2 再做编辑器 | | Playbook | 条款的标准立场与备选立场 | `clm_clause` 标准文本 / 备选文本 / 风险级别;`clm_deviation` 记录偏离,高风险偏离触发法务负责人台阶 | | Repository / Properties | 结构化属性与检索 | `clm_contract` 字段 + 导入映射 + AI 抽取(S1) | -| Signature | 电子签 | 连接器集成(F8);国内特有的**用印**单独建模(`clm_seal_request`) | +| Signature | 电子签与执行 | 连接器集成(F8):DocuSign、Adobe Acrobat Sign、Dropbox Sign 首发,区域提供商作区域包;每一轮签署是一条 `clm_signature` 记录,类型要求的执行形式(回签副本、公司印章、公证、见证)在记录上勾齐才能生效 | | Insights | 周转分析 | 阶段时间戳 → dataset → 看板(§09) | | Jurist | AI 法务助手 | 四个 skill(§07),无 AI 运行时时显式降级 | @@ -78,7 +90,7 @@ clm_contract_type [public_read] clm_contract [private] clm_obligati clm_clause [public_read] clm_contract_version [MD] clm_payment_plan [MD] clm_approval_rule [public_read] clm_review [MD] clm_party [public_read] clm_deviation [MD] - clm_seal_request [MD] + clm_signature [MD] ``` ### 字段清单 @@ -87,15 +99,15 @@ clm_party [public_read] clm_deviation [MD] | 对象 | 字段 | |---|---| -| `clm_contract_type` `public_read` | name* · code*(编号前缀,如 `NDA`/`PUR`/`SAL`)· direction* `sales/purchase/other` · category* `nda/sales/purchase/service/lease/labor/framework/amendment/other` · description · template_file file · template_placeholders json(`{key,label,type,required}[]`,对应 spec 的 `DocumentTemplate.placeholders`)· intake_fields multiselect(本类型在发起表单上出现的可选字段)· requires_legal_review boolean · requires_seal boolean · sign_method `esign/wet_ink/both` · default_term_months · review_sla_days · retention_years · is_active | +| `clm_contract_type` `public_read` | name* · code*(编号前缀,如 `NDA`/`MSA`/`SOW`)· direction* `sales/purchase/other` · category* `nda/sales/purchase/service/lease/employment/framework/dpa/amendment/other` · description · template_file file · template_placeholders json(`{key,label,type,required}[]`,对应 spec 的 `DocumentTemplate.placeholders`)· intake_fields multiselect(本类型在发起表单上出现的可选字段)· requires_legal_review boolean · execution_formalities multiselect `countersigned_copy/company_seal/notarized/witnessed` · sign_method `esign/wet_ink/either`(默认 esign) · default_term_months · review_sla_days · retention_years · is_active | | `clm_clause` `public_read` | title* · category `liability/payment/termination/confidentiality/ip/warranty/dispute/other` · standard_text* richtext · fallback_text richtext · position_note(不可接受的底线,文字)· risk_level `low/medium/high` · applies_to multiselect(合同 category)· requires_legal_head boolean(偏离即需法务负责人)· is_active | | `clm_approval_rule` `public_read` | name* · applies_to multiselect(合同 category)· direction `sales/purchase/other/any` · amount_min currency · amount_max currency · only_with_deviation boolean · route_legal_head boolean · route_finance boolean · route_executive boolean · route_gm boolean · priority number · is_active | | `clm_party` `public_read` | name* · party_kind `company/individual/government/other` · registration_no(统一登记号)· legal_representative · contact_name · _contact_phone_ · contact_email · address · bank_name · _bank_account_ · crm_account lookup(跨包,可选)· risk_flag `none/watch/blocked` · risk_note · verified_at · is_active。唯一索引 `(registration_no)` scope organization | -| `clm_contract` `private` | contract_number autonumber `CT-{00000}` · title* · contract_type* lookup · category(自类型盖戳,只读)· direction(同上)· party* lookup · our_entity select(签约主体,种子)· department select(种子)· owner_id(业务承办)· legal_owner lookup user · amount currency · currency_code · is_amount_estimated boolean · start_date · end_date · term_months · auto_renew boolean · renewal_notice_days · renewed_from lookup clm_contract · parent_contract lookup clm_contract(框架合同 / 补充协议的主合同)· **status**(§状态机)· risk_level `low/medium/high` · summary richtext · governing_law · payment_terms select · confidentiality_term_months · liability_cap currency · current_turn `internal/counterparty/none` · turn_since datetime · route_legal_head / route_finance / route_executive / route_gm boolean(hook 盖戳,只读)· approval_status(审批节点镜像)· submitted_at · review_started_at · approved_at · signed_at · activated_at · closed_at · signed_file file · esign_provider select · esign_envelope_id · esign_status `none/sent/completed/declined/voided` · requires_seal boolean(自类型盖戳)· sealed_at · is_expiring boolean(日任务盖戳)· archive_no · archived_at · crm_contract lookup(跨包,可选)· 汇总:version_count · open_deviation_count · overdue_obligation_count · planned_amount · actual_amount | +| `clm_contract` `private` | contract_number text(hook 生成 `--<0000>`,按类型按年流水,提交时盖戳后只读,唯一索引 scope organization;§13 Q5)· is_backfilled boolean(补录的已签合同,§13 Q8)· title* · contract_type* lookup · category(自类型盖戳,只读)· direction(同上)· party* lookup · our_entity select(签约主体,种子)· department select(种子)· owner_id(业务承办)· legal_owner lookup user · amount currency · currency_code(种子:`USD` 默认、`EUR`、`GBP`、`CNY`、`JPY`)· is_amount_estimated boolean · start_date · end_date · term_months · auto_renew boolean · renewal_notice_days · renewed_from lookup clm_contract · parent_contract lookup clm_contract(框架合同 / 补充协议的主合同)· **status**(§状态机)· risk_level `low/medium/high` · summary richtext · governing_law · jurisdiction · contract_language select(种子,默认 `en`)· payment_terms select · confidentiality_term_months · liability_cap currency · current_turn `internal/counterparty/none` · turn_since datetime · route_legal_head / route_finance / route_executive / route_gm boolean(hook 盖戳,只读)· approval_status(审批节点镜像)· submitted_at · review_started_at · approved_at · signed_at · activated_at · closed_at · execution_formalities multiselect(自类型盖戳,只读)· executed_at datetime · ai_summary richtext · ai_risk_score number(0–100)· ai_risk_rationale textarea · ai_reviewed_at datetime(四个 AI 字段只由「采纳建议」动作写入,§07)· is_expiring boolean(日任务盖戳)· archive_no · archived_at · crm_contract lookup(跨包,可选)· 汇总:version_count · open_deviation_count · overdue_obligation_count · planned_amount · actual_amount | | `clm_contract_version` `by parent` | display_name(存储镜像 "v · ",nameField)· contract* MD cascade · version_no* · kind* `draft/internal_redline/counterparty_redline/clean/final_signed` · file* · submitted_by user · turn `internal/counterparty` · notes · is_current boolean | | `clm_review` `by parent` | display_name(镜像 " · ")· contract* MD cascade · reviewer* user · stage* `legal/finance/compliance/business` · decision `pending/approved/changes_requested/rejected` · risk_level_assessed · comments richtext(对发起人可见)· _internal_note_ richtext(仅法务)· started_at · decided_at | | `clm_deviation` `by parent` | display_name(镜像 " · ")· contract* MD cascade · clause* lookup · deviation_text* · requested_position `standard/fallback/custom` · justification · status `open/accepted/rejected/withdrawn` · decided_by user · decided_at | -| `clm_seal_request` `by parent` | display_name(镜像 " ×")· contract* MD cascade · seal_kind* `company/contract/legal_rep/finance`(标签由种子给:公章 / 合同章 / 法人章 / 财务章)· copies* number · purpose · requested_by user · status `pending/approved/sealed/rejected/cancelled` · sealed_by user · sealed_at · courier_no · return_confirmed boolean | +| `clm_signature` `by parent` | display_name(镜像 " · ")· contract* MD cascade · method* `esign/wet_ink` · provider select(DocuSign / Adobe Acrobat Sign / Dropbox Sign;区域包追加)· envelope_id · signers json(`[{side: our|counterparty, name, email, order, status, signed_at}]`)· status `draft/sent/completed/declined/voided` · formalities_done multiselect(与类型 `execution_formalities` 同值域)· executed_file file · completed_at · notes | | `clm_obligation` `by parent` | display_name(镜像 title)· contract* MD cascade · title* · kind `deliverable/payment/report/renewal/compliance/other` · due_date* · owner lookup user · status `pending/in_progress/done/overdue/waived` · completed_at · evidence file · notes | | `clm_payment_plan` `by parent` | display_name(镜像 "第期 · ")· contract* MD cascade · seq* · planned_date* · planned_amount* currency · condition · actual_date · actual_amount currency · status `planned/due/partial/paid/overdue` · invoice_no · notes | @@ -113,7 +125,7 @@ clm_party [public_read] clm_deviation [MD] | in_review | draft | 审查 `changes_requested` | | in_approval | approved / rejected / draft | 审批流决定;send-back 回 draft | | approved | signing | 存在 `kind: clean` 的当前版本 | -| signing | active | 存在 `final_signed` 版本;`requires_seal` 时 `sealed_at` 非空;`signed_at` 非空 | +| signing | active | 存在 `completed` 的签署记录且其 `formalities_done` 覆盖类型的 `execution_formalities`;存在 `final_signed` 版本;`signed_at` 非空 | | signing | approved | 签署失败回退 | | active | expired | 仅日任务(F13) | | active | terminated | `closed_at` 与终止原因必填 | @@ -124,7 +136,7 @@ clm_party [public_read] clm_deviation [MD] 其余子对象的状态机: - `clm_deviation.status`:open→accepted/rejected/withdrawn;终态不可回 -- `clm_seal_request.status`:pending→approved/rejected/cancelled;approved→sealed/cancelled +- `clm_signature.status`:draft→sent/completed/voided(湿签直接 completed);sent→completed/declined/voided;declined→draft - `clm_obligation.status`:pending→in_progress/done/waived/overdue;overdue→done/waived;in_progress→done/waived - `clm_payment_plan.status`:planned→due→partial/paid/overdue;overdue→partial/paid @@ -132,9 +144,10 @@ clm_party [public_read] clm_deviation [MD] - **没有 `clm_template` 对象。** 模板文件和占位符挂在合同类型上;换模板就是换文件。一个类型一份现行模板,历史模板不管。 - **没有 `clm_amendment` 对象。** 补充协议是一份合同,靠 `parent_contract` 和 `category` 表达;两个对象只会制造两份真相。 -- **没有 `clm_signatory` 对象。** 签署方就是 `party` 加 `our_entity`;电子签的信封与状态是合同上的三个字段。 +- **没有 `clm_signatory` 对象。** 签署方是 `clm_signature.signers` 里的 JSON 行;一轮签署一条记录,信封、状态与执行形式都在记录上,合同只保留 `executed_at`。 - **审批台阶固定五级。** 直接主管 → 法务负责人 → 财务负责人 → 分管领导 → 总经理。矩阵决定走哪几级,不决定台阶本身。Ironclad 的任意条件审批人在本平台对应「客户覆盖层加台阶」,不进标准品(§13 Q3)。 - **没有相对方门户。** 平台外部门户能力仍是缺口(PLATFORM_GAPS #27);相对方红线走邮件往来,法务上传为 `counterparty_redline` 版本。 +- **没有印章模块。** 公司印章是 `execution_formalities` 的一个值,与公证、见证、回签副本同级;印章流转(申请、执行、快递)属于中国区域包,标准品不建模。 ## 04 权限与隔离 @@ -144,28 +157,28 @@ clm_party [public_read] clm_deviation [MD] `clm_contract` `private`;五个子对象 `controlled_by_parent`;四个配置对象 `public_read`,写权限仅管理岗。 -Position 扁平,八个:`clm_legal_counsel`(法务经办)· `clm_legal_head`(法务负责人)· `clm_finance_controller`(财务负责人)· `clm_executive`(分管领导)· `clm_general_manager`(总经理)· `clm_seal_keeper`(印章管理员)· `clm_archivist`(档案管理员)· `clm_admin`。 +Position 扁平,七个:`clm_legal_counsel`(法务经办)· `clm_legal_head`(法务负责人)· `clm_finance_controller`(财务负责人)· `clm_executive`(分管领导)· `clm_general_manager`(总经理)· `clm_records_manager`(档案与记录管理员:执行登记、归档、台账)· `clm_admin`。 -Permission set 六个:`clm_requester`(所有员工默认)· `clm_legal` · `clm_finance` · `clm_seal` · `clm_archive` · `clm_admin`。 +Permission set 五个:`clm_requester`(所有员工默认)· `clm_legal` · `clm_finance` · `clm_records` · `clm_admin`。 -导航分区的门控能力由权限集 `systemPermissions` 授予:`clm_requester.access` · `clm_legal.access` · `clm_finance.access` · `clm_seal.access` · `clm_archive.access` · `clm_admin.access`。 -动作门控同时在 UI 与服务端生效(ADR-0066 D4):`approve_contract` · `seal_contract` · `archive_contract` · `terminate_contract` · `manage_clauses` · `manage_approval_rules`。 +导航分区的门控能力由权限集 `systemPermissions` 授予:`clm_requester.access` · `clm_legal.access` · `clm_finance.access` · `clm_records.access` · `clm_admin.access`。 +动作门控同时在 UI 与服务端生效(ADR-0066 D4):`approve_contract` · `execute_contract` · `archive_contract` · `terminate_contract` · `manage_clauses` · `manage_approval_rules`。 ### 权限矩阵 R 读 · C 建 · U 改 · D 删;括号内为行级作用域。 -| 对象 | clm_requester | clm_legal | clm_finance | clm_seal | clm_archive | clm_admin | -|---|---|---|---|---|---|---| -| clm_contract | RCU(本人发起,`draft`/`submitted` 可改) | RCU(全部) | RU(`approved` 及之后,FLS 锁法律字段) | R(`signing`) | RU(终态;归档字段) | RCUD | -| clm_contract_version | RC(本人合同) | RCU | R | R | R | RCUD | -| clm_review | R(`comments`,不含 `internal_note`) | RCU | RCU(stage=finance) | — | R | RCUD | -| clm_deviation | RC(本人合同) | RCU | R | — | R | RCUD | -| clm_seal_request | RC(本人合同) | RCU | — | RU(执行) | R | RCUD | -| clm_obligation | RU(本人负责) | RCU | R | — | R | RCUD | -| clm_payment_plan | R(本人合同) | RC | RCU | — | R | RCUD | -| clm_party | R(不含银行与电话) | RCU | RU(银行信息) | — | R | RCUD | -| clm_contract_type · clm_clause · clm_approval_rule | R | R(clause RCU) | R | R | R | RCUD | +| 对象 | clm_requester | clm_legal | clm_finance | clm_records | clm_admin | +|---|---|---|---|---|---| +| clm_contract | RCU(本人发起,`draft`/`submitted` 可改) | RCU(全部) | RU(`approved` 及之后,FLS 锁法律字段) | RU(`signing` 及之后;执行与归档字段) | RCUD | +| clm_contract_version | RC(本人合同) | RCU | R | RC(执行副本) | RCUD | +| clm_review | R(`comments`,不含 `internal_note`) | RCU | RCU(stage=finance) | R | RCUD | +| clm_deviation | RC(本人合同) | RCU | R | R | RCUD | +| clm_signature | R(本人合同) | RCU | R | RU(执行形式、执行副本) | RCUD | +| clm_obligation | RU(本人负责) | RCU | R | R | RCUD | +| clm_payment_plan | R(本人合同) | RC | RCU | R | RCUD | +| clm_party | R(不含银行与电话) | RCU | RU(银行信息) | R | RCUD | +| clm_contract_type · clm_clause · clm_approval_rule | R | R(clause RCU) | R | R | RCUD | ### 共享规则 @@ -173,8 +186,7 @@ R 读 · C 建 · U 改 · D 删;括号内为行级作用域。 |---|---|---|---| | `contract_legal_all` | clm_contract | 全部 | position `clm_legal_counsel` · `clm_legal_head` — edit | | `contract_finance_post_approval` | clm_contract | `status in [approved, signing, active, expired, terminated]` | position `clm_finance_controller` — edit(FLS 锁法律字段,§13 Q1) | -| `contract_seal_signing` | clm_contract | `status == 'signing' && requires_seal == true` | position `clm_seal_keeper` — read | -| `contract_archive_terminal` | clm_contract | `status in [active, expired, terminated]` | position `clm_archivist` — edit | +| `contract_records_execution` | clm_contract | `status in [signing, active, expired, terminated]` | position `clm_records_manager` — edit(FLS 限执行与归档字段) | | `contract_executive_routed` | clm_contract | `route_executive == true` | position `clm_executive` — read | | `contract_gm_routed` | clm_contract | `route_gm == true` | position `clm_general_manager` — read | | `contract_manager_reports` | clm_contract | — | `writeScope: 'own_and_reports'`(企业版 `hierarchy-security`,开源版退化为 owner-only) | @@ -185,10 +197,11 @@ RLS 谓词不能跨对象(ADR-0055),所以「同部门可见」无法用 ` | 字段 | 对谁遮蔽 | 理由 | |---|---|---| -| `clm_party.bank_account` · `contact_phone` | clm_requester · clm_seal · clm_archive | 付款与联系信息最易外泄;读取落审计 | +| `clm_party.bank_account` · `contact_phone` | clm_requester · clm_records | 付款与联系信息最易外泄;读取落审计 | | `clm_review.internal_note` | clm_requester · clm_finance | 法务内部意见;对发起人的结论走 `comments` | | `clm_contract.risk_level` · `liability_cap` | clm_requester 只读 | 由法务评定 | | `clm_contract.route_*` · `approval_status` · 阶段时间戳 | 所有岗位只读 | 只由 hook 与审批流写 | +| `clm_contract.ai_*` | 所有岗位只读 | 只由「采纳建议」动作写入,写入前 AI 输出不落字段 | ## 05 视图与受众端 @@ -199,10 +212,10 @@ RLS 谓词不能跨对象(ADR-0055),所以「同部门可见」无法用 ` | 我的合同(所有人) | `clm_requester.access` | 发起合同 · 我发起的 · 待我处理 · 我负责的履约 | 发起 = screen flow 动作;我发起的 grid(按 status 分组);待我处理 = 平台审批收件箱;履约 grid(due_date 升序) | | 法务工作台 | `clm_legal.access` | 待受理 · 审查中 · 谈判中 · 全部合同 · 到期日历 · 条款库 · 合同类型 | 待受理 grid(`submitted` 且未分配)· 审查中 grid(`legal_owner == me`)· 谈判中 grid(`current_turn == counterparty`,按 `turn_since` 升序)· **状态看板** kanban(groupBy status)· 到期 calendar(end_date) | | 财务 | `clm_finance.access` | 收付款计划 · 生效合同 · 收付款看板 | 计划 grid ×3 listView(本月到期 / 逾期 / 已付)· 生效合同 grid | -| 用印与档案 | `clm_seal.access` / `clm_archive.access` | 用印申请 · 待归档 · 合同台账 | 用印 grid(`pending`/`approved`)· 待归档 grid(终态且 `archive_no` 空)· 台账 grid(全字段,可导出) | +| 执行与档案 | `clm_records.access` | 待执行 · 待归档 · 合同台账 | 待执行 grid(`signing` 且签署记录未 `completed` 或执行形式未齐)· 待归档 grid(终态且 `archive_no` 空)· 台账 grid(全字段,可导出) | | 管理 | `clm_admin.access` | 审批矩阵 · 相对方 · 签约主体与部门 · 报表 | 配置对象 grid | -**合同详情页**(slotted):header 挂「提交 / 受理 / 送审 / 发起签署 / 生效 / 终止 / 发起续签」动作,按 status 与门控显隐;highlights:编号 · 相对方 · 金额 · 到期日 · 当前轮次;path 组件显示 draft→submitted→in_review→in_approval→approved→signing→active;tab:概要 / 版本(timeline)/ 审查与偏离 / 审批记录(平台 `sys_approval_request`)/ 履约与收付款 / 用印与归档 / 讨论(平台 discussion slot,评论与 @)。 +**合同详情页**(slotted):header 挂「提交 / 受理 / 送审 / 发起签署 / 生效 / 终止 / 发起续签」动作,按 status 与门控显隐;highlights:编号 · 相对方 · 金额 · 到期日 · 当前轮次;path 组件显示 draft→submitted→in_review→in_approval→approved→signing→active;tab:概要 / 版本(timeline)/ 审查与偏离 / 审批记录(平台 `sys_approval_request`)/ 履约与收付款 / 签署与归档 / 讨论(平台 discussion slot,评论与 @)。 无匿名公开表单:合同发起必须登录。 @@ -211,12 +224,12 @@ RLS 谓词不能跨对象(ADR-0055),所以「同部门可见」无法用 ` | # | 名称 | 类型 | 行为 | |---|---|---|---| | F1 | `contract_intake` | screen flow(发起表单) | 选类型 → 按类型 `intake_fields` 显示条件字段 → 相对方查找或新建 → 上传首版或标记「按模板」→ 建合同(`draft`)与版本 v1 → 可选一键提交。`ai.exposed`,输入变量齐全时可由 MCP 调用 | -| F2 | `contract_route` | hook beforeUpdate(进入 `submitted`) | 自类型盖戳 `category`/`direction`/`requires_seal`;按 `clm_approval_rule` 命中项盖 `route_*`;写 `submitted_at`;`requires_legal_review` 时在 `clm_legal_counsel` 中按未结合同数最少轮询分配 `legal_owner` 并进 `in_review`,否则直进 `in_approval` | +| F2 | `contract_route` | hook beforeUpdate(进入 `submitted`) | 自类型盖戳 `category`/`direction`/`execution_formalities`;按 `clm_approval_rule` 命中项盖 `route_*`;写 `submitted_at`;`requires_legal_review` 时在 `clm_legal_counsel` 中按未结合同数最少轮询分配 `legal_owner` 并进 `in_review`,否则直进 `in_approval` | | F3 | `legal_review_sla` | 定时(日) | `in_review` 超过类型 `review_sla_days`:提醒 `legal_owner`,超一倍抄送 `clm_legal_head` | | F4 | `turn_stalled` | 定时(日) | `current_turn == counterparty` 且 `turn_since` 超 7 天:提醒业务承办催对方 | | F5 | `contract_approval` | record_change(进入 `in_approval`),`runAs: 'system'` | 台阶 1 直接主管(`type: 'manager'`)→ decision 按 `route_legal_head` / `route_finance` 决定台阶 2 是否为法务加财务**会签**(`per_group`)或单方 → decision `route_executive` → 台阶 4 分管领导(position)→ decision `route_gm` → 台阶 5 总经理。`lockRecord: true`,`approvalStatusField: approval_status`;approve → `approved` + `approved_at`;reject → `rejected`;send-back → `draft` | | F6 | `deviation_gate` | hook beforeUpdate | 存在 `open` 偏离时拒绝进入 `in_approval`;接受了 `requires_legal_head` 条款的偏离即置 `route_legal_head = true` | -| F7 | `seal_request_approval` | record_change(`clm_seal_request` 新建) | 法务负责人审批 → `approved` → 通知印章管理员;管理员标 `sealed` → hook 盖合同 `sealed_at` | +| F7 | `signature_record` | record_change(`clm_signature` 进入 `completed`) | hook 比对 `formalities_done` 与类型 `execution_formalities`:齐备则盖合同 `executed_at` 并由 `executed_file` 建 `final_signed` 版本;缺项则通知法务经办并点名缺哪一项。湿签路径:法务或档案岗在签署记录上传执行副本并勾选形式 | | F8 | `esign_dispatch` / `esign_callback` | 动作 + api 触发流 | 「发起电子签」经 durable HTTP 把 clean 版本与签署方送给连接器指定的提供商;回调 api 流按信封状态写 `esign_status`,完成时建 `final_signed` 版本并写 `signed_at` | | F9 | `contract_activate` | hook afterUpdate(进入 `active`) | 写 `activated_at`;按类型默认建续签提醒义务;发起时填了付款安排则生成 `clm_payment_plan`;并装 HotCRM 时回写 `crm_contract`(status `activated`、`signed_date`、文件) | | F10 | `obligation_due` | 定时(日) | T-7 与 T-0 提醒义务 owner;过期未完成置 `overdue`,父合同汇总 `overdue_obligation_count` 随之变化 | @@ -224,31 +237,57 @@ RLS 谓词不能跨对象(ADR-0055),所以「同部门可见」无法用 ` | F12 | `renewal_notice` | 定时(日) | `active` 且 `end_date - renewal_notice_days <= today`:置 `is_expiring`,提醒业务承办与法务;动作「发起续签」预填新 draft | | F13 | `expiration_sweep` | 定时(日) | `active` 且 `end_date < today`:非自动续签置 `expired`;自动续签则建续签 draft 并提醒 | | F14 | `contract_archive` | hook beforeUpdate | 终态合同由档案岗填 `archive_no` 后置 `archived_at`,此后除 `notes` 外只读 | +| F16 | `executed_upload` | 动作(补录已签合同,§13 Q8) | 档案或法务岗「补录已签合同」:一步填核心字段、相对方、执行副本与签署日期,合同直接进入 `active` 并置 `is_backfilled`,跳过审查与审批但全部留审计;仅 `clm_records.access` 与 `clm_legal.access` 可用 | | F15 | `crm_handoff` | record_change(`crm_contract` 进入 `in_approval`) | **仅 `CLM_COMPOSITION=with-hotcrm` 装配时注册**:建 `clm_contract`(direction `sales`,party 自 `crm_account` 查找或新建,金额期限预填,`crm_contract` 回链) | 定时流与对审批结果做出反应的 record_change 流一律 `runAs: 'system'` 并注明理由(审批服务的镜像写不带用户,默认身份会被拒绝)。 -## 07 AI(skills-only,挂平台 `ask` 助手) +## 07 AI 融合(维护者要求:与 AI 怎么融合,2026-09-07) -AI 运行时只在云版存在。开源版启动时没有 `ai` 能力:按钮不出现、字段不出现,**绝不用占位输出冒充预测**(templates 仓库的教训)。 +AI 是流程里的**参与者**,不是旁边的聊天窗。三条治理原则先于任何能力:与人同权限同审计(AI 只能看调用者能看的合同,每次调用落审计:谁、哪份合同、哪个 skill、哪个模型、结论);只建议不直接写(每条建议经人「采纳」才落字段或改状态,AI 永远不能推动状态机);没有 AI 运行时就隐藏(开源版无 `ai` 能力时按钮与字段不出现,绝不用占位输出冒充结果)。 -| # | skill | 触发 | 行为 | -|---|---|---|---| -| S1 | `extract_terms` | 上传 PDF 或存量导入 | 提出 party · amount · start/end · governing_law · payment_terms · 关键条款摘要;用户确认后写入字段。存量合同导入的主路径 | -| S2 | `review_summary` | 法务打开新版本 | 对比上一版本,按 `clm_clause` 类别列出变动,提出偏离草案;用户确认后建 `clm_deviation` | -| S3 | `deviation_check` | 建偏离时 | 对照标准文本与备选文本,建议 `risk_level` 与是否需法务负责人 | -| S4 | `contract_qa` | 合同库问答 | 在当前用户可见的合同内检索作答,附来源合同编号 | +### 三层落地机制 + +| 层 | 机制 | 本应用的用法 | +|---|---|---| +| 技能 | skills-only 挂平台 `ask` 助手(ADR-0063,`surface` 绑定),无应用自有 agent | S1–S6 | +| 工具 | 每个 `ai.exposed` 动作即 AI 工具,并经平台 MCP 暴露给外部 agent(Claude、Copilot、客户自己的 agent) | 发起合同、查状态、查到期义务、检索合同、登记偏离,权限按调用用户 | +| 数据 | 合同上四个 `ai_*` 字段只由「采纳建议」动作写入;审计里 AI 建议与人工采纳各一条 | 摘要、风险分与理由、审查时间 | -四个 skill 都只**建议**,写入都经用户确认;每次调用带合同编号落审计。 +### 能力地图(按生命周期) + +| # | 阶段 | skill / 能力 | 输入 | 输出 | 写入方式 | 版本 | +|---|---|---|---|---|---|---| +| S1 | 导入 / 发起 | `extract_terms` 条款抽取 | 上传的 PDF / DOCX | 相对方、金额、币种、起止、适用法律、付款条款、关键条款摘要 | 人确认后写字段 | M4 | +| S5 | 导入 / 生效 | `extract_obligations` 义务抽取 | 终版文本 | 义务草案(标题、类型、到期、负责人建议) | 人确认后建 `clm_obligation` | M4 | +| S2 | 审查 | `review_summary` 版本变动摘要 | 新版本 vs 上一版 | 按条款类别列出变动,偏离草案 | 人确认后建 `clm_deviation` | M4 | +| S3 | 审查 | `deviation_check` 偏离风险 | 偏离文本 vs 条款标准 / 备选 | 风险级别建议、是否需法务负责人 | 人确认后写偏离字段 | M4 | +| S6 | 审批 | `approver_memo` 审批备忘录 | 合同、偏离、同类合同 | 一页备忘录:金额与阈值、偏离与风险、同类对比、关注点;`ai_risk_score` 与理由 | 备忘录附在审批请求上,标「AI 生成,未经法务复核」;分数经法务采纳才写 | M4 | +| S4 | 检索 | `contract_qa` 合同库问答 | 自然语言 | 答案附合同编号 | 不写 | M4 | +| — | 发起 | 对话式发起 | 助手对话或 MCP 调用 F1 | 同 F1 | 同 F1 校验 | M2(随 F1 的 `ai.exposed`) | +| — | 谈判 | playbook 建议回复 | 对方红线条款 | 备选立场文本 | 不写 | 二期 | +| — | 检索 | 相似合同与条款召回(向量检索,平台 knowledge 服务) | 条款文本 | 相似条款与所在合同 | 不写 | 二期 | +| — | 定制 | 用 AI 改应用:客户经 Claude Code 等改合同类型、矩阵、视图 | 自然语言 | 元数据变更,走同一条 verify 链 | 覆盖层 | 随平台 | + +### 治理规则 + +| 规则 | 内容 | +|---|---| +| 模型无关 | 走平台模型注册表(Anthropic、OpenAI、Bedrock、本地),应用不写任何提供商代码 | +| 数据边界 | 合同文本只送给组织配置的模型端点;自托管可全内网 | +| 提示词版本化 | 提示词在 skill 元数据里,随包版本,可 diff | +| 置信度 | 抽取字段带置信度,低于阈值不展示建议只展示原文 | +| 一键关闭 | 组织级设置关闭全部 AI;关闭后 `ai_*` 字段保留但只读 | +| 审计 | 每次调用一条审计,采纳一条审计,两条互链 | ## 08 集成 | 对象 | 方式 | 现状 | |---|---|---| -| 电子签 | REST 连接器(Docusign · 契约锁 · 法大大 · e签宝),提供商与凭证在 `sys_setting`;回调走 api 触发流 | 平台**无**电子签引擎(spec 17 已明示移除),只集成不自建 | +| 电子签 | REST 连接器(DocuSign 首发;Adobe Acrobat Sign、Dropbox Sign 随后;区域提供商如 契约锁 / 法大大 / e签宝 作区域包),提供商与凭证在 `sys_setting`;回调走 api 触发流 | 平台**无**电子签引擎(spec 17 已明示移除),只集成不自建 | | HotCRM | F15 交接 + F9 回写;跨包 lookup | 组合开关装配,单装 CLM 不含 | -| 相对方核验 | 企查查 / 天眼查连接器,写 `verified_at` 与 `risk_flag` | 可选 | -| 通知 | 站内 inbox · email · sms | 钉钉 / 飞书 / 企微 通道平台未实现(PLATFORM_GAPS #1),只能声明不能承诺 | +| 相对方筛查 | 制裁名单(OFAC / EU / UK)与公司登记核验(OpenCorporates、Dun & Bradstreet)连接器,区域包接本地登记库;写 `screening_status` 与 `screened_at` | 可选 | +| 通知 | 站内 inbox · email · sms · Slack(平台 `connector-slack`) | Microsoft Teams 与区域即时通讯通道平台未实现(PLATFORM_GAPS #1),只能声明不能承诺 | | 台账导出 | 平台导出 CSV / XLSX | PDF 打印仍是缺口(#9) | ## 09 分析 @@ -268,22 +307,22 @@ Dataset(语义层): ## 10 种子数据 -一家虚构公司,六个月历史,让每个看板第一屏就有内容。`demo-zh` 默认(国内买家),`demo-en` 同构。 +一家虚构的跨国集团(美国母公司,欧洲与亚太子公司;合同以 USD / EUR / GBP 计价,适用法律分布在 US-NY、England and Wales、Germany),六个月历史,让每个看板第一屏就有内容。`demo-en` 默认,`demo-zh` 同构。 | 对象 | 条数 | 要点 | |---|---|---| -| clm_contract_type | 8 | NDA · 销售 · 采购 · 服务 · 租赁 · 劳务 · 框架 · 补充协议 | +| clm_contract_type | 9 | NDA · MSA · SOW · 订单 · 供应商协议 · DPA · 租赁 · 独立承包人 · 补充协议 | | clm_clause | 30 | 覆盖全部 category,每类至少一条 `high` | | clm_approval_rule | 6 | 三档金额 × 有无偏离 | | clm_party | 40 | 客户 / 供应商 / 个人 / 政府各有;2 条 `blocked` | | clm_contract | 120 | draft 10 · submitted 6 · in_review 12 · in_approval 8 · approved 4 · signing 6 · active 60 · expired 8 · terminated 4 · cancelled 2;其中 10 条 30 天内到期 | | clm_contract_version | 300 | 谈判中的合同有 3 到 5 版,含对方红线 | | clm_review · clm_deviation | 60 · 25 | 8 条偏离 `open`,让门槛可演示 | -| clm_seal_request | 20 | 4 条待办 | +| clm_signature | 30 | 6 条 `sent`,2 条执行形式未齐 | | clm_obligation | 200 | 未来 30 天内到期 40 条,逾期 10 条 | | clm_payment_plan | 300 | 本月到期 30 条,逾期 12 条 | -用户不可种子;各岗位账号在 Setup 建用户后分配 position(法务经办 ×2、法务负责人、财务负责人、分管领导、总经理、印章管理员、档案管理员、业务承办 ×3)。 +用户不可种子;各岗位账号在 Setup 建用户后分配 position(法务经办 ×2、法务负责人、财务负责人、分管领导、总经理、档案与记录管理员、业务承办 ×3)。 ## 11 仓库与里程碑 @@ -295,12 +334,12 @@ src/objects/ 11 个 *.object.ts + *.hook.ts(状态机守卫、 src/views/ src/pages/ 五个分区的视图;合同详情 slotted 页 src/apps/ 1 个 App,五组受众分区 src/flows/ F1–F15(F15 受组合开关控制) -src/skills/ S1–S4 +src/skills/ S1–S6(§07) src/datasets/ src/dashboards/ 4 dataset · 3 dashboard -src/profiles/ src/sharing/ 6 permission set · 8 position · 7 sharing rule · FLS +src/profiles/ src/sharing/ 5 permission set · 7 position · 6 sharing rule · FLS src/mappings/ 存量合同 / 相对方导入映射 -src/translations/ zh-CN(默认)· en -src/data/ demo-zh/ · demo-en/ +src/translations/ en(默认)· zh-CN +src/data/ demo-en/ · demo-zh/ content/docs/ 产品文档(法务 / 财务 / 管理员 / 发布) docs/requirements/ 客户需求分诊记录(A/B/C/D) docs/backlog/ 派发卡片 @@ -309,9 +348,9 @@ docs/backlog/ 派发卡片 | 里程碑 | 内容 | 验收 | |---|---|---| | M1 数据与权限骨架 | 11 对象 · 状态机守卫 · 8 position / 6 set · 共享与 FLS · 配置域种子 | `validate`/`lint`/`typecheck` 绿;业务承办经 REST 看不到他人合同;财务看不到 `in_review` 合同 | -| M2 发起与审批 | F1 · F2 · F5 · F6 · F7 · 法务工作台 · 详情页 · 全量种子 | 走通 发起→受理→偏离→会签→用印→生效,审批记录与审计齐全 | +| M2 发起与审批 | F1 · F2 · F5 · F6 · F7 · 法务工作台 · 详情页 · 全量种子 | 走通 发起→受理→偏离→会签→签署与执行形式→生效,审批记录与审计齐全 | | M3 签后与分析 | F9–F14 · 履约与收付款 · 4 dataset · 3 看板 · zh/en | 演示数据下无空图;到期、逾期提醒在收件箱可见 | -| M4 集成与可发布 | F8 电子签 · F15 CRM 交接 · S1–S4 · 导入映射 · 文档 · 截图 · marketplace 发布 | 陌生人 clone 一条命令跑起;marketplace 一键安装;需求书逐条对应 feature-inventory 与测试 | +| M4 集成与可发布 | F8 电子签 · F15 CRM 交接 · S1–S6 与审批备忘录 · MCP 工具面 · 导入映射 · 文档 · 截图 · marketplace 发布 | 陌生人 clone 一条命令跑起;marketplace 一键安装;需求书逐条对应 feature-inventory 与测试 | 一次只做一个里程碑;token ratchet 上限:业务语义 ≤ 60k,交互层 ≤ 30k,M1 起就卡。 @@ -321,26 +360,28 @@ docs/backlog/ 派发卡片 |---|---|---|---| | 在线红线编辑器 | — | 版本文件 + `kind` 标记;对方红线上传 | 编辑器内比对 | | 模板填充生成文档 | — | `DocumentTemplate.placeholders` 有 schema 无渲染引擎:下载模板 + 变量清单,法务填后上传 | 一键生成 v1 | -| PDF / 打印 | #9 | 浏览器打印 | 台账与用印单模板打印 | +| PDF / 打印 | #9 | 浏览器打印 | 台账与执行单模板打印 | | 电子签引擎 | — | 连接器集成 | 不自建 | | 入站邮件 | #39 | 手动上传对方版本 | 邮件附件自动成版本 | | 外部相对方门户 | #27 | 邮件往来 | 相对方在线红线 | -| IM 通知通道 | #1 | inbox / email / sms | 钉钉 / 飞书 / 企微 | +| IM 通知通道 | #1 | inbox / email / sms / Slack | Teams;区域 IM 由区域包承担 | | CEL 日期算术 | #7 | 到期、逾期由日任务盖戳字段 | 公式字段 | -| 跨对象公式 | #36 | hook 冗余 `category` / `direction` / `requires_seal` | 直接引用类型 | +| 跨对象公式 | #36 | hook 冗余 `category` / `direction` / `execution_formalities` | 直接引用类型 | 规则:平台能力受限**只上报** objectstack,不在本仓库修平台;应用侧只允许带环境闸门的临时夹具并注明平台 issue;新发现追加到 objectstack 的 `docs/PLATFORM_GAPS_FROM_TEMPLATES.md`。 -## 13 待裁决项 - -**Q1 · 财务对生效合同的写权限。** 当前:`edit` + FLS 锁法律字段。替代:`clm_payment_plan` 脱离 master-detail、自持 OWD 和共享。前者简单但财务可改合同非法律字段;后者失去汇总字段。建议前者,M1 验证 FLS 能否锁住 `status`。 - -**Q2 · 部门内可见性。** RLS 不能表达「与当前用户同部门」。选项:不做(默认,靠 `own_and_reports`);或按客户覆盖层加 team 共享规则,部门 = team。建议不进标准品。 +## 13 裁决记录(2026-09-07,维护者:「16 项全部同意默认」) -**Q3 · 审批台阶是否够。** 固定五级覆盖国内中型企业常见的分级审批;Ironclad 式任意条件审批人留给客户覆盖层。若第一个客户就要第六级,改为矩阵驱动台阶数(hook 盖 `approver_n` 字段、节点 `type: 'field'`),成本一周。 +设计方案 V1.0 第 13 章 16 项与本节 Q1–Q7 于同日一次裁定,全部采用默认口径。逐条记录,此后改动走新的 Q 编号,不改已裁决项。 -**Q4 · 相对方与 `crm_account` 的关系。** 当前:永远独立 `clm_party`,可选 lookup 到 `crm_account`。替代:并装时直接复用 `crm_account`。后者让 CLM 单装时缺相对方主数据,否决;保留 lookup 即可。 - -**Q5 · 合同编号。** `autonumber` 只有静态格式(`CT-{00000}`),做不到「按类型前缀 + 年份 + 流水」。选项:接受单一流水,类型 code 作独立列;或 hook 生成编号并存 `contract_number` 文本字段(放弃 autonumber)。国内客户对编号规则要求刚性,建议 M1 用 hook 方案并把规则做成类型配置。 - -**Q6 · 是否复用 HotCRM 的 `crm_contract` 六种类型枚举。** 不复用。CLM 的 category 是流程分类,crm_contract 的类型是商务分类,两者语义不同,硬对齐只会互相牵制;F15 做一次映射即可。 +| # | 事项 | 裁定 | 落实 | +|---|---|---|---| +| Q1 | 财务对生效合同的写权限 | `edit` + FLS 锁法律字段与 `status` | 卡 04;M1 验证 FLS 能锁 `status` | +| Q2 | 部门内可见性 | 不进标准品,靠 `own_and_reports`;team 规则留客户覆盖层 | 卡 04 | +| Q3 | 审批台阶 | 固定五级,矩阵选台阶 | 卡 06 | +| Q4 | 相对方与 `crm_account` | 永远独立 `clm_party`,可选 lookup | 已落地 | +| Q5 | 合同编号 | hook 生成 `--<0000>`,放弃 autonumber | 卡 02,§03 已改 | +| Q6 | 类别与 HotCRM 类型 | 不对齐,F15 映射 | 卡 12 | +| Q7 | 区域包装配 | marketplace 扩展包,依赖 HotCLM;开关只作过渡 | 2.x | +| Q8 | 补录已签合同(方案第 12 项) | 允许:F16 `executed_upload`,直接 `active`,`is_backfilled` 标记并留审计 | 卡 09 追加 F16 | +| 方案 1–16 | 财务写权限、部门可见性、台阶、相对方、编号、类别、对方红线由法务上传、执行形式按类型、DocuSign 首发、IM 通道本期不承诺、出厂 USD 与英文、补录通道、保留期默认 10 年、补充协议走自己的矩阵、AI 四字段进合同、区域包用扩展包 | 全部默认 | 已分别体现在 §01–§12 | diff --git a/README.md b/README.md index 4c6a6e0..5cfd533 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,9 @@ # HotCLM **Contract lifecycle management on [ObjectStack](https://github.com/objectstack-ai/objectstack) — buy-side, sell-side and everything in between, as typed metadata.** -Self-serve intake, a clause playbook, a data-driven approval matrix, sealing and e-signature, obligations and payment schedules: the whole lifecycle in one readable repository. +Self-serve intake, a clause playbook, a data-driven approval matrix, e-signature and execution formalities, obligations and payment schedules: the whole lifecycle in one readable repository. -**基于 ObjectStack 的合同全生命周期管理。** 业务自助发起、条款库与偏离、审批矩阵、用印与电子签、履约义务、收付款计划 —— 全部是类型化元数据。 +**基于 ObjectStack 的合同全生命周期管理。** 业务自助发起、条款库与偏离、审批矩阵、电子签与执行形式、履约义务、收付款计划 —— 全部是类型化元数据。 > Status: **M0 — scaffold and configuration domain.** See [DESIGN.md](./DESIGN.md) for the model and > [docs/backlog](./docs/backlog/README.md) for what is being built next. Sibling app of @@ -16,8 +16,9 @@ Self-serve intake, a clause playbook, a data-driven approval matrix, sealing and - **Ironclad-shaped, not OA-shaped.** A contract type *is* a workflow: intake fields, review, approval ladder, signing method, archive rules — configuration, not code. - **Business users launch, legal controls.** One intake form per contract type; the approval matrix decides who signs off. - **Contracts are data.** Obligations, payment schedules, renewals and deviations from the clause playbook are queryable records with reminders, not paragraphs in a PDF. -- **Built for the market it sells in.** Sealing requests (用印), a counterparty register with verification, and a `zh-CN`-first demo. -- **Industry-neutral by rule** — contract types, thresholds, seal kinds and payment terms live in seed data only. +- **Global by default, local by configuration.** English-first UI with full `zh-CN`; multi-entity, multi-currency, governing law and jurisdiction on every contract; e-signature through DocuSign, Adobe Acrobat Sign or Dropbox Sign; a company seal, notarization or witnessing are execution formalities a contract type can require, not modules. +- **AI is a participant under governance.** Intake by chat or MCP, extraction of executed contracts, review memos for approvers, deviation detection against the playbook — every AI step proposes, a person confirms, and the audit trail records both. +- **Industry- and region-neutral by rule** — contract types, thresholds, execution formalities, currencies and payment terms live in seed data only. ## Quick start diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..69036d2 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,24 @@ +# docs/ — how HotCLM manages goals, requirements and work + +Four layers, each with one job. Nothing lives in two of them. + +| Layer | Where | What it holds | Changes how | +|---|---|---|---| +| **Direction** | [`ROADMAP.md`](./ROADMAP.md) | Releases, themes, what each release unlocks and what it depends on | Maintainer edits; a dated entry per change | +| **Requirements baseline** | [`design/00-设计方案.md`](./design/00-设计方案.md) | The complete business design; §待确认事项 becomes 已确认口径 when the maintainer answers | Versioned, append-only version record; V1.0 = the baseline for release 1.0 | +| **Engineering authority** | [`../DESIGN.md`](../DESIGN.md) | Names, enums, OWD, guards, flows, milestones — what a card may not contradict | Amended by decision; a card that conflicts stops with `needs_decision` | +| **Customer asks** | [`requirements/`](./requirements/) *(created with the first customer)* | One file per raw requirement, verbatim, with an A/B/C/D disposition (already supported · standard enhancement · customer overlay · decline) | File per ask; only B lands in `src/` | +| **Work** | [`backlog/`](./backlog/) → GitHub issues | Dispatch-ready cards; an issue exists only while a card is ready or in flight | Card → issue with `pm:queue` → draft PR → closed on merge | + +## Why issues stay small + +GitHub issues are for **work that is ready to dispatch, bugs, and `needs-user-decision` questions** — nothing else. Goals live in the roadmap, requirements in the versioned design documents, and "what exists" in the feature inventory (`feature-inventory.md`, created at M4 with stable ids `CON-001 …`). An issue that would restate a design chapter is a sign the chapter is missing, not a reason to open the issue. + +Traceability runs through ids, not through issue links: a customer ask (`requirements/NNNN-slug.md`) → a design chapter (§) → a feature-inventory row (`CON-nnn`) → a test. The dispatch report and the PR body name the ids they touched. + +## GitHub conventions + +- **Milestones** `M1 数据与权限骨架` · `M2 发起与审批` · `M3 签后与分析` · `M4 集成与发布` mirror `DESIGN.md` §11; every issue carries one. +- **Labels**: `pm:queue` (ready) · `pm:dispatched` (in flight) · `needs-user-decision` (blocked on the maintainer) · `bug` · `platform-gap` (reported upstream, fixture in place). +- **`Blocked-by: #n`** in the issue body is honoured by the dispatch loop. +- One issue per PR, draft PRs, squash merges by the maintainer. diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md new file mode 100644 index 0000000..b668dbe --- /dev/null +++ b/docs/ROADMAP.md @@ -0,0 +1,26 @@ +# HotCLM Roadmap + +> Direction, not a commitment. Each release lists what it ships, what it unlocks for a buyer, and what it depends on. Items move between releases by a dated entry in the log at the bottom; the design documents change first, this file second. + +## Releases + +| Release | Theme | Ships | Buyer can now | Depends on | +|---|---|---|---|---| +| **0.1** | Skeleton | 11 objects, state machine guards, positions and permission sets, sharing and FLS, configuration seeds (M1) | Load a contract register with correct visibility | — | +| **0.2** | Launch to approval | Intake screen flow, routing, five-rung approval ladder with 会签, signature record and execution formalities, legal workbench, contract page, full demo data (M2) | Run intake → review → deviation → approval → execution → active end to end | 0.1 | +| **0.3** | After signature | Obligations, payment schedules, renewal and expiry sweeps, archive, four datasets, three dashboards, `en` + `zh-CN` (M3) | Manage the live book: what is due, what is late, what renews | 0.2 | +| **1.0** | Marketplace GA | E-signature (DocuSign first), HotCRM hand-off, AI participation (six skills, approver memo, MCP tool surface), legacy import, docs site, screenshots, marketplace listing (M4) | Install with one click and sell it as a standalone CLM | 0.3 · cloud AI tier for AI features | +| **1.x** | Widen the core | Adobe Acrobat Sign and Dropbox Sign connectors; sanctions and registry screening connectors; Slack notifications; Salesforce contract hand-off; self-serve report views | Fit more stacks without custom work | Platform connectors as they land | +| **2.0** | Document layer | Template-driven generation, redline comparison, print and PDF, inbound email to version | Draft and negotiate inside the product, not in Word attachments | Platform: document generation and editor, PDF (#9), inbound channels (#39) | +| **2.x** | Outside the wall | Counterparty portal, external auditor read-only access, first region pack (China: regional e-sign providers, local registry screening, seal circulation) | Let the other side and outside reviewers in; sell in a region with its own formalities | Platform: external portal (#27); extension-package install (ADR-0126) | + +## How items move + +1. A capability enters the roadmap only with a named buyer outcome and a named dependency. +2. Anything whose dependency is a **platform gap** stays in 2.0/2.x until the gap closes upstream; the gap is reported once to objectstack-ai/objectstack and referenced here, never patched in this repo. +3. A customer ask (`docs/requirements/`) with disposition **B** may pull an item forward; disposition **C** never touches the roadmap. +4. AI capabilities ship only when they run for real on the cloud tier and degrade honestly elsewhere; no roadmap item is "AI-ready" or "scaffolded". + +## Log + +- 2026-09-07 — Created. Global-first revision folded in: execution formalities replace the sealing module, DocuSign leads e-signature, region packs move to 2.x. diff --git a/docs/backlog/02-contract-domain.md b/docs/backlog/02-contract-domain.md index 45f5794..c864842 100644 --- a/docs/backlog/02-contract-domain.md +++ b/docs/backlog/02-contract-domain.md @@ -4,39 +4,40 @@ Milestone: M1 · Labels: `pm:queue` · Blocked-by: — (builds on the initial co ## Scope `src/objects/contract.object.ts`, `contract-version.object.ts`, `review.object.ts`, `deviation.object.ts`, -`seal-request.object.ts`, plus `contract.hook.ts` (state machine) and `mirror.hook.ts` (display_name +`signature.object.ts`, plus `contract.hook.ts` (state machine) and `mirror.hook.ts` (display_name stamps). Export from `src/objects/index.ts` under the "Contract domain" comment, `Contract` first. ## Spec — pinned in DESIGN.md §03, repeated here where a choice exists **`clm_contract`** — `sharingModel: 'private'`, `nameField: 'title'`, icon `file-signature`. Fields exactly as DESIGN.md §03, with these decisions taken: -- `contract_number`: **text, stored, generated by the hook** (DESIGN.md §13 Q5 — `autonumber` cannot express +- `contract_number`: **text, stored, generated by the hook** (ruled 2026-09-07, DESIGN.md §13 Q5 — `autonumber` cannot express `--`). Format `${type.code}-${year}-${4-digit seq per type per year}`, stamped beforeInsert, readonly, unique index `(contract_number)` scope organization. -- `category`, `direction`, `requires_seal`: stamped from `contract_type` beforeInsert/beforeUpdate, readonly. -- `amount`: currency, scale 2, min 0. `currency_code`: select seeded (`CNY` default, `USD`, `EUR`). +- `category`, `direction`, `execution_formalities`: stamped from `contract_type` beforeInsert/beforeUpdate, readonly. +- `amount`: currency, scale 2, min 0. `currency_code`: select seeded (`USD` default, `EUR`, `GBP`, `CNY`, `JPY`); the organization default is a setting, not schema. Add `governing_law` (text, ISO country or state, e.g. `US-NY`, `England and Wales`), `jurisdiction` (text), `contract_language` (select seeded `en` default). - `status`: select with the exact values of the §03 state machine, default `draft`; every option carries a color. -- `route_*`, `approval_status`, stage timestamps (`submitted_at` … `closed_at`), `is_expiring`, `sealed_at`, +- `route_*`, `approval_status`, stage timestamps (`submitted_at` … `closed_at`), `is_expiring`, `executed_at`, `archived_at`: readonly, hook/flow-written only. - Lookups: `contract_type*` → `clm_contract_type`; `party*` → `clm_party`; `legal_owner` → `Field.user`; `renewed_from` / `parent_contract` → `clm_contract`; `crm_contract` → lookup `crm_contract` **only if** `objectstack validate` accepts a cross-package reference to an object not in this stack — otherwise leave the field out and return `needs_decision` naming the refusal. +- `is_backfilled` boolean, readonly, default false — set only by the F16 `executed_upload` action (card 09). - Roll-ups (`version_count`, `open_deviation_count`, `planned_amount`, `actual_amount`, `overdue_obligation_count`) are **card 03** — declare nothing here. **Children** — all `sharingModel: 'controlled_by_parent'`, `nameField: 'display_name'`, `contract*` masterDetail `clm_contract` with `deleteBehavior: 'cascade'`, `inlineEdit: 'grid'`: `clm_contract_version` (icon `file-stack`, inlineTitle `Versions`) · `clm_review` (icon `gavel`, `Reviews`) · -`clm_deviation` (icon `git-branch`, `Deviations`) · `clm_seal_request` (icon `stamp`, `Seal Requests`). +`clm_deviation` (icon `git-branch`, `Deviations`) · `clm_signature` (icon `pen-line`, `Signatures`) — one execution record per signing round: `method` `esign/wet_ink`, `provider`, `envelope_id`, `signers` json (`[{ side: our|counterparty, name, email, order, status, signed_at }]`), `status` `draft/sent/completed/declined/voided`, `formalities_done` multiselect mirroring the type's `execution_formalities`, `completed_at`, `executed_file` file. Fields and enums exactly as DESIGN.md §03. `display_name` is a stored text mirror stamped by `mirror.hook.ts` with the format DESIGN.md gives per object. **State machine** — `contract.hook.ts`, beforeUpdate on `status`: the transition table of DESIGN.md §03, including every guard (required intake fields, party not `blocked`, no `open` deviation before -`in_approval`, `clean` version before `signing`, `final_signed` + `sealed_at` before `active`, `closed_at` +`in_approval`, `clean` version before `signing`, a `completed` signature whose `formalities_done` covers the type's `execution_formalities` + `final_signed` version before `active`, `closed_at` on `terminated`). Refuse with a structured error (`code`, `status: 422`) — never silently coerce. -Stamp the stage timestamp on each entry. Child state machines (deviation, seal request) in the same file. +Stamp the stage timestamp on each entry. Child state machines (deviation, signature) in the same file. ## Acceptance - Gates green; `pnpm validate` reports 9 objects. diff --git a/docs/backlog/04-security.md b/docs/backlog/04-security.md index 71fc40c..0609486 100644 --- a/docs/backlog/04-security.md +++ b/docs/backlog/04-security.md @@ -3,15 +3,15 @@ Milestone: M1 · Labels: `pm:queue` · Blocked-by: 02, 03 ## Scope -`src/profiles/*.profile.ts` (6 permission sets), `src/sharing/positions.ts` (8 positions), -`src/sharing/*.sharing.ts` (7 rules), FLS declarations, `src/security/bind-position-sets.ts` + +`src/profiles/*.profile.ts` (5 permission sets), `src/sharing/positions.ts` (7 positions), +`src/sharing/*.sharing.ts` (6 rules), FLS declarations, `src/security/bind-position-sets.ts` + `onEnable` in `objectstack.config.ts`. Adds `requires: ['sharing']`. ## Spec — DESIGN.md §04, verbatim -Positions, sets, the permission matrix, the seven sharing rules and the FLS table are pinned there. +Positions, sets, the permission matrix, the six sharing rules and the FLS table are pinned there (global-first revision, 2026-09-07: no seal keeper; `clm_records_manager` covers execution and archive). Capabilities granted via `systemPermissions`: `clm_requester.access` · `clm_legal.access` · `clm_finance.access` -· `clm_seal.access` · `clm_archive.access` · `clm_admin.access`; action gates `approve_contract` · -`seal_contract` · `archive_contract` · `terminate_contract` · `manage_clauses` · `manage_approval_rules`. +· `clm_records.access` · `clm_admin.access`; action gates `approve_contract` · +`execute_contract` · `archive_contract` · `terminate_contract` · `manage_clauses` · `manage_approval_rules`. `contract_manager_reports` uses `writeScope: 'own_and_reports'` **only if** declaring it does not require the `hierarchy-security` capability at validate time; if it does, declare the capability (it is safe on an open-edition boot — see HotCRM's `objectstack.config.ts` note) and record the edition boundary in the PR. diff --git a/docs/backlog/05-intake-and-route.md b/docs/backlog/05-intake-and-route.md index cd299a0..4f4de22 100644 --- a/docs/backlog/05-intake-and-route.md +++ b/docs/backlog/05-intake-and-route.md @@ -13,7 +13,7 @@ type's `intake_fields` lists (`visibleWhen`/`requiredWhen` on the screen fields) tick "draft from template" (which attaches the type's `template_file` as version 1 with kind `draft`) → create `clm_contract` (`draft`) + `clm_contract_version` v1 → optional "submit now" toggle → `submitted`. Declare `ai: { exposed: true }` with every input as an `isInput` variable so MCP can complete it headlessly. -F2 (hook, entering `submitted`): stamp category/direction/requires_seal; evaluate active +F2 (hook, entering `submitted`): stamp category/direction/execution_formalities; evaluate active `clm_approval_rule` rows (category ∈ applies_to or empty; direction match or `any`; amount band; `only_with_deviation`) and stamp the union of `route_*`; `submitted_at`; if the type requires legal review, assign `legal_owner` round-robin among holders of `clm_legal_counsel` by open-contract count and enter diff --git a/docs/backlog/06-approval-ladder.md b/docs/backlog/06-approval-ladder.md index 96963db..f0a492a 100644 --- a/docs/backlog/06-approval-ladder.md +++ b/docs/backlog/06-approval-ladder.md @@ -1,9 +1,9 @@ -# F5 approval ladder · F7 seal request approval +# F5 approval ladder · F7 signature record and execution formalities Milestone: M2 · Labels: `pm:queue` · Blocked-by: 04 ## Scope -`src/flows/contract-approval.flow.ts` (F5), `src/flows/seal-request-approval.flow.ts` (F7). +`src/flows/contract-approval.flow.ts` (F5), `src/flows/signature-record.flow.ts` (F7). Adds `requires: ['approvals', 'messaging']`. ## Spec — DESIGN.md §06 F5/F7 @@ -15,8 +15,7 @@ neither → skip. Decision `route_executive` → position `clm_executive`. Decis `clm_general_manager`. `lockRecord: true`, `approvalStatusField: 'approval_status'`. Out-edges: approve → `update_record` status `approved` + `approved_at`; reject → `rejected`; send-back → `draft`. `notify` the owner on every terminal outcome (inbox). Approving is gated on `approve_contract`. -F7: `record_change` on `clm_seal_request` create → approval by `clm_legal_head` → `approved` + notify -`clm_seal_keeper` holders; keeper's transition to `sealed` stamps the parent's `sealed_at` (hook). +F7: `record_change` on `clm_signature` reaching `completed` → hook checks `formalities_done` against the type's `execution_formalities`; when covered, stamp the parent's `executed_at` and create the `final_signed` version from `executed_file`; when a formality is missing, notify legal (`clm_legal_counsel` owner) naming it. Wet-ink path: legal uploads the executed copy on the signature record and ticks the formalities. ## Acceptance - Gates green; `os lint` shows no `approval-approver-not-membership-tier`. diff --git a/docs/backlog/08-seed-data.md b/docs/backlog/08-seed-data.md index 3ea24ae..7399005 100644 --- a/docs/backlog/08-seed-data.md +++ b/docs/backlog/08-seed-data.md @@ -1,10 +1,10 @@ -# Seed data: `demo-zh` (default) and `demo-en` +# Seed data: `demo-en` (default) and `demo-zh` Milestone: M2 · Labels: `pm:queue` · Blocked-by: 03 ## Scope -`src/data/demo-zh/`, `src/data/demo-en/`, `src/data/index.ts` selecting by `OS_SEED_LOCALE` -(default `zh`), `pnpm demo` / `pnpm demo:en` scripts as Duly does. +`src/data/demo-en/`, `src/data/demo-zh/`, `src/data/index.ts` selecting by `OS_SEED_LOCALE` +(default `en`), `pnpm demo` / `pnpm demo:zh` scripts as Duly does. ## Spec — DESIGN.md §10 One fictional company, six months of history, the counts in the §10 table, the status spread for @@ -14,7 +14,8 @@ positions to assign after creating users. Dynamic dates relative to boot (`daysF never ages. Industry-neutral schema: the company's industry shows only in names and descriptions. ## Acceptance -- `pnpm demo` on a clean checkout boots with every list non-empty; `pnpm demo:en` is row-for-row identical. +- `pnpm demo` on a clean checkout boots with every list non-empty; `pnpm demo:zh` is row-for-row identical. +- The fictional company is a multi-entity group (US parent, EU and APAC subsidiaries) with contracts in USD, EUR and GBP, governing law spread across US-NY, England and Wales, and Germany. - No seeded value that looks computed (roll-ups are recomputed by the engine, not seeded). ## Out of scope diff --git a/docs/backlog/09-post-signature-jobs.md b/docs/backlog/09-post-signature-jobs.md index 673f1f2..05dfa6a 100644 --- a/docs/backlog/09-post-signature-jobs.md +++ b/docs/backlog/09-post-signature-jobs.md @@ -5,7 +5,7 @@ Milestone: M3 · Labels: `pm:queue` · Blocked-by: 04 ## Scope `src/objects/contract.hook.ts` (F9, F14), `src/flows/obligation-due.flow.ts` (F10), `payment-overdue.flow.ts` (F11), `renewal-notice.flow.ts` (F12), `expiration-sweep.flow.ts` (F13), -`legal-review-sla.flow.ts` (F3), `turn-stalled.flow.ts` (F4). +`legal-review-sla.flow.ts` (F3), `turn-stalled.flow.ts` (F4), and the `executed_upload` action (F16, DESIGN.md §13 Q8): a records/legal-only action that creates an already-executed contract straight into `active` with `is_backfilled = true`, skipping review and approval, fully audited. ## Spec — DESIGN.md §06 Exactly the behaviors in the table. All scheduled flows `runAs: 'system'` with the reason stated; diff --git a/docs/backlog/11-i18n.md b/docs/backlog/11-i18n.md index 49d3e3b..b30c2b9 100644 --- a/docs/backlog/11-i18n.md +++ b/docs/backlog/11-i18n.md @@ -1,16 +1,17 @@ -# Translations: `zh-CN` (default) and `en` +# Translations: `en` (default) and `zh-CN` Milestone: M3 · Labels: `pm:queue` · Blocked-by: 07 ## Scope -`src/translations/{zh-CN,en}/*.ts`, `i18n` block in `objectstack.config.ts` -(`defaultLocale: 'zh-CN'`, `supportedLocales: ['zh-CN', 'en']`, `fallbackLocale: 'en'`), +`src/translations/{en,zh-CN}/*.ts`, `i18n` block in `objectstack.config.ts` +(`defaultLocale: 'en'`, `supportedLocales: ['en', 'zh-CN']`, `fallbackLocale: 'en'`), `pnpm lint:i18n-gate` script modeled on HotCRM's `scripts/check-lint-i18n-gate.mjs`. ## Spec Every object, field, option, view, page, app navigation item, action, flow screen label and dashboard -label has both bundles; the gate fails on a missing key. Chinese copy follows the plain-language rules -(no internal codenames, no raw exception text, three-part error messages). +label has both bundles; the gate fails on a missing key. English is the source language and every label is +authored in English first; Chinese copy follows the plain-language rules (no internal codenames, no raw +exception text, three-part error messages). ## Acceptance - Gates green including the i18n gate; switching locale in the Console shows no mixed-language screen. diff --git a/docs/backlog/12-esign-and-crm-handoff.md b/docs/backlog/12-esign-and-crm-handoff.md index f05b128..d3a3669 100644 --- a/docs/backlog/12-esign-and-crm-handoff.md +++ b/docs/backlog/12-esign-and-crm-handoff.md @@ -13,8 +13,7 @@ one flow. F8 dispatch: durable `http` node (`durable: true`) posting the current `clean` version and the signers to the configured provider; callback is an `api`-triggered flow that maps envelope status to `esign_status`, creates the `final_signed` version and stamps `signed_at` on completion. No e-signature -engine is built here — the platform has none (spec 17). Providers: Docusign first; 契约锁 / 法大大 / -e签宝 as further connector definitions with the same contract. +engine is built here — the platform has none (spec 17). Providers: DocuSign first, then Adobe Acrobat Sign and Dropbox Sign; regional providers (e.g. 契约锁, 法大大, e签宝 for China) are further connector definitions with the same contract, shipped as region packs. F15: `record_change` on `crm_contract` entering `in_approval` creates `clm_contract` (direction `sales`, party find-or-create from `crm_account`, amount/dates pre-filled, `crm_contract` back-link). diff --git a/docs/backlog/13-ai-skills.md b/docs/backlog/13-ai-skills.md index 439cf50..5723ed1 100644 --- a/docs/backlog/13-ai-skills.md +++ b/docs/backlog/13-ai-skills.md @@ -1,10 +1,13 @@ -# S1–S4 skills with honest degradation +# AI participation: S1–S6 skills, the pre-review memo, MCP tool surface, honest degradation Milestone: M4 · Labels: `pm:queue` · Blocked-by: 05 ## Scope -`src/skills/{extract-terms,review-summary,deviation-check,contract-qa}.skill.ts`; the actions they call; -UI affordances gated on the `ai` capability being present at runtime. +`src/skills/{extract-terms,review-summary,deviation-check,contract-qa,obligation-extract,approver-memo}.skill.ts`; +the `ai.exposed` actions they call; the `ai_summary` / `ai_risk_score` / `ai_risk_rationale` / `ai_reviewed_at` +fields on `clm_contract` (proposed by S6, written only on confirmation); the MCP tool surface (launch, status, +obligations due, search) — see DESIGN.md §07 for the full map and the governance rules; UI affordances gated on +the `ai` capability being present at runtime. ## Spec — DESIGN.md §07 Skills-only surface attached to the platform `ask` assistant by `surface` (ADR-0063); no app agents. diff --git a/docs/backlog/README.md b/docs/backlog/README.md index 93bf364..4e8c31d 100644 --- a/docs/backlog/README.md +++ b/docs/backlog/README.md @@ -12,18 +12,18 @@ dispatch is worth anything. | Card | Title | Milestone | Blocked by | |:--|:--|:--|:--| | ~~01~~ | Scaffold · configuration domain (`clm_contract_type`, `clm_clause`, `clm_approval_rule`, `clm_party`) | M1 | **landed** | -| [02](./02-contract-domain.md) | Contract domain: `clm_contract`, `clm_contract_version`, `clm_review`, `clm_deviation`, `clm_seal_request` + state-machine hooks | M1 | — | +| [02](./02-contract-domain.md) | Contract domain: `clm_contract`, `clm_contract_version`, `clm_review`, `clm_deviation`, `clm_signature` + state-machine hooks | M1 | — | | [03](./03-post-signature-domain.md) | Post-signature domain: `clm_obligation`, `clm_payment_plan` + roll-ups | M1 | 02 | | [04](./04-security.md) | Positions, permission sets, sharing rules, FLS, `onEnable` bindings | M1 | 02, 03 | | [05](./05-intake-and-route.md) | F1 intake screen flow · F2 route hook · F6 deviation gate | M2 | 04 | -| [06](./06-approval-ladder.md) | F5 approval ladder · F7 seal request approval | M2 | 04 | +| [06](./06-approval-ladder.md) | F5 approval ladder · F7 signature record and formalities | M2 | 04 | | [07](./07-views-and-app.md) | Views, contract detail page, the one App with five audience groups | M2 | 04 | | [08](./08-seed-data.md) | Seed data: `demo-zh` (default) and `demo-en` | M2 | 03 | | [09](./09-post-signature-jobs.md) | F9 activation · F10–F14 scheduled jobs (obligations, payments, renewal, expiry, archive) | M3 | 04 | | [10](./10-analytics.md) | Four datasets, three dashboards | M3 | 08 | -| [11](./11-i18n.md) | Translations `zh-CN` (default) and `en` | M3 | 07 | +| [11](./11-i18n.md) | Translations `en` (default) and `zh-CN` | M3 | 07 | | [12](./12-esign-and-crm-handoff.md) | F8 e-signature connector · F15 HotCRM hand-off behind `CLM_COMPOSITION` | M4 | 06, 09 | -| [13](./13-ai-skills.md) | S1–S4 skills with honest degradation | M4 | 05 | +| [13](./13-ai-skills.md) | AI participation: S1–S6 skills, the pre-review memo, MCP tool surface, honest degradation | M4 | 05 | | [14](./14-release.md) | Release: docs site, screenshots, feature inventory, marketplace publish | M4 | 10, 11, 12, 13 | Every card inherits the same acceptance floor: `pnpm validate && pnpm lint && pnpm typecheck` green, diff --git "a/docs/design/00-\350\256\276\350\256\241\346\226\271\346\241\210.md" "b/docs/design/00-\350\256\276\350\256\241\346\226\271\346\241\210.md" new file mode 100644 index 0000000..166088e --- /dev/null +++ "b/docs/design/00-\350\256\276\350\256\241\346\226\271\346\241\210.md" @@ -0,0 +1,610 @@ +
+ +# HotCLM 合同全生命周期管理 + +# 设计方案 + +**版本号:V1.0(一期基准)** + +**发布日期:2026 年 09 月 07 日** + +**编制方:ObjectStack 产品组(AI 架构师)** + +**审阅方:维护者** + +
+ +--- + +## 版本记录 + +| 版本号 | 日期 | 修订说明 | 编制人 | 审核 / 确认 | +|---|---|---|---|---| +| V0.9 | 2026-09-07 | 首版送审稿:依据仓库 `DESIGN.md`(架构蓝图)展开为完整业务设计;参照 Ironclad(流程与发起)、Sirion(签后管理)、Agiloft(可配置性);含 14 项待确认事项 | AI 架构师 | 已被 V0.10 取代 | +| V0.10 | 2026-09-07 | 按维护者三条意见修订:① 设计基于全球客户而非中国客户 —— 用印改为可配置的「执行形式」之一,电子签、相对方筛查、通知通道、默认币种与语言全部改为全球通行做法,区域差异走区域包;② 新增第 10 章「AI 融合设计」;③ 新增第 11 章「与 Agiloft 的差距」;待确认事项增至 16 项;原第 10~14 章顺延为第 12~16 章 | AI 架构师 | 维护者 2026-09-07 确认 | +| V1.0 | 2026-09-07 | 维护者对第 13 章 16 项全部回复「同意默认」,第 13 章改为「已确认口径」,本版即一期需求基准;`DESIGN.md` §13 同步记录裁定并落实第 5 项编号规则与第 12 项补录通道;进入 M1 开发 | AI 架构师 | 维护者书面确认(2026-09-07) | + +依据文件:`DESIGN.md`(2026-09-07,架构权威);ObjectStack 平台 17.3 能力与 `docs/PLATFORM_GAPS_FROM_TEMPLATES.md` 缺口清单;HotCRM 3.0 的 `crm_contract` 定义。 + +--- + +## 目录 + +1. 一页纸摘要 +2. 建设目标与范围 +3. 角色与数据范围 +4. 核心业务流程 +5. 功能模块设计 +6. 业务对象总览 +7. 规则设计 +8. 权限与安全 +9. 集成设计 +10. AI 融合设计 +11. 与 Agiloft 的差距 +12. 非功能与运维基线 +13. 已确认口径 +14. 实施与迭代计划 +15. 当前状态 +16. 确认方式 + +--- + +# 1. 一页纸摘要 + +- **做什么**:一套面向企业法务、财务、合规与业务部门的合同全生命周期管理系统,把「发起 → 法务审查 → 条款偏离 → 审批 → 签署与执行 → 生效 → 履约义务与收付款 → 变更续签 → 到期终止 → 归档台账」全流程搬到线上,替代现在靠 Word 附件、群聊和 Excel 台账来回传递的做法。买卖双边合同与非交易类合同一并覆盖。 +- **怎么做**:基于 ObjectStack 元数据平台构建。组织、账号、权限、审计、附件、审批收件箱、导入导出、通知直接复用平台;合同专属的流程配置、审批矩阵、状态机、条款库、履约与收付款由本系统以元数据内置,口径改动只改配置不改代码。 +- **三条产品原则**(取自 Ironclad):业务自助发起、法务把关不当瓶颈;合同类型即流程,新增一种合同是加一条配置;合同是数据不是文件,义务、付款、到期都是可查询可提醒的记录。 +- **全球优先**:英文为默认与源语言;多签约主体、多币种;每份合同带适用法律与管辖;电子签是默认执行方式,公司印章、公证、见证只是类型可配置的「执行形式」;区域差异(中国的电子签提供商、本地登记库、印章流转)走区域包,标准品零区域词汇。 +- **AI 是参与者**:发起、导入抽取、审查摘要、偏离检测、审批备忘录、合同库问答六项能力,全部在「同权限同审计、只建议人采纳、无运行时则隐藏」三条治理原则之下;应用本身对外是 MCP 工具面,客户可用 AI 改配置。 +- **与 HotCRM 的关系**:独立产品,可单装。商务信息(金额、期限、续约)以 HotCRM 的销售合同为准,法律状态(审批、执行、履约、归档)以本系统为准;两者并装时销售合同自动交接、签署后自动回写。 +- **不做什么**:在线红线编辑器(二期)、电子签引擎(只集成)、供应商准入评价(SRM)、应收应付账(财务系统)。 +- **现状**:仓库 `objectstack-ai/hotclm` 已建立,配置域四个对象与十四张开发卡片已落地;本文 V1.0 已确认,M1 开发已派发。 + +# 2. 建设目标与范围 + +**目标**:合同口径统一(一份台账、一套编号、一套状态);流程按合同类型可配置;发起到归档全程线上、全程留痕;到期、履约、付款主动提醒而不是靠人记;法务工作量可度量。 + +**范围**: + +| 域 | 内容 | +|---|---| +| 配置 | 合同类型与流程定义、条款库与立场、审批矩阵、相对方主数据、签约主体与部门字典 | +| 签前 | 业务发起表单、法务受理与分派、审查意见、条款偏离、谈判轮次与版本、审批台阶、电子签与执行形式 | +| 签后 | 生效、履约义务、收付款计划与核对、变更补充、续签、到期与终止、归档与台账 | +| 支撑 | 存量合同导入、通知、看板报表、AI 参与(第 10 章)、MCP 工具面、与 HotCRM 交接、区域包 | + +## 2.1 全球优先的设计约束 + +| 约束 | 做法 | +|---|---| +| 语言 | 英文为默认与源语言,简体中文为完整第二语言;界面、文档、演示数据先有英文版 | +| 主体与币种 | 签约主体多个,合同级币种,组织级默认币种是设置不是结构,出厂 USD | +| 法域 | 每份合同带适用法律、管辖与合同语言;相对方带国家代码 | +| 执行 | 电子签为默认执行方式,法律效力由 ESIGN / eIDAS 等框架下的提供商承担;回签副本、公司印章、公证、见证是类型可配置的执行形式 | +| 相对方筛查 | 制裁名单(OFAC、EU、UK)与公司登记核验(OpenCorporates、Dun & Bradstreet)走连接器,可选 | +| 数据保护 | 类型级保留年限与处置,满足 GDPR 存储限制;导出与删除按平台数据主体流程 | +| 区域包 | 中国等区域差异(电子签提供商、本地登记库、印章流转)以扩展包装配,标准品零区域词汇 | + +**不在本期范围**:在线起草与红线比对编辑器;电子签引擎自建;供应商准入、评价与考核;应收应付账与发票开具;法律案件与诉讼管理;相对方在线门户(平台外部门户能力尚缺);区域包本身(随首个区域客户立项)。 + +**范围分级**:一期(M1–M3)、一期补强(M4)、二期、产品化候选四档,各项归属见第 14 章表 17。 + +# 3. 角色与数据范围 + +**表 1 角色与数据范围** + +| 角色 | 在系统里做什么 | 能看到的范围 | +|---|---|---| +| 业务承办 | 发起合同、补充材料、催办、跟踪履约、确认收付款事实 | 本人发起或负责履约的合同 | +| 法务经办 | 受理、审查、登记偏离、上传对方版本、发起签署、登记执行形式、维护条款库 | 全部合同 | +| 法务负责人 | 高风险偏离审批、分派与改派、SLA 超期处理 | 全部合同 | +| 财务负责人 | 财务口径审批(会签)、维护收付款计划、登记实际收付 | 审批通过及之后阶段的合同 | +| 分管领导 / 总经理 | 大额与高风险合同审批 | 路由到本人的合同 | +| 档案与记录管理员 | 登记执行形式与执行副本、归档编号、台账导出、保留期管理 | 签署阶段及之后的合同 | +| 系统管理员 | 维护合同类型、审批矩阵、签约主体、部门与岗位 | 全部 | + +数据范围的实现方式:系统按「谁发起、谁经办、谁被路由到」和「岗位」自动放开可见范围,人员变动只改岗位分配不改配置;越权访问被明确拒绝;经办人、审批人、执行登记人以登录账号为准,由系统盖章,不能手工填写。 + +# 4. 核心业务流程 + +```mermaid +flowchart LR + A[草稿] -->|提交| B[已提交] + B -->|法务受理| C[审查中] + B -->|类型免审| D[审批中] + C -->|无未决偏离| D + D -->|台阶全部通过| E[已批准] + E -->|发起签署| F[签署中] + F -->|签妥且执行形式齐备| G[生效] + G -->|到期扫描| H[已到期] + G -->|终止| I[已终止] + C -->|退回| A + D -->|退回或驳回| A + F -->|签署失败| E +``` + +图 1 合同主流程与状态(自左向右推进;退回回到草稿;终态为已到期、已终止、已作废) + +**表 2 流程步骤与系统保证** + +| 步骤 | 谁 | 做什么 | 系统保证 | +|---|---|---|---| +| 1 发起 | 业务承办 | 选合同类型 → 填该类型要求的字段 → 选或建相对方 → 上传首版或按模板起草 → 提交 | 类型必填项齐全、相对方非黑名单、至少一个版本,否则不能提交并逐条提示;提交即盖发起时间、自动编号 | +| 2 受理与路由 | 系统 | 按合同类型与审批矩阵计算审批路径;免审类型直达审批;需审类型按未结合同数最少分派法务经办 | 路由结果写在合同上只读;分派可由法务负责人改派 | +| 3 法务审查 | 法务经办 | 出审查意见(通过 / 要求修改 / 驳回)、登记条款偏离、上传对方红线、记录轮次 | 存在未决偏离不能送审;审查超 SLA 自动提醒并升级 | +| 4 审批 | 直接主管 → 法务负责人 / 财务负责人(会签)→ 分管领导 → 总经理 | 在审批收件箱审批、退回修改或驳回 | 只走矩阵命中的台阶;审批期间合同锁定;任一驳回即终止链路;每一步谁、何时、意见全部留痕 | +| 5 签署与执行 | 法务经办、档案与记录管理员 | 发起电子签或线下签署;登记类型要求的执行形式(回签副本、公司印章、公证、见证) | 执行形式未齐不能生效;签妥版本为终版,此后版本只读 | +| 6 生效 | 系统 | 盖生效时间;按类型默认生成续签提醒义务;按发起时填写的付款安排生成收付款计划;并装 HotCRM 时回写 | 生效后核心条款只读,改动走补充协议 | +| 7 履约 | 业务承办、财务 | 完成义务并上传证据;登记实际收付 | 到期前 7 天与当天提醒;逾期自动标红并汇总到合同 | +| 8 续签 / 终止 / 到期 | 业务承办、法务、系统 | 提前 N 天收到续签提醒,一键发起续签草稿;终止需原因;到期由系统扫描 | 续签是新合同并回链原合同;自动续签类型到期自动生成续签草稿 | +| 9 归档 | 档案管理员 | 填归档编号,导出台账 | 终态且归档后除备注外只读;按类型保留期管理 | + +## 4.1 分支流程 + +| 分支 | 触发 | 处理 | +|---|---|---| +| 法务退回 | 审查意见为「要求修改」 | 合同回到草稿,发起人修改后重新提交,轮次加一 | +| 审批退回修改 | 审批人选择「退回」 | 区别于驳回:回到草稿保留审批记录,重提后从第一台阶重走 | +| 撤回 | 发起人或法务在生效前作废 | 进入已作废终态,理由必填 | +| 补充协议 | 生效合同需要变更 | 新建合同,类型为补充协议,主合同回链;走独立的审批矩阵 | +| 续签 | 到期提醒或手工发起 | 预填原合同信息生成新草稿,`renewed_from` 回链 | +| 先签后补 | 业务已在线下签署 | 见第 13 章第 12 项(待确认) | + +# 5. 功能模块设计 + +## 5.1 合同类型与流程配置 + +- **界面**:类型列表(名称、编号前缀、方向、类别、是否法务审查、签署方式、执行形式、状态),类型详情四页签:基本信息 / 流程(发起字段、法务审查、签署方式、执行形式、审查 SLA)/ 模板(模板文件、占位符清单)/ 默认与保留(默认期限、保留年限)。 +- **规则**:编号前缀在组织内唯一;停用不删除,存量合同保留类型;类别是流程分类,与 HotCRM 的商务类型不对齐(第 13 章第 6 项)。 +- **出厂种子**:NDA、MSA、SOW、订单、供应商协议、数据处理协议(DPA)、租赁、独立承包人、补充协议九种。 + +## 5.2 发起合同(Launch Form) + +**表 3 发起表单设计** + +| 步 | 字段 | 规则 | +|---|---|---| +| 1 选类型 | 合同类型(仅启用的) | 选定后决定后续字段与流程 | +| 2 基本信息 | 标题、签约主体、部门、金额与币种、是否估算金额、起止日期或期限、摘要 | 核心字段恒必填;类型 `intake_fields` 列出的可选字段(适用法律、付款条款、保密期限、责任上限、自动续约、主合同)按类型显隐与必填 | +| 3 相对方 | 搜索相对方;不存在则内联新建(名称、类型、登记号、联系人) | 黑名单相对方拒绝选择并提示原因;观察名单允许但标记 | +| 4 文件 | 上传首版文件,或勾选「按模板起草」 | 勾选模板时把类型的模板文件与占位符清单作为 v1 挂上,由起草人填写后替换 | +| 5 付款安排(可选) | 期数、计划日期、计划金额、条件 | 生效时自动生成收付款计划 | +| 6 提交 | 「保存草稿」或「立即提交」 | 提交即路由;提交后核心字段锁定,修改需法务退回 | + +发起表单是平台的屏幕流,对 AI 开放:输入齐全时可由助手或 MCP 无界面完成,与人工发起走同一条校验。 + +## 5.3 法务受理与审查 + +- **界面**:法务工作台四个队列:待受理(已提交未分派)、审查中(我经办)、谈判中(球在对方)、超期。合同详情页的「审查与偏离」页签:审查意见列表(阶段、审查人、结论、对外意见、内部备注)、偏离列表(条款、偏离内容、申请立场、理由、状态)。 +- **规则**:受理即分派法务经办并进入审查中;审查结论三种:通过、要求修改(退回草稿)、驳回(作废);内部备注对发起人不可见;至少一条法务「通过」且无未决偏离方可送审;审查 SLA 按类型天数计,超期提醒经办,超一倍抄送法务负责人。 + +## 5.4 条款库与偏离(Playbook) + +- **界面**:条款库列表(标题、类别、风险级别、适用类别、状态),条款详情三栏:标准文本 / 备选文本 / 底线说明。 +- **规则**:偏离登记在合同上,引用一条条款,记录对方要求的立场(标准 / 备选 / 自定义)与理由;偏离状态:待决 → 接受 / 拒绝 / 撤回;接受了「需法务负责人」条款的偏离,自动把法务负责人台阶加入审批路径;有任何待决偏离不能送审。 + +## 5.5 谈判与版本 + +- **界面**:详情页「版本」页签为时间线:版本号、类型(草稿 / 我方红线 / 对方红线 / 清稿 / 签妥终版)、提交人、轮次、备注、文件。 +- **规则**:上传对方红线即把「当前轮次」记为我方,上传我方红线记为对方;球在对方超过 7 天提醒业务承办催办;送签必须存在一份清稿;签妥终版只能由签署流程或档案与记录管理员登记,登记后所有版本只读。 + +## 5.6 审批矩阵与审批台阶 + +审批路径固定五级台阶:直接主管 → 法务负责人 → 财务负责人 → 分管领导 → 总经理。矩阵决定一份合同走哪几级,法务与财务同时命中时为会签(各出一人,任一驳回即终止)。 + +**表 4 审批矩阵出厂样例(可整表改配置)** + +| 规则 | 适用类别 | 方向 | 金额区间 | 仅含偏离 | 法务负责人 | 财务负责人 | 分管领导 | 总经理 | +|---|---|---|---|---|---|---|---|---| +| 小额 | 全部 | 任意 | < 10 万 | 否 | | | | | +| 中额 | 全部 | 任意 | 10 万 ≤ x < 100 万 | 否 | | ✓ | | | +| 大额 | 全部 | 任意 | 100 万 ≤ x < 500 万 | 否 | ✓ | ✓ | ✓ | | +| 特大额 | 全部 | 任意 | ≥ 500 万 | 否 | ✓ | ✓ | ✓ | ✓ | +| 高风险偏离 | 全部 | 任意 | 不限 | 是 | ✓ | | | | +| NDA 免财务 | NDA | 任意 | 不限 | 否 | | | | | + +命中多条时取台阶的并集;直接主管恒为第一台阶。 + +**表 5 三份合同的审批路径示例** + +| 合同 | 金额 | 偏离 | 命中规则 | 实际路径 | +|---|---|---|---|---| +| 与某供应商的采购合同 | 8 万 | 无 | 小额 | 直接主管 | +| 与某客户的销售合同 | 260 万 | 无 | 大额 | 直接主管 → 法务负责人 与 财务负责人 会签 → 分管领导 | +| 与某客户的框架合同 | 120 万 | 责任上限条款偏离(高风险) | 大额 + 高风险偏离 | 直接主管 → 法务负责人 与 财务负责人 会签 → 分管领导 | + +- **规则**:审批期间合同锁定;审批人可「通过」「退回修改」「驳回」;退回回草稿保留记录,驳回进入已驳回可修改重提;不在岗委派与批量审批由平台审批收件箱提供;审批结论镜像到合同的审批状态字段供列表筛选。 + +## 5.7 签署与执行 + +- **电子签(默认)**:法务在已批准合同上「发起电子签」,选择提供商与签署方(我方签约主体、相对方联系人、签署顺序),系统把清稿送至提供商生成信封;回调把状态写回签署记录,完成时自动登记签妥终版并盖签署时间。首发 DocuSign,随后 Adobe Acrobat Sign 与 Dropbox Sign;区域提供商作为区域包按同一契约追加。 +- **线下签署**:法务或档案与记录管理员上传签妥扫描件为执行副本,填签署日期。 +- **执行形式**:类型可要求回签副本、公司印章、公证、见证中的若干项;在签署记录上逐项勾选,缺项时系统点名提醒。多数类型为空;公司印章是中国、日本、韩国等地的常见形式,公证与见证是契据类文件的形式。 +- **规则**:签妥终版存在、类型要求的执行形式齐备、签署日期非空三者齐备方可生效;签署失败或拒签回到已批准;一轮签署一条记录,重签是新记录。 + +## 5.8 生效与履约义务 + +- **界面**:详情页「履约与收付款」页签:义务列表(标题、类型、到期日、负责人、状态、证据);「我负责的履约」列表按到期升序。 +- **规则**:生效时按类型默认生成续签提醒义务;义务类型:交付、付款、报告、续签、合规、其他;到期前 7 天与当天提醒负责人;逾期由日任务置为逾期并汇总到合同「逾期义务数」;完成需勾选并可上传证据;可豁免需说明。 + +## 5.9 收付款计划 + +- **界面**:财务「收付款计划」三视图:本月到期、逾期、已付;行内登记实际日期与金额。 +- **规则**:方向随合同(销售为收、采购为付);状态:计划 → 到期 → 部分 / 已付 / 逾期;逾期由日任务判定并提醒财务负责人与业务承办;合同汇总计划金额与实际金额;只做计划与事实登记,不做账。 + +## 5.10 变更、续签、终止 + +- 补充协议是一份新合同(类别为补充协议,主合同回链),走自己的审批矩阵,生效后在主合同详情页「关联合同」中并列显示。 +- 续签:到期前按类型或合同的提前天数提醒;「发起续签」预填原合同信息生成新草稿并回链;自动续签类型到期时系统自动生成续签草稿并提醒。 +- 终止:生效合同可终止,终止原因与终止日期必填;终止后义务与未付款项保留但标记。 + +## 5.11 到期与归档、台账 + +- 到期由每日扫描判定;非自动续签合同到期置为已到期。 +- 归档:终态合同由档案管理员填归档编号后归档;归档后除备注只读;保留期按类型年限计。 +- 台账:全字段列表可按类型、方向、部门、相对方、状态、到期区间筛选并导出 CSV / XLSX。 + +## 5.12 相对方管理 + +- 相对方独立于 HotCRM 客户:公司、个人、政府机构均可;登记号组织内唯一;联系人电话与银行账号受字段级保护。 +- 风险标记:无 / 观察 / 黑名单;黑名单不可用于新合同;配置了核验连接器时记录核验时间。 +- 并装 HotCRM 时可链到客户,销售合同交接时自动查找或新建。 + +## 5.13 存量合同导入 + +- 导入映射:合同台账(Excel)→ 合同、相对方按名称或登记号匹配或新建;已签合同直接进入生效或已到期,不走审批。 +- 云版可用 AI 抽取:上传 PDF 自动提出相对方、金额、起止日期、适用法律、付款条款,人工确认后写入。 +- 导入需档案管理员或系统管理员权限,全部行记审计。 + +## 5.14 通知清单 + +**表 6 通知事件与接收人** + +| 事件 | 接收人 | 通道 | +|---|---|---| +| 合同提交并分派 | 法务经办 | 站内 + 邮件 | +| 审查超 SLA | 法务经办;超一倍抄送法务负责人 | 站内 + 邮件 | +| 法务退回 / 驳回 | 业务承办 | 站内 + 邮件 | +| 审批待办 | 当前台阶审批人 | 站内 + 邮件(平台审批收件箱) | +| 审批通过 / 退回 / 驳回 | 业务承办、法务经办 | 站内 | +| 谈判停滞 7 天 | 业务承办 | 站内 | +| 执行形式缺项 | 法务经办、档案与记录管理员 | 站内 | +| 电子签完成 / 拒签 | 法务经办、业务承办 | 站内 + 邮件 | +| 合同生效 | 业务承办、财务负责人 | 站内 | +| 义务到期前 7 天 / 当天 / 逾期 | 义务负责人;逾期抄送业务承办 | 站内 + 邮件 | +| 付款逾期 | 财务负责人、业务承办 | 站内 + 邮件 | +| 续签提醒 | 业务承办、法务经办 | 站内 + 邮件 | +| 合同到期 / 自动生成续签草稿 | 业务承办 | 站内 | + +通道现状:站内、邮件、短信、Slack 为平台已实现通道;Microsoft Teams 与各区域即时通讯为平台缺口,本期不承诺(第 13 章第 10 项)。 + +## 5.15 看板与报表 + +**表 7 看板与指标定义** + +| 看板 | 指标 | 口径 | +|---|---|---| +| 法务工作台 | 待受理数、审查中数、超 SLA 数 | 实时计数 | +| 法务工作台 | 平均周转天数(本月 vs 上月) | 生效时间 − 提交时间,按生效月 | +| 法务工作台 | 各阶段合同数 | 按当前状态 | +| 法务工作台 | 谈判停滞数 | 球在对方超 7 天 | +| 管理层 | 生效合同额(按方向、按月) | 生效合同金额合计 | +| 管理层 | 90 天内到期合同数与金额 | 到期日在未来 90 天内的生效合同 | +| 管理层 | 高风险合同数 | 风险级别为高的生效合同 | +| 管理层 | 审批瓶颈 | 各台阶平均停留天数 | +| 财务 | 本月应收 / 应付 | 计划日期在本月的未付计划金额,按方向 | +| 财务 | 逾期金额 | 状态逾期的计划金额合计 | +| 财务 | 相对方未付 Top 10 | 按相对方合计未付 | + +报表:合同台账、审批记录明细、义务明细、收付款明细,均可按筛选导出。 + +## 5.16 AI 参与 + +AI 在每个阶段的能力、写入方式与治理规则见第 10 章;本节只记入口:发起表单可由助手对话或 MCP 调用完成;导入与生效时抽取条款与义务;审查时给版本变动摘要与偏离草案;进入审批时生成审批备忘录;助手可对合同库问答。所有能力只建议不直接写,开源版无 AI 运行时时不出现。 + +# 6. 业务对象总览 + +**表 8 业务对象总览** + +| 对象 | 说明 | 关系 | +|---|---|---| +| 合同类型 | 一种合同及其流程定义 | 合同引用它 | +| 条款 | 条款库:标准 / 备选 / 底线 | 偏离引用它 | +| 审批规则 | 审批矩阵的一行 | 路由时读取 | +| 相对方 | 合同的另一方 | 合同引用它;可链 HotCRM 客户 | +| 合同 | 主对象,携带状态、阶段时间戳与 AI 字段 | 版本、审查、偏离、签署记录、义务、收付款从属于它;续签与主合同自引用 | +| 合同版本 | 一份文件及其类型与轮次 | 从属于合同 | +| 审查意见 | 法务 / 财务 / 合规 / 业务的审查结论 | 从属于合同 | +| 条款偏离 | 对某条条款的偏离与决定 | 从属于合同,引用条款 | +| 签署记录 | 一轮签署:方式、提供商、信封、签署方、执行形式、执行副本 | 从属于合同 | +| 履约义务 | 一项到期事项 | 从属于合同 | +| 收付款计划 | 一期计划与实际 | 从属于合同 | +| 审批请求 / 审批动作(平台) | 审批链留痕 | 平台对象,引用合同 | +| 审计日志 / 活动 / 评论(平台) | 变更留痕、讨论 | 平台对象 | + +```mermaid +erDiagram + CONTRACT_TYPE ||--o{ CONTRACT : "类型" + PARTY ||--o{ CONTRACT : "相对方" + CONTRACT ||--o{ CONTRACT_VERSION : "版本" + CONTRACT ||--o{ REVIEW : "审查意见" + CONTRACT ||--o{ DEVIATION : "条款偏离" + CLAUSE ||--o{ DEVIATION : "引用条款" + CONTRACT ||--o{ SIGNATURE : "签署记录" + CONTRACT ||--o{ OBLIGATION : "履约义务" + CONTRACT ||--o{ PAYMENT_PLAN : "收付款计划" + CONTRACT o|--o| CONTRACT : "续签自 / 主合同" + APPROVAL_RULE }o--o{ CONTRACT : "路由时匹配" +``` + +图 2 对象关系(实体名为业务名;机器名见 `DESIGN.md` §03) + +# 7. 规则设计 + +## 7.1 合同状态机 + +```mermaid +stateDiagram-v2 + [*] --> draft + draft --> submitted : 提交 + submitted --> in_review : 法务受理 + submitted --> in_approval : 类型免审 + submitted --> draft : 退回 + in_review --> in_approval : 无未决偏离且审查通过 + in_review --> draft : 要求修改 + in_approval --> approved : 台阶全部通过 + in_approval --> rejected : 驳回 + in_approval --> draft : 退回修改 + approved --> signing : 存在清稿 + signing --> active : 终版 + 执行形式齐备 + 签署日期 + signing --> approved : 签署失败 + active --> expired : 到期扫描 + active --> terminated : 终止 + rejected --> draft : 修改重提 + draft --> cancelled : 作废 + submitted --> cancelled + in_review --> cancelled + in_approval --> cancelled + approved --> cancelled + signing --> cancelled + expired --> [*] + terminated --> [*] + cancelled --> [*] +``` + +图 3 合同状态机(每条转换的守卫在写入层强制,界面隐藏按钮只是辅助) + +**表 9 状态转换守卫** + +| 转换 | 守卫 | +|---|---| +| 草稿 → 已提交 | 类型必填字段齐全;相对方非黑名单;至少一个版本或类型带模板 | +| 已提交 → 审查中 | 类型需法务审查;已分派法务经办 | +| 已提交 → 审批中 | 类型免审 | +| 审查中 → 审批中 | 无待决偏离;至少一条法务审查结论为通过 | +| 审批中 → 已批准 / 已驳回 / 草稿 | 仅由审批流写入 | +| 已批准 → 签署中 | 存在清稿版本 | +| 签署中 → 生效 | 存在已完成的签署记录且执行形式齐备;存在签妥终版;签署日期非空 | +| 生效 → 已到期 | 仅日任务 | +| 生效 → 已终止 | 终止日期与原因必填 | +| 任一生效前状态 → 已作废 | 理由必填 | + +## 7.2 编号规则 + +格式 `<类型前缀>-<年份>-<四位流水>`,如 `PUR-2026-0042`;流水按类型按年从 1 起;提交时生成,此后只读;补充协议使用自己的前缀并在主合同上可见。平台自动编号只支持固定格式,本规则由写入钩子生成(第 13 章第 5 项)。 + +## 7.3 审批路由算法 + +1. 取合同的类别、方向、金额、是否含已接受偏离。 +2. 遍历启用的审批规则,按优先级:类别匹配(规则未限定视为匹配)、方向匹配(任意视为匹配)、金额落在区间、若规则「仅含偏离」则要求合同含已接受偏离。 +3. 命中规则的四个台阶标记取并集,写到合同的路由标志。 +4. 审查阶段接受了「需法务负责人」条款的偏离,追加法务负责人标志。 +5. 审批流按标志逐级进入:直接主管恒走;法务负责人与财务负责人同时为真时会签;分管领导、总经理按标志。 + +## 7.4 计时口径 + +| 计时 | 起点 | 终点 | 用途 | +|---|---|---|---| +| 审查 SLA | 进入审查中 | 出审查结论 | 超类型天数提醒,超一倍升级 | +| 谈判停滞 | 最近一次轮次切换到对方 | 对方版本上传 | 超 7 天提醒 | +| 各台阶停留 | 进入台阶 | 该台阶决定 | 审批瓶颈看板 | +| 周转 | 提交时间 | 生效时间 | 平均周转天数 | +| 到期预警 | 到期日 − 提前天数 | 到期日 | 续签提醒 | + +日期差由每日任务计算并盖戳,不用公式字段(平台公式库暂无日期差函数)。 + +# 8. 权限与安全 + +**表 10 权限矩阵**(R 读 · C 建 · U 改 · D 删;括号为行级范围) + +| 对象 | 业务承办 | 法务 | 财务 | 档案与记录 | 管理员 | +|---|---|---|---|---|---| +| 合同 | RCU(本人,草稿 / 已提交可改) | RCU(全部) | RU(已批准及之后,法律字段只读) | RU(签署中及之后,执行与归档字段) | RCUD | +| 版本 | RC(本人合同) | RCU | R | RC(执行副本) | RCUD | +| 审查意见 | R(不含内部备注) | RCU | RCU(财务阶段) | R | RCUD | +| 偏离 | RC(本人合同) | RCU | R | R | RCUD | +| 签署记录 | R(本人合同) | RCU | R | RU(执行形式、执行副本) | RCUD | +| 履约义务 | RU(本人负责) | RCU | R | R | RCUD | +| 收付款计划 | R(本人合同) | RC | RCU | R | RCUD | +| 相对方 | R(不含银行与电话) | RCU | RU(银行信息) | R | RCUD | +| 类型 / 条款 / 矩阵 | R | R(条款 RCU) | R | R | RCUD | + +- 合同默认仅发起人可见,法务全见,财务在审批通过后可见,档案与记录岗按阶段可见,领导按路由可见;部门负责人经「本人及下属」范围看到下属发起的合同(企业版能力,开源版退化为仅本人)。 +- 字段级保护:相对方银行账号与联系电话对业务承办与档案岗隐藏;审查内部备注对业务承办与财务隐藏;风险级别与责任上限对业务承办只读;路由标志、审批状态与阶段时间戳对所有人只读;AI 字段对所有人只读,只由「采纳建议」动作写入。 +- 审计:状态变更、审批动作、执行登记、终版登记、归档、导入、每次 AI 调用与采纳全部进平台审计日志;相对方敏感字段读取落审计。 +- 平台账号体系提供密码策略、登录失败锁定、SSO 接入(企业版)。 + +# 9. 集成设计 + +## 9.1 电子签 + +| 项 | 内容 | +|---|---| +| 提供商 | DocuSign(首发);Adobe Acrobat Sign、Dropbox Sign 随后;区域提供商(如中国的契约锁、法大大、e签宝)作为区域包按同一契约追加 | +| 发起 | 合同「发起电子签」动作 → 平台可靠 HTTP 出站 → 提供商创建信封;请求含合同编号、清稿文件、签署方(我方签约主体、相对方联系人)、签署顺序 | +| 回调 | 提供商 → 平台 API 触发流;状态映射:已发送 / 已完成 / 已拒签 / 已作废;完成时下载签妥文件登记终版并盖签署日期 | +| 配置 | 提供商与凭证在系统设置中维护,不进代码与元数据 | +| 边界 | 不自建签署引擎;法律效力(ESIGN、eIDAS 等)由提供商承担;提供商不可用时退回线下签署路径 | + +## 9.2 与 HotCRM 交接 + +**表 11 销售合同交接映射** + +| HotCRM `crm_contract` | HotCLM `clm_contract` | 方向 | +|---|---|---| +| 进入「审批中」 | 新建,类别销售、方向销售 | CRM → CLM | +| 客户 | 相对方(按登记号或名称查找或新建,回链客户) | CRM → CLM | +| 合同金额 / 起止日期 / 付款条款 | 金额 / 起止 / 付款条款 | CRM → CLM(以 CRM 为准) | +| 合同类型 | 合同类型(按映射表) | CRM → CLM | +| 状态 = 生效、签署日期、文件 | 生效时回写 | CLM → CRM(以 CLM 为准) | + +方向规则:商务信息以 HotCRM 为准,法律状态以 HotCLM 为准,同一字段永远只有一个可编辑侧。交接流程只在「随 HotCRM 组合」装配时存在,单装不含。 + +## 9.3 其他 + +- 相对方筛查:制裁名单(OFAC、EU、UK)与公司登记核验(OpenCorporates、Dun & Bradstreet)连接器,可选;区域包接本地登记库;写筛查结果与时间。 +- 通知通道:站内、邮件、短信、Slack;Microsoft Teams 与区域即时通讯待平台提供。 +- 导出:台账与明细 CSV / XLSX;打印与 PDF 待平台提供。 + +# 10. AI 融合设计 + +## 10.1 定位与治理原则 + +AI 是流程里的参与者,不是旁边的聊天窗:它在发起时替人填表,在导入时替人抄数,在审查时替人比对,在审批前替人写备忘录。三条治理原则先于任何能力: + +1. **同权限同审计**:AI 只能看调用者能看的合同;每次调用一条审计(谁、哪份合同、哪项能力、哪个模型、结论),采纳再一条,两条互链。 +2. **只建议不直接写**:每条建议经人「采纳」才落字段或改状态;AI 永远不能推动状态机、不能批准、不能签署。 +3. **无运行时则隐藏**:开源版没有 AI 运行时时,按钮与字段不出现,绝不用占位输出冒充结果。 + +## 10.2 三层落地机制 + +| 层 | 机制 | 本系统的用法 | +|---|---|---| +| 技能 | 技能挂在平台助手上,随应用包发布,提示词版本化可 diff | 六项能力(表 12) | +| 工具 | 每个对 AI 开放的动作即工具,并经平台 MCP 暴露给外部助手(Claude、Copilot、客户自建 agent),权限按调用用户 | 发起合同、查状态、查到期义务、检索合同、登记偏离 | +| 数据 | 合同上四个 AI 字段(摘要、风险分、理由、审查时间)只由「采纳建议」写入 | 看板按风险分筛选,审批人看摘要 | + +## 10.3 能力地图 + +**表 12 AI 能力地图(按生命周期)** + +| 阶段 | 能力 | 输入 | 输出 | 写入方式 | 版本 | +|---|---|---|---|---|---| +| 发起 | 对话式发起 | 助手对话或 MCP 调用发起表单 | 与人工发起相同的合同与版本 | 同一条校验 | M2 | +| 导入 | 条款抽取 | 上传的 PDF / DOCX | 相对方、金额、币种、起止、适用法律、付款条款、关键条款摘要 | 人确认后写字段 | M4 | +| 生效 | 义务抽取 | 终版文本 | 义务草案(标题、类型、到期、负责人建议) | 人确认后建义务 | M4 | +| 审查 | 版本变动摘要 | 新版本 vs 上一版 | 按条款类别列出变动,偏离草案 | 人确认后建偏离 | M4 | +| 审查 | 偏离风险建议 | 偏离文本 vs 条款标准与备选 | 风险级别、是否需法务负责人 | 人确认后写偏离 | M4 | +| 审批 | 审批备忘录 | 合同、偏离、同类合同 | 一页备忘录:金额与阈值、偏离与风险、同类对比、关注点;风险分与理由 | 备忘录附在审批请求上并标「AI 生成,未经法务复核」;风险分经法务采纳才写 | M4 | +| 检索 | 合同库问答 | 自然语言 | 答案附合同编号 | 不写 | M4 | +| 谈判 | 立场建议回复 | 对方红线条款 | 备选立场文本 | 不写 | 二期 | +| 检索 | 相似合同与条款召回 | 条款文本(向量检索) | 相似条款与所在合同 | 不写 | 二期 | +| 定制 | 用 AI 改应用 | 自然语言 | 合同类型、矩阵、视图的元数据变更,走同一条校验链 | 覆盖层 | 随平台 | + +## 10.4 审批备忘录 + +进入审批时系统生成一页备忘录附在审批请求上,审批人先看备忘录再决定是否读全文:合同金额与命中的阈值;偏离清单与风险级别;与本组织同类合同的对比(金额分位、期限、付款条款);建议关注点。备忘录明确标注「AI 生成,未经法务复核」,法务经办可复核并「采纳」,采纳后标注变为「法务已复核」并把风险分写入合同。 + +## 10.5 治理规则 + +**表 13 AI 治理规则** + +| 规则 | 内容 | +|---|---| +| 模型无关 | 走平台模型注册表(Anthropic、OpenAI、Bedrock、本地模型),应用不写任何提供商代码 | +| 数据边界 | 合同文本只送给组织配置的模型端点;自托管可全内网 | +| 提示词版本化 | 提示词在技能定义里,随应用包版本,可 diff、可回滚 | +| 置信度 | 抽取字段带置信度,低于阈值不展示建议只展示原文 | +| 一键关闭 | 组织级设置关闭全部 AI;关闭后 AI 字段保留但只读 | +| 审计 | 每次调用一条,采纳一条,两条互链;审计可导出 | +| 人是终点 | AI 不批准、不签署、不改状态、不删除 | + +# 11. 与 Agiloft 的差距 + +Agiloft 是 Gartner 连续六年的 CLM Leader,也是「无代码平台上的可配置 CLM」这一定位的标杆。逐项对比是为了说清本方案在哪里追、在哪里不追、在哪里能领先。 + +**表 14 与 Agiloft 的能力对比** + +| 能力域 | Agiloft | 本方案 | 差距与关闭路径 | +|---|---|---|---| +| 可配置数据模型与流程 | 无代码全可配:对象、字段、规则、图形化工作流编辑器,管理员自行改流程 | 元数据可改,但打包应用对客户是锁定的,改动走覆盖层或克隆(平台 ADR-0126);审批固定五级台阶,矩阵选台阶 | 管理员图形化改流程的自由度不如;关闭依赖平台 Studio 覆盖层成熟,与矩阵驱动台阶数(第 13 章第 3 项) | +| 起草与 Word 集成 | Word 插件、模板生成、条款库插入、红线比对、版本对比 | 模板文件与占位符清单、版本上传;无生成、无比对 | **差距最大**;依赖平台文档生成与编辑器能力,列入二期 | +| AI | AI Core:抽取、条款识别、风险评分、生成式能力、AI 代理,训练在自有条款分类体系上 | 六项能力、审批备忘录、MCP 工具面,云版可用 | 抽取覆盖面与准确率没有历史积累;**可领先处**:MCP 原生、agent 与人同权限同审计、客户可用 AI 改应用 | +| 电子签 | 原生集成 DocuSign、Adobe Sign 等 | 连接器集成,DocuSign 首发 | 差距小,M4 关闭 | +| 外部门户 | 供应商与客户自助门户 | 无 | 平台外部门户缺口(#27),产品化候选 | +| 入站邮件 | 邮件进系统成记录 | 无 | 平台缺口(#39),二期 | +| 集成生态 | Salesforce、SAP、NetSuite、Coupa、Microsoft 365、Google Workspace,自有集成平台 | REST / OpenAPI / MCP 通用连接器、Slack、HotCRM | 缺预置 ERP 连接器;按客户需求逐个补 | +| 报表 | 自助报表编辑器、定时报表、图表 | 数据集与看板、导出、邮件摘要 | 缺自助报表编辑器;平台能力 | +| 打印与文档输出 | 打印模板、PDF | 无 | 平台缺口(#9),二期 | +| 企业能力 | SSO、SOC 2 与 ISO 认证、移动端、多语言、多区域数据中心 | SSO 在企业版;认证依赖云平台;移动端缺;英文与中文 | 认证与移动端依赖平台路线 | +| 成熟度 | 三十年产品、大量实施伙伴与行业模板 | 新产品 | 只能靠开箱体验与 AI 补 | +| 开放与成本 | 商业许可,企业级报价 | Apache-2.0,自托管或云,一键安装 | **可领先处** | + +结论:差距集中在三处,文档层(生成、比对、打印)、外部面(门户、入站邮件)、生态(预置连接器),三处都依赖平台而不是本应用;可能领先的三处是 AI 原生(MCP、同权限同审计、AI 改应用)、开源可自托管与一键安装、Ironclad 式的发起体验。策略是不追 Agiloft 的配置广度,赢在 AI 与开箱体验,文档层等平台补齐后再进二期。 + +# 12. 非功能与运维基线 + +| 项 | 目标值(待确认) | +|---|---| +| 数据量 | 单组织 5 万份合同、50 万版本文件、100 万义务与计划行内列表与看板秒级响应 | +| 附件 | 单文件 ≤ 50 MB;对象存储可切换本地 / S3 / OSS | +| 可用性 | 与平台一致;日任务失败可重跑且幂等 | +| 备份 | 数据库与对象存储每日备份;归档合同不可变 | +| 语言 | 英文默认且为源语言,简体中文完整;界面文案不含内部代号与异常原文 | +| 移动端 | 审批与查看走响应式;专用移动端不在本期 | +| 审计保留 | 与平台一致,不少于合同保留期 | +| 升级 | 元数据包升级不改客户数据;客户定制走覆盖层不 fork | +| 数据驻留 | 云版按区域部署;自托管全内网,AI 模型端点由组织配置 | + +# 13. 已确认口径(2026-09-07 维护者确认) + +维护者于 2026-09-07 对下列 16 项全部回复「同意默认」。「产品默认」列即确认口径,「备选」列保留作历史;此后改动走版本记录,不再重开。 + +**表 15 已确认口径** + +| # | 事项 | 产品默认 | 备选 | 建议 | +|---|---|---|---|---| +| 1 | 财务对已批准合同的写权限 | 可改,但法律字段与状态只读 | 收付款计划独立权限,财务不可改合同 | 默认;M1 验证字段级只读能锁住状态 | +| 2 | 同部门可见性 | 不做,仅「本人及下属」 | 按客户以团队规则开放部门内可见 | 默认,进客户定制层 | +| 3 | 审批台阶数 | 固定五级,矩阵选台阶 | 矩阵驱动任意台阶 | 默认;首个客户要第六级再改 | +| 4 | 相对方与 HotCRM 客户 | 独立相对方,可链客户 | 并装时直接复用客户 | 默认 | +| 5 | 合同编号 | 类型前缀 + 年 + 四位流水,钩子生成 | 平台单一流水 | 默认 | +| 6 | 类别与 HotCRM 类型 | 不对齐,交接时映射 | 强制一致 | 默认 | +| 7 | 业务承办能否上传对方红线 | 不能,由法务上传 | 允许并标记来源 | 默认 | +| 8 | 执行形式 | 按类型配置:回签副本、公司印章、公证、见证,多数类型为空 | 固定要求某一形式 | 默认 | +| 9 | 电子签首选提供商 | DocuSign 首发,Adobe Acrobat Sign 与 Dropbox Sign 随后 | 区域提供商首发 | 默认;区域客户经区域包 | +| 10 | 即时通讯通知 | 本期不承诺 | 等平台通道 | 默认 | +| 11 | 默认币种与语言 | 组织级设置,出厂 USD 与英文 | 出厂 CNY 与中文 | 默认 | +| 12 | 先签后补 | 允许:档案或法务通过「补录」直接进入生效,标记补录并留痕 | 不允许,必须走流程 | 默认(真实需求高频) | +| 13 | 归档保留期 | 类型上配置,默认 10 年 | 统一固定 | 默认 | +| 14 | 补充协议是否走独立矩阵 | 走自己的类别规则 | 沿用主合同路径 | 默认 | +| 15 | AI 字段是否进合同对象 | 进:摘要、风险分、理由、审查时间四个字段,只由「采纳建议」写入 | 不进,AI 输出只留在审计 | 默认;看板要按风险分筛选 | +| 16 | 区域包的装配方式 | marketplace 扩展包,依赖 HotCLM | 仓库内组合开关 | 默认;扩展包机制未验证时用开关过渡 | + +# 14. 实施与迭代计划 + +**表 16 里程碑与验收** + +| 里程碑 | 内容 | 验收 | +|---|---|---| +| M1 数据与权限骨架 | 11 个对象、状态机守卫、8 岗位 6 权限集、共享与字段级保护、配置域种子 | 校验、规范、类型检查全绿;业务承办互相看不到合同;财务看不到审查中合同 | +| M2 发起与审批 | 发起表单、路由、审批台阶、签署记录与执行形式、法务工作台、合同详情页、全量演示数据 | 走通 发起 → 受理 → 偏离 → 会签 → 签署与执行 → 生效,审批记录与审计齐全 | +| M3 签后与分析 | 生效处理、义务与收付款、续签到期扫描、四个数据集、三个看板、中英双语 | 演示数据下无空图;到期与逾期提醒在收件箱可见 | +| M4 集成与发布 | 电子签、HotCRM 交接、AI 六项能力与审批备忘录、MCP 工具面、存量导入、文档站、截图、市场发布 | 一条命令跑起;市场一键安装;需求逐条对应功能清单与测试 | + +**表 17 范围分级** + +| 档 | 事项 | +|---|---| +| 一期(M1–M3) | 第 5 章 5.1–5.12、5.14、5.15;第 7、8 章全部 | +| 一期补强(M4) | 电子签、HotCRM 交接、AI 参与、MCP 工具面、存量导入、发布 | +| 二期 | 在线红线编辑器、模板一键生成、打印 PDF、Teams 通道、入站邮件成版本、playbook 建议回复、相似合同召回、首个区域包 | +| 产品化候选 | 相对方在线门户、多主体集团合并台账、外部审计员只读访问 | + +# 15. 当前状态 + +仓库 `objectstack-ai/hotclm` 已建立并推送首个提交:`defineStack` 入口、CI 门槛、架构蓝图 `DESIGN.md`、`AGENTS.md` 约定、十四张开发卡片,以及配置域四个对象(合同类型、条款、审批规则、相对方,共 52 个字段,已按全球优先改为执行形式与筛查字段)。四道门槛(校验、规范、类型检查、构建)在平台 17.3 上全绿。尚未开始:合同域与签后域对象、权限、流程、界面、种子数据。本文确认后按第 14 章进入 M1。 + +# 16. 确认方式 + +第 13 章表 15 的 16 项已于 2026-09-07 由维护者逐条确认,本文 V1.0 为一期需求基准,`DESIGN.md` §13 记录同一批裁定。后续变更走版本记录,只增不改;新的待确认事项另起一节编号续接,不改已确认口径。 diff --git a/objectstack.config.ts b/objectstack.config.ts index a9375a9..c94c899 100644 --- a/objectstack.config.ts +++ b/objectstack.config.ts @@ -15,7 +15,7 @@ export default defineStack({ version: '0.1.0', type: 'app', name: 'HotCLM', - description: 'Contract lifecycle management — intake, review, approval, signing, obligations and archive.', + description: 'Contract lifecycle management — intake, review, approval, execution, obligations and archive. Global by default, AI-assisted under governance.', // Protocol major this app is authored against. The runtime checks the // range at load time and refuses a major-incompatible runtime with a // structured diagnostic instead of failing deep in a schema parse. diff --git a/objectstack.manifest.json b/objectstack.manifest.json index 012f177..b687689 100644 --- a/objectstack.manifest.json +++ b/objectstack.manifest.json @@ -8,14 +8,14 @@ }, "manifestId": "app.objectstack.hotclm", "displayName": "HotCLM", - "description": "Contract lifecycle management for the ObjectStack marketplace — intake, clause playbook, approval matrix, sealing and e-signature, obligations, payment schedules, renewals and archive.", + "description": "Contract lifecycle management for the ObjectStack marketplace — intake, clause playbook, approval matrix, e-signature and execution formalities, obligations, payment schedules, renewals and archive. AI-assisted under governance.", "tagline": "Contracts as data — from intake to archive.", "category": "contracts", "isStarter": false, "publisher": "objectstack", "license": "Apache-2.0", "homepageUrl": "https://github.com/objectstack-ai/hotclm", - "tags": ["clm", "contracts", "legal", "approvals", "obligations", "sealing", "e-signature"], + "tags": ["clm", "contracts", "legal", "approvals", "obligations", "e-signature", "ai"], "skills": [ "objectstack-platform", "objectstack-data", @@ -27,7 +27,7 @@ "translations": { "zh-CN": { "displayName": "HotCLM 合同管理", - "description": "ObjectStack 市场的合同全生命周期管理:发起、条款库、审批矩阵、用印与电子签、履约义务、收付款计划、续签与归档。", + "description": "ObjectStack 市场的合同全生命周期管理:发起、条款库、审批矩阵、电子签与执行形式、履约义务、收付款计划、续签与归档。AI 在治理下参与。", "tagline": "合同即数据 —— 从发起到归档。" } } diff --git a/src/objects/approval-rule.object.ts b/src/objects/approval-rule.object.ts index 982f3ef..92ca309 100644 --- a/src/objects/approval-rule.object.ts +++ b/src/objects/approval-rule.object.ts @@ -45,8 +45,9 @@ export const ApprovalRule = ObjectSchema.create({ { label: 'Purchase', value: 'purchase' }, { label: 'Service', value: 'service' }, { label: 'Lease', value: 'lease' }, - { label: 'Labor', value: 'labor' }, + { label: 'Employment / Contractor', value: 'employment' }, { label: 'Framework', value: 'framework' }, + { label: 'Data Processing (DPA)', value: 'dpa' }, { label: 'Amendment', value: 'amendment' }, { label: 'Other', value: 'other' }, ], diff --git a/src/objects/clause.object.ts b/src/objects/clause.object.ts index dccd93a..82cf314 100644 --- a/src/objects/clause.object.ts +++ b/src/objects/clause.object.ts @@ -87,8 +87,9 @@ export const Clause = ObjectSchema.create({ { label: 'Purchase', value: 'purchase' }, { label: 'Service', value: 'service' }, { label: 'Lease', value: 'lease' }, - { label: 'Labor', value: 'labor' }, + { label: 'Employment / Contractor', value: 'employment' }, { label: 'Framework', value: 'framework' }, + { label: 'Data Processing (DPA)', value: 'dpa' }, { label: 'Amendment', value: 'amendment' }, { label: 'Other', value: 'other' }, ], diff --git a/src/objects/contract-type.object.ts b/src/objects/contract-type.object.ts index ccb1d4d..feb1df9 100644 --- a/src/objects/contract-type.object.ts +++ b/src/objects/contract-type.object.ts @@ -3,19 +3,21 @@ import { ObjectSchema, Field } from '@objectstack/spec/data'; /** * A contract type IS a workflow definition (DESIGN.md §02, Ironclad's * Workflow Designer): which optional intake fields the launch form shows, - * whether legal reviews it, whether it must be sealed, how it is signed, and - * the template the first version is drafted from. Adding a kind of contract - * is adding a row here, not a flow. + * whether legal reviews it, how it is executed and which execution + * formalities activation waits for, and the template the first version is + * drafted from. Adding a kind of contract is adding a row here, not a flow. * - * Industry-neutral by rule: the eight seeded types (NDA, sales, purchase, - * service, lease, labor, framework, amendment) are data, not schema. + * Industry- and region-neutral by rule: the seeded types (NDA, MSA, SOW, + * order form, supplier agreement, DPA, lease, contractor, amendment) are + * data, not schema; a company seal is one execution formality among + * notarization, witnessing and countersignature, not a module. */ export const ContractType = ObjectSchema.create({ name: 'clm_contract_type', label: 'Contract Type', pluralLabel: 'Contract Types', icon: 'file-cog', - description: 'A kind of contract and the workflow it runs: intake fields, review, sealing, signing method, template.', + description: 'A kind of contract and the workflow it runs: intake fields, review, execution method and formalities, template.', // A configuration dictionary is useless if it is not readable by everyone // who launches a contract. Write access is withheld from every non-admin @@ -67,8 +69,9 @@ export const ContractType = ObjectSchema.create({ { label: 'Purchase', value: 'purchase' }, { label: 'Service', value: 'service' }, { label: 'Lease', value: 'lease' }, - { label: 'Labor', value: 'labor' }, + { label: 'Employment / Contractor', value: 'employment' }, { label: 'Framework', value: 'framework' }, + { label: 'Data Processing (DPA)', value: 'dpa' }, { label: 'Amendment', value: 'amendment' }, { label: 'Other', value: 'other', default: true }, ], @@ -98,19 +101,26 @@ export const ContractType = ObjectSchema.create({ defaultValue: true, description: 'When off, a submitted contract of this type goes straight to approval (DESIGN.md §03 状态机).', }), - requires_seal: Field.boolean({ - label: 'Requires Seal', + execution_formalities: Field.select({ + label: 'Execution Formalities', group: 'workflow', - defaultValue: true, - description: 'Activation waits for a completed seal request when on.', + multiple: true, + description: 'Formalities activation waits for, recorded on the signature record. Company seal, notarization and witnessing are regional or deed-type requirements; most types need none.', + options: [ + { label: 'Countersigned copy returned', value: 'countersigned_copy' }, + { label: 'Company seal', value: 'company_seal' }, + { label: 'Notarized', value: 'notarized' }, + { label: 'Witnessed', value: 'witnessed' }, + ], }), sign_method: Field.select({ label: 'Signing Method', group: 'workflow', + description: 'How this type is normally executed. E-signature goes through the configured provider (DocuSign, Adobe Acrobat Sign, Dropbox Sign, or a regional provider); wet ink records an uploaded executed copy.', options: [ - { label: 'E-signature', value: 'esign' }, + { label: 'E-signature', value: 'esign', default: true }, { label: 'Wet ink', value: 'wet_ink' }, - { label: 'Either', value: 'both', default: true }, + { label: 'Either', value: 'either' }, ], }), review_sla_days: Field.number({ @@ -120,7 +130,7 @@ export const ContractType = ObjectSchema.create({ min: 0, max: 90, defaultValue: 5, - description: 'Working days legal has to finish review before the overdue reminder fires (F3).', + description: 'Calendar days legal has to finish review before the overdue reminder fires (F3).', }), template_file: Field.file({ diff --git a/src/objects/party.object.ts b/src/objects/party.object.ts index b50e457..0d43acd 100644 --- a/src/objects/party.object.ts +++ b/src/objects/party.object.ts @@ -7,7 +7,9 @@ import { ObjectSchema, Field } from '@objectstack/spec/data'; * HotCRM is installed alongside, `crm_account` links the two records. * * Party master data only: qualification, scoring and onboarding are an SRM's - * job, not this object's (DESIGN.md §01 范围外). + * job, not this object's (DESIGN.md §01 范围外). Screening (sanctions, + * registry lookup) is an optional connector that stamps the two screening + * fields; the object never calls anything itself. */ export const Party = ObjectSchema.create({ name: 'clm_party', @@ -18,7 +20,7 @@ export const Party = ObjectSchema.create({ sharingModel: 'public_read', nameField: 'name', - highlightFields: ['name', 'party_kind', 'registration_no', 'risk_flag'], + highlightFields: ['name', 'party_kind', 'country_code', 'risk_flag'], fieldGroups: [ { key: 'identity', label: 'Identity', icon: 'building-2' }, @@ -46,12 +48,18 @@ export const Party = ObjectSchema.create({ { label: 'Other', value: 'other' }, ], }), + country_code: Field.text({ + label: 'Country', + group: 'identity', + maxLength: 2, + description: 'ISO 3166-1 alpha-2 country code of the party (e.g. US, DE, CN). Drives governing-law defaults and screening.', + }), registration_no: Field.text({ - label: 'Registration No.', + label: 'Registration / Tax ID', group: 'identity', searchable: true, maxLength: 40, - description: 'Unified registration or tax identifier. Unique per organization when present.', + description: 'Company registration number, VAT/tax ID or equivalent national identifier. Unique per organization when present.', }), legal_representative: Field.text({ label: 'Legal Representative', @@ -105,10 +113,20 @@ export const Party = ObjectSchema.create({ label: 'Risk Note', group: 'risk', }), - verified_at: Field.datetime({ - label: 'Verified At', + screening_status: Field.select({ + label: 'Screening', + group: 'risk', + required: true, + description: 'Result of the last sanctions / registry screening. Written by the screening connector when one is configured (DESIGN.md §08), otherwise by legal.', + options: [ + { label: 'Not screened', value: 'not_screened', color: '#94A3B8', default: true }, + { label: 'Clear', value: 'clear', color: '#2F7D5B' }, + { label: 'Hit', value: 'hit', color: '#EF4444' }, + ], + }), + screened_at: Field.datetime({ + label: 'Screened At', group: 'risk', - description: 'Stamped by the registry verification connector when one is configured (DESIGN.md §08).', }), is_active: Field.boolean({ label: 'Active',