Filed by the domain:services PM seat (#6021) as the delivering seat's open_questions on #16659 / PR #17126, which asked PM to file rather than guess. ⛔ Correct call — every option below is a product decision.
⚠️ This gates #17126's landing, not its correctness. The PR implements the maintainer's ruling faithfully; the ruling simply did not anticipate that the repo's own examples cannot satisfy it.
The consequence, and it is not hypothetical
#16659's ruling — 「多组织定时任务本来只能在组织内运行,应该带组织ID,不允许跨组织的定时任务」 — is implemented as: a time-triggered flow declares its acting organization on the start node, and a flow declaring none is REFUSED at bind, no job registered. That refusal is consequence (3) of the ruling and is explicitly not a silent default and not a fallback to a platform organization.
⇒ These four flows in this repo are now refused, each named in the error (verified on the tree at ce7bae8b4):
| flow |
file |
task_reminder |
examples/app-todo/src/flows/task.flow.ts:10 |
overdue_escalation |
examples/app-todo/src/flows/task.flow.ts:62 |
showcase_scheduled_digest |
examples/app-showcase/src/automation/flows/index.ts:366 |
showcase_task_due_reminder |
examples/app-showcase/src/automation/flows/index.ts:1664 |
⛔ And they cannot be fixed in scope, because an organization id is minted at runtime and no example seeds a sys_organization row — so there is no value an author of a package-shipped flow could write. PR #17126 touches examples/ in zero files, deliberately.
⭐ The delivering seat refused to write a placeholder id, and that judgement is right: a value matching no row is exactly the "wrong organization_id, silently authoritative" outcome the ruling forbids, and strictly worse than the refusal.
⚠️ A correction to the supporting measurement, made by this seat
The delivery's report states: "no platform-organization constant exists anywhere in packages/ (zero non-test hits)." That is false. packages/runtime/src/http-dispatcher.ts:
/** Well-known system project id — bypassed for any authenticated user. */
private static readonly SYSTEM_ENVIRONMENT_ID = '00000000-0000-0000-0000-000000000001';
/** Well-known platform org id — members bypass project membership. */
private static readonly PLATFORM_ORG_ID = '00000000-0000-0000-0000-000000000000';
and it is used at :1412 (if (activeOrganizationId === HttpDispatcher.PLATFORM_ORG_ID) return null;). One grep with three spellings found it. ⇒ a zero from a sweep that cannot answer "yes" is NOT MEASURED — this lane's own standing rule, applied here to a delivery's negative result.
⚠️ The conclusion may still stand — that constant is private, unexported, not authorable, and a well-known sentinel in the dispatcher's membership logic is not the same thing as a seeded sys_organization row a scheduled run could execute as. ⭐ But the option analysis changes: option A is not starting from nothing. There is already a documented well-known platform organization id, a sibling SYSTEM_ENVIRONMENT_ID in the same family, and the seed layer's os.org.id CEL binding (packages/spec/src/data/seed-loader.zod.ts:310) that the delivery itself cited as A's mechanism.
The decision
|
what it means |
cost |
| A (delivery's rec.) |
a symbolic organization reference a package-shipped flow can name, resolved per organization the way seeds already resolve os.org.id |
keeps the ruling intact and keeps the platform able to ship a scheduled flow in a package; ⚠️ needs the symbol designed — and now also needs to be reconciled with the existing PLATFORM_ORG_ID sentinel rather than inventing a second one |
| B |
rule that a scheduled flow is deployment data, never package source — the examples drop theirs or move them to seeded metadata, and the refusal is simply correct |
defensible, but it silently retires a capability the examples currently demonstrate; that is a maintainer call, not a delivery one |
| C |
give the examples a seeded sys_organization row with a fixed id and have them name it |
works, but changes example seed data and makes every demo multi-organization-shaped |
You are being asked for one letter — A, B or C.
A second, smaller reading the delivery asked for, and this seat's answer
Consequence (3) says "refused at validation/boot". I read that as per-flow refusal at BIND (boot), not at FlowSchema.parse. Is that the intended reading?
Yes, and no maintainer time is needed on it. Under bind-time refusal there is no path by which an organization-less time-triggered run reaches the data layer, which is the substance of (3). Parse-time would add no safety and would make every package-shipped scheduled flow unparseable — a strictly worse version of the same problem this card is about. ⛔ Raised here only because the delivery asked; ⚠️ ⛔ do not treat it as part of the A/B/C decision.
⚠️ A coverage hole this exposed, recorded rather than folded in
PR #17126's CI is green while those four example flows are refused at bind. ⇒ nothing in CI boots the examples' schedule bindings. That is a gap worth its own card once the decision above lands — a refusal that the repo's own examples trip and no gate notices is the same silence class this lane has spent the day on. ⛔ Not filed yet, because what the gate should assert depends on which letter you pick.
Related
#16659 (the card, ruled) · PR #17126 (the implementation, complete, parked on contract review and on this decision) · #17123 (the green-run-masks-zero-delivery hole, filed separately per the ruling's consequence 4) · #15207 / ADR-0131 D7 (where 方向三 lives, ruled out for #16659)
Filed by the
domain:servicesPM seat (#6021) as the delivering seat'sopen_questionson #16659 / PR #17126, which asked PM to file rather than guess. ⛔ Correct call — every option below is a product decision.The consequence, and it is not hypothetical
#16659's ruling — 「多组织定时任务本来只能在组织内运行,应该带组织ID,不允许跨组织的定时任务」 — is implemented as: a time-triggered flow declares its acting organization on the start node, and a flow declaring none is REFUSED at bind, no job registered. That refusal is consequence (3) of the ruling and is explicitly not a silent default and not a fallback to a platform organization.
⇒ These four flows in this repo are now refused, each named in the error (verified on the tree at
ce7bae8b4):task_reminderexamples/app-todo/src/flows/task.flow.ts:10overdue_escalationexamples/app-todo/src/flows/task.flow.ts:62showcase_scheduled_digestexamples/app-showcase/src/automation/flows/index.ts:366showcase_task_due_reminderexamples/app-showcase/src/automation/flows/index.ts:1664⛔ And they cannot be fixed in scope, because an organization id is minted at runtime and no example seeds a
sys_organizationrow — so there is no value an author of a package-shipped flow could write. PR #17126 touchesexamples/in zero files, deliberately.⭐ The delivering seat refused to write a placeholder id, and that judgement is right: a value matching no row is exactly the "wrong
organization_id, silently authoritative" outcome the ruling forbids, and strictly worse than the refusal.The delivery's report states: "no platform-organization constant exists anywhere in
packages/(zero non-test hits)." That is false.packages/runtime/src/http-dispatcher.ts:and it is used at
:1412(if (activeOrganizationId === HttpDispatcher.PLATFORM_ORG_ID) return null;). One grep with three spellings found it. ⇒ a zero from a sweep that cannot answer "yes" is NOT MEASURED — this lane's own standing rule, applied here to a delivery's negative result.private, unexported, not authorable, and a well-known sentinel in the dispatcher's membership logic is not the same thing as a seededsys_organizationrow a scheduled run could execute as. ⭐ But the option analysis changes: option A is not starting from nothing. There is already a documented well-known platform organization id, a siblingSYSTEM_ENVIRONMENT_IDin the same family, and the seed layer'sos.org.idCEL binding (packages/spec/src/data/seed-loader.zod.ts:310) that the delivery itself cited as A's mechanism.The decision
os.org.idPLATFORM_ORG_IDsentinel rather than inventing a second onesys_organizationrow with a fixed id and have them name itYou are being asked for one letter — A, B or C.
A second, smaller reading the delivery asked for, and this seat's answer
Yes, and no maintainer time is needed on it. Under bind-time refusal there is no path by which an organization-less time-triggered run reaches the data layer, which is the substance of (3). Parse-time would add no safety and would make every package-shipped scheduled flow unparseable — a strictly worse version of the same problem this card is about. ⛔ Raised here only because the delivery asked;⚠️ ⛔ do not treat it as part of the A/B/C decision.
PR #17126's CI is green while those four example flows are refused at bind. ⇒ nothing in CI boots the examples' schedule bindings. That is a gap worth its own card once the decision above lands — a refusal that the repo's own examples trip and no gate notices is the same silence class this lane has spent the day on. ⛔ Not filed yet, because what the gate should assert depends on which letter you pick.
Related
#16659 (the card, ruled) · PR #17126 (the implementation, complete, parked on contract review and on this decision) · #17123 (the green-run-masks-zero-delivery hole, filed separately per the ruling's consequence 4) · #15207 / ADR-0131 D7 (where 方向三 lives, ruled out for #16659)