feat(voice): booking calls + schema negotiation - #48
Merged
Conversation
Carries the call-delete tombstone. Calls are otherwise immutable one-way pushes; this is the one exception, because a hard DELETE can't sync under a push-the-row model — so a delete rides as an ordinary upsert with deletedAt set, same as the account tombstone already does. Two things a consumer needs to know, documented on the field: the platform treats this tombstone as *sticky* (COALESCE, not last-write-wins — a call has no updatedAt to resolve on), so re-syncing with None can never undelete; and deleting also destroys the recording bytes, the transcript, and any live share link, not just the flag. VoiceCallsQuery gains includeDeleted so a device can pull tombstones and reap its local copies. Step 2 of the three-repo train — wavekat-platform accepts the field already; wavekat-voice needs a release of this before it can build. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EEyoayhGVRqCCY9BWJTKDD
Two additions the daemon needs before it can run a `book` step (wavekat-platform docs/30 §4). **The booking pair.** `booking_slots` and `booking_book` — "when is this business free?" and "put the caller in at this time". Unlike everything else in this file these are synchronous and in-call: nothing is queued, batched or retried, because a person is on the line. The calendar credential never reaches this crate; the platform holds the connection and answers in times and outcomes, which is what makes booking two platform calls rather than a Google client in every daemon. Both routes speak snake_case, unlike the camelCase sync resources, so these types carry no `rename_all` — with a test pinning it, since a camelCased body is rejected mid-call and the flow can only render that as "unavailable". `status` stays a string rather than an enum: failing to deserialize an unknown status would drop a live call. **`VoiceFlowsQuery::schema_versions`.** The caller states which document versions its flow engine can run, and the platform withholds the rest rather than serving something that fails to parse and leaves a line unarmed. `None` is not "anything goes" — the platform reads a missing value as version 1 only, because the parameter arrived alongside version 2. Explicitly renamed to the server's `schema_versions`: the struct is camelCase, and a silently camelCased key is ignored by the server, which reads exactly like an account with no flows in that version. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018stjkZJ4kxDViq1ENnVDmH
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two additions the daemon needs before it can run a
bookstep(wavekat-platform docs/30 §4).
The booking pair.
booking_slotsandbooking_book— "when is thisbusiness free?" and "put the caller in at this time". Unlike everything
else in this file these are synchronous and in-call: nothing is queued,
batched or retried, because a person is on the line. The calendar
credential never reaches this crate; the platform holds the connection
and answers in times and outcomes, which is what makes booking two
platform calls rather than a Google client in every daemon.
Both routes speak snake_case, unlike the camelCase sync resources, so
these types carry no
rename_all— with a test pinning it, since acamelCased body is rejected mid-call and the flow can only render that
as "unavailable".
statusstays a string rather than an enum: failingto deserialize an unknown status would drop a live call.
VoiceFlowsQuery::schema_versions. The caller states which documentversions its flow engine can run, and the platform withholds the rest
rather than serving something that fails to parse and leaves a line
unarmed.
Noneis not "anything goes" — the platform reads a missingvalue as version 1 only, because the parameter arrived alongside version
2. Explicitly renamed to the server's
schema_versions: the struct iscamelCase, and a silently camelCased key is ignored by the server, which
reads exactly like an account with no flows in that version.
🤖 Generated with Claude Code
https://claude.ai/code/session_018stjkZJ4kxDViq1ENnVDmH