Skip to content

v1.2.0 — writes are verified, not assumed

Latest

Choose a tag to compare

@ConalMullan ConalMullan released this 14 Aug 14:00
0c7d1ed

Writes are verified, not assumed

Every write tool used to report success on any 2xx. That is not evidence: several Digital Samba endpoints accept a request, return 200, and do nothing. A tool that says "Successfully imported polls" when nothing was imported is worse than one that errors, because the caller acts on the lie.

A read-back sweep on 2026-08-13/14 covered ~65 of the 145 tools, including a live-session phase with a human in a browser, and found seven such defects. Four were ours and are fixed here. Three are API-side and are now contained, so they fail loudly instead of lying.

Three of those four were only identified as ours by reading the API's source before reporting them as backend bugs — they had already been written up as the platform's.

⚠️ Behaviour changes worth knowing

These tools previously reported success and now return errors. Nothing they claimed to do was ever happening:

  • publish-poll-results — the API has no publish-results endpoint. It is not routed anywhere in the backend, so the call could only ever 404. The "Session ID is required" message that made this look like an API constraint was this server's own guard, so the request was never actually sent.
  • copy-library-content — there is no copy endpoint either. For a file this created an empty placeholder stuck at status uploading and called it a copy, for every file type. Webapps are now genuinely duplicated from their URL; stored files are refused with the reason; folders no longer call themselves copies.
  • update-recording — the API has no recording-update endpoint, so "rename recording" was always a no-op returning a bare message with no error flag.

Fixed

  • update-role silently dropped displayName and update-webhook silently dropped authorizationHeader. Both passed camelCase fields to a snake_case API, which ignored them, returned 200, and were reported as updated. update-role partially applied — permissions landed, the rename did not, and the tool claimed both.
  • period on the analytics tools was never an API parameter, so asking for "last week" silently returned all-time figures. It is now translated into the date range the API does accept; an explicit dateStart/dateEnd always wins.
  • create-question now returns the question ID, recovered via the Q&A export. The create endpoint does not return one, which previously left callers unable to act on what they had just created.
  • create-room exposes tags. The API accepts them on POST; PATCH does not, so creation is the only opportunity — which had made delete-rooms-by-tag impossible to target from this server.
  • delete-rooms-by-tag stops claiming deletion. The endpoint answers 202 with an empty body, so the work is asynchronous and uncounted, and an unmatched tag is indistinguishable from a matched one. For a bulk delete, that distinction matters.
  • connect-phone refuses when the room has no telephony, rather than reporting a connection the account cannot make.
  • create-whiteboard stops requiring a name the API discards.

Added

  • list-polls — the API exposes GET /rooms/{id}/polls and the client already had it, but no tool surfaced it, so listing a room's polls meant fetching the whole room object. 145 tools (was 144). No tools were removed or renamed.

Still broken upstream — please read

Three defects are in the platform, not this server, and remain broken for customers after this release. What changes is that they now fail visibly instead of reporting success:

  • import-polls — the endpoint is hardcoded to preview mode and never saves. Reported with a root-cause analysis; a fix is a two-line change.
  • send-chat-message — the signalling server has no chat endpoint on any released build, so the API accepts the message, drops it, and returns 200. Confirmed by the backend team, fix scheduled. This tool now reads the chat back and reports the real outcome.
  • connect-phone — the API returns success on accounts without telephony. Now pre-checked here.

Under the hood

  • New src/tools/verified-write.ts: one path that reports the response body's evidence where there is any, runs a read-back where one is cheap, and otherwise states plainly that the request was accepted and nothing more.
  • Root cause was in the API client, not the handlers — Q&A, chat and live-control writes were Promise<void> doing await this.request<void>(...), discarding the response body entirely.
  • Chat verification is conditional on chat_persistence_enabled, because without persistence an empty export proves nothing.
  • npm run smoke — a live, read-back-verified smoke test against dev, now the release gate. It drives the built server over stdio, so a stale build tests stale code.

604 tests (was 525 at v1.1.0). Smoke against dev: 24 passed, 0 failed, 1 known issue.