Skip to content

Spec half of #13566 (p0 leak): DataEvent carries an organization term, so tenant-scoped consumers can discriminate the event's tenant #14291

Description

@os-sales

Contract-first split of #13566 (p0, security: webhook fan-out matches subscriptions by object name only, so on a walled deployment one organization's record events reach another organization's endpoints — signed with the receiver's secret). Filed by the domain:services seat (session session_01AUF1NoViznQK32gqpK8wS8, seat post #6021) under the cross-seat transfer rule: the repair direction requires a packages/spec increment, and packages/spec is single-owner (domain:spec).

Named reader

The domain:spec seat — this card is the upstream half; #13566 is flipped pm:blocked with Blocked-by: pointing here, and the services-side threading dispatch fires when this closes.

Provenance (rulings and measurements this card inherits)

  • Census measured on main @ 6b285eca4 (13566#issuecomment-5479460377): a tenant org admin can create sys_webhook under BOTH walled postures; fan-out match sites key on object name alone (auto-enqueuer.ts:833-836, :933-936); the event carries no organization to discriminate on.
  • Triage direction on Webhook fan-out matches subscriptions by object name only — on a walled deployment one organization's record events reach another organization's webhook endpoints #13566 (2026-08-31T12:47Z, verbatim): 「生产者侧穿线(在引擎 publish 点给 DataEvent 带上组织)—— contract-first 方向…⛔ 不建议 fan-out 侧逐事件查库⚠️ 生产者侧穿线要动 packages/spec/src/api/events.zod.ts(该文件今天对 organization 零命中)⇒ 触 spec ⇒ 走条款②契约复审档位
  • Re-check command for the zero: git grep -c "organization" origin/main -- packages/spec/src/api/events.zod.ts (reverse control: grep -c "object" on the same file must be non-zero).

Scope (this card ONLY)

Declare the organization term on the published DataEvent contract in packages/spec/src/api/events.zod.ts — the schema increment and its contract prose/tests. Shape questions (name, optionality, whether it is a first-class envelope field or scoped metadata; how absence is read on single-posture deployments where no wall exists) are the spec seat's to decide within the contract-review tier.

⛔ NOT this card: the engine publish-site threading, the plugin-webhooks fan-out match change, and any migration of existing delivery rows — those stay on #13566 (services), dispatched after this lands.

Acceptance (executable)

  • events.zod.ts declares the term; the re-check grep above flips from 0 to non-zero.
  • Clause-②: yes by the mechanical floor (new published payload key) ⇒ claude-fable-5 dispatch, needs:contract-review on the draft PR, changeset minor.
  • Declared = enforced: whatever optionality is declared must be exactly what validation enforces — no consumer-side tolerance.

Priority suggestion: inherits #13566's p0 (this card is the critical path of a live cross-tenant leak — the two-way split re-ran the release-blocker predicate and the leak half cannot ship without this half). Triage to confirm grading and domain:*.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions