Skip to content

Tags: Calnode/calnode

Tags

v0.10.1

Toggle v0.10.1's commit message
docs(changelog): 0.10.1 notes for #103-106 (rate limit, CalDAV oracle…

…, auth redirect, boot panic)

v0.10.0

Toggle v0.10.0's commit message
chore(release): 0.10.0

v0.9.0

Toggle v0.9.0's commit message
0.9.0

v0.6.0

Toggle v0.6.0's commit message
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

Toggle v0.5.0's commit message
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

Toggle v0.4.0's commit message
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

Toggle v0.3.0's commit message
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.