From 844cf6160794e269082b49b4c0b80dc379c3827f Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 8 Sep 2026 21:03:07 +0000 Subject: [PATCH 1/2] docs(spec): name the shape the transports carry in the websocket retirement note MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The retirement note for the deleted `FilterOperator` / `EventFilterCondition` / `EventFilterSchema` vocabulary said the subscription shape the transports actually carry is the `filters: z.unknown()` on `SubscriptionEventSchema` (`api/realtime.zod.ts`). Measured, no transport parses that schema at all: the shipped subscription path carries a plain TS interface one directory over, `contracts/realtime-service.ts#RealtimeSubscriptionOptions`, whose `object` and `eventTypes` are the only two fields `matchesSubscription` reads. Only the sentence's second half moves. Its first half — `matchesSubscription` matches on object name and event type only — was already exact. `SubscriptionEventSchema.filters` keeps its place in the note as the sibling declaration of the same unenforced kind, which is what it is; it is simply no longer described as a shape anything transports. The correction uses a symbol anchor rather than a bare name, because the whole point of the sentence is which of four same-ish spellings is meant, and rather than a line number, because prose citations by line rot. No key, type, export or tombstone is touched, and no behaviour changes. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_016N6xmWt5hYm94ffVEwGH8x --- packages/spec/src/api/websocket.zod.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/spec/src/api/websocket.zod.ts b/packages/spec/src/api/websocket.zod.ts index ef6005d206..3348dd7674 100644 --- a/packages/spec/src/api/websocket.zod.ts +++ b/packages/spec/src/api/websocket.zod.ts @@ -61,9 +61,12 @@ export type WebSocketMessageType = z.input; // Nothing imported any of it — not this repo, not objectui, not cloud — and no // runtime ever evaluated an event filter: `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`). +// subscription shape the transports actually carry is a plain TS interface one +// directory over — `contracts/realtime-service.ts#RealtimeSubscriptionOptions`, +// whose `object` and `eventTypes` are the only two fields that predicate reads. +// The separate, deliberately unvalidated `filters: z.unknown()` on +// `SubscriptionEventSchema` (`api/realtime.zod.ts`) is a sibling declaration of +// the same unenforced kind, not a shape any transport carries. // // So this was a *second* spelling of event filtering, disagreeing with both the // live one and with `VALID_AST_OPERATORS`, and it described a capability no code From fdb725a6bda3468bcfd12d57ca348f0b4b8f03cf Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 8 Sep 2026 21:48:56 +0000 Subject: [PATCH 2/2] chore(changeset): patch @objectstack/spec for the websocket retirement-note correction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both halves of the publish test say yes, so this is not a `skip-changeset`: the changed path matches `src/**/*.zod.ts` in the package's `files[]`, and the changed text is byte-present in the packed tarball. Measured on the real `npm pack` output with controls — a `.describe()` from the same file reaches `src` + `dist` + `json-schema` (7 files), a string unique to a sibling `*.test.ts` reaches none, and this `//` comment reaches exactly the shipped source file. `src/**/*.zod.ts` is the tree that decides it. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_016N6xmWt5hYm94ffVEwGH8x --- .../websocket-retirement-note-carried-shape.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .changeset/websocket-retirement-note-carried-shape.md diff --git a/.changeset/websocket-retirement-note-carried-shape.md b/.changeset/websocket-retirement-note-carried-shape.md new file mode 100644 index 0000000000..a4a0d54e13 --- /dev/null +++ b/.changeset/websocket-retirement-note-carried-shape.md @@ -0,0 +1,15 @@ +--- +"@objectstack/spec": patch +--- + +`websocket.zod.ts`'s retirement note now names the subscription shape the transports actually carry. + +The note recording the deletion of the `FilterOperator` / `EventFilterCondition` / `EventFilterSchema` vocabulary stated, as a positive fact, that "the subscription shape the transports actually carry" is the deliberately unvalidated `filters: z.unknown()` on `SubscriptionEventSchema` (`api/realtime.zod.ts`). Measured, no transport parses that schema at all — nothing outside `packages/spec` imports it — so the sentence read as evidence that the schema *has* a consumer, and it was the only prose in the repo connecting the two. + +The shipped subscription path carries a plain TypeScript interface one directory over: `contracts/realtime-service.ts#RealtimeSubscriptionOptions`, whose `object` and `eventTypes` are the only two fields `matchesSubscription` (`service-realtime/src/in-memory-realtime-adapter.ts`) reads. + +- **Only the sentence's second half moved.** Its first half — `matchesSubscription` matches on object name and event type only — was already exact, and is untouched. +- **`SubscriptionEventSchema.filters` keeps its place in the note**, as the sibling declaration of the same unenforced kind. That is what it is; it is simply no longer described as a shape anything transports. +- **The correction anchors on a symbol** — not a bare name, and not a line number. Four same-ish spellings of a realtime subscription exist and only one is executed, so a bare name would re-plant the ambiguity the sentence exists to remove, and a line-number citation would rot out of date. + +**What moves for consumers.** Comment text only, and it is genuinely shipped: `@objectstack/spec` publishes `src/**/*.zod.ts`, so `src/api/websocket.zod.ts` reaches the npm tarball verbatim, comments included. Nothing else moves — no key, type, export, tombstone or accept set, no `.describe()` string, and no generated artifact.