SAPE-1 added productVersion to the welcome frame,
so a connected client can record which build of the server answered — as opposed to
version, which is the protocol version and is a constant.
The Go client reads it: wire.Welcome.ProductVersion
(internal/wire/wire.go:107), surfaced by the shell at
internal/cli/shell.go:469.
The TypeScript client does not have the field. Its welcome handler decodes the frame into a type that names one key and discards everything else:
// packages/ecosy-sapedb/src/client/index.ts:831-833
} else if (frame.type === FrameType.welcome) {
const body = decodeJsonPayload<{ challenge?: string }>(frame);
if (body?.challenge) entry.resolveChallenge(body.challenge);
}
So the bytes arrive, are parsed, and are thrown away — there is nowhere in the client to put them and nothing a caller can ask.
grep -rnI -F productVersion packages/ecosy-sapedb/src → 0. Same
for tests/ and fixtures/. The identifier does not exist in the
package.Welcome type in the TypeScript client at all — no interface, no
exported shape. The welcome body exists only as the inline
{ challenge?: string } at the decode site, which is why adding a field to the frame
changes nothing on this side, for good or ill.internal/server/server.go:544 declares
ProductVersion with the JSON tag productVersion, filled at
server.go:580 from options.ProductVersion, which defaults to
build.Version (server.go:149-150).TestAClientThatPredatesTheProductVersionStillReadsTheWelcome
(internal/server/product_version_test.go:126). That is the property that makes this
Defer rather than Fix. The other direction is pinned by
TestAConnectedClientReadsTheDaemonsProductVersion
(version_live_test.go:126).Cogeze\Sapedb\Welcome (packages/cogeze-sapedb/src/Welcome.php) is a real
typed value object with seven readonly fields — version, account,
dbname, mode, lsn, encrypted,
challenge — and fromArray reads exactly those seven. No
productVersion. It is one constructor argument away, which makes it the cheaper of the
two.grep -rn ProductVersion packages/sape-desktop → 0 — so its status bar says
the account, the database, the explore right and the round-trip time, and not which build
answered.Does it lose data, break a promise on a public surface, or stop somebody installing and running? No, no, and no — and the first two were checked rather than assumed.
Nothing is lost: the field is informational and the server keeps a copy of what it sent. Nothing on a public surface is broken: the wire rule for 1.0.0 is that fields may be added and never renamed or removed, this is an addition, and an old client meeting a new daemon connects and runs normally — measured in both directions, not reasoned about. Nothing blocks installing or running.
Defer. This is the mildest kind of gap: a capability that exists on one side and has not yet been picked up on the other. It is the mirror of ISS-12 and it is triaged the opposite way for a reason worth stating — ISS-12 makes an operation uncallable from a client, while this one makes a field unreadable. One blocks work; the other withholds a convenience.
sapedb version; it is not answerable from a TypeScript or PHP application, which is
where most reports will come from.Welcome type instead of widening the inline
{ challenge?: string }. As it stands, every future welcome field will be dropped by
default, and dropping by default is why this issue exists.