Uh oh!
There was an error while loading. Please reload this page.
test(dogfood): record the measured cross-organization reach of the automation toggle - #10996
Conversation
…tomation toggle #10243 splits into an exposure half — already measured and pinned by #10145's `automation-write-capability-gate.test.ts` audit block — and a blast-radius half that had never been reproduced over HTTP: whether flow ENABLEMENT is environment-scoped such that one tenant's toggle reaches every organization. This is that measurement, recorded. On a real, non-degraded `isolated` posture with three principals (two org owners in two different organizations, plus the platform admin), tenant A's `POST /automation/:name/toggle {enabled:false}` answers 200 and both tenant B and the platform admin read the flow back as `enabled: false`; re-enabling is symmetric. The file records reality and rules nothing. Whether toggle belongs in the `manage_metadata` write set is the maintainer's decision; when it is made, this file is where it lands alongside the existing audit pin. Part of #10243 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019bmVFqoQPq63zhKrxdYG1r
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. |
os-elon
commented
Aug 22, 2026
Enqueued — marked ready for review by the
|
| check | verdict | ran for |
|---|---|---|
TypeScript Type Check · workspace | success | 55s |
TypeScript Type Check · debt ledger | success | 4m59s |
TypeScript Type Check · source gates | success | 2m04s |
TypeScript Type Check · consumer gates | success | 2m49s |
Lint & Repo Gates | success | 8m24s |
Test Core (6 shards) | success | 58s – 10m17s |
Dogfood Regression Gate (3 shards) | success | 2m37s / 2m38s / 9m21s |
Build Core | success | 54s |
Temporal Conformance (live PG + MySQL) | success | 3m35s |
The four Type Check lanes are quoted individually because the roll-up completes in ~3s whether or not the lanes did anything — reading the roll-up alone cannot distinguish a pass from a no-op. All four ran in minutes. Likewise the Dogfood Regression Gate shards ran 2–9 minutes rather than being excused by a path filter, which matters here: the diff is a dogfood test, so a filtered skip would have meant nothing exercised it.
⛔ No other red gate. One note on Check Changeset: the pre-refresh head carried a failed run of it from 03:40:47Z, before Auto Label applied skip-changeset; a later run superseded it as skipped. On the refreshed head there is a single clean skipped, so the stale red is gone rather than merely outvoted. Console Pin Gate and Build Docs are skipped by path filter on a test-only diff — stating that explicitly rather than counting them as passes.
⛔ The fence this PR set for itself still stands — enqueueing did NOT move it
This is the measurement half of #10243. It changes no behaviour: one new test file, isFlowAuthoringWrite and every policy predicate, gate and route untouched.
It grades nothing, and neither do I. Whether POST /api/v1/automation/:name/toggle belongs in the manage_metadata write set is a product and security decision, and it is the maintainer's alone. What merging this buys is that the measured reality is on the record — tenant A's toggle reaching tenant B and the org-less platform admin, symmetric in both directions — so that when the ruling lands, the file it flips is already there. An unrecorded verdict cannot be revisited.
403, and that flip is the point of the file rather than a regression in it.
Generated by Claude Code
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 32589382595 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
Uh oh!
There was an error while loading. Please reload this page.
os-elon
commented
Aug 22, 2026
队列踢出 —— 签名读数收据,据此重投一次18:15Z 前后本 PR 掉出合并队列:既不在 签名:队列重建的连带取消,不是红
三条同时成立 = 连带取消的签名。没有任何证据指向本 PR 的内容:它名下压根没跑过 merge_group 检查,所以不存在「红了」这回事,而同批四条走完同一条队列全部成功,排除了批次共因。 入队前的门禁读数未变六项必需检查此前已在 head ⛔ 与本卡裁决无关重投只关乎落地通路。#10243 的 severity 裁决仍然完全开放,且是维护者的 —— 本 PR 是该卡的测量半边,不改任何行为、不给任何定级:它把「一个租户的 toggle 触达全部组织、且双向对称」这一实测事实记录下来,好让日后的裁决有据可查、可被推翻。⛔ 合入它不代表该行为被接受。 Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 32591821258 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
Part of #10243 — this is the measurement half of that card. It changes no behaviour and rules nothing.
What was open, and what this measures
The card splits into two facts, and only the second was ever open:
POST /api/v1/automation/:name/toggleis reachable by any authenticated caller with no authoring capabilitypackages/runtime/src/domains/automation-write-capability-gate.test.tsThis PR adds one dogfood test that reproduces the second over HTTP and records the result.
The read-back table, as measured
Harness:
bootStack(crm, { automation: true, multiTenant: 'posture-only' })— a real, non-degradedisolatedtenancy posture. Three principals: two org owners who each create their own organization (differentactiveOrganizationIds, asserted not assumed), plus the seeded platform admin. Flow: the CRM app's own shippedcrm_convert_lead_wizard.Tenant A is unentitled, and the gated neighbours prove it in the same session:
PUT /meta/object/crm_leadanswers 403FORBIDDEN, andPOST /automationandDELETE /automation/:nameanswer 403PERMISSION_DENIED.Tenant A then calls
POST /automation/crm_convert_lead_wizard/togglewith{ enabled: false }and gets 200:enabled: trueenabled: falseenabled: trueenabled: falseenabled: trueenabled: trueenabled: falseenabled: trueIt reproduces. The effect is symmetric in both directions.
Why this is not vacuous, stated up front
multiTenant: 'posture-only'activates the tenancy posture and no row wall — the enterprise multi-org runtime is cloud-private and genuinely absent from this workspace. A fixture that booted this way and asserted isolation would assert nothing. The mirror image is the trap for this file: in a stack with no wall, "tenant B saw tenant A's write" is true of everything.What keeps it honest is that the bit under test never reaches the plane a wall operates on. An organization wall scopes rows. The enabled bit is not a row:
toggleFlow(name, enabled)writes the engine's in-processflowEnabledmap keyed by flow name and nothing else, andgetFlowRuntimeStates()reads that same map with no caller, no organization, and no argument at all. One test leg measures exactly that discriminator over HTTP — after the toggle the flow's persistedstatusis stillactivewhile its runtimeenabledisfalse, and the automation service is one instance for the whole environment. That leg is what would fail, loudly, if enablement ever became org-stamped state a wall could scope.Separately measured and reported on the card: the override is process-local and does not survive a cold boot on the same database file.
The fence this PR keeps
isFlowAuthoringWriteand every policy predicate, gate and route are untouched — the diff is one new test file.manage_metadatawrite set is a product and security decision for the maintainer.skip-changeset: the diff is one test file in a private package and publishes nothing.Verification
At
ce6a2862f7, clean tree:pnpm --filter @objectstack/dogfood exec vitest run test/automation-toggle-tenant-scope.dogfood.test.ts—Test Files 1 passed (1),Tests 6 passed (6)pnpm --filter @objectstack/dogfood typecheck— exit 0node scripts/pm/dispatch-gates.mjs(no paths), all green, quoting each gate's own verdict line:check:slot-lookup("baseline key set verified against 047ac86: no files added"),check:query-options-erasure("test surface: 240 site(s) in 47 file(s) — at the ceiling"),check:where-matcher("276 matcher(s) discovered, 276 answer the combinator battery correctly or refuse it loudly"),check:engine-double-contract("OK — 377 pinned, 133 in the DEBT ledger, 2 exempt"),check:type-check-coverage("OK — 64/77 workspace packages type-checked"),check:type-check-debt("OK — 33 ledger entr(ies) re-measured in 202.8s, 1908 raw tsc error(s) total, none above its recorded number", after a full closure build),check:test-source-alias,check:type-source-resolution,check:nul-bytes,check:plugin-teardown-shape,check-ci-filter-parity,docs-audit/check-affected-docs, and the fourpackages/specliveness families.⛔ Draft on purpose. Do not merge, do not arm auto-merge, do not mark ready — the result is evidence for the maintainer's ruling, not a fix.
Generated by Claude Code