You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[Decision] group posture is an on-premise shape — should package-authored scheduled flows run under group with the switch on, and which organization do their writes carry? (ruling G item 3, reopened by the maintainer) #18378
Filed by the director seat (session_01WCEaPsmKY4UyoivKkkaUHt) on the maintainer's instruction during the 2026-09-16 design discussion of PR #18198. Maintainer, verbatim and untranslated (live PM chat):
group 模式是本地部署的,运行 schedule 应该是可以的,但是你没有权限,可以单独开一个决策卡
⇒ Ruling G item 3 (#17396, 5642381255: 「group is off by default, like isolated」, and with the switch on 「behaves as walled」) is reopened for group only by the maintainer's own words; it stays a tenancy-boundary decision, so this seat files the card and does not rule it. ⛔ Nothing about single or isolated is reopened; ⛔ nothing here delays PR #18198.
Ruling G item 3 and its recorded reason: 「resolveSystemWriteOrganization refuses an organization-less system insert under any wall (walled-posture), and TenancyService.defaultOrgId() answers null under any wall by ADR-0093 D3. An organization-less scheduled run in group could read the whole group and update records in place, but the inbox, delivery and sys_automation_run rows it inserts would be refused … Which organization a group-wide sweep's inserts belong to is the part the maintainer said is not yet thought through」.
ADR-0105 D1: group = 「organizations share one database as data」 with membership/invitation boundaries, group-wide visibility and cross-org workflow inherent to the shape (the multi-plant MES example is the ADR's own); postureEnforcesWall('group') = true, postureStampsOrganization('group') = true (packages/spec/src/security/tenancy-posture.ts).
ADR-0093 D3: target-org resolution consumes declared mode — single ⇒ the bootstrap organization (slug='default'); a walled mode ⇒ none, the framework never guesses.
git grep -n "requiresActingOrganization" origin/main -- packages/types/src/env.ts # the policy table (after #18198 lands)
git grep -n "defaultOrgId" origin/main -- packages/spec/src packages/core/src | head # null under walls (ADR-0093 D3)
git grep -n "walled-posture" origin/main -- packages/spec/src/api/error-code-ledger.zod.ts # the refusal an org-less system insert meets
git grep -n "never filled from the swept row" origin/main -- packages/triggers # the time_relative pin option A retargets
Options × real cost
what
what a customer sees
A (seat recommends)
group + on binds without a declaration, like single. Writes follow the record: a time_relative run carries the swept record'sorganization_id; a cron schedule run that has no record carries config.organization if declared, otherwise the group's bootstrap organization (slug='default'), and the boot/audit line states which. Group-wide reads stay group-wide (inherent to the posture).
Packaged schedules (contract expiry, SLA monitors, reminders) run on a multi-plant install out of the box; a record-less cron flow's artefacts land in the group's home organization unless the author declares one
B
Keep ruling G: group stays walled; declaration required; packaged flows do not run; admins clone per organization (ADR-0126 §7.1)
Every plant clones every packaged schedule by hand
C
Automatic per-organization fan-out under group: one run per organization, reads scoped to it
Unambiguous ownership, no cross-org logic possible, cost ∝ organizations, new scheduler machinery
D
Bind without a declaration, but a write whose organization cannot be resolved (record-less cron, no declaration) is refused loudly (ADR-0112 envelope); record-derived writes follow the record
Strictest; a cron flow that emits notifications without declaring fails at runtime, by name
业务含义直译
A = 集团总部的定时任务照常跑,单据写到它所属的工厂,没有单据的写到总部。B = 每个工厂各自复制一份任务。C = 每个工厂各跑一份,总部看不到跨厂的汇总。D = 跑可以,写不清归属就当场拒绝。
Prior rulings read: group,posture,schedule,organization,wall,defaultorgid,time_relative,bootstrap → 66 hits; ADR-0105 D1/D4/D5, ADR-0131 D3, ADR-0057 D9, ADR-0099 D2, ADR-0106 D6, ADR-0120 D5 — none rules the write-ownership of an organization-less scheduled run under group; ruling G item 3 recorded it as unanswered.
推荐:A(回退 D)。自检:只看①选 A;②③④ 是否翻转:否(③ 只要求兜底被响亮说出)。 置信缺口:① 09-08 「不允许跨组织的定时任务」是否有意覆盖 group(其上下文是多租户),只有维护者能答;② sys_automation_run / inbox 的其他消费者是否假定 group 下的 tenantId 必来自声明;③ 现网 group 部署数未测。
Filed by the director seat (
session_01WCEaPsmKY4UyoivKkkaUHt) on the maintainer's instruction during the 2026-09-16 design discussion of PR #18198. Maintainer, verbatim and untranslated (live PM chat):⇒ Ruling G item 3 (#17396, 5642381255: 「
groupis off by default, likeisolated」, and with the switch on 「behaves as walled」) is reopened forgrouponly by the maintainer's own words; it stays a tenancy-boundary decision, so this seat files the card and does not rule it. ⛔ Nothing aboutsingleorisolatedis reopened; ⛔ nothing here delays PR #18198.一句话问题
一个集团版本地部署(
group姿态:多个工厂或分公司作为组织,共用一个数据库)把定时开关打开之后,包内的定时流要不要跑;跑的时候,它写出来的通知、运行记录、待办归哪个组织。Governing text
resolveSystemWriteOrganizationrefuses an organization-less system insert under any wall (walled-posture), andTenancyService.defaultOrgId()answersnullunder any wall by ADR-0093 D3. An organization-less scheduled run ingroupcould read the whole group and update records in place, but the inbox, delivery andsys_automation_runrows it inserts would be refused … Which organization a group-wide sweep's inserts belong to is the part the maintainer said is not yet thought through」.group= 「organizations share one database as data」 with membership/invitation boundaries, group-wide visibility and cross-org workflow inherent to the shape (the multi-plant MES example is the ADR's own);postureEnforcesWall('group') = true,postureStampsOrganization('group') = true(packages/spec/src/security/tenancy-posture.ts).single⇒ the bootstrap organization (slug='default'); a walled mode ⇒ none, the framework never guesses.notifydelivers nothing on a multi-organization install: the run carries no organization, so the tenant-scoped inbox/delivery writes are refused (#8844) while the run reads healthy #16659 (「多组织定时任务本来只能在组织内运行,应该带组织ID,不允许跨组织的定时任务」) — made for the multi-tenant shape; whether it binds a group (one legal group, cross-org visibility inherent) is exactly what this card asks.resolveScheduledWorkPolicy()(packages/types/src/env.ts) answersgroup+ on ⇒requiresActingOrganization: true;schedule-organization.zod.ts's docblock and.describe()say the declaration is required under a walled posture. Option A changes that protocol prose and that row — 「协议不正确的应该先修改协议」 applies, so the change is inpackages/spec/packages/typesfirst.Premises, with re-check commands
Options × real cost
group+ on binds without a declaration, likesingle. Writes follow the record: atime_relativerun carries the swept record'sorganization_id; a cronschedulerun that has no record carriesconfig.organizationif declared, otherwise the group's bootstrap organization (slug='default'), and the boot/audit line states which. Group-wide reads stay group-wide (inherent to the posture).groupstays walled; declaration required; packaged flows do not run; admins clone per organization (ADR-0126 §7.1)group: one run per organization, reads scoped to it业务含义直译
A = 集团总部的定时任务照常跑,单据写到它所属的工厂,没有单据的写到总部。B = 每个工厂各自复制一份任务。C = 每个工厂各跑一份,总部看不到跨厂的汇总。D = 跑可以,写不清归属就当场拒绝。
四轴(从业务立场)
group按 ADR-0105 就是「一家集团、多个分支、一个数据库」,集团级批处理是这个形状的固有能力(主流 ERP 多工厂、Salesforce/Dynamics 多业务部门都在一个 org 内跑全局批处理,行级归属由记录自己决定)。A 只新增一条「无记录时归总部」的兜底规则;C 新增一套扇出机制;B 把成本永久推给管理员。⇒ A。group本地部署要跑包内定时流只能逐组织克隆;维护者本人指出group是本地部署、应可运行。group部署在线。os doctor打印。D 最响亮但把失败推到运行时。B/C 无此风险但代价见①。Prior rulings read: group,posture,schedule,organization,wall,defaultorgid,time_relative,bootstrap → 66 hits; ADR-0105 D1/D4/D5, ADR-0131 D3, ADR-0057 D9, ADR-0099 D2, ADR-0106 D6, ADR-0120 D5 — none rules the write-ownership of an organization-less scheduled run under
group; ruling G item 3 recorded it as unanswered.推荐:A(回退 D)。自检:只看①选 A;②③④ 是否翻转:否(③ 只要求兜底被响亮说出)。
置信缺口:① 09-08 「不允许跨组织的定时任务」是否有意覆盖
group(其上下文是多租户),只有维护者能答;②sys_automation_run/ inbox 的其他消费者是否假定group下的tenantId必来自声明;③ 现网group部署数未测。裁后执行
packages/spec先:schedule-organization.zod.ts的 docblock 与.describe()、ADR-0087 条目 18 的group行),再 types/triggers/service-automation:resolveScheduledWorkPolicy的group行改为不要求声明并带写归属规则;time_relative在group下把tenantId从被扫记录填入(退掉「never filled from the swept row」在 group 上的那半钉子);无记录的 cron 走config.organization否则 bootstrap 组织,boot/audit 行点名;文档四页;changesetminor+ BREAKING;Clause-②: yes。在 PR feat(types,triggers,service-automation,runtime,cli,spec,lint)!: package-authored scheduled work is a deployment decision, off by default #18198 落地之后再动,⛔ 不并入它。Refs: #17396 (ruling G) · PR #18198 · #16659 (2026-09-08 ruling) · ADR-0105 · ADR-0093 D3 · ADR-0126 §7.1
os-decision-facets
group是一家集团一个库,集团级批处理是固有能力;A 一条兜底规则,C 一套机制,B 永久人工。group本地部署今天只能逐组织克隆;维护者指出应可运行;部署数未测。维护者速读
事情。 您说
group(集团版本地部署,多个工厂或分公司共用一个库)应该可以跑定时任务。裁决 G 当时把group和云上多租户一样默认关、开了也要每条流声明组织,原因是那时没想清楚:一条集团级定时任务写出来的通知和运行记录归哪个组织——在围墙姿态下,没有组织的系统写入会被拒绝。选项。 A 像单租户一样直接跑;写入跟着记录走(扫描到哪个工厂的单据就归哪个工厂),没有单据的任务归总部组织,启动日志写明。B 维持现状,每个工厂自己克隆一份。C 自动给每个组织各跑一份,互不可见。D 跑可以,但写不清归属的当场拒绝。
席位意见。 推荐 A:
group的定义就是一家集团一个库,跨分支可见是它的本意;A 只多一条兜底规则,并且在日志里说清楚。回退 D。你要做的:回一个字母 —— A / B / C / D。
Generated by Claude Code