Repository navigation
Tags: Calnode/calnode
Tags
v0.6.0 Slot interval is configurable, and the MCP connector URL is discoverable. Bookable slots being "always 30 minutes apart regardless of duration" (#13) was not a slot-generation bug: slot interval and duration are separate settings on purpose, since that is what allows a 45-minute meeting to be offered on the hour. The real problem was that the interval appeared nowhere in the admin UI, so every event type was pinned to the schema default of 30 unless you drove the REST API by hand. From a user's chair that is indistinguishable from duration being ignored. It now appears in the event-type editor, and new event types default it to their duration instead of a fixed 30 - a default that was wrong in both directions, offering a 15-minute event slots every half hour while offering a 90-minute one starts it could not honour. Existing event types keep whatever interval is stored. Upgrading changes nothing about how they behave; set the field explicitly to change one. Both create and update now validate it. Slot generation refuses a non-positive interval, so a 0 previously produced an event type with no bookable times and nothing explaining why. Also: the Connected apps page now shows the MCP connector URL with a copy button. It listed the apps you had connected but never said how to connect one - the only guidance lived in the empty state and disappeared as soon as the first app was approved. Upgrading is a straight image bump. No migrations.
v0.5.0 Choose which calendar bookings are written into, and fixes for a booking page that could render blank. Bookings can now be written into a specific calendar inside a connected account, not just that account's default. Reported in discussion #10 by a user whose work calendar was checked for conflicts but could not be made the one bookings landed in. The picker and the free/busy wiring had shipped; the write path had not. Each provider applies the choice where its own write target lives: Google and CalDAV swap the calendar id, while Microsoft posts to /me/events - the default calendar by definition - so a chosen calendar means /me/calendars/{id}/events. Read-only calendars are shown greyed out rather than failing at booking time. booking_hosts.external_calendar_id (migration 00055) records where each event was actually written, so reschedule and cancel act on that calendar rather than re-resolving the current destination. Without it, changing the destination would leave existing bookings' events unreachable: the provider 404s, the booking cancels in Calnode, and the meeting stays on the host's calendar. Fixes: - The public booking page rendered blank for any event type with a dropdown question. A template error aborted rendering mid-response, producing a 200 with a truncated body - everything up to the dropdown present, the calendar and every script missing. Present since 0.3.0. - Choosing where bookings are written failed with "calendar connection not found", and disconnecting a calendar could report success while deleting nothing. Both addressed connections by a row id that is recreated on every OAuth token refresh. - Disconnecting left the account's calendar selections behind, so reconnecting the same address silently inherited stale picks. Upgrading is a straight image bump. Migration 00055 is an additive column and runs automatically on boot.
v0.4.0 Email delivery over Resend's HTTPS API, and hardening for the image uploads. The headline is that SMTP is not universally available. Several hosting platforms block outbound SMTP on their cheaper plans - Railway does below Pro - by dropping the packets rather than refusing the connection, so it presents first as a hang and then as a wrong password, on every SMTP port, for every provider. Nothing at the SMTP layer fixes it. Setting a Resend API key under Settings > Email now sends over port 443 instead. The transport follows the credentials you supply rather than probing and silently switching, and the settings page badges which path is actually live. Verified end to end on a Railway Hobby instance, including that calendar invites still arrive RSVP-able over the API path rather than degrading to a plain file attachment. Also fixes a failed SMTP dial hanging for roughly two minutes - the timeout was applied only after the connection opened, so the dial itself ran to the OS SYN-retry limit and stalled the job queue behind it. Security: all three image uploads now check dimensions before decoding. The 5 MB body limit bounds bytes on the wire, not pixels; a 164 KB PNG can decode to hundreds of megabytes. The branding logo and banner are admin-only, but the user avatar upload is not, so any authenticated member could have taken the process down with a single request. Upgrading is a straight image bump. Migration 00054 is an additive column and runs automatically on boot.
v0.3.0 Multi-language public surfaces. The booking page, manage page, embed widget, all four emails, the calendar invite and the conversational booking assistant now render in English, Spanish, French, German, Italian, Portuguese, Dutch and Swedish. Locale is negotiated from Accept-Language with a footer switcher and an operator fallback setting, and is stored on the booking so reminders arrive in the language the booker used. Adding a language is adding one JSON file - no code change. Also fixes: paid (Stripe) bookings always emailed in English, required checkboxes were not enforced, and the public event-type endpoint was missing a Vary header. Non-English translations are machine drafts without native review; the admin UI and the built-in video room remain English-only.
PreviousNext