Observation found out of scope while seeding the realtime liveness ledger for #14446 (PR #15242). Comment-only defect in shipped source; nothing executes differently either way. Filed rather than fixed because #14446's PR is ledger-rows-only by triage ruling.
What the comment says
packages/spec/src/api/websocket.zod.ts:54-77 is the retirement note for the deleted FilterOperator / EventFilterCondition / EventFilterSchema vocabulary. Two sentences in, it says (lines 61-63):
matchesSubscription matches on object name and event type only (see contracts/realtime-service.ts), and the subscription shape the transports actually carry is the separate, deliberately unvalidated filters: z.unknown() on SubscriptionEventSchema (api/realtime.zod.ts).
The first half is exact. The second half names the wrong shape.
What is measured
At 5f5511f0, nothing outside packages/spec imports SubscriptionEventSchema, SubscriptionSchema or RealtimeConfigSchema at all. git grep -nE 'SubscriptionEventSchema|SubscriptionSchema|RealtimeConfigSchema' over the repo excluding CHANGELOGs hits eleven files, every one of them spec's own tree, a generated artifact (api-surface/, declaration-map/, export-origins/) or published prose (content/docs/references/api/realtime.mdx, skills/objectstack-api). No transport parses a SubscriptionEvent.
The shape the shipped subscription path actually carries is a plain TypeScript interface one directory over: packages/spec/src/contracts/realtime-service.ts#RealtimeSubscriptionOptions, with object and eventTypes: string[]. That is what packages/services/service-realtime/src/in-memory-realtime-adapter.ts#matchesSubscription reads — it takes sub.options typed as those options and compares opts.object and opts.eventTypes against the event. The same file's Subscription is a file-local interface, unrelated to the spec symbol of that name.
So there are three spellings of a realtime subscription and only the third is executed: SubscriptionSchema / SubscriptionEventSchema (api/realtime.zod.ts), EventSubscriptionSchema (api/websocket.zod.ts), and RealtimeSubscriptionOptions (contracts/realtime-service.ts).
Why it is worth a card rather than nothing
The sentence is the kind a census believes. It reads as a positive statement that SubscriptionEventSchema has a consumer — the transports — and it is the first thing a reader hits when asking who reads that schema, because it is the only prose in the repo that connects the two. The liveness ledger seeded in PR #15242 classifies all six SubscriptionSchema properties dead on the opposite measurement, so the tree currently carries a ledger row and a source comment that disagree; the row records the contradiction as a warning, which is a patch over the wrong half.
Suggested disposition
Correct the clause to name contracts/realtime-service.ts#RealtimeSubscriptionOptions as the carried shape and keep SubscriptionEventSchema.filters where it belongs — as the sibling declaration that shares the z.unknown() treatment, not as the shape anything transports. A symbol anchor rather than a bare name, since the point of the sentence is which of three same-named things is meant. No behaviour changes; packages/spec/src/api/websocket.zod.ts is the only file involved.
⚠️ Not urgent and not a blocker for anything: #14446's ledger rows already carry the correction as a ⚠️ do not read this as a consumer note, so the next census is protected whether or not this lands.
Observation found out of scope while seeding the realtime liveness ledger for #14446 (PR #15242). Comment-only defect in shipped source; nothing executes differently either way. Filed rather than fixed because #14446's PR is ledger-rows-only by triage ruling.
What the comment says
packages/spec/src/api/websocket.zod.ts:54-77is the retirement note for the deletedFilterOperator/EventFilterCondition/EventFilterSchemavocabulary. Two sentences in, it says (lines 61-63):The first half is exact. The second half names the wrong shape.
What is measured
At
5f5511f0, nothing outsidepackages/specimportsSubscriptionEventSchema,SubscriptionSchemaorRealtimeConfigSchemaat all.git grep -nE 'SubscriptionEventSchema|SubscriptionSchema|RealtimeConfigSchema'over the repo excluding CHANGELOGs hits eleven files, every one of them spec's own tree, a generated artifact (api-surface/,declaration-map/,export-origins/) or published prose (content/docs/references/api/realtime.mdx,skills/objectstack-api). No transport parses aSubscriptionEvent.The shape the shipped subscription path actually carries is a plain TypeScript interface one directory over:
packages/spec/src/contracts/realtime-service.ts#RealtimeSubscriptionOptions, withobjectandeventTypes: string[]. That is whatpackages/services/service-realtime/src/in-memory-realtime-adapter.ts#matchesSubscriptionreads — it takessub.optionstyped as those options and comparesopts.objectandopts.eventTypesagainst the event. The same file'sSubscriptionis a file-local interface, unrelated to the spec symbol of that name.So there are three spellings of a realtime subscription and only the third is executed:
SubscriptionSchema/SubscriptionEventSchema(api/realtime.zod.ts),EventSubscriptionSchema(api/websocket.zod.ts), andRealtimeSubscriptionOptions(contracts/realtime-service.ts).Why it is worth a card rather than nothing
The sentence is the kind a census believes. It reads as a positive statement that
SubscriptionEventSchemahas a consumer — the transports — and it is the first thing a reader hits when asking who reads that schema, because it is the only prose in the repo that connects the two. The liveness ledger seeded in PR #15242 classifies all sixSubscriptionSchemapropertiesdeadon the opposite measurement, so the tree currently carries a ledger row and a source comment that disagree; the row records the contradiction as a warning, which is a patch over the wrong half.Suggested disposition
Correct the clause to name
contracts/realtime-service.ts#RealtimeSubscriptionOptionsas the carried shape and keepSubscriptionEventSchema.filterswhere it belongs — as the sibling declaration that shares thez.unknown()treatment, not as the shape anything transports. A symbol anchor rather than a bare name, since the point of the sentence is which of three same-named things is meant. No behaviour changes;packages/spec/src/api/websocket.zod.tsis the only file involved.⚠️ do not read this as a consumernote, so the next census is protected whether or not this lands.