Three clients, in three languages, in three repositories:
github.com/sapedb/sapedb at the module root
(sapedb.go), a thin public wrapper over internal/wire: twenty type
aliases for the value shapes a caller handles, Parse and Dial,
Client and Explored, and nine methods on Client. 33 names.@ecosy/sapedb
(packages/ecosy-sapedb): protocol, connection, signer, node transport, client,
commander and shape layers.cogeze-sapedb: connection, signing, frames, invoke.
Each of the three is exercised against a real sapedbd process over a real socket, not
against a mock of the protocol.
Every unit test on either side of a wire passes when each side agrees with itself. The TypeScript driver's own header lists what only a live server found: field names that differed, a failure payload the driver could not read, a mode the server had never implemented, and a signing label where a blank configuration field silently chose an incompatible key. None of those is findable without the two processes in one room.
The Go client had the same shape of bug and it survived until the first live invoke:
Invoke sent arguments under "arguments" where the server decodes
"args", so the server saw no arguments at all on every call.
declare_live_test.go starts a real sapedbd, seeds
the collection through internal/server before the daemon starts, and does
everything after that over a socket — the daemon is the subject, not the instrument. The
assertion is not only that the call works: the pid started at the top is the pid still serving at
the bottom, it was never signalled, and one connection carried both the declaration and the call
that used it.tests/server.test.mjs spawns the Go binaries named by
SAPEDB_SERVER_BIN and SAPEDB_CLI_BIN and drives
dist/ — the built artifact, not the sources. Its CI job
(.github/workflows/test.yml) clones the server repository beside the checkout,
builds both binaries and runs the suite with them, so the live half is not an opt-in somebody
forgets.tests/e2e/InvokeE2ETest.php is the one test in that package
that dials a real sapedbd.fixtures/frames.json is the shared conformance artifact all three build against, and
TestEveryRequestFixtureDecodesIntoTheStructThatServesIt
(internal/server/fixture_decode_test.go:28) is what stops it drifting from the structs
the server actually decodes.SAPEDB_TEST_HOST is set, and cogeze-sapedb has no CI workflow at all, so
nothing runs it unattended. "Run against a real daemon" is true of all three; "run against a real
daemon on every change" is true of two.Client.Present). TypeScript and PHP carry no grant code — measured:
grep -i grant over ecosy-sapedb/src returns 0. So an operation that
declares a scope is callable from one of the three. ISS-12.productVersion to the welcome after this ticket closed; the Go client reads it and the
other two drop it — ISS-16. Two features in one release that one
client has and two do not is a pattern, not a coincidence: nothing in this ticket's definition of
done required the three surfaces to match.