Skip to main content

RoomVox - Releases

← App details

Nextcloud 34

RoomVox 1.3.0
Release Details
UpdatedAug. 13, 2026, 5:23 p.m.
Changelog

Room metadata that RoomVox already held — floor, address, building — never fully arrived at the calendar clients that show it. This release fixes the publishing side, which matters now that Nextcloud Calendar is gaining a room browser that groups rooms per building and filters on floor and capacity (nextcloud/calendar#8264). It also fixes booking one event into two rooms at once, and makes notification emails translatable. No stored data changes; the room editor keeps its fields exactly as they are.

A minor rather than a patch release: notification emails become translatable, bookings gain an allDay field in the API, and RoomVox moves onto the Nextcloud community translation workflow — which changes how the app is built and which files ship.

Translations. The strings added in this release are not translated yet: RoomVox is being onboarded onto the Nextcloud community translation platform (nextcloud/docker-ci#986). Until translators pick them up, untranslated text falls back to English — the interface stays translated where it already was. New translations arrive in later releases without any configuration change.

Added

  • Notification emails are translatable and sent in the recipient's language (#24): every subject and body in MailService was a hardcoded English string — the app had no IL10N at all — so a French user with a French interface still received English mail. All 14 notification types now resolve their text through Nextcloud's translation system, and the language is chosen per recipient rather than from the server default: the organizer, each room manager, and the admin can each receive the same booking in their own language, resolved from their Nextcloud account (external addresses, which have no account to read a preference from, fall back to the instance default; an address matching more than one account is treated as unknown rather than guessed). Values are never translated — room names, event titles and dates are substituted into placeholders, so translators get whole sentences instead of fragments. Alongside this, RoomVox moved to the Nextcloud community translation workflow: all 526 frontend call sites were converted to the t('roomvox', …) form the Nextcloud translation bot extracts (it reads only that literal form, so with the previous $t(…) wrapper it would have found none of them), a POT template is generated from both the Vue and PHP sources, and the existing German, French and Dutch translations were carried over so no language restarts from zero. A prebuild guard fails the build when a new source string has not been pushed for translation yet.
  • Rooms publish their building name: RoomVox holds the building as its own field, but CalDAV had nowhere to put it, so clients that group rooms per building had to infer one from the address — usually by taking everything before the first comma, which turns a room at "1098 XG, Amsterdam" into a building called "1098 XG". Rooms now publish {http://nextcloud.com/ns}room-building-name, taken from the building field itself rather than guessed. An empty building field publishes nothing rather than letting the street stand in for it. Proposed upstream as IRoomMetadata::BUILDING_NAME; clients that do not know the key yet simply ignore it.

Changed

  • Interface labels follow the Nextcloud writing guidelines: 44 labels used Title Case where Nextcloud uses sentence case ("Save Changes" → "Save changes", "My Rooms" → "My rooms"), and twelve progress labels ended in three full stops rather than a real ellipsis ("Saving..." → "Saving …"). Acronyms, product names and Microsoft's own field labels keep their capitals, so "API tokens", "SMTP Host" and "Client Secret" still read the way an administrator sees them in Entra. Existing German, French and Dutch translations were carried over to the renamed labels, so nothing that was translated became untranslated. Cosmetic only — no behaviour changes.
  • Translations no longer carry strings the app removed: each language bundle held 79 entries for labels deleted in earlier releases. They were never shown (Nextcloud simply never looked them up) but shipped in every release and would have been imported into the translation platform as translations without a source string. Each language now holds exactly the 359 strings the app actually uses.

Fixed

  • Some CSV columns were silently dropped on import (#29): importing a room with every column filled in lost roomNumber, roomType, postalCode and autoAccept — which also meant RoomVox's own CSV export could not be imported back, the very file the export offers as a template. CSV headers are matched case-insensitively, but the parser compared the lowercased header (roomnumber) against field names that are camelCase (roomNumber); the four columns whose names contain a capital matched nothing and were skipped without warning, while the ten all-lowercase ones came through fine. Headers are now resolved to their canonical field name through a single map derived from the export column list, so the export/import round-trip cannot drift apart again. Case-insensitive matching and the MS365/Exchange column mapping are unchanged.
  • Month view showed the wrong month in the header (#26): the booking calendar's month view labelled August 2026 as "July 2026". The heading was taken from the first cell in the grid, and a month view pads its first row with the tail of the previous month (August 2026 starts on a Saturday, so the grid opens on 27 July). Months could therefore appear twice or not at all while paging through the calendar. The heading now comes from the period the view actually represents.
  • Approval requests stayed in the queue after the meeting had passed (#28): a manager's approval list showed every pending request ever made, including meetings that were weeks in the past, because the bookings were fetched with no date range at all. Requests whose meeting has already ended are now filtered out at the source. A meeting that has started but not yet finished is still listed — it can still meaningfully be approved. Nothing is deleted: an expired request only disappears from the queue, so the booker's own calendar entry and history stay intact.
  • All-day bookings were shifted by the timezone (#27): an all-day event showed as running 02:00–02:00 across two days instead of covering one whole day. An all-day VEVENT stores a plain calendar date (DTSTART;VALUE=DATE:20260813) with no time and no timezone, but RoomVox serialised every booking as a precise timestamp — which turns midnight into an instant that renders as 02:00 in UTC+2 and spills into the next day. All-day bookings are now detected and passed to the interface as a bare date with an explicit all-day flag, so the calendar and the booking list show them as a full day with no time attached, labelled "All day" rather than a clock time. The resource timeline needed the same care: it only renders 08:00–19:00, so a booking running midnight to midnight was drawn straight through into the next day's slots — all-day bookings are now bounded to the hours the timeline shows, while a multi-day booking keeps its real length. Timed bookings are unaffected. API consumers see this too: booking objects gain an allDay boolean, and for an all-day booking dtstart/dtend are a plain YYYY-MM-DD date instead of a timestamp — clients that assume a timestamp should check the flag.
  • Booking two rooms on one event without auto-accept only requested approval for the first (#22): the second room stayed on "Needs action", never appeared in the approval queue, and a manager could not change it. An event booked into two rooms carries both room ATTENDEE lines, and each room calendar holds its own copy of that same event — but every PARTSTAT lookup scanned for the first CUTYPE=ROOM attendee rather than the attendee belonging to the room whose calendar was being read. So room B reported room A's status (ACCEPTED once A was approved, hiding B from the queue, which filters strictly on TENTATIVE), and approving room B wrote ACCEPTED onto room A's line, leaving B stuck forever. The three affected lookups in CalDAVService (getBookings(), getRawCalendarObjects(), updateBookingPartstat()) now match the owning room's own email first, via a shared extractRoomPartstat() helper; the previous CUTYPE=ROOM/non-organizer heuristic remains as the fallback for single-room events and for clients like iOS that send CUTYPE=INDIVIDUAL. Two related multi-room defects are fixed alongside it: declining one room removed its attendee mid-iteration, which invalidated the loop and silently skipped the PARTSTAT write-back for every later room on the event (removals are now deferred until after the loop), and that same decline cleared the event LOCATION even when another room was still attached (LOCATION is now only cleared when no room attendee survives, otherwise it is rebuilt from the remaining room). Earlier analysis had suspected Sabre/Nextcloud's iTIP dispatch; the scheduling path is in fact correct and fully per-room — the defect was one layer down, in reading the result back.
  • Room floor was invisible to every CalDAV client: the room backend published the floor under {http://nextcloud.com/ns}room-building-floor, which is not a key any client asks for. Nextcloud defines the property as IRoomMetadata::BUILDING_STORY (room-building-story), and cdav-library requests only that one in its PROPFIND, so the value never reached Nextcloud Calendar, Outlook, Apple Calendar or Thunderbird. The backend now publishes room-building-story. Nothing consumed the old key, so this only adds data where there was none — on our test instance 97 of 113 rooms had a floor set that no client could see. Floors appear after the hourly UpdateCalendarResourcesRoomsBackgroundJob has run, or immediately after occ background-job:execute.
  • Imported rooms published a malformed address: addresses are stored in a fixed four part format ("Building, Street, PostalCode, City") so the room editor can split them back apart, but that is an internal detail. A room imported without a building or street was published to CalDAV clients as , , 1098 XG, Amsterdam, which clients show verbatim and use to derive a building name. Empty positions are now dropped when publishing, and in the room description, without touching how rooms are stored — the editor keeps its four fields. This matters more now that Nextcloud Calendar groups rooms by building; see nextcloud/calendar#8264.
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureTuRtOoNTIAfHxKuFfgxldiQjduru8p+rl2W2QR+KfudIh44YAQn0+Q5bAIti+8uupMo2pIwJxZYOfN6qwfyMd7hmC9ngiEs9F2gQpRmu7Ko0ocdLp+F+H1ajHAk8Z7UJQXS3IIaLrwrjDF5F1G0UOacufnSB4Dp5GdJcFHy7kmwfrk5ynNmOxvFHuMho0M12n7jfS1get2yUgB2zWyg2GByiu4d9haUj2NESybi30SaUit0I8COJyF5uMZi3CezaIiXZLtM+QaOvIfps6U1QcA/5D9nJViUYgNuFGFC3tsE39o+RZ3ArNE3zZbhR5lxaqJlgnmU+pqLqS/R6srL3uR+NuzmJs6LgFCzmgQt4JFLuHr7xU7WBe5+dhtppolj9oX8dzmdVZeUulHS+YLltzTRhoxdLUWNMAXaMxejRZ8fmgA57/ljDXvHULqjWNIKS7Bnpufe32QTUhxAo3Qjro/bIlNlay94ST8SLXbWveCMDVUJ4h/NJTM/JHKXOwuHZ3SoAxkshdJgGrQ92fQA/qMVQehWL8FdyUU4YmA7zP6PPsf1aEfZkwcSEm7WDsjYDbesjY6P0PunQxoTS9b543jhLKSOevsXb3mmaxGmLz8LrY1ZQzf7KADoCznC6OLYYpVpILRis/v2cs3q37o8tox82KlJAC9tnbqhCuMiKPfg=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<35.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.2.1
Release Details
UpdatedAug. 3, 2026, 5:56 p.m.
Changelog

Changed

  • Booking administration room filter now shows the room group (#19): in installations with multiple room groups, room names are often reused (e.g. "Church" and "Office" in both "Parish A" and "Parish B"), and the filter listed them indistinguishably. Each option is now labelled "Room (Group)" — e.g. "Church (Parish A)" — so rooms can be told apart. Rooms without a group keep their plain name. Frontend-only; no API or data changes.
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureYJ2npvyqg6agBjsoTDT1VVZGa1LI9d4XhZdQ1NMz3tee56ch76U94qAA/POOA2+a00B5LvIpPtrWr2EIqX8f/+ndlJUkQ+FtWADGprnwim/KIm+/u2srj9l6Efe9WDfc0JEY4GTQDt+n8bmT7fLtcDrwCLT9CpJncKe7SlRTYC8YJSzMfadM8/OAGbPTcWnIQsOw5l84+vBgjorkGkz87m1DxG/TrCaxmRe7P4h5BWk+yHo/OoUzP31D63XFcX9i1YBsn+CfomO622rJ7eGW7EnfB870E0x9q5bMkx3q+Oq2kFK1uw7LoO1azV53EaprG4twE5ytwrgafbUcT42dO7Usa6JrdGCl03nN3ZjGfkpyyZ2h61/H+8ecm7I8uVIlnIFOPofyCg45UqDNC7DtdOlIBUMuZ90XpIowttmWm9X4MS1CJSbEXt27o/7kMerYQHvk9xXoiaorqaJ345PNupFBkcqcfDFnYk/iiUmbmud0GAiGcc1raCUsL+A6n5VqDR2edA5BG1Y8BVYU1DB79EJa3Qj0XM6Gjd3DWbRyRptQ0G2Fbu667rVmc1rSHUedUw5xOIa8TG5wkCTfund2v/1uy3omDnIjDM5zcCnSHDd0NDCrQf4S9XSsru6EE9Lrt3m2AIpws+dpYlGFGOY+mVMP7xvE14jcOLCWDbUO3Ac=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<35.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.2.0
Release Details
UpdatedAug. 3, 2026, 5:42 p.m.
Changelog

Security

  • "Show all rooms" dialog ignored room visibility permissions (#20): In the Nextcloud Calendar room picker, the type-ahead field correctly hid rooms a user may not view, but the "Show all rooms" dialog listed every room — exposing room names, locations, and organisational structure to unauthorised users. The dialog now intersects the calendar's room list against a server-authoritative allow-list (GET /api/personal/rooms/viewable, filtered by PermissionService::canView), so it shows exactly the rooms the type-ahead does. The allow-list endpoint returns only room id + email (no other detail), and the dialog fails closed — if the allow-list can't be loaded it shows no rooms rather than risk leaking. Booking was already enforced server-side by the scheduling plugin; this closes the information-disclosure gap in the browse UI.

Added

  • Public, subscribe-able iCal feed per room (#16): The iCal feed at /api/v1/rooms/{id}/calendar.ics already existed, but required a Bearer token — which external calendar apps (Nextcloud Calendar, Outlook, Apple Calendar, Thunderbird) and signage displays cannot send, so nobody could actually subscribe to it. Rooms can now expose an opt-in feed at /api/v1/rooms/{id}/feed/{secret}/calendar.ics, authenticated by a per-room secret in the URL path instead of a header. Admins/room-managers enable, copy, and regenerate the feed URL from the room editor. The secret is read-only and room-scoped by construction: a leaked URL only exposes that one room's bookings and can be rotated per room without affecting API tokens or other rooms. Endpoint is brute-force protected against secret enumeration, comparison is timing-safe (hash_equals), the raw secret is never logged nor returned in room-list responses, and feeds are off by default (explicit opt-in per room). The existing Bearer-authenticated calendar.ics route is unchanged; both share one iCalendar builder so their output is byte-identical.

Changed

  • A manager booking their own room no longer needs a second manager to approve it (#23): On a room with manual approval (autoAccept=false), a booking whose organizer is a manager of that room is now accepted directly instead of being parked as TENTATIVE in the approval queue. Requiring a manager to approve their own booking was a pointless extra step. Non-managers are unaffected — their bookings still go through the normal approval flow — and rooms without any configured managers are unchanged. The decision lives at the single PARTSTAT branch in SchedulingPlugin::handleRequest().

Fixed

  • German umlauts stripped instead of transliterated in generated identifiers (#18): Room/room-group slugs derived from names removed ä/ö/ü/ß outright, so "Küche" became kche and "Außenbereich" became auenbereich. They are now transliterated the standard German way (ä→ae, ö→oe, ü→ue, ß→ss), yielding kueche / aussenbereich. The slug logic — previously duplicated in RoomService, RoomGroupService, and ImportExportService — was consolidated into a single RoomService::generateSlug() so CSV import-matching stays byte-identical to room creation.
  • Unnecessary comma between postal code and city in event locations (#17): A room address of "…, 01324, Dresden" produced the event LOCATION "…, 01324, Dresden" instead of "…, 01324 Dresden". The calendar patch now formats the room address (postal code and city space-joined, building/room number folded into a trailing detail) instead of pasting the raw comma-separated address string, and the 3-part postal-code detection in buildRoomLocation() now also recognises 5-digit German postal codes (previously only the Dutch "1234 AB" form).
  • User's locale ignored in dates and times (#21): Dialogs and list views formatted dates/times with the browser default locale (often US MM/DD), confusingly disagreeing with the user's Nextcloud language. All toLocale*String() calls now pass the Nextcloud user locale (getLanguage()), matching the calendar view which already did so.
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureLxXT6mBOx39KwNvqF8NjAEjd9mBwHEfwC+Ddi61112p2hXAmhywHBF+CtJ5r16n/ibbvmnvOmP4TvOmaxjbfpTdxVIQ7zGH/euheSpBHPXEkN072KKIVGVVDprlkkS2g/S+aBtcR4R1/pr1RDi0mvlN0IGeRkTDkNkqGEiFNsck1pg9P6rscwVXZSi4BxY79FJKkoetv3jlGBZrBjN1xJ1ldchw0LKeqhg/OITc7j0BTj43F/j4tRJTC8h/PFh+fGFacHMTrxFkEVdncwiMBra4s8fL3p0NU9BP5+J3VFoPADtsLuo1SnvWSyOk/WqtaoExecVW79ZcjwXtLHLW7EnQZCThF6nr11/o4YG8ybOR3lRn6Qmf8dE+4KpOxVtH5SgCA3khtnsx2Ee+oTfqgvQvCPzalhmH4RFNLimzw6geIhLFDTV72Go3743S2OeFrRBYxMB6qagmFAQZj3H735pDOdc4tIK0CffsZWgCQulK71h1w18iBYMxiPPPKUnLWsnWXJ08OpTmFqhcBpAnEJZxDVUR8GsX3qQodOFvl68WqHsu4sxQ1flTH/Z3Ikij8OwBObxL2mqKHSDqxXd/94mapkLIJM/kUUZPVBu9uudpdWfGCFTTFsh3AfJtaVJSimI5mBJQJAwiOS4dfUqEQIznUCRUd+x89PbX+PsW87Gk=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<35.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.1.2
Release Details
UpdatedJune 12, 2026, 10:11 a.m.
Changelog

Changed

  • Nextcloud 34 support — Bumped max-version in appinfo/info.xml from 33 to 34. No code changes required: Application.php is Bootstrap-based (IBootstrap), all \OC::$server->get*() service-locator calls were eliminated in prior releases (notably MailService::notifyManagers / sendCancelled in v1.1.1), logging is PSR-3 throughout (LoggerInterface), getAppValue() calls all have defaults, and DAV registration uses registerCalendarRoomBackend() (the NC 30+ API). Sabre plugin registration via SabrePluginAuthInitEvent continues to work on NC 34. Verified by smoke-test on a Nextcloud 34.0.0 development instance.
  • Documentation restructured to match IntroVox/IntraVox/MetaVox layout — Replaced the previous flat docs/ tree (with one troubleshooting.md, comparison.md, and future-*.md at root) with a nested structure: docs/index.md hub, docs/getting-started.md, plus admin/, user/, features/, architecture/, and deployment/ subdirectories. Added 14 new docs covering admin guide / settings / best-practices / FAQ, user overview / personal-settings / FAQ / tips / troubleshooting (split from the combined troubleshooting file), features/{approval-workflow, availability-rules, email-notifications, public-api}, and architecture/{backend-architecture, caldav-scheduling, exchange-integration}. Removed three internal-only docs (future-ideas.md, future-personal-settings.md, exchange-sync-changelog.md) from the public tree. README and appinfo/info.xml <documentation> block updated to point at the new hub pages.
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
Signatures0uN/kj68S45tZHtOh80rIsHorH0axrB0w8umB+Z6wIPtl7vC6R5QSWvB+puvu87P0zwTgZRx9rNAb6wsZDA+ey2c0hiSg8NqKnQy55qtuX0EeZrwE/wFGsLYkemFtFJ047CLRbSSFcEvbAkkekLbIMdnOOZ9k8eItPsdnPS0pR2l4wPNqzc0/htzlnInVgtZIkuk4q4e57QuKd69HW3MJ0FUKvwHWtVPMdjTKqslCwaDIAxqgK57O0rrQgsxm03YZ20NaxmY2gAlXscz3JEfFstBXxNz0kxVf/ct/qRLoiqZZY+7eUCdR5BUbAu8h9KeZ7s8XmAoCMYBAMAPWj2B0ZmAfoAtqWh1sRyOVeExp+icWbSJbVdg1niKvxMhv47WVyW/u6dNw01ZcYWAejFd2+iZ96EKTUMhCQx1ItcUnzL9dC93O65laBZ2Cm/9BKZSONGxVjh3zgMVyj98Bd4MTpjsB1k8vj4yDjq39OJgbQF/N3jiYeVUpAoKQLB0DnSa8czOAM0GO8TTwe/k050yR8XJ8eJfc6aSyp8AEGNrhZPEo4GY1DyKLYRPSHsnUkP3VcvoC4HV6dgkcrjplNgqTQKMUPxp2JccFq2r4m9j3Dj2HET/+7cF9ZyVkdPKfI9yoEUzSmxzVkRoS+M7ecGizR67XxIh5C/kQn7wvykiU0=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<35.0.0
Minimum Integer bits32
PHP>=8.2.0

Nextcloud 33

RoomVox 1.3.0
Release Details
UpdatedAug. 13, 2026, 5:23 p.m.
Changelog

Room metadata that RoomVox already held — floor, address, building — never fully arrived at the calendar clients that show it. This release fixes the publishing side, which matters now that Nextcloud Calendar is gaining a room browser that groups rooms per building and filters on floor and capacity (nextcloud/calendar#8264). It also fixes booking one event into two rooms at once, and makes notification emails translatable. No stored data changes; the room editor keeps its fields exactly as they are.

A minor rather than a patch release: notification emails become translatable, bookings gain an allDay field in the API, and RoomVox moves onto the Nextcloud community translation workflow — which changes how the app is built and which files ship.

Translations. The strings added in this release are not translated yet: RoomVox is being onboarded onto the Nextcloud community translation platform (nextcloud/docker-ci#986). Until translators pick them up, untranslated text falls back to English — the interface stays translated where it already was. New translations arrive in later releases without any configuration change.

Added

  • Notification emails are translatable and sent in the recipient's language (#24): every subject and body in MailService was a hardcoded English string — the app had no IL10N at all — so a French user with a French interface still received English mail. All 14 notification types now resolve their text through Nextcloud's translation system, and the language is chosen per recipient rather than from the server default: the organizer, each room manager, and the admin can each receive the same booking in their own language, resolved from their Nextcloud account (external addresses, which have no account to read a preference from, fall back to the instance default; an address matching more than one account is treated as unknown rather than guessed). Values are never translated — room names, event titles and dates are substituted into placeholders, so translators get whole sentences instead of fragments. Alongside this, RoomVox moved to the Nextcloud community translation workflow: all 526 frontend call sites were converted to the t('roomvox', …) form the Nextcloud translation bot extracts (it reads only that literal form, so with the previous $t(…) wrapper it would have found none of them), a POT template is generated from both the Vue and PHP sources, and the existing German, French and Dutch translations were carried over so no language restarts from zero. A prebuild guard fails the build when a new source string has not been pushed for translation yet.
  • Rooms publish their building name: RoomVox holds the building as its own field, but CalDAV had nowhere to put it, so clients that group rooms per building had to infer one from the address — usually by taking everything before the first comma, which turns a room at "1098 XG, Amsterdam" into a building called "1098 XG". Rooms now publish {http://nextcloud.com/ns}room-building-name, taken from the building field itself rather than guessed. An empty building field publishes nothing rather than letting the street stand in for it. Proposed upstream as IRoomMetadata::BUILDING_NAME; clients that do not know the key yet simply ignore it.

Changed

  • Interface labels follow the Nextcloud writing guidelines: 44 labels used Title Case where Nextcloud uses sentence case ("Save Changes" → "Save changes", "My Rooms" → "My rooms"), and twelve progress labels ended in three full stops rather than a real ellipsis ("Saving..." → "Saving …"). Acronyms, product names and Microsoft's own field labels keep their capitals, so "API tokens", "SMTP Host" and "Client Secret" still read the way an administrator sees them in Entra. Existing German, French and Dutch translations were carried over to the renamed labels, so nothing that was translated became untranslated. Cosmetic only — no behaviour changes.
  • Translations no longer carry strings the app removed: each language bundle held 79 entries for labels deleted in earlier releases. They were never shown (Nextcloud simply never looked them up) but shipped in every release and would have been imported into the translation platform as translations without a source string. Each language now holds exactly the 359 strings the app actually uses.

Fixed

  • Some CSV columns were silently dropped on import (#29): importing a room with every column filled in lost roomNumber, roomType, postalCode and autoAccept — which also meant RoomVox's own CSV export could not be imported back, the very file the export offers as a template. CSV headers are matched case-insensitively, but the parser compared the lowercased header (roomnumber) against field names that are camelCase (roomNumber); the four columns whose names contain a capital matched nothing and were skipped without warning, while the ten all-lowercase ones came through fine. Headers are now resolved to their canonical field name through a single map derived from the export column list, so the export/import round-trip cannot drift apart again. Case-insensitive matching and the MS365/Exchange column mapping are unchanged.
  • Month view showed the wrong month in the header (#26): the booking calendar's month view labelled August 2026 as "July 2026". The heading was taken from the first cell in the grid, and a month view pads its first row with the tail of the previous month (August 2026 starts on a Saturday, so the grid opens on 27 July). Months could therefore appear twice or not at all while paging through the calendar. The heading now comes from the period the view actually represents.
  • Approval requests stayed in the queue after the meeting had passed (#28): a manager's approval list showed every pending request ever made, including meetings that were weeks in the past, because the bookings were fetched with no date range at all. Requests whose meeting has already ended are now filtered out at the source. A meeting that has started but not yet finished is still listed — it can still meaningfully be approved. Nothing is deleted: an expired request only disappears from the queue, so the booker's own calendar entry and history stay intact.
  • All-day bookings were shifted by the timezone (#27): an all-day event showed as running 02:00–02:00 across two days instead of covering one whole day. An all-day VEVENT stores a plain calendar date (DTSTART;VALUE=DATE:20260813) with no time and no timezone, but RoomVox serialised every booking as a precise timestamp — which turns midnight into an instant that renders as 02:00 in UTC+2 and spills into the next day. All-day bookings are now detected and passed to the interface as a bare date with an explicit all-day flag, so the calendar and the booking list show them as a full day with no time attached, labelled "All day" rather than a clock time. The resource timeline needed the same care: it only renders 08:00–19:00, so a booking running midnight to midnight was drawn straight through into the next day's slots — all-day bookings are now bounded to the hours the timeline shows, while a multi-day booking keeps its real length. Timed bookings are unaffected. API consumers see this too: booking objects gain an allDay boolean, and for an all-day booking dtstart/dtend are a plain YYYY-MM-DD date instead of a timestamp — clients that assume a timestamp should check the flag.
  • Booking two rooms on one event without auto-accept only requested approval for the first (#22): the second room stayed on "Needs action", never appeared in the approval queue, and a manager could not change it. An event booked into two rooms carries both room ATTENDEE lines, and each room calendar holds its own copy of that same event — but every PARTSTAT lookup scanned for the first CUTYPE=ROOM attendee rather than the attendee belonging to the room whose calendar was being read. So room B reported room A's status (ACCEPTED once A was approved, hiding B from the queue, which filters strictly on TENTATIVE), and approving room B wrote ACCEPTED onto room A's line, leaving B stuck forever. The three affected lookups in CalDAVService (getBookings(), getRawCalendarObjects(), updateBookingPartstat()) now match the owning room's own email first, via a shared extractRoomPartstat() helper; the previous CUTYPE=ROOM/non-organizer heuristic remains as the fallback for single-room events and for clients like iOS that send CUTYPE=INDIVIDUAL. Two related multi-room defects are fixed alongside it: declining one room removed its attendee mid-iteration, which invalidated the loop and silently skipped the PARTSTAT write-back for every later room on the event (removals are now deferred until after the loop), and that same decline cleared the event LOCATION even when another room was still attached (LOCATION is now only cleared when no room attendee survives, otherwise it is rebuilt from the remaining room). Earlier analysis had suspected Sabre/Nextcloud's iTIP dispatch; the scheduling path is in fact correct and fully per-room — the defect was one layer down, in reading the result back.
  • Room floor was invisible to every CalDAV client: the room backend published the floor under {http://nextcloud.com/ns}room-building-floor, which is not a key any client asks for. Nextcloud defines the property as IRoomMetadata::BUILDING_STORY (room-building-story), and cdav-library requests only that one in its PROPFIND, so the value never reached Nextcloud Calendar, Outlook, Apple Calendar or Thunderbird. The backend now publishes room-building-story. Nothing consumed the old key, so this only adds data where there was none — on our test instance 97 of 113 rooms had a floor set that no client could see. Floors appear after the hourly UpdateCalendarResourcesRoomsBackgroundJob has run, or immediately after occ background-job:execute.
  • Imported rooms published a malformed address: addresses are stored in a fixed four part format ("Building, Street, PostalCode, City") so the room editor can split them back apart, but that is an internal detail. A room imported without a building or street was published to CalDAV clients as , , 1098 XG, Amsterdam, which clients show verbatim and use to derive a building name. Empty positions are now dropped when publishing, and in the room description, without touching how rooms are stored — the editor keeps its four fields. This matters more now that Nextcloud Calendar groups rooms by building; see nextcloud/calendar#8264.
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureTuRtOoNTIAfHxKuFfgxldiQjduru8p+rl2W2QR+KfudIh44YAQn0+Q5bAIti+8uupMo2pIwJxZYOfN6qwfyMd7hmC9ngiEs9F2gQpRmu7Ko0ocdLp+F+H1ajHAk8Z7UJQXS3IIaLrwrjDF5F1G0UOacufnSB4Dp5GdJcFHy7kmwfrk5ynNmOxvFHuMho0M12n7jfS1get2yUgB2zWyg2GByiu4d9haUj2NESybi30SaUit0I8COJyF5uMZi3CezaIiXZLtM+QaOvIfps6U1QcA/5D9nJViUYgNuFGFC3tsE39o+RZ3ArNE3zZbhR5lxaqJlgnmU+pqLqS/R6srL3uR+NuzmJs6LgFCzmgQt4JFLuHr7xU7WBe5+dhtppolj9oX8dzmdVZeUulHS+YLltzTRhoxdLUWNMAXaMxejRZ8fmgA57/ljDXvHULqjWNIKS7Bnpufe32QTUhxAo3Qjro/bIlNlay94ST8SLXbWveCMDVUJ4h/NJTM/JHKXOwuHZ3SoAxkshdJgGrQ92fQA/qMVQehWL8FdyUU4YmA7zP6PPsf1aEfZkwcSEm7WDsjYDbesjY6P0PunQxoTS9b543jhLKSOevsXb3mmaxGmLz8LrY1ZQzf7KADoCznC6OLYYpVpILRis/v2cs3q37o8tox82KlJAC9tnbqhCuMiKPfg=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<35.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.2.1
Release Details
UpdatedAug. 3, 2026, 5:56 p.m.
Changelog

Changed

  • Booking administration room filter now shows the room group (#19): in installations with multiple room groups, room names are often reused (e.g. "Church" and "Office" in both "Parish A" and "Parish B"), and the filter listed them indistinguishably. Each option is now labelled "Room (Group)" — e.g. "Church (Parish A)" — so rooms can be told apart. Rooms without a group keep their plain name. Frontend-only; no API or data changes.
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureYJ2npvyqg6agBjsoTDT1VVZGa1LI9d4XhZdQ1NMz3tee56ch76U94qAA/POOA2+a00B5LvIpPtrWr2EIqX8f/+ndlJUkQ+FtWADGprnwim/KIm+/u2srj9l6Efe9WDfc0JEY4GTQDt+n8bmT7fLtcDrwCLT9CpJncKe7SlRTYC8YJSzMfadM8/OAGbPTcWnIQsOw5l84+vBgjorkGkz87m1DxG/TrCaxmRe7P4h5BWk+yHo/OoUzP31D63XFcX9i1YBsn+CfomO622rJ7eGW7EnfB870E0x9q5bMkx3q+Oq2kFK1uw7LoO1azV53EaprG4twE5ytwrgafbUcT42dO7Usa6JrdGCl03nN3ZjGfkpyyZ2h61/H+8ecm7I8uVIlnIFOPofyCg45UqDNC7DtdOlIBUMuZ90XpIowttmWm9X4MS1CJSbEXt27o/7kMerYQHvk9xXoiaorqaJ345PNupFBkcqcfDFnYk/iiUmbmud0GAiGcc1raCUsL+A6n5VqDR2edA5BG1Y8BVYU1DB79EJa3Qj0XM6Gjd3DWbRyRptQ0G2Fbu667rVmc1rSHUedUw5xOIa8TG5wkCTfund2v/1uy3omDnIjDM5zcCnSHDd0NDCrQf4S9XSsru6EE9Lrt3m2AIpws+dpYlGFGOY+mVMP7xvE14jcOLCWDbUO3Ac=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<35.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.2.0
Release Details
UpdatedAug. 3, 2026, 5:42 p.m.
Changelog

Security

  • "Show all rooms" dialog ignored room visibility permissions (#20): In the Nextcloud Calendar room picker, the type-ahead field correctly hid rooms a user may not view, but the "Show all rooms" dialog listed every room — exposing room names, locations, and organisational structure to unauthorised users. The dialog now intersects the calendar's room list against a server-authoritative allow-list (GET /api/personal/rooms/viewable, filtered by PermissionService::canView), so it shows exactly the rooms the type-ahead does. The allow-list endpoint returns only room id + email (no other detail), and the dialog fails closed — if the allow-list can't be loaded it shows no rooms rather than risk leaking. Booking was already enforced server-side by the scheduling plugin; this closes the information-disclosure gap in the browse UI.

Added

  • Public, subscribe-able iCal feed per room (#16): The iCal feed at /api/v1/rooms/{id}/calendar.ics already existed, but required a Bearer token — which external calendar apps (Nextcloud Calendar, Outlook, Apple Calendar, Thunderbird) and signage displays cannot send, so nobody could actually subscribe to it. Rooms can now expose an opt-in feed at /api/v1/rooms/{id}/feed/{secret}/calendar.ics, authenticated by a per-room secret in the URL path instead of a header. Admins/room-managers enable, copy, and regenerate the feed URL from the room editor. The secret is read-only and room-scoped by construction: a leaked URL only exposes that one room's bookings and can be rotated per room without affecting API tokens or other rooms. Endpoint is brute-force protected against secret enumeration, comparison is timing-safe (hash_equals), the raw secret is never logged nor returned in room-list responses, and feeds are off by default (explicit opt-in per room). The existing Bearer-authenticated calendar.ics route is unchanged; both share one iCalendar builder so their output is byte-identical.

Changed

  • A manager booking their own room no longer needs a second manager to approve it (#23): On a room with manual approval (autoAccept=false), a booking whose organizer is a manager of that room is now accepted directly instead of being parked as TENTATIVE in the approval queue. Requiring a manager to approve their own booking was a pointless extra step. Non-managers are unaffected — their bookings still go through the normal approval flow — and rooms without any configured managers are unchanged. The decision lives at the single PARTSTAT branch in SchedulingPlugin::handleRequest().

Fixed

  • German umlauts stripped instead of transliterated in generated identifiers (#18): Room/room-group slugs derived from names removed ä/ö/ü/ß outright, so "Küche" became kche and "Außenbereich" became auenbereich. They are now transliterated the standard German way (ä→ae, ö→oe, ü→ue, ß→ss), yielding kueche / aussenbereich. The slug logic — previously duplicated in RoomService, RoomGroupService, and ImportExportService — was consolidated into a single RoomService::generateSlug() so CSV import-matching stays byte-identical to room creation.
  • Unnecessary comma between postal code and city in event locations (#17): A room address of "…, 01324, Dresden" produced the event LOCATION "…, 01324, Dresden" instead of "…, 01324 Dresden". The calendar patch now formats the room address (postal code and city space-joined, building/room number folded into a trailing detail) instead of pasting the raw comma-separated address string, and the 3-part postal-code detection in buildRoomLocation() now also recognises 5-digit German postal codes (previously only the Dutch "1234 AB" form).
  • User's locale ignored in dates and times (#21): Dialogs and list views formatted dates/times with the browser default locale (often US MM/DD), confusingly disagreeing with the user's Nextcloud language. All toLocale*String() calls now pass the Nextcloud user locale (getLanguage()), matching the calendar view which already did so.
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureLxXT6mBOx39KwNvqF8NjAEjd9mBwHEfwC+Ddi61112p2hXAmhywHBF+CtJ5r16n/ibbvmnvOmP4TvOmaxjbfpTdxVIQ7zGH/euheSpBHPXEkN072KKIVGVVDprlkkS2g/S+aBtcR4R1/pr1RDi0mvlN0IGeRkTDkNkqGEiFNsck1pg9P6rscwVXZSi4BxY79FJKkoetv3jlGBZrBjN1xJ1ldchw0LKeqhg/OITc7j0BTj43F/j4tRJTC8h/PFh+fGFacHMTrxFkEVdncwiMBra4s8fL3p0NU9BP5+J3VFoPADtsLuo1SnvWSyOk/WqtaoExecVW79ZcjwXtLHLW7EnQZCThF6nr11/o4YG8ybOR3lRn6Qmf8dE+4KpOxVtH5SgCA3khtnsx2Ee+oTfqgvQvCPzalhmH4RFNLimzw6geIhLFDTV72Go3743S2OeFrRBYxMB6qagmFAQZj3H735pDOdc4tIK0CffsZWgCQulK71h1w18iBYMxiPPPKUnLWsnWXJ08OpTmFqhcBpAnEJZxDVUR8GsX3qQodOFvl68WqHsu4sxQ1flTH/Z3Ikij8OwBObxL2mqKHSDqxXd/94mapkLIJM/kUUZPVBu9uudpdWfGCFTTFsh3AfJtaVJSimI5mBJQJAwiOS4dfUqEQIznUCRUd+x89PbX+PsW87Gk=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<35.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.1.2
Release Details
UpdatedJune 12, 2026, 10:11 a.m.
Changelog

Changed

  • Nextcloud 34 support — Bumped max-version in appinfo/info.xml from 33 to 34. No code changes required: Application.php is Bootstrap-based (IBootstrap), all \OC::$server->get*() service-locator calls were eliminated in prior releases (notably MailService::notifyManagers / sendCancelled in v1.1.1), logging is PSR-3 throughout (LoggerInterface), getAppValue() calls all have defaults, and DAV registration uses registerCalendarRoomBackend() (the NC 30+ API). Sabre plugin registration via SabrePluginAuthInitEvent continues to work on NC 34. Verified by smoke-test on a Nextcloud 34.0.0 development instance.
  • Documentation restructured to match IntroVox/IntraVox/MetaVox layout — Replaced the previous flat docs/ tree (with one troubleshooting.md, comparison.md, and future-*.md at root) with a nested structure: docs/index.md hub, docs/getting-started.md, plus admin/, user/, features/, architecture/, and deployment/ subdirectories. Added 14 new docs covering admin guide / settings / best-practices / FAQ, user overview / personal-settings / FAQ / tips / troubleshooting (split from the combined troubleshooting file), features/{approval-workflow, availability-rules, email-notifications, public-api}, and architecture/{backend-architecture, caldav-scheduling, exchange-integration}. Removed three internal-only docs (future-ideas.md, future-personal-settings.md, exchange-sync-changelog.md) from the public tree. README and appinfo/info.xml <documentation> block updated to point at the new hub pages.
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
Signatures0uN/kj68S45tZHtOh80rIsHorH0axrB0w8umB+Z6wIPtl7vC6R5QSWvB+puvu87P0zwTgZRx9rNAb6wsZDA+ey2c0hiSg8NqKnQy55qtuX0EeZrwE/wFGsLYkemFtFJ047CLRbSSFcEvbAkkekLbIMdnOOZ9k8eItPsdnPS0pR2l4wPNqzc0/htzlnInVgtZIkuk4q4e57QuKd69HW3MJ0FUKvwHWtVPMdjTKqslCwaDIAxqgK57O0rrQgsxm03YZ20NaxmY2gAlXscz3JEfFstBXxNz0kxVf/ct/qRLoiqZZY+7eUCdR5BUbAu8h9KeZ7s8XmAoCMYBAMAPWj2B0ZmAfoAtqWh1sRyOVeExp+icWbSJbVdg1niKvxMhv47WVyW/u6dNw01ZcYWAejFd2+iZ96EKTUMhCQx1ItcUnzL9dC93O65laBZ2Cm/9BKZSONGxVjh3zgMVyj98Bd4MTpjsB1k8vj4yDjq39OJgbQF/N3jiYeVUpAoKQLB0DnSa8czOAM0GO8TTwe/k050yR8XJ8eJfc6aSyp8AEGNrhZPEo4GY1DyKLYRPSHsnUkP3VcvoC4HV6dgkcrjplNgqTQKMUPxp2JccFq2r4m9j3Dj2HET/+7cF9ZyVkdPKfI9yoEUzSmxzVkRoS+M7ecGizR67XxIh5C/kQn7wvykiU0=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<35.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.1.1
Release Details
UpdatedMay 26, 2026, 7:41 a.m.
Changelog

Fixed

  • responsibleContact silently dropped on room create/update & opaque permission denies (#15): Two unrelated defects rolled into one user report. (1) The "Responsible contact" field (introduced in #11) reached the frontend form and RoomService, but RoomApiController::create() and update() whitelisted the request payload field by field and responsibleContact was missing from both lists — so the value was filtered out before reaching the service layer and any edit appeared to "not save". The field is now in both whitelists; a regression test exercises the round-trip. (2) Permission denies caused by the iTIP sender resolving to zero or multiple Nextcloud users (typical for LDAP/AD setups where the same email address exists on more than one account) were logged at debug level only, so admins saw an "automatically declined — you do not have permission" mail without any actionable trace in the server log. The log is now warning level and names the sender email, the match count, and a sample of the resolved UIDs, so duplicate-account configurations are immediately visible. No behaviour change to the deny itself — the underlying group-permission resolution was correct
  • Approval mail never sent for non-auto-accept bookings via REST API & malformed ORGANIZER (#14): Two related defects on the API booking-create path. (1) POST /api/v1/rooms/{id}/bookings and POST /api/rooms/{id}/bookings on a room with autoAccept=false produced a TENTATIVE booking but skipped the manager-approval mail, because both controllers wrote directly to the room calendar via CalDavBackend and never traversed the Sabre SchedulingPlugin (where the manager-notification hook lives). Both endpoints now invoke the same notification path the iTIP flow uses, so managers see API-created bookings in their approval queue exactly as they do bookings made from Nextcloud Calendar — including the room-move case in the internal API. (2) CalDAVService::createBooking() unconditionally appended @localhost to the organizer when building the ORGANIZER property, so external emails became mailto:user@company.com@localhost (undeliverable) and CN was set to the raw email instead of a display name. The property is now built via a shared resolver: external addresses are emitted as-is (enriched with a CN only when they match exactly one Nextcloud user), Nextcloud user IDs resolve to canonical email + display name (the same logic that fixed #5 for the LOCATION-fallback), and unresolvable organizers cause the property to be omitted rather than fabricated. Internal cleanup: MailService migrated off the \OC::$server->get() service-locator anti-pattern in notifyManagers and sendCancelled, in favour of proper constructor injection of IUserManager
  • Cancelling one occurrence of a recurring booking removed the whole series (#13): The confirmation dialog mentioned only the clicked event, but on confirm the entire iCal object was deleted, taking every occurrence with it. The admin UI now offers an explicit choice between "Cancel this occurrence" and "Cancel entire series" whenever the booking is part of a recurring series; single-occurrence cancellation writes an EXDATE on the master VEVENT and removes any matching RECURRENCE-ID override instead of deleting the calendar object. The booker's own calendar gets a RECURRENCE-ID override VEVENT with the room attendee marked DECLINED and LOCATION cleared for that one instance, and the cancellation mail names the specific occurrence so it cannot be mistaken for a series-wide cancel. Exchange-synced rooms cancel the matching instance via the Graph events/{master}/instances endpoint. The internal API (DELETE /api/rooms/{id}/bookings/{uid}) and Public API v1 (DELETE /api/v1/rooms/{id}/bookings/{uid}) both accept a new optional ?recurrenceId= query parameter; the existing series-delete behaviour is unchanged when it is omitted
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureVP+0b42txWRHoOd+uUqC0R6aUPFE8mHjzbfRthoKpph6c490rhAXQLn9IBW95f9xcWkzjB3Zt5cXEV0JaWxZBC63d1bfK3oduyKYjgBARm7OFYaBIzo9GwsacqDSqERw7ZZLjrTTftc6adahPGMzXjpXaqe9BlN6c9E2Va7pGAaKW2WVlkROwbspZwMZSsZSbSUSyt1aBnKUkaBDJxlglK/CYbfiSSUwxUQmPqxNhQpGsHi9wjemdHFZHLf/dDCfmZZaeq9Yv3arOfZCboclVfRKB5BTdyVqkDnrUN4LiOhm69fKvkUA4C4PL/osEuy0k56uflhWKPnHEZcdrpRTKE/N+bzlps9aWaVHT4ofYMU5WxXILWPN4lh87lg3I+9653XMjABNOE8Pyg91EpyJAqsjh748vckjnvU+NcKpmHqs6TuQnLixSCfdkvTS9qcYuNak9HzFSd1js1uv7CkcLT5UL02FSTSXVvQ7gD9jo6D5owKFNC6odnz+5XilDz9mepOL7Vdu03AyPdIYH97gixepMt4wvhWVMkFPnItP90UIwlVXrMQN/B8X4lb3dw3wS/ZL+94KGIbIK+nOvPfnf7ytYYracYLLD7LnddloEYwHKD1mpbcCuQAWYSznirWHcRoBydsJQx4TbSvLCC8EeNhk3U36efZobp5R1iqK/ts=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<34.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.1.0
Release Details
UpdatedMay 18, 2026, 5:53 p.m.
Changelog

Added

  • Manager Bookings overview (#12): Managers now get a third "Bookings" tab in Settings → Personal → RoomVox (next to "My Rooms" and "Approvals"), showing the same overview admins already had under Settings → Administration. It is scoped to rooms the user can manage via a new ?scope=manage query param on the /api/all-bookings endpoint, and inherits everything from the existing BookingOverview component: stats cards, room and status filters, list/calendar toggle, and drag-and-drop move-between-rooms in the calendar view. The tab only appears for users with at least one managed (or admin) room
  • Responsible contact field for rooms (#11): Admins and managers can now set a free-text "Responsible contact" on each room (e.g. Anne Janssen (anne@voxcloud.nl) or Ask building manager). The value is visible to every user with view-permission in Personal Settings → My Rooms, so viewers know who to approach when they cannot book a room themselves. Stored alongside the existing room JSON (no migration needed), clamped to 255 characters. Also exposed via the Public API: GET /api/v1/rooms now includes a responsibleContact field in each room object

Fixed

  • Admin booking-deletion not communicated to the booker (#10): When an admin or manager removed an already-accepted booking via the UI, the booker was not notified and the room kept showing as reserved in the booker's own calendar event. The cancel flow now mirrors the iTIP-CANCEL path: the room attendee is removed from the booker's event (and LOCATION cleared) and a sendRespondCancelled mail goes out explaining the booking was cancelled by a room manager. The action is renamed "Cancel booking" in the UI (with a "Keep booking" dismiss action) so it no longer looks like a destructive admin-only delete

Added

  • Translations for the Calendar patch UI (#9): RoomVox-specific labels in the patched Nextcloud Calendar editor (In-person, Online (Talk), Suggested conference rooms, room types, facility names, room status badges and more) now resolve via the roomvox translation bundle instead of asking Calendar's own bundle for strings it never had. Adds 34 source strings in l10n/en.{json,js} with translations for German, Dutch and French. Hardcoded English labels in resourceProps.js and the "Room " number prefix in principal.js / ResourceList.vue are now wrapped in t() calls so they pick up locale too

Fixed

  • Conflicts not detected on later occurrences of a recurring booking (#8): hasConflict() compared the requested time only against the master event's DTSTART/DTEND, so booking the second (or any later) occurrence of a weekly meeting was wrongly seen as a free slot — even though auto-accept would happily add the room a second time. The check now expands recurrences via Sabre's EventIterator and walks each occurrence inside the query window, with native EXDATE / RECURRENCE-ID handling. Same pattern as the iCal-feed fix from #4
  • Resource booking silently ignored when it exceeds the booking horizon (#7): Bookings that exceeded the room's maxBookingHorizon were declined without any notification to the organizer — the calendar event was simply created without the room attached. The scheduling plugin now sends a decline mail naming the configured horizon (in days) and the earliest date that is no longer bookable, so the organizer can reschedule without guessing. The same fix is applied to two other previously-silent reject paths: bookings outside the room's availability hours, and bookings made while a room's initial Exchange sync is still running
  • Location fields shift between Building/Street/Postal code when some are left empty (#6): The Room editor composed the stored address by joining the four parts (Building, Street, Postal code, City) and silently dropping empty ones. Reloading the room split that shorter string positionally, so e.g. Postal code would migrate into Street. The composer now always emits all four positions (empty parts kept), matching the convention already used by the CSV import path. Existing rooms whose address was saved via the buggy UI may need to be re-edited once; rooms imported via CSV are unaffected
  • ORGANIZER malformed when booking a room without explicit organizer (#5): Clients like eM Client omit the ORGANIZER property on single-organizer events. RoomVox's LOCATION-fallback path filled it in with mailto:<userId> (a Nextcloud username, no @domain, no CN). It now resolves the calendar owner's real email and display name via IUserManager, producing ORGANIZER;CN=<name>:mailto:<email>. If the user has no email configured the property is left unset, since the LOCATION-fallback writes the booking directly into the room calendar and does not need iTIP REPLY mails
  • Recurring bookings only show first occurrence (#4): A weekly (or other RRULE) booking appeared only once in both the iCal feed and the Booking Overview. Two underlying causes:
  • The iCal feed (/api/v1/rooms/{id}/calendar.ics) expanded RRULE server-side and emitted N VEVENTs sharing one UID with no RECURRENCE-ID, which clients deduplicate per RFC 5545 §3.8.4.7. The feed now passes through master VEVENTs with RRULE/EXDATE/RECURRENCE-ID intact so clients expand recurrences themselves. The hard-coded ±30-day window is also gone — open-ended series are no longer truncated
  • CalDAVService::getBookings() relied on VCalendar::expand(), which silently returns only the master event when the VTIMEZONE contains DAYLIGHT/STANDARD components with 1970 DTSTARTs (the standard Nextcloud Calendar output). Replaced with EventIterator, which expands the series reliably regardless of timezone definitions
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureLJiGuney8fSKqE5+SzWyFanHkAX7CzcZdgR/g8vYA2IWnj7v5HZSj1IkUzak6GPUyMmYcwFuREVc1fK2yVQOsv0e+I5C5+xMxmXEZ6D3nTvehZ9eMF/ZrEM8L8ygFtWh/qd6a28CsVnFO4/uVl1qlv+rX3jCQdmFk8PFhUeuyV1LEwI75lFxx8bk3bF7kIf2rJiDJi0tUtgc6ZQ8ie/UzglVC5vLsv1rQL2yg5J6qBl0eMZ9ubp2hqOYNaQ0mIDfI2O7N/blRNgHoo3pKT7JZlEbwBIsYlTtZeEXIZPP+yicY9b4cYA0Kq4UNN084d7No7wq8Cgqm8oMO3xrJvE+S1J1RttkPvCr3HJrV6HCB+dzbEbOy0GpYofJIboaCu8jt7eum9lJYsyPcV5xQJaYLcqgr7rv5XBw69lI3Hfok1NOsMcgwcSQEMkghcd/XugtAgf8K+GZf9phsFsb24fPyLZTIg38gsjAYP+uuirLhXTOsENLj+8QDBArW9QqA4aHbFwG0z65lrNrAokPEGXCNO3Qs42pC7Kfuv5HH+6fSVTZ58PbGUEt7cUCq9gQWN/SwsM7gXKssyY52GiVnumYRHSq648zb9m6XPCex6qAdTfERpSOjIaPoKLBw/JAgLEB3JCX23n2jQlJ3/JXcLZjjwFfcl6nurX5O4fbsHQz8L8=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<34.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.0.6
Release Details
UpdatedApril 17, 2026, 2:49 p.m.
Changelog

Fixed

  • Rooms visible to users without permission: new Sabre RoomVisibilityPlugin filters room principals out of PROPFIND responses for users who lack view access
  • Calendar patch toggles unresponsive on NC 6.3: migrated NcCheckboxRadioSwitch bindings from Vue 2 to Vue 3 / @nextcloud/vue v9 syntax
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignaturehsPPvvgv33Nkosy+QPwMUgukZNJMWaCcZ58Y8e9hhBtu379oSQfYsFEBnBN2P7KfidKc9Hog67/vKHTiaFt6AtcL4Qz7onfDnz6hOt0FylP/h+NZFjbhS8wxuFnQYlAnJ5SoiB2zrDsXGb9qzJMzij4w1Ofr0qoWAWHKHgQe90VbiTW8yO1M5WDNyNP36L4JpgIq7+DGglWUVctW4438CnGyLtyv4cRQHSRw4jeq/azl2QA3hJkWUwszsD20m9FsC0QgzjixBbHCo7BgzDSs+1pbTS19y5OgpxdcSq2ZgKYH2NEX8R3fsyMGFP89xFZlKTFvH+tjj141UhYWCmNucjwGhRLamq4YA+som2QPkaEWe7EnRLCasRJ6XUsogH918oLfM7KguQDrej03xkavmSHUCMHCmKeGYF/Sxd9q6bsjpNpbes0LXjndqWt3QS+CBPx+oBEDqqfdCwcyLSFczvgDV6A+3NA9sYpwomip5Xcv6rTQVLzcWor3b5k9I0Nl+g2FDis6mzDRZBigiOnVqT1qsvqrGLOZ2epTCPvlbuPHYHguU1KKMP3tptuX20ZNFHOGub7Ou2E2+b4IgHY2qpmXPiODjzJiamn6VjcDaoUj8Q1Cljnfzg78jtFT8OC+BdbdJzKAZFKnl+DWSx7GxXw/gX+xFQ1xRRUINn4/z5I=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<34.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.0.5
Release Details
UpdatedApril 15, 2026, 9:03 p.m.
Changelog

Fixed

  • Room visibility ignores group permissions: Rooms in a group with configured permissions were still visible to all users in "Suggested conference rooms". The group_restrictions in Nextcloud's room cache remained empty because the PermissionService did not always have access to the RoomService during background sync (DI timing issue). The RoomBackend now resolves group permissions directly when the normal merge path fails
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureOaQyULcfWOavUOfhGyKmc1cGwopTsR07vuU5roQMKrap2+cPIf7TWGEdKYcbjElQQN7ZuPIaSXfRObQioB73XQYtSbSOxMl3tDVRYESaHRAIFGZUjGAtjVNHBFyY0S9Ors8YWgEfWP0zJizVjGzA1rmd5ZiquojbT+dQ+zDBcMme5crDiWj6sQSsiUhSnRgmH3TjKJfwRY5fmRwgcfdK8deGt1P9oMGQnVPAbr5sk9lOua58sg0dDC+996M+11n1dNIuaRi0CSQ7UCcx7vXOq+NWlhO6MNQJph+ZkfrqRmxvFdAhNZbPzdDzTHoqwFT2FgGHPPcx6styXHbT/Mj8971ZqYoEyC2iFE4FOihUP1zleaoO/tUeahXxgoedj6aFqGgGJ/VyQbsob6R8ld6dO4cDzjsDA++VZw89hiR36vK7jaSoxAqTTf8kAzhmvzY1/YYP7T1cLDViDVQ14jOLRK+HNdTqPwm2UOC1grCodQUIMEKBLiFEa5VDGmZVXBtcC1UsNPrVUkbgQWjPt1py3+B7giCuEjIvFmqjWlrP1b9LiOZJDh8b0fUR5fV3PdrkCWBHGSG8G9rDEUWWeK/sA1c0Q3812Eh+Zc5BEfWNMQblN/tPZqoxosh4kEzqve6M7lbcB4Wh3eto6H1gLlUTQ4OOylR8V50uJ5Qpdbn3eLs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<34.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.0.4
Release Details
UpdatedApril 14, 2026, 5:17 p.m.
Changelog

Fixed

  • Cannot remove room from group: Moving a room to "No group" had no effect because the controller filtered out null values, so the groupId was never cleared. Moving to a different group worked fine since that sent a non-null value
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureVfhXBtW86BgGXESdEUUnP6yMQPo9pDQPQ4+IE3wtVWiFJ4Oo7/ywooHI7+D2OcgKLRg/AaNlh8ARBO4SsWku4WnfaAaab0gkR1fwzE/SNLNakPMtejpAU2IaHVhRrKh5M2ivQo1lOrOPFOyBSK3nAFGn4+sjHC7sKLrAklBXn01FaqwRmjUDBs8CEp0aKCR7rSlF8A8OoCM4wD+9GPjUSJgfblrnkKkMl2RdCkDyCo71+c5uKs6GO5SC75rU3DoHVT0iFVa82W5IOaOsfa2CDg/pc9pG/mMmDaq8neXey56Ikr3fjziSPKV3eHPtGyVTeBHnsfQUmunJOwSbFylUrG0UwS+ISdkHob0M0dCLgYJErhL8ypv61UR9C1sjzlk4E+Cbk26ZzOY/jAMTjKrV/muD2B5Wr4YrCjtoRlxpyWNTL4TuYpSf8siB/6rOh5geLIuNjhWtw/XZyQ/ySfAMXi4lfE1XPUARrG9Mxupdvb0jOiphkIiX+c6Ohh6d4S9zVAd0aUO2LnWFQguU0VGdb6jT+mkK2aJyAWTszkZkvgCutOcx3NiO3OTy9MWlvuS4ERvxkKMqT1QxX3ZiDIjMtjmWwye12LgzWOuN1z7xuyVob2hxR/lgwyArsgyiOVW4NwzC2N8TG1Cg8liosAt2TPr+geIexMC5eUNNrNkvbNY=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<34.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.0.3
Release Details
UpdatedApril 14, 2026, 3:39 p.m.
Changelog

Fixed

  • Room visibility not updating after permission changes: Changing permissions on a room or room group did not trigger a sync of Nextcloud's room cache, so rooms remained visible (or hidden) in the Room Finder until a different room update triggered the sync
  • No email notification on permission-denied bookings: When a user without permission tried to book a room, the booking was silently declined with no feedback other than a small warning icon in the calendar. Now a "Booking not permitted" email is sent to the organizer explaining they lack permission
  • Declined booking not cleaned up in organizer's calendar: When a booking was automatically declined (e.g. due to permissions), the room attendee and LOCATION remained in the organizer's event. Now the room attendee is removed and LOCATION is cleared for all automatic declines, matching the existing behavior for manager declines

Improved

  • Permission Editor shows inherited group permissions: When editing permissions for a room in a group, the editor now displays inherited group permissions as read-only entries with an "inherited" badge alongside the editable room-specific permissions
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureadwNoCn/+c8cghGCzvBJY9MO5EeEHsOdwJOnzpT57cBHz93EEA54EKL48xatgapWRuMzV2/1fS9KrK9mJHF4MO6Csv04z+tGcZ9nORhhXsKeg3G4vpyGTfcsoS0f1+M5W4Uf4iFztZUs76UDq8mrEHzpIwmGZoQL5v1VwvqqxYR6XS575qtKgAA+0r7ODHZUUFd/ANSkGdGSDVqfIfaEGdVRsRsvDB+p0WKoAXh64WB2lznQJxGztkmqxttP7pw5pavnXyijBI2gANSaAW4wnj/JTypiNf3PvLxoxEK+SiJqMp4O1lu8v3o8cK3TjTDrKBlJVowIKwu3ymqHTVGJzQhEUBdFsSmHkGwp57ds0GSePPk/weBoDZ7uNN9Dj3piOeZWllOnrCXa/JgH3DfULt1FFoD9bgseXv80UTAa4rCsilDrUt064KO81ka0z+Mbp1yo9AXbXXI63pnBwhbhQZrdHEY1VtiXUZy74NA4F7uuXJvEfOg/hKNYoeRUDE8T6RVSdcnwjO049Bcjt4w4HU3qdQuIASna1c12Nffxj4twHVUqLFxOlzqLeRIQoWcOaDB+0M4OhA8WCwrMV9VcOkQiR44Gzb8fj0j/C7SAM+LIkLKACoHcJPSXAF0TZxjctDIjEQpLgW137TtvlQjBWpYCAguu4Nb0EcEsc4ZBhQw=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<34.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.0.2
Release Details
UpdatedApril 10, 2026, 11:04 a.m.
Changelog

Fixed

  • Manager role cannot accept/decline bookings: Non-admin users with the Manager role received "Failed to process response" because the booking API endpoints were missing the #[NoAdminRequired] attribute, causing Nextcloud's security middleware to block the request before the internal permission check could run
  • Group-level permissions not enforced at booking time: The scheduling plugin only checked room-level permissions, ignoring inherited group permissions. Rooms with group-only permission rules were bookable by anyone
  • Room creation loses fields: Creating a new room discarded Room number, Floor, Room type, and Address because the controller did not extract these fields from the request. Editing the room afterwards worked because the update endpoint did handle them (except Floor, which was also missing there)
  • Declined booking still shows "Reserved" in Room Finder: The previous fix (v1.0.0) propagated the decline to the organizer's calendar but kept the room as an attendee with PARTSTAT=DECLINED. The Room Finder only checked attendee presence, not status. Now the room attendee is removed entirely and LOCATION is cleared on decline. The frontend also treats DECLINED attendees as not added
  • Permission Editor UI inconsistency for grouped rooms: The group permission editor stated that individual rooms can have additional permissions, but the room editor was read-only for rooms in a group. The backend already supported merging room + group permissions; the UI now allows setting room-specific permissions
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureaGpq5T9hp9uBtS1HOt691u9gw559kx1tuwL7bj8C0oY74zgrGdWXsPI2MG/3E+0jRp5ZdlE3Lh5o/jA/dM51Xs9QTWicjAU2FviAYw8Zwkjz8qqgj3wspu4X+L3TlhZgEHgQnfq6NQ2229CZUCwu8CgOk6vjabVsTwXM0dbmMlz6cESP1+BHeJkoX2do6XbSXAS5efL9dxWunYnAlNlKCvLJMgtIKXV/IocXy7MPi2FV5yrHIpzkB7+nqJXNsoiWmPvGoatxVEhY86sMXbCQ1Qw9wOvQ0S0UkUYh5UUfubOk01BGzWxNN3mdMAYm8kkbbz5YXW7yOje1fhDJ9qYd8+8X0F4Jj1JxJ9HhYWbeY3Hitpqtdpz+rBPDfpMl5pIFDsFbohff67B4Er7HGT/x8vucha/hQS+G4YF4gvP6/uOi+MLstc7AUqLojoOMCGxpH8RFVPHFTA7jyHfF9xSjpsIGdC17z+jA8c3NURCQwldeqwCm3ltcGvGYfLZEWWGLEZk+jBSiKtJcH7R4y2SBBT8ZoT9xUPugBH3t2rj/4qXRhPILMbIq6P0E1H3JYS0iXJzVpPEb91POOGhBJARuppyEKkMaJY3GHBsK+c3soOcT95T5Ed1guO+pXLm3Pvz8/04BgaI5FeuE61J8MIp7Irz7mfyqVaVpqVi7Dpq8PIA=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<34.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.0.1
Release Details
UpdatedApril 9, 2026, 4:34 p.m.
Changelog

Added

  • Telemetry send button: Admins can now manually send a usage report from the Support tab, with clear feedback on success or failure
  • Telemetry toggle: Enable/disable anonymous usage statistics directly from the Support tab

Changed

  • App Store description: Removed evaluation disclaimer, cleaned up formatting, added VoxCloud as author
  • App Store metadata: Added office category and GitHub Discussions link

Fixed

  • Telemetry error feedback: The "Send report now" button now shows the actual server error message instead of a generic failure notice
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureOU/DKlkz4BJCi2XSSjawjaSgCbRFwY+GCEvqsVMd03KPm0oCFuvRuO3G0asw9l10vURGNh1rwcOhOuR3rLALvO7Kp7BetltAdruOJXdNFAgmyS4w2D3Q1yE055K3rHYV1rtQs7ewtj7GTFs2rkvFekh7vRWn018QpSepjrQbM0D8QmpEVC1GVRgeeh78AkFZn4jbub3d6lrV6JnlgvSah3Or+9gze65KyrI3txLngjPqxdaot6NSqnS0EHyFJGtR2/K7A/dnRd1yj/f0V9nSDzDQvNgDH5VgZtaRiJ/cLU4vxileuBmBMH0+X1c8oahkyx1ea+yTsyvLF5JWclmQ8YGm4fnJOlXItrgHCuAJzZWIOOkxwFk5C5joXAJ0xULKDkZqbwWKHEC3kS+Yj6wa5rYkBOZD2ovBbNsGX6kL/aTC/Il3UWkjY3b585rFWydzgUDw+kJDxstdDUV/UgWQ36J3JH5xyHPig0s4UGoEemttPCV7UTP5mhbI/jxXepoW4mWZs/OLxTuyOp+L6l5u5orcXz9rSaKe0Le40irQweqCped3IKiqqd0fLQz6o4pr29ZStrPPm/BGJSboFywzzQAdW6f3P88Ur8FaR2sgjb9j9SrTNOypINx4ePhA0dRbQTBYMCODcwNrsdCEt4sXzCnARz70rziNMOvup2zacb8=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<34.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.0.0
Release Details
UpdatedApril 9, 2026, 3:39 p.m.
Changelog

Added

  • Improved MS365 import: Extended column mapping for Street, PostalCode, device names (AudioDeviceName, VideoDeviceName, DisplayDeviceName → facilities), Nickname (→ description), and BookingType (Standard → auto-accept)
  • Exchange sync on import: New checkbox in MS365 import preview to automatically link imported rooms to their MS365 mailbox for bidirectional calendar sync
  • Show weekends toggle: New setting in Settings > General to show or hide weekends in the booking calendar (default: visible). Closes #3

Changed

  • MS365 export documentation: Replaced broken one-liner (Get-EXOMailbox | Get-Place | Export-Csv) with two options — a simple Get-Place export and a recommended full script that preserves email addresses by joining Get-EXOMailbox with Get-Place data
  • Permissions documentation: Added prominent clarification that RoomVox uses its own permission system, separate from Nextcloud Calendar's sharing permissions. Getting-started guide now emphasizes that permissions must be configured to restrict room access

Fixed

  • MS365 import missing email: The previously documented PowerShell command lost the email address because Get-Place returns a different object type than Get-EXOMailbox. Documentation now explains this and provides a correct export script
  • Declined bookings not updating organizer calendar: When a manager declined a booking via the RoomVox admin UI, the organizer's calendar still showed the room as "Reserved" (TENTATIVE). The respond flow now propagates the PARTSTAT change directly to the organizer's calendar event
  • No notification on booking accept/decline: Managers accepting or declining bookings via the admin UI did not send any email to the organizer. The respond flow now sends confirmation or decline emails using the existing mail infrastructure
  • Recurring events showing only first occurrence: The booking overview and personal approvals now expand recurring events (RRULE) into individual occurrences within the selected date range. Closes #2
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
Signatureiufjb3kzU1ga+jNcl/Gstr+rP+s1GEVt2r/dib2hjPoZBHm79v5hjS4iOVt2f4+OY0QLhSkDL8RhjqHqsis884IH5FEy/thZiFOllAfSxvRNKIFMZoUX8sPiZ+XCtIy0rT7H5Aja+67ElyOjbQyzsj4d4wqG8+JIT6AQveTF4lviv11i6ze3YWq+kNU8XZ0MisSbx/Bld0Q8hjJrTqqhNMxRaLHE8F5O2zeSUSWLHvvfv0LxZV6ZpQtVlPybB2JcZXh5WRdecgZU8F6sIU1Xz+DTRiV4anp5DsIAj1+cN//tuj/BA/clMiWEojdl+uTpd7c7+jUQj9jfztl8hEZwM5VlxRIc0yCrftFUHkTUl8iX2i6J55kw3pl52fLg06tdYxezu+axfxHToBLWKdpXxIX+f4kWkZF4+ia4VOMJ6KnDaO0T43wuILxjvjOltZqcOYbhRp35W4q8uVNRV2bN36zTO4vUvmevDVvKp1bO+h4km5+d5/lzXUwTNTh+xRbiewNQ/fkASZdMbJtqetS+5b6LMFNOMrZmKaa8a+Am44BzXSf/41Dwd1lbrN/2D1ytZ8HgM9Uh4fcX5Hfpf+U1qehiT2nMuAsIOXcl1fU/RkOodU6KYCs2lCSfcg+3+BdJQ3cPJaOC+ATzJqp2/yI98a59yBIx+um0Mryac6c6ysg=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<34.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 0.4.0
Release Details
UpdatedFeb. 20, 2026, 8:28 p.m.
Changelog

Added

  • Configurable Facilities: Admins can now add, edit, remove, and reorder facility options (projector, whiteboard, etc.) in the Settings tab — same UI pattern as room types
  • Personal Settings page: All users now see a "RoomVox" section under Settings > Personal with two tabs:
  • My Rooms — overview of rooms the user has access to, with role badges (Admin/Manager/Booker/Viewer)
  • Approvals — pending booking requests for rooms where the user is a manager, with accept/decline buttons
  • Slug-based duplicate detection during CSV import: rooms are matched by generated ID in addition to email and name

Changed

  • Updated App Store description with evaluation disclaimer and improved formatting
  • Added compatible calendar clients list to description
  • Approval notification emails now include a direct link to Personal Settings instead of referencing "admin panel"
  • CSV import now matches @roomvox.local emails for duplicate detection (previously excluded)

Fixed

  • Fixed facility ID mismatch between frontend and ImportExportService (videoconf vs video-conference, audio vs audio-system, etc.)
  • Fixed CSV import creating duplicate rooms when re-importing exported data with @roomvox.local emails
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureDcKMlKWNOecIXoF47OjlQwoPwEqdbtf38MYWmCwhPBNf56lSAy2v3z2j1kkzaaLCztiuuCW3obwRUp/0894rMulFGqFAAkwF1bkzzRz5Rl56QN/OoxjUpYC3APjbS0p29XOaZ64k/gSg4N/dGNUQOGZVvgclyGkb9530TT6UwDOxKWRGJpvC3W+0JixQwGVm2/yW/W8o/fyIjU+lOiq26jS8kjBpWHmNtdzqgiAbijMYdpguPNKWXqLzC29vqnDXhXDX1XuixkFddJ15lo1YHV1hwNcFdiHwuy4MerRRv3ckOmHHNOliMgUzN7SsNnxAXrH49KQpNbWIgkj3DWlXkclk8Fw3rretsZEvgrXbKC8b3zq+a/NK96sEcrQ5JdwyttojF/337kGEhKZc9Z4x9ivnG6w8cIVuY/xdG9680nA7NTeTGQe6bx+Ez+WaXq4IiXYi6ZokYJlk0taCRlCl4GmXjdRwe4JZHpwrg7tTu/K9ylpj4XlGcl3Pxz8KVpK1cX7EKqP/PgV4oFR8ZY5jhHHLkBlL2agbx3ziF0YJjn/D++isdjCaqa/Zr/rZf6WjQhWysfps6vVToSHpJJoODGPTjCYocWQij1hScwzEkS+oQHKg7xzfqHrBioJt6V5ExKSya37yXnIohYeqQzqPeXvwy8njL5cESLsaNZf3spE=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<34.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 0.3.1
Release Details
UpdatedFeb. 19, 2026, 12:40 p.m.
Changelog

Changed

  • Updated App Store description with evaluation disclaimer and improved formatting
  • Added compatible calendar clients list to description
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureB6xpwCS49tuWj8tpROVwrt9D+7BAPWC9EXxqV6nijSqXn4oKBZEao5nocPJo2BDYrq7xeD8YPg7JcB7ExBCSWMgSHabfb0FQP70lilP/QbQW9JmWbHAp67V33qLruzePhtJPSNgFe7oExzu3csWkmqZUovMMdJTymN3c+lmVVO/SMpFF+up2o2ERrZ0hxpCiipdzRhY9uIlta2WUuGdaHsSu6llKXjP8mMk7ZdY255ZxcTjO3PlTmtDUZE5k/N649XKaeSIo7Di/0DPEnf7AJz5v08OqmQVLbD3iOzwExDXA86ueGXik10k3iDb6fd0Yt91PZVtpEkWuWT0gCuwHegtgYgn5Ucg9ymsjACW9T2Lkn7lvSvBFCszegYztquD0oruLF3duHiBfmR4ChjWZ67ST+oUpj2NLVgjnz4aMblI1pgdvPRWkROK0mTx+YIVfNqApIz1u6bs37jZSJF+TfuFbVs/EoVaLyPOhMQjpVjhKNJqS9ygfONv3CBpF5mTNvDJ5jY76ii8E6/yFlIj1kFwQHk+6kqj+X2HWSDNy/83i3YTrgbvJ64dZOGZDXbM4VMgg79Hv50yBbqQtgv4Dv1cgZ0LVy43EkWmQFwPZrlAucc31qDW6FrhFsV0PCbJqRbPXO4z0TCA2QZSicoudVoeqJTU22ktWwi6kbiTob/E=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<34.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 0.3.0
Release Details
UpdatedFeb. 19, 2026, 12:32 p.m.
Changelog

Added

  • Public REST API (v1): Full API for external integrations (displays, kiosks, digital signage, Power Automate, custom apps)
  • GET /api/v1/rooms — List rooms with filters (active, type, capacity)
  • GET /api/v1/rooms/{id} — Room details
  • GET /api/v1/rooms/{id}/status — Real-time room status (free/busy/unavailable)
  • GET /api/v1/rooms/{id}/availability — Time slot availability for a given date
  • GET /api/v1/rooms/{id}/bookings — List bookings with date/status filters
  • POST /api/v1/rooms/{id}/bookings — Create bookings via API
  • DELETE /api/v1/rooms/{id}/bookings/{uid} — Cancel bookings via API
  • GET /api/v1/rooms/{id}/calendar.ics — iCalendar feed per room
  • GET /api/v1/statistics — Usage statistics and utilization data
  • API Token Authentication: Bearer token system for external API access
  • Token management UI in admin Settings tab
  • Three scopes: read, book, admin (hierarchical)
  • Optional room restrictions per token
  • Optional token expiry dates
  • SHA-256 hashed token storage
  • Automatic last-used tracking
  • CSV Import/Export: Bulk room management via CSV files
  • Export all rooms as CSV (13 columns)
  • Import from RoomVox CSV format
  • Import from MS365/Exchange format (auto-detected)
  • Preview before import with validation
  • Two import modes: create-only or create + update existing
  • Download sample CSV file
  • Internationalization: Added German (de) and French (fr) translations
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignaturefV4q5gfB1YN0APkHUrov/EMrhR186lJ1av7tJIRP9CHqyHlggaJ+plVholqsmauv4QylnZSpvWgtdv+A9F2EKZNyxGfZpRKqSIuj0mqrBckNnfLD/9lVQR00ZXZNapO8BZTtGDjfFgOMDq7U/GxO68entOXfUuPE4l+tVJp+ZtFlsBXj+1M5X/OW5OyXzg2NSrzAsDtMWdJGo4Bg+TdO/h3Rr+Ph9rd63Y9g1NxmqTToZ6xkL8bspJ0zuX5aRjyo4cR2xJAbGTl/Gd2+xuRlIZpzIFKEjUnqMYAjabbXPvPVgW3Y0Gs6zsn1+4mL56sHLiLcN+a3bbVy3saz5RYH9qfrTHRqPqcvUp+yF0OifJQ2JA2GzZW95f5Cr87O24ffRzYC4E+7Wxzn49tD7uyHCD0jJAbik/1uN4gELmue+QdfVoJbwJv160UDDEIBSqB7GYRJuPr5dOrTbOz80rhc564IORlJrsfifUgSo0JS37FA6L5jLws0ehM+t67nlFpwCageEiNPbe0E7B6LdDnxkztyNrvjiwl6pt1gRfNmPR8fFACn+v1B/6/rodw6QlNcdqCuseftY9duxdbrzq5MnEhn+PW3QjlOaTTIS6QsHk+zPxMxoknlsrMXkQl3SoBUaJcYCpRJjN8gulUDTl8kFihigbT7u7SVaDuKnDbhteY=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<34.0.0
Minimum Integer bits32
PHP>=8.2.0

Nextcloud 32

RoomVox 1.3.0
Release Details
UpdatedAug. 13, 2026, 5:23 p.m.
Changelog

Room metadata that RoomVox already held — floor, address, building — never fully arrived at the calendar clients that show it. This release fixes the publishing side, which matters now that Nextcloud Calendar is gaining a room browser that groups rooms per building and filters on floor and capacity (nextcloud/calendar#8264). It also fixes booking one event into two rooms at once, and makes notification emails translatable. No stored data changes; the room editor keeps its fields exactly as they are.

A minor rather than a patch release: notification emails become translatable, bookings gain an allDay field in the API, and RoomVox moves onto the Nextcloud community translation workflow — which changes how the app is built and which files ship.

Translations. The strings added in this release are not translated yet: RoomVox is being onboarded onto the Nextcloud community translation platform (nextcloud/docker-ci#986). Until translators pick them up, untranslated text falls back to English — the interface stays translated where it already was. New translations arrive in later releases without any configuration change.

Added

  • Notification emails are translatable and sent in the recipient's language (#24): every subject and body in MailService was a hardcoded English string — the app had no IL10N at all — so a French user with a French interface still received English mail. All 14 notification types now resolve their text through Nextcloud's translation system, and the language is chosen per recipient rather than from the server default: the organizer, each room manager, and the admin can each receive the same booking in their own language, resolved from their Nextcloud account (external addresses, which have no account to read a preference from, fall back to the instance default; an address matching more than one account is treated as unknown rather than guessed). Values are never translated — room names, event titles and dates are substituted into placeholders, so translators get whole sentences instead of fragments. Alongside this, RoomVox moved to the Nextcloud community translation workflow: all 526 frontend call sites were converted to the t('roomvox', …) form the Nextcloud translation bot extracts (it reads only that literal form, so with the previous $t(…) wrapper it would have found none of them), a POT template is generated from both the Vue and PHP sources, and the existing German, French and Dutch translations were carried over so no language restarts from zero. A prebuild guard fails the build when a new source string has not been pushed for translation yet.
  • Rooms publish their building name: RoomVox holds the building as its own field, but CalDAV had nowhere to put it, so clients that group rooms per building had to infer one from the address — usually by taking everything before the first comma, which turns a room at "1098 XG, Amsterdam" into a building called "1098 XG". Rooms now publish {http://nextcloud.com/ns}room-building-name, taken from the building field itself rather than guessed. An empty building field publishes nothing rather than letting the street stand in for it. Proposed upstream as IRoomMetadata::BUILDING_NAME; clients that do not know the key yet simply ignore it.

Changed

  • Interface labels follow the Nextcloud writing guidelines: 44 labels used Title Case where Nextcloud uses sentence case ("Save Changes" → "Save changes", "My Rooms" → "My rooms"), and twelve progress labels ended in three full stops rather than a real ellipsis ("Saving..." → "Saving …"). Acronyms, product names and Microsoft's own field labels keep their capitals, so "API tokens", "SMTP Host" and "Client Secret" still read the way an administrator sees them in Entra. Existing German, French and Dutch translations were carried over to the renamed labels, so nothing that was translated became untranslated. Cosmetic only — no behaviour changes.
  • Translations no longer carry strings the app removed: each language bundle held 79 entries for labels deleted in earlier releases. They were never shown (Nextcloud simply never looked them up) but shipped in every release and would have been imported into the translation platform as translations without a source string. Each language now holds exactly the 359 strings the app actually uses.

Fixed

  • Some CSV columns were silently dropped on import (#29): importing a room with every column filled in lost roomNumber, roomType, postalCode and autoAccept — which also meant RoomVox's own CSV export could not be imported back, the very file the export offers as a template. CSV headers are matched case-insensitively, but the parser compared the lowercased header (roomnumber) against field names that are camelCase (roomNumber); the four columns whose names contain a capital matched nothing and were skipped without warning, while the ten all-lowercase ones came through fine. Headers are now resolved to their canonical field name through a single map derived from the export column list, so the export/import round-trip cannot drift apart again. Case-insensitive matching and the MS365/Exchange column mapping are unchanged.
  • Month view showed the wrong month in the header (#26): the booking calendar's month view labelled August 2026 as "July 2026". The heading was taken from the first cell in the grid, and a month view pads its first row with the tail of the previous month (August 2026 starts on a Saturday, so the grid opens on 27 July). Months could therefore appear twice or not at all while paging through the calendar. The heading now comes from the period the view actually represents.
  • Approval requests stayed in the queue after the meeting had passed (#28): a manager's approval list showed every pending request ever made, including meetings that were weeks in the past, because the bookings were fetched with no date range at all. Requests whose meeting has already ended are now filtered out at the source. A meeting that has started but not yet finished is still listed — it can still meaningfully be approved. Nothing is deleted: an expired request only disappears from the queue, so the booker's own calendar entry and history stay intact.
  • All-day bookings were shifted by the timezone (#27): an all-day event showed as running 02:00–02:00 across two days instead of covering one whole day. An all-day VEVENT stores a plain calendar date (DTSTART;VALUE=DATE:20260813) with no time and no timezone, but RoomVox serialised every booking as a precise timestamp — which turns midnight into an instant that renders as 02:00 in UTC+2 and spills into the next day. All-day bookings are now detected and passed to the interface as a bare date with an explicit all-day flag, so the calendar and the booking list show them as a full day with no time attached, labelled "All day" rather than a clock time. The resource timeline needed the same care: it only renders 08:00–19:00, so a booking running midnight to midnight was drawn straight through into the next day's slots — all-day bookings are now bounded to the hours the timeline shows, while a multi-day booking keeps its real length. Timed bookings are unaffected. API consumers see this too: booking objects gain an allDay boolean, and for an all-day booking dtstart/dtend are a plain YYYY-MM-DD date instead of a timestamp — clients that assume a timestamp should check the flag.
  • Booking two rooms on one event without auto-accept only requested approval for the first (#22): the second room stayed on "Needs action", never appeared in the approval queue, and a manager could not change it. An event booked into two rooms carries both room ATTENDEE lines, and each room calendar holds its own copy of that same event — but every PARTSTAT lookup scanned for the first CUTYPE=ROOM attendee rather than the attendee belonging to the room whose calendar was being read. So room B reported room A's status (ACCEPTED once A was approved, hiding B from the queue, which filters strictly on TENTATIVE), and approving room B wrote ACCEPTED onto room A's line, leaving B stuck forever. The three affected lookups in CalDAVService (getBookings(), getRawCalendarObjects(), updateBookingPartstat()) now match the owning room's own email first, via a shared extractRoomPartstat() helper; the previous CUTYPE=ROOM/non-organizer heuristic remains as the fallback for single-room events and for clients like iOS that send CUTYPE=INDIVIDUAL. Two related multi-room defects are fixed alongside it: declining one room removed its attendee mid-iteration, which invalidated the loop and silently skipped the PARTSTAT write-back for every later room on the event (removals are now deferred until after the loop), and that same decline cleared the event LOCATION even when another room was still attached (LOCATION is now only cleared when no room attendee survives, otherwise it is rebuilt from the remaining room). Earlier analysis had suspected Sabre/Nextcloud's iTIP dispatch; the scheduling path is in fact correct and fully per-room — the defect was one layer down, in reading the result back.
  • Room floor was invisible to every CalDAV client: the room backend published the floor under {http://nextcloud.com/ns}room-building-floor, which is not a key any client asks for. Nextcloud defines the property as IRoomMetadata::BUILDING_STORY (room-building-story), and cdav-library requests only that one in its PROPFIND, so the value never reached Nextcloud Calendar, Outlook, Apple Calendar or Thunderbird. The backend now publishes room-building-story. Nothing consumed the old key, so this only adds data where there was none — on our test instance 97 of 113 rooms had a floor set that no client could see. Floors appear after the hourly UpdateCalendarResourcesRoomsBackgroundJob has run, or immediately after occ background-job:execute.
  • Imported rooms published a malformed address: addresses are stored in a fixed four part format ("Building, Street, PostalCode, City") so the room editor can split them back apart, but that is an internal detail. A room imported without a building or street was published to CalDAV clients as , , 1098 XG, Amsterdam, which clients show verbatim and use to derive a building name. Empty positions are now dropped when publishing, and in the room description, without touching how rooms are stored — the editor keeps its four fields. This matters more now that Nextcloud Calendar groups rooms by building; see nextcloud/calendar#8264.
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureTuRtOoNTIAfHxKuFfgxldiQjduru8p+rl2W2QR+KfudIh44YAQn0+Q5bAIti+8uupMo2pIwJxZYOfN6qwfyMd7hmC9ngiEs9F2gQpRmu7Ko0ocdLp+F+H1ajHAk8Z7UJQXS3IIaLrwrjDF5F1G0UOacufnSB4Dp5GdJcFHy7kmwfrk5ynNmOxvFHuMho0M12n7jfS1get2yUgB2zWyg2GByiu4d9haUj2NESybi30SaUit0I8COJyF5uMZi3CezaIiXZLtM+QaOvIfps6U1QcA/5D9nJViUYgNuFGFC3tsE39o+RZ3ArNE3zZbhR5lxaqJlgnmU+pqLqS/R6srL3uR+NuzmJs6LgFCzmgQt4JFLuHr7xU7WBe5+dhtppolj9oX8dzmdVZeUulHS+YLltzTRhoxdLUWNMAXaMxejRZ8fmgA57/ljDXvHULqjWNIKS7Bnpufe32QTUhxAo3Qjro/bIlNlay94ST8SLXbWveCMDVUJ4h/NJTM/JHKXOwuHZ3SoAxkshdJgGrQ92fQA/qMVQehWL8FdyUU4YmA7zP6PPsf1aEfZkwcSEm7WDsjYDbesjY6P0PunQxoTS9b543jhLKSOevsXb3mmaxGmLz8LrY1ZQzf7KADoCznC6OLYYpVpILRis/v2cs3q37o8tox82KlJAC9tnbqhCuMiKPfg=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<35.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.2.1
Release Details
UpdatedAug. 3, 2026, 5:56 p.m.
Changelog

Changed

  • Booking administration room filter now shows the room group (#19): in installations with multiple room groups, room names are often reused (e.g. "Church" and "Office" in both "Parish A" and "Parish B"), and the filter listed them indistinguishably. Each option is now labelled "Room (Group)" — e.g. "Church (Parish A)" — so rooms can be told apart. Rooms without a group keep their plain name. Frontend-only; no API or data changes.
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureYJ2npvyqg6agBjsoTDT1VVZGa1LI9d4XhZdQ1NMz3tee56ch76U94qAA/POOA2+a00B5LvIpPtrWr2EIqX8f/+ndlJUkQ+FtWADGprnwim/KIm+/u2srj9l6Efe9WDfc0JEY4GTQDt+n8bmT7fLtcDrwCLT9CpJncKe7SlRTYC8YJSzMfadM8/OAGbPTcWnIQsOw5l84+vBgjorkGkz87m1DxG/TrCaxmRe7P4h5BWk+yHo/OoUzP31D63XFcX9i1YBsn+CfomO622rJ7eGW7EnfB870E0x9q5bMkx3q+Oq2kFK1uw7LoO1azV53EaprG4twE5ytwrgafbUcT42dO7Usa6JrdGCl03nN3ZjGfkpyyZ2h61/H+8ecm7I8uVIlnIFOPofyCg45UqDNC7DtdOlIBUMuZ90XpIowttmWm9X4MS1CJSbEXt27o/7kMerYQHvk9xXoiaorqaJ345PNupFBkcqcfDFnYk/iiUmbmud0GAiGcc1raCUsL+A6n5VqDR2edA5BG1Y8BVYU1DB79EJa3Qj0XM6Gjd3DWbRyRptQ0G2Fbu667rVmc1rSHUedUw5xOIa8TG5wkCTfund2v/1uy3omDnIjDM5zcCnSHDd0NDCrQf4S9XSsru6EE9Lrt3m2AIpws+dpYlGFGOY+mVMP7xvE14jcOLCWDbUO3Ac=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<35.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.2.0
Release Details
UpdatedAug. 3, 2026, 5:42 p.m.
Changelog

Security

  • "Show all rooms" dialog ignored room visibility permissions (#20): In the Nextcloud Calendar room picker, the type-ahead field correctly hid rooms a user may not view, but the "Show all rooms" dialog listed every room — exposing room names, locations, and organisational structure to unauthorised users. The dialog now intersects the calendar's room list against a server-authoritative allow-list (GET /api/personal/rooms/viewable, filtered by PermissionService::canView), so it shows exactly the rooms the type-ahead does. The allow-list endpoint returns only room id + email (no other detail), and the dialog fails closed — if the allow-list can't be loaded it shows no rooms rather than risk leaking. Booking was already enforced server-side by the scheduling plugin; this closes the information-disclosure gap in the browse UI.

Added

  • Public, subscribe-able iCal feed per room (#16): The iCal feed at /api/v1/rooms/{id}/calendar.ics already existed, but required a Bearer token — which external calendar apps (Nextcloud Calendar, Outlook, Apple Calendar, Thunderbird) and signage displays cannot send, so nobody could actually subscribe to it. Rooms can now expose an opt-in feed at /api/v1/rooms/{id}/feed/{secret}/calendar.ics, authenticated by a per-room secret in the URL path instead of a header. Admins/room-managers enable, copy, and regenerate the feed URL from the room editor. The secret is read-only and room-scoped by construction: a leaked URL only exposes that one room's bookings and can be rotated per room without affecting API tokens or other rooms. Endpoint is brute-force protected against secret enumeration, comparison is timing-safe (hash_equals), the raw secret is never logged nor returned in room-list responses, and feeds are off by default (explicit opt-in per room). The existing Bearer-authenticated calendar.ics route is unchanged; both share one iCalendar builder so their output is byte-identical.

Changed

  • A manager booking their own room no longer needs a second manager to approve it (#23): On a room with manual approval (autoAccept=false), a booking whose organizer is a manager of that room is now accepted directly instead of being parked as TENTATIVE in the approval queue. Requiring a manager to approve their own booking was a pointless extra step. Non-managers are unaffected — their bookings still go through the normal approval flow — and rooms without any configured managers are unchanged. The decision lives at the single PARTSTAT branch in SchedulingPlugin::handleRequest().

Fixed

  • German umlauts stripped instead of transliterated in generated identifiers (#18): Room/room-group slugs derived from names removed ä/ö/ü/ß outright, so "Küche" became kche and "Außenbereich" became auenbereich. They are now transliterated the standard German way (ä→ae, ö→oe, ü→ue, ß→ss), yielding kueche / aussenbereich. The slug logic — previously duplicated in RoomService, RoomGroupService, and ImportExportService — was consolidated into a single RoomService::generateSlug() so CSV import-matching stays byte-identical to room creation.
  • Unnecessary comma between postal code and city in event locations (#17): A room address of "…, 01324, Dresden" produced the event LOCATION "…, 01324, Dresden" instead of "…, 01324 Dresden". The calendar patch now formats the room address (postal code and city space-joined, building/room number folded into a trailing detail) instead of pasting the raw comma-separated address string, and the 3-part postal-code detection in buildRoomLocation() now also recognises 5-digit German postal codes (previously only the Dutch "1234 AB" form).
  • User's locale ignored in dates and times (#21): Dialogs and list views formatted dates/times with the browser default locale (often US MM/DD), confusingly disagreeing with the user's Nextcloud language. All toLocale*String() calls now pass the Nextcloud user locale (getLanguage()), matching the calendar view which already did so.
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureLxXT6mBOx39KwNvqF8NjAEjd9mBwHEfwC+Ddi61112p2hXAmhywHBF+CtJ5r16n/ibbvmnvOmP4TvOmaxjbfpTdxVIQ7zGH/euheSpBHPXEkN072KKIVGVVDprlkkS2g/S+aBtcR4R1/pr1RDi0mvlN0IGeRkTDkNkqGEiFNsck1pg9P6rscwVXZSi4BxY79FJKkoetv3jlGBZrBjN1xJ1ldchw0LKeqhg/OITc7j0BTj43F/j4tRJTC8h/PFh+fGFacHMTrxFkEVdncwiMBra4s8fL3p0NU9BP5+J3VFoPADtsLuo1SnvWSyOk/WqtaoExecVW79ZcjwXtLHLW7EnQZCThF6nr11/o4YG8ybOR3lRn6Qmf8dE+4KpOxVtH5SgCA3khtnsx2Ee+oTfqgvQvCPzalhmH4RFNLimzw6geIhLFDTV72Go3743S2OeFrRBYxMB6qagmFAQZj3H735pDOdc4tIK0CffsZWgCQulK71h1w18iBYMxiPPPKUnLWsnWXJ08OpTmFqhcBpAnEJZxDVUR8GsX3qQodOFvl68WqHsu4sxQ1flTH/Z3Ikij8OwBObxL2mqKHSDqxXd/94mapkLIJM/kUUZPVBu9uudpdWfGCFTTFsh3AfJtaVJSimI5mBJQJAwiOS4dfUqEQIznUCRUd+x89PbX+PsW87Gk=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<35.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.1.2
Release Details
UpdatedJune 12, 2026, 10:11 a.m.
Changelog

Changed

  • Nextcloud 34 support — Bumped max-version in appinfo/info.xml from 33 to 34. No code changes required: Application.php is Bootstrap-based (IBootstrap), all \OC::$server->get*() service-locator calls were eliminated in prior releases (notably MailService::notifyManagers / sendCancelled in v1.1.1), logging is PSR-3 throughout (LoggerInterface), getAppValue() calls all have defaults, and DAV registration uses registerCalendarRoomBackend() (the NC 30+ API). Sabre plugin registration via SabrePluginAuthInitEvent continues to work on NC 34. Verified by smoke-test on a Nextcloud 34.0.0 development instance.
  • Documentation restructured to match IntroVox/IntraVox/MetaVox layout — Replaced the previous flat docs/ tree (with one troubleshooting.md, comparison.md, and future-*.md at root) with a nested structure: docs/index.md hub, docs/getting-started.md, plus admin/, user/, features/, architecture/, and deployment/ subdirectories. Added 14 new docs covering admin guide / settings / best-practices / FAQ, user overview / personal-settings / FAQ / tips / troubleshooting (split from the combined troubleshooting file), features/{approval-workflow, availability-rules, email-notifications, public-api}, and architecture/{backend-architecture, caldav-scheduling, exchange-integration}. Removed three internal-only docs (future-ideas.md, future-personal-settings.md, exchange-sync-changelog.md) from the public tree. README and appinfo/info.xml <documentation> block updated to point at the new hub pages.
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
Signatures0uN/kj68S45tZHtOh80rIsHorH0axrB0w8umB+Z6wIPtl7vC6R5QSWvB+puvu87P0zwTgZRx9rNAb6wsZDA+ey2c0hiSg8NqKnQy55qtuX0EeZrwE/wFGsLYkemFtFJ047CLRbSSFcEvbAkkekLbIMdnOOZ9k8eItPsdnPS0pR2l4wPNqzc0/htzlnInVgtZIkuk4q4e57QuKd69HW3MJ0FUKvwHWtVPMdjTKqslCwaDIAxqgK57O0rrQgsxm03YZ20NaxmY2gAlXscz3JEfFstBXxNz0kxVf/ct/qRLoiqZZY+7eUCdR5BUbAu8h9KeZ7s8XmAoCMYBAMAPWj2B0ZmAfoAtqWh1sRyOVeExp+icWbSJbVdg1niKvxMhv47WVyW/u6dNw01ZcYWAejFd2+iZ96EKTUMhCQx1ItcUnzL9dC93O65laBZ2Cm/9BKZSONGxVjh3zgMVyj98Bd4MTpjsB1k8vj4yDjq39OJgbQF/N3jiYeVUpAoKQLB0DnSa8czOAM0GO8TTwe/k050yR8XJ8eJfc6aSyp8AEGNrhZPEo4GY1DyKLYRPSHsnUkP3VcvoC4HV6dgkcrjplNgqTQKMUPxp2JccFq2r4m9j3Dj2HET/+7cF9ZyVkdPKfI9yoEUzSmxzVkRoS+M7ecGizR67XxIh5C/kQn7wvykiU0=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<35.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.1.1
Release Details
UpdatedMay 26, 2026, 7:41 a.m.
Changelog

Fixed

  • responsibleContact silently dropped on room create/update & opaque permission denies (#15): Two unrelated defects rolled into one user report. (1) The "Responsible contact" field (introduced in #11) reached the frontend form and RoomService, but RoomApiController::create() and update() whitelisted the request payload field by field and responsibleContact was missing from both lists — so the value was filtered out before reaching the service layer and any edit appeared to "not save". The field is now in both whitelists; a regression test exercises the round-trip. (2) Permission denies caused by the iTIP sender resolving to zero or multiple Nextcloud users (typical for LDAP/AD setups where the same email address exists on more than one account) were logged at debug level only, so admins saw an "automatically declined — you do not have permission" mail without any actionable trace in the server log. The log is now warning level and names the sender email, the match count, and a sample of the resolved UIDs, so duplicate-account configurations are immediately visible. No behaviour change to the deny itself — the underlying group-permission resolution was correct
  • Approval mail never sent for non-auto-accept bookings via REST API & malformed ORGANIZER (#14): Two related defects on the API booking-create path. (1) POST /api/v1/rooms/{id}/bookings and POST /api/rooms/{id}/bookings on a room with autoAccept=false produced a TENTATIVE booking but skipped the manager-approval mail, because both controllers wrote directly to the room calendar via CalDavBackend and never traversed the Sabre SchedulingPlugin (where the manager-notification hook lives). Both endpoints now invoke the same notification path the iTIP flow uses, so managers see API-created bookings in their approval queue exactly as they do bookings made from Nextcloud Calendar — including the room-move case in the internal API. (2) CalDAVService::createBooking() unconditionally appended @localhost to the organizer when building the ORGANIZER property, so external emails became mailto:user@company.com@localhost (undeliverable) and CN was set to the raw email instead of a display name. The property is now built via a shared resolver: external addresses are emitted as-is (enriched with a CN only when they match exactly one Nextcloud user), Nextcloud user IDs resolve to canonical email + display name (the same logic that fixed #5 for the LOCATION-fallback), and unresolvable organizers cause the property to be omitted rather than fabricated. Internal cleanup: MailService migrated off the \OC::$server->get() service-locator anti-pattern in notifyManagers and sendCancelled, in favour of proper constructor injection of IUserManager
  • Cancelling one occurrence of a recurring booking removed the whole series (#13): The confirmation dialog mentioned only the clicked event, but on confirm the entire iCal object was deleted, taking every occurrence with it. The admin UI now offers an explicit choice between "Cancel this occurrence" and "Cancel entire series" whenever the booking is part of a recurring series; single-occurrence cancellation writes an EXDATE on the master VEVENT and removes any matching RECURRENCE-ID override instead of deleting the calendar object. The booker's own calendar gets a RECURRENCE-ID override VEVENT with the room attendee marked DECLINED and LOCATION cleared for that one instance, and the cancellation mail names the specific occurrence so it cannot be mistaken for a series-wide cancel. Exchange-synced rooms cancel the matching instance via the Graph events/{master}/instances endpoint. The internal API (DELETE /api/rooms/{id}/bookings/{uid}) and Public API v1 (DELETE /api/v1/rooms/{id}/bookings/{uid}) both accept a new optional ?recurrenceId= query parameter; the existing series-delete behaviour is unchanged when it is omitted
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureVP+0b42txWRHoOd+uUqC0R6aUPFE8mHjzbfRthoKpph6c490rhAXQLn9IBW95f9xcWkzjB3Zt5cXEV0JaWxZBC63d1bfK3oduyKYjgBARm7OFYaBIzo9GwsacqDSqERw7ZZLjrTTftc6adahPGMzXjpXaqe9BlN6c9E2Va7pGAaKW2WVlkROwbspZwMZSsZSbSUSyt1aBnKUkaBDJxlglK/CYbfiSSUwxUQmPqxNhQpGsHi9wjemdHFZHLf/dDCfmZZaeq9Yv3arOfZCboclVfRKB5BTdyVqkDnrUN4LiOhm69fKvkUA4C4PL/osEuy0k56uflhWKPnHEZcdrpRTKE/N+bzlps9aWaVHT4ofYMU5WxXILWPN4lh87lg3I+9653XMjABNOE8Pyg91EpyJAqsjh748vckjnvU+NcKpmHqs6TuQnLixSCfdkvTS9qcYuNak9HzFSd1js1uv7CkcLT5UL02FSTSXVvQ7gD9jo6D5owKFNC6odnz+5XilDz9mepOL7Vdu03AyPdIYH97gixepMt4wvhWVMkFPnItP90UIwlVXrMQN/B8X4lb3dw3wS/ZL+94KGIbIK+nOvPfnf7ytYYracYLLD7LnddloEYwHKD1mpbcCuQAWYSznirWHcRoBydsJQx4TbSvLCC8EeNhk3U36efZobp5R1iqK/ts=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<34.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.1.0
Release Details
UpdatedMay 18, 2026, 5:53 p.m.
Changelog

Added

  • Manager Bookings overview (#12): Managers now get a third "Bookings" tab in Settings → Personal → RoomVox (next to "My Rooms" and "Approvals"), showing the same overview admins already had under Settings → Administration. It is scoped to rooms the user can manage via a new ?scope=manage query param on the /api/all-bookings endpoint, and inherits everything from the existing BookingOverview component: stats cards, room and status filters, list/calendar toggle, and drag-and-drop move-between-rooms in the calendar view. The tab only appears for users with at least one managed (or admin) room
  • Responsible contact field for rooms (#11): Admins and managers can now set a free-text "Responsible contact" on each room (e.g. Anne Janssen (anne@voxcloud.nl) or Ask building manager). The value is visible to every user with view-permission in Personal Settings → My Rooms, so viewers know who to approach when they cannot book a room themselves. Stored alongside the existing room JSON (no migration needed), clamped to 255 characters. Also exposed via the Public API: GET /api/v1/rooms now includes a responsibleContact field in each room object

Fixed

  • Admin booking-deletion not communicated to the booker (#10): When an admin or manager removed an already-accepted booking via the UI, the booker was not notified and the room kept showing as reserved in the booker's own calendar event. The cancel flow now mirrors the iTIP-CANCEL path: the room attendee is removed from the booker's event (and LOCATION cleared) and a sendRespondCancelled mail goes out explaining the booking was cancelled by a room manager. The action is renamed "Cancel booking" in the UI (with a "Keep booking" dismiss action) so it no longer looks like a destructive admin-only delete

Added

  • Translations for the Calendar patch UI (#9): RoomVox-specific labels in the patched Nextcloud Calendar editor (In-person, Online (Talk), Suggested conference rooms, room types, facility names, room status badges and more) now resolve via the roomvox translation bundle instead of asking Calendar's own bundle for strings it never had. Adds 34 source strings in l10n/en.{json,js} with translations for German, Dutch and French. Hardcoded English labels in resourceProps.js and the "Room " number prefix in principal.js / ResourceList.vue are now wrapped in t() calls so they pick up locale too

Fixed

  • Conflicts not detected on later occurrences of a recurring booking (#8): hasConflict() compared the requested time only against the master event's DTSTART/DTEND, so booking the second (or any later) occurrence of a weekly meeting was wrongly seen as a free slot — even though auto-accept would happily add the room a second time. The check now expands recurrences via Sabre's EventIterator and walks each occurrence inside the query window, with native EXDATE / RECURRENCE-ID handling. Same pattern as the iCal-feed fix from #4
  • Resource booking silently ignored when it exceeds the booking horizon (#7): Bookings that exceeded the room's maxBookingHorizon were declined without any notification to the organizer — the calendar event was simply created without the room attached. The scheduling plugin now sends a decline mail naming the configured horizon (in days) and the earliest date that is no longer bookable, so the organizer can reschedule without guessing. The same fix is applied to two other previously-silent reject paths: bookings outside the room's availability hours, and bookings made while a room's initial Exchange sync is still running
  • Location fields shift between Building/Street/Postal code when some are left empty (#6): The Room editor composed the stored address by joining the four parts (Building, Street, Postal code, City) and silently dropping empty ones. Reloading the room split that shorter string positionally, so e.g. Postal code would migrate into Street. The composer now always emits all four positions (empty parts kept), matching the convention already used by the CSV import path. Existing rooms whose address was saved via the buggy UI may need to be re-edited once; rooms imported via CSV are unaffected
  • ORGANIZER malformed when booking a room without explicit organizer (#5): Clients like eM Client omit the ORGANIZER property on single-organizer events. RoomVox's LOCATION-fallback path filled it in with mailto:<userId> (a Nextcloud username, no @domain, no CN). It now resolves the calendar owner's real email and display name via IUserManager, producing ORGANIZER;CN=<name>:mailto:<email>. If the user has no email configured the property is left unset, since the LOCATION-fallback writes the booking directly into the room calendar and does not need iTIP REPLY mails
  • Recurring bookings only show first occurrence (#4): A weekly (or other RRULE) booking appeared only once in both the iCal feed and the Booking Overview. Two underlying causes:
  • The iCal feed (/api/v1/rooms/{id}/calendar.ics) expanded RRULE server-side and emitted N VEVENTs sharing one UID with no RECURRENCE-ID, which clients deduplicate per RFC 5545 §3.8.4.7. The feed now passes through master VEVENTs with RRULE/EXDATE/RECURRENCE-ID intact so clients expand recurrences themselves. The hard-coded ±30-day window is also gone — open-ended series are no longer truncated
  • CalDAVService::getBookings() relied on VCalendar::expand(), which silently returns only the master event when the VTIMEZONE contains DAYLIGHT/STANDARD components with 1970 DTSTARTs (the standard Nextcloud Calendar output). Replaced with EventIterator, which expands the series reliably regardless of timezone definitions
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureLJiGuney8fSKqE5+SzWyFanHkAX7CzcZdgR/g8vYA2IWnj7v5HZSj1IkUzak6GPUyMmYcwFuREVc1fK2yVQOsv0e+I5C5+xMxmXEZ6D3nTvehZ9eMF/ZrEM8L8ygFtWh/qd6a28CsVnFO4/uVl1qlv+rX3jCQdmFk8PFhUeuyV1LEwI75lFxx8bk3bF7kIf2rJiDJi0tUtgc6ZQ8ie/UzglVC5vLsv1rQL2yg5J6qBl0eMZ9ubp2hqOYNaQ0mIDfI2O7N/blRNgHoo3pKT7JZlEbwBIsYlTtZeEXIZPP+yicY9b4cYA0Kq4UNN084d7No7wq8Cgqm8oMO3xrJvE+S1J1RttkPvCr3HJrV6HCB+dzbEbOy0GpYofJIboaCu8jt7eum9lJYsyPcV5xQJaYLcqgr7rv5XBw69lI3Hfok1NOsMcgwcSQEMkghcd/XugtAgf8K+GZf9phsFsb24fPyLZTIg38gsjAYP+uuirLhXTOsENLj+8QDBArW9QqA4aHbFwG0z65lrNrAokPEGXCNO3Qs42pC7Kfuv5HH+6fSVTZ58PbGUEt7cUCq9gQWN/SwsM7gXKssyY52GiVnumYRHSq648zb9m6XPCex6qAdTfERpSOjIaPoKLBw/JAgLEB3JCX23n2jQlJ3/JXcLZjjwFfcl6nurX5O4fbsHQz8L8=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<34.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.0.6
Release Details
UpdatedApril 17, 2026, 2:49 p.m.
Changelog

Fixed

  • Rooms visible to users without permission: new Sabre RoomVisibilityPlugin filters room principals out of PROPFIND responses for users who lack view access
  • Calendar patch toggles unresponsive on NC 6.3: migrated NcCheckboxRadioSwitch bindings from Vue 2 to Vue 3 / @nextcloud/vue v9 syntax
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignaturehsPPvvgv33Nkosy+QPwMUgukZNJMWaCcZ58Y8e9hhBtu379oSQfYsFEBnBN2P7KfidKc9Hog67/vKHTiaFt6AtcL4Qz7onfDnz6hOt0FylP/h+NZFjbhS8wxuFnQYlAnJ5SoiB2zrDsXGb9qzJMzij4w1Ofr0qoWAWHKHgQe90VbiTW8yO1M5WDNyNP36L4JpgIq7+DGglWUVctW4438CnGyLtyv4cRQHSRw4jeq/azl2QA3hJkWUwszsD20m9FsC0QgzjixBbHCo7BgzDSs+1pbTS19y5OgpxdcSq2ZgKYH2NEX8R3fsyMGFP89xFZlKTFvH+tjj141UhYWCmNucjwGhRLamq4YA+som2QPkaEWe7EnRLCasRJ6XUsogH918oLfM7KguQDrej03xkavmSHUCMHCmKeGYF/Sxd9q6bsjpNpbes0LXjndqWt3QS+CBPx+oBEDqqfdCwcyLSFczvgDV6A+3NA9sYpwomip5Xcv6rTQVLzcWor3b5k9I0Nl+g2FDis6mzDRZBigiOnVqT1qsvqrGLOZ2epTCPvlbuPHYHguU1KKMP3tptuX20ZNFHOGub7Ou2E2+b4IgHY2qpmXPiODjzJiamn6VjcDaoUj8Q1Cljnfzg78jtFT8OC+BdbdJzKAZFKnl+DWSx7GxXw/gX+xFQ1xRRUINn4/z5I=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<34.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.0.5
Release Details
UpdatedApril 15, 2026, 9:03 p.m.
Changelog

Fixed

  • Room visibility ignores group permissions: Rooms in a group with configured permissions were still visible to all users in "Suggested conference rooms". The group_restrictions in Nextcloud's room cache remained empty because the PermissionService did not always have access to the RoomService during background sync (DI timing issue). The RoomBackend now resolves group permissions directly when the normal merge path fails
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureOaQyULcfWOavUOfhGyKmc1cGwopTsR07vuU5roQMKrap2+cPIf7TWGEdKYcbjElQQN7ZuPIaSXfRObQioB73XQYtSbSOxMl3tDVRYESaHRAIFGZUjGAtjVNHBFyY0S9Ors8YWgEfWP0zJizVjGzA1rmd5ZiquojbT+dQ+zDBcMme5crDiWj6sQSsiUhSnRgmH3TjKJfwRY5fmRwgcfdK8deGt1P9oMGQnVPAbr5sk9lOua58sg0dDC+996M+11n1dNIuaRi0CSQ7UCcx7vXOq+NWlhO6MNQJph+ZkfrqRmxvFdAhNZbPzdDzTHoqwFT2FgGHPPcx6styXHbT/Mj8971ZqYoEyC2iFE4FOihUP1zleaoO/tUeahXxgoedj6aFqGgGJ/VyQbsob6R8ld6dO4cDzjsDA++VZw89hiR36vK7jaSoxAqTTf8kAzhmvzY1/YYP7T1cLDViDVQ14jOLRK+HNdTqPwm2UOC1grCodQUIMEKBLiFEa5VDGmZVXBtcC1UsNPrVUkbgQWjPt1py3+B7giCuEjIvFmqjWlrP1b9LiOZJDh8b0fUR5fV3PdrkCWBHGSG8G9rDEUWWeK/sA1c0Q3812Eh+Zc5BEfWNMQblN/tPZqoxosh4kEzqve6M7lbcB4Wh3eto6H1gLlUTQ4OOylR8V50uJ5Qpdbn3eLs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<34.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.0.4
Release Details
UpdatedApril 14, 2026, 5:17 p.m.
Changelog

Fixed

  • Cannot remove room from group: Moving a room to "No group" had no effect because the controller filtered out null values, so the groupId was never cleared. Moving to a different group worked fine since that sent a non-null value
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureVfhXBtW86BgGXESdEUUnP6yMQPo9pDQPQ4+IE3wtVWiFJ4Oo7/ywooHI7+D2OcgKLRg/AaNlh8ARBO4SsWku4WnfaAaab0gkR1fwzE/SNLNakPMtejpAU2IaHVhRrKh5M2ivQo1lOrOPFOyBSK3nAFGn4+sjHC7sKLrAklBXn01FaqwRmjUDBs8CEp0aKCR7rSlF8A8OoCM4wD+9GPjUSJgfblrnkKkMl2RdCkDyCo71+c5uKs6GO5SC75rU3DoHVT0iFVa82W5IOaOsfa2CDg/pc9pG/mMmDaq8neXey56Ikr3fjziSPKV3eHPtGyVTeBHnsfQUmunJOwSbFylUrG0UwS+ISdkHob0M0dCLgYJErhL8ypv61UR9C1sjzlk4E+Cbk26ZzOY/jAMTjKrV/muD2B5Wr4YrCjtoRlxpyWNTL4TuYpSf8siB/6rOh5geLIuNjhWtw/XZyQ/ySfAMXi4lfE1XPUARrG9Mxupdvb0jOiphkIiX+c6Ohh6d4S9zVAd0aUO2LnWFQguU0VGdb6jT+mkK2aJyAWTszkZkvgCutOcx3NiO3OTy9MWlvuS4ERvxkKMqT1QxX3ZiDIjMtjmWwye12LgzWOuN1z7xuyVob2hxR/lgwyArsgyiOVW4NwzC2N8TG1Cg8liosAt2TPr+geIexMC5eUNNrNkvbNY=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<34.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.0.3
Release Details
UpdatedApril 14, 2026, 3:39 p.m.
Changelog

Fixed

  • Room visibility not updating after permission changes: Changing permissions on a room or room group did not trigger a sync of Nextcloud's room cache, so rooms remained visible (or hidden) in the Room Finder until a different room update triggered the sync
  • No email notification on permission-denied bookings: When a user without permission tried to book a room, the booking was silently declined with no feedback other than a small warning icon in the calendar. Now a "Booking not permitted" email is sent to the organizer explaining they lack permission
  • Declined booking not cleaned up in organizer's calendar: When a booking was automatically declined (e.g. due to permissions), the room attendee and LOCATION remained in the organizer's event. Now the room attendee is removed and LOCATION is cleared for all automatic declines, matching the existing behavior for manager declines

Improved

  • Permission Editor shows inherited group permissions: When editing permissions for a room in a group, the editor now displays inherited group permissions as read-only entries with an "inherited" badge alongside the editable room-specific permissions
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureadwNoCn/+c8cghGCzvBJY9MO5EeEHsOdwJOnzpT57cBHz93EEA54EKL48xatgapWRuMzV2/1fS9KrK9mJHF4MO6Csv04z+tGcZ9nORhhXsKeg3G4vpyGTfcsoS0f1+M5W4Uf4iFztZUs76UDq8mrEHzpIwmGZoQL5v1VwvqqxYR6XS575qtKgAA+0r7ODHZUUFd/ANSkGdGSDVqfIfaEGdVRsRsvDB+p0WKoAXh64WB2lznQJxGztkmqxttP7pw5pavnXyijBI2gANSaAW4wnj/JTypiNf3PvLxoxEK+SiJqMp4O1lu8v3o8cK3TjTDrKBlJVowIKwu3ymqHTVGJzQhEUBdFsSmHkGwp57ds0GSePPk/weBoDZ7uNN9Dj3piOeZWllOnrCXa/JgH3DfULt1FFoD9bgseXv80UTAa4rCsilDrUt064KO81ka0z+Mbp1yo9AXbXXI63pnBwhbhQZrdHEY1VtiXUZy74NA4F7uuXJvEfOg/hKNYoeRUDE8T6RVSdcnwjO049Bcjt4w4HU3qdQuIASna1c12Nffxj4twHVUqLFxOlzqLeRIQoWcOaDB+0M4OhA8WCwrMV9VcOkQiR44Gzb8fj0j/C7SAM+LIkLKACoHcJPSXAF0TZxjctDIjEQpLgW137TtvlQjBWpYCAguu4Nb0EcEsc4ZBhQw=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<34.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.0.2
Release Details
UpdatedApril 10, 2026, 11:04 a.m.
Changelog

Fixed

  • Manager role cannot accept/decline bookings: Non-admin users with the Manager role received "Failed to process response" because the booking API endpoints were missing the #[NoAdminRequired] attribute, causing Nextcloud's security middleware to block the request before the internal permission check could run
  • Group-level permissions not enforced at booking time: The scheduling plugin only checked room-level permissions, ignoring inherited group permissions. Rooms with group-only permission rules were bookable by anyone
  • Room creation loses fields: Creating a new room discarded Room number, Floor, Room type, and Address because the controller did not extract these fields from the request. Editing the room afterwards worked because the update endpoint did handle them (except Floor, which was also missing there)
  • Declined booking still shows "Reserved" in Room Finder: The previous fix (v1.0.0) propagated the decline to the organizer's calendar but kept the room as an attendee with PARTSTAT=DECLINED. The Room Finder only checked attendee presence, not status. Now the room attendee is removed entirely and LOCATION is cleared on decline. The frontend also treats DECLINED attendees as not added
  • Permission Editor UI inconsistency for grouped rooms: The group permission editor stated that individual rooms can have additional permissions, but the room editor was read-only for rooms in a group. The backend already supported merging room + group permissions; the UI now allows setting room-specific permissions
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureaGpq5T9hp9uBtS1HOt691u9gw559kx1tuwL7bj8C0oY74zgrGdWXsPI2MG/3E+0jRp5ZdlE3Lh5o/jA/dM51Xs9QTWicjAU2FviAYw8Zwkjz8qqgj3wspu4X+L3TlhZgEHgQnfq6NQ2229CZUCwu8CgOk6vjabVsTwXM0dbmMlz6cESP1+BHeJkoX2do6XbSXAS5efL9dxWunYnAlNlKCvLJMgtIKXV/IocXy7MPi2FV5yrHIpzkB7+nqJXNsoiWmPvGoatxVEhY86sMXbCQ1Qw9wOvQ0S0UkUYh5UUfubOk01BGzWxNN3mdMAYm8kkbbz5YXW7yOje1fhDJ9qYd8+8X0F4Jj1JxJ9HhYWbeY3Hitpqtdpz+rBPDfpMl5pIFDsFbohff67B4Er7HGT/x8vucha/hQS+G4YF4gvP6/uOi+MLstc7AUqLojoOMCGxpH8RFVPHFTA7jyHfF9xSjpsIGdC17z+jA8c3NURCQwldeqwCm3ltcGvGYfLZEWWGLEZk+jBSiKtJcH7R4y2SBBT8ZoT9xUPugBH3t2rj/4qXRhPILMbIq6P0E1H3JYS0iXJzVpPEb91POOGhBJARuppyEKkMaJY3GHBsK+c3soOcT95T5Ed1guO+pXLm3Pvz8/04BgaI5FeuE61J8MIp7Irz7mfyqVaVpqVi7Dpq8PIA=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<34.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.0.1
Release Details
UpdatedApril 9, 2026, 4:34 p.m.
Changelog

Added

  • Telemetry send button: Admins can now manually send a usage report from the Support tab, with clear feedback on success or failure
  • Telemetry toggle: Enable/disable anonymous usage statistics directly from the Support tab

Changed

  • App Store description: Removed evaluation disclaimer, cleaned up formatting, added VoxCloud as author
  • App Store metadata: Added office category and GitHub Discussions link

Fixed

  • Telemetry error feedback: The "Send report now" button now shows the actual server error message instead of a generic failure notice
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureOU/DKlkz4BJCi2XSSjawjaSgCbRFwY+GCEvqsVMd03KPm0oCFuvRuO3G0asw9l10vURGNh1rwcOhOuR3rLALvO7Kp7BetltAdruOJXdNFAgmyS4w2D3Q1yE055K3rHYV1rtQs7ewtj7GTFs2rkvFekh7vRWn018QpSepjrQbM0D8QmpEVC1GVRgeeh78AkFZn4jbub3d6lrV6JnlgvSah3Or+9gze65KyrI3txLngjPqxdaot6NSqnS0EHyFJGtR2/K7A/dnRd1yj/f0V9nSDzDQvNgDH5VgZtaRiJ/cLU4vxileuBmBMH0+X1c8oahkyx1ea+yTsyvLF5JWclmQ8YGm4fnJOlXItrgHCuAJzZWIOOkxwFk5C5joXAJ0xULKDkZqbwWKHEC3kS+Yj6wa5rYkBOZD2ovBbNsGX6kL/aTC/Il3UWkjY3b585rFWydzgUDw+kJDxstdDUV/UgWQ36J3JH5xyHPig0s4UGoEemttPCV7UTP5mhbI/jxXepoW4mWZs/OLxTuyOp+L6l5u5orcXz9rSaKe0Le40irQweqCped3IKiqqd0fLQz6o4pr29ZStrPPm/BGJSboFywzzQAdW6f3P88Ur8FaR2sgjb9j9SrTNOypINx4ePhA0dRbQTBYMCODcwNrsdCEt4sXzCnARz70rziNMOvup2zacb8=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<34.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 1.0.0
Release Details
UpdatedApril 9, 2026, 3:39 p.m.
Changelog

Added

  • Improved MS365 import: Extended column mapping for Street, PostalCode, device names (AudioDeviceName, VideoDeviceName, DisplayDeviceName → facilities), Nickname (→ description), and BookingType (Standard → auto-accept)
  • Exchange sync on import: New checkbox in MS365 import preview to automatically link imported rooms to their MS365 mailbox for bidirectional calendar sync
  • Show weekends toggle: New setting in Settings > General to show or hide weekends in the booking calendar (default: visible). Closes #3

Changed

  • MS365 export documentation: Replaced broken one-liner (Get-EXOMailbox | Get-Place | Export-Csv) with two options — a simple Get-Place export and a recommended full script that preserves email addresses by joining Get-EXOMailbox with Get-Place data
  • Permissions documentation: Added prominent clarification that RoomVox uses its own permission system, separate from Nextcloud Calendar's sharing permissions. Getting-started guide now emphasizes that permissions must be configured to restrict room access

Fixed

  • MS365 import missing email: The previously documented PowerShell command lost the email address because Get-Place returns a different object type than Get-EXOMailbox. Documentation now explains this and provides a correct export script
  • Declined bookings not updating organizer calendar: When a manager declined a booking via the RoomVox admin UI, the organizer's calendar still showed the room as "Reserved" (TENTATIVE). The respond flow now propagates the PARTSTAT change directly to the organizer's calendar event
  • No notification on booking accept/decline: Managers accepting or declining bookings via the admin UI did not send any email to the organizer. The respond flow now sends confirmation or decline emails using the existing mail infrastructure
  • Recurring events showing only first occurrence: The booking overview and personal approvals now expand recurring events (RRULE) into individual occurrences within the selected date range. Closes #2
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
Signatureiufjb3kzU1ga+jNcl/Gstr+rP+s1GEVt2r/dib2hjPoZBHm79v5hjS4iOVt2f4+OY0QLhSkDL8RhjqHqsis884IH5FEy/thZiFOllAfSxvRNKIFMZoUX8sPiZ+XCtIy0rT7H5Aja+67ElyOjbQyzsj4d4wqG8+JIT6AQveTF4lviv11i6ze3YWq+kNU8XZ0MisSbx/Bld0Q8hjJrTqqhNMxRaLHE8F5O2zeSUSWLHvvfv0LxZV6ZpQtVlPybB2JcZXh5WRdecgZU8F6sIU1Xz+DTRiV4anp5DsIAj1+cN//tuj/BA/clMiWEojdl+uTpd7c7+jUQj9jfztl8hEZwM5VlxRIc0yCrftFUHkTUl8iX2i6J55kw3pl52fLg06tdYxezu+axfxHToBLWKdpXxIX+f4kWkZF4+ia4VOMJ6KnDaO0T43wuILxjvjOltZqcOYbhRp35W4q8uVNRV2bN36zTO4vUvmevDVvKp1bO+h4km5+d5/lzXUwTNTh+xRbiewNQ/fkASZdMbJtqetS+5b6LMFNOMrZmKaa8a+Am44BzXSf/41Dwd1lbrN/2D1ytZ8HgM9Uh4fcX5Hfpf+U1qehiT2nMuAsIOXcl1fU/RkOodU6KYCs2lCSfcg+3+BdJQ3cPJaOC+ATzJqp2/yI98a59yBIx+um0Mryac6c6ysg=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<34.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 0.4.0
Release Details
UpdatedFeb. 20, 2026, 8:28 p.m.
Changelog

Added

  • Configurable Facilities: Admins can now add, edit, remove, and reorder facility options (projector, whiteboard, etc.) in the Settings tab — same UI pattern as room types
  • Personal Settings page: All users now see a "RoomVox" section under Settings > Personal with two tabs:
  • My Rooms — overview of rooms the user has access to, with role badges (Admin/Manager/Booker/Viewer)
  • Approvals — pending booking requests for rooms where the user is a manager, with accept/decline buttons
  • Slug-based duplicate detection during CSV import: rooms are matched by generated ID in addition to email and name

Changed

  • Updated App Store description with evaluation disclaimer and improved formatting
  • Added compatible calendar clients list to description
  • Approval notification emails now include a direct link to Personal Settings instead of referencing "admin panel"
  • CSV import now matches @roomvox.local emails for duplicate detection (previously excluded)

Fixed

  • Fixed facility ID mismatch between frontend and ImportExportService (videoconf vs video-conference, audio vs audio-system, etc.)
  • Fixed CSV import creating duplicate rooms when re-importing exported data with @roomvox.local emails
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureDcKMlKWNOecIXoF47OjlQwoPwEqdbtf38MYWmCwhPBNf56lSAy2v3z2j1kkzaaLCztiuuCW3obwRUp/0894rMulFGqFAAkwF1bkzzRz5Rl56QN/OoxjUpYC3APjbS0p29XOaZ64k/gSg4N/dGNUQOGZVvgclyGkb9530TT6UwDOxKWRGJpvC3W+0JixQwGVm2/yW/W8o/fyIjU+lOiq26jS8kjBpWHmNtdzqgiAbijMYdpguPNKWXqLzC29vqnDXhXDX1XuixkFddJ15lo1YHV1hwNcFdiHwuy4MerRRv3ckOmHHNOliMgUzN7SsNnxAXrH49KQpNbWIgkj3DWlXkclk8Fw3rretsZEvgrXbKC8b3zq+a/NK96sEcrQ5JdwyttojF/337kGEhKZc9Z4x9ivnG6w8cIVuY/xdG9680nA7NTeTGQe6bx+Ez+WaXq4IiXYi6ZokYJlk0taCRlCl4GmXjdRwe4JZHpwrg7tTu/K9ylpj4XlGcl3Pxz8KVpK1cX7EKqP/PgV4oFR8ZY5jhHHLkBlL2agbx3ziF0YJjn/D++isdjCaqa/Zr/rZf6WjQhWysfps6vVToSHpJJoODGPTjCYocWQij1hScwzEkS+oQHKg7xzfqHrBioJt6V5ExKSya37yXnIohYeqQzqPeXvwy8njL5cESLsaNZf3spE=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<34.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 0.3.1
Release Details
UpdatedFeb. 19, 2026, 12:40 p.m.
Changelog

Changed

  • Updated App Store description with evaluation disclaimer and improved formatting
  • Added compatible calendar clients list to description
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignatureB6xpwCS49tuWj8tpROVwrt9D+7BAPWC9EXxqV6nijSqXn4oKBZEao5nocPJo2BDYrq7xeD8YPg7JcB7ExBCSWMgSHabfb0FQP70lilP/QbQW9JmWbHAp67V33qLruzePhtJPSNgFe7oExzu3csWkmqZUovMMdJTymN3c+lmVVO/SMpFF+up2o2ERrZ0hxpCiipdzRhY9uIlta2WUuGdaHsSu6llKXjP8mMk7ZdY255ZxcTjO3PlTmtDUZE5k/N649XKaeSIo7Di/0DPEnf7AJz5v08OqmQVLbD3iOzwExDXA86ueGXik10k3iDb6fd0Yt91PZVtpEkWuWT0gCuwHegtgYgn5Ucg9ymsjACW9T2Lkn7lvSvBFCszegYztquD0oruLF3duHiBfmR4ChjWZ67ST+oUpj2NLVgjnz4aMblI1pgdvPRWkROK0mTx+YIVfNqApIz1u6bs37jZSJF+TfuFbVs/EoVaLyPOhMQjpVjhKNJqS9ygfONv3CBpF5mTNvDJ5jY76ii8E6/yFlIj1kFwQHk+6kqj+X2HWSDNy/83i3YTrgbvJ64dZOGZDXbM4VMgg79Hv50yBbqQtgv4Dv1cgZ0LVy43EkWmQFwPZrlAucc31qDW6FrhFsV0PCbJqRbPXO4z0TCA2QZSicoudVoeqJTU22ktWwi6kbiTob/E=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<34.0.0
Minimum Integer bits32
PHP>=8.2.0
RoomVox 0.3.0
Release Details
UpdatedFeb. 19, 2026, 12:32 p.m.
Changelog

Added

  • Public REST API (v1): Full API for external integrations (displays, kiosks, digital signage, Power Automate, custom apps)
  • GET /api/v1/rooms — List rooms with filters (active, type, capacity)
  • GET /api/v1/rooms/{id} — Room details
  • GET /api/v1/rooms/{id}/status — Real-time room status (free/busy/unavailable)
  • GET /api/v1/rooms/{id}/availability — Time slot availability for a given date
  • GET /api/v1/rooms/{id}/bookings — List bookings with date/status filters
  • POST /api/v1/rooms/{id}/bookings — Create bookings via API
  • DELETE /api/v1/rooms/{id}/bookings/{uid} — Cancel bookings via API
  • GET /api/v1/rooms/{id}/calendar.ics — iCalendar feed per room
  • GET /api/v1/statistics — Usage statistics and utilization data
  • API Token Authentication: Bearer token system for external API access
  • Token management UI in admin Settings tab
  • Three scopes: read, book, admin (hierarchical)
  • Optional room restrictions per token
  • Optional token expiry dates
  • SHA-256 hashed token storage
  • Automatic last-used tracking
  • CSV Import/Export: Bulk room management via CSV files
  • Export all rooms as CSV (13 columns)
  • Import from RoomVox CSV format
  • Import from MS365/Exchange format (auto-detected)
  • Preview before import with validation
  • Two import modes: create-only or create + update existing
  • Download sample CSV file
  • Internationalization: Added German (de) and French (fr) translations
Licenses AGPLv3+
Certificate-----BEGIN CERTIFICATE-----
MIIEAjCCAuoCAhL3MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwMjE5MTIwNTE4WhcNMzYwNTI3MTIwNTE4WjASMRAwDgYD
VQQDDAdyb29tdm94MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAttus
Y6YXBg6yUmVuMx4HBehu4N+amN4uYe1K9GSML5JlA0KuO0ehH4TzAXSan/EOJmys
UVKUrMhM7c26l1SzPJA7u68Mf3D90zb7FIyNrFSCeHDfk4aOTdNBHxic9HVf0c3k
mk3hQ1t9lQGsB4vtAVM+FMH4KTyd1fXeaz4jfxRpLVVoxOSp/XTXwKS26KrxiKs8
2lHi8Q1hxqUW9zLqXh7H50yr+AghiHuFu1xZ7Jh/E/1nNGs1dMVvGgse+4ZuPrSB
unbZ93R2tTI4ReJvaqQX/bdMKYto0GMyx0SbOW9eBcs8bRfj4yWNhEy+6aTNwha5
9kMKmW4OeblnzqMhu/wBcKPLcnFgshtn1OJvoXn3FDzSeJA7Oq9YxaNnadfbbl4g
9ux9Tn6FtFLfufnovxLlKxn9AO9lbmyWaU4HWpEatlCHxLfYyHAqF/cXFJSaPLaC
wlJkH9Ly/IQsilAh2XlPrIq40kjFzXT7NG0s2Ka7tyTH8ImKDLvi+QYldSvpy9cl
WTMzHKXEIrusaEdaR5E9Ne70EVHN0YVnSzR9q8oTbQtrprgN291iRmFbPHbrqkk7
D8vKY9JAdxl4eT2DrKWpvMpGr85bYLfPv4vQMOAG7fWEMSKLjUSLD9JtetP2SPBe
XrfdgaSWGZutqDSmNLF2P0OF/zCKuaUuUJO+OFUCAwEAATANBgkqhkiG9w0BAQsF
AAOCAQEAYgfaakYEY4Lj9B8rTjoVMFbEC4chnc6ZJjAu80bPfaBtAAFtOpIaNPbq
wNF+byNriPZ1YvsonMz2Jkrzcv7uY6TjbQfkjXcVl15sSZXFBIRmgVXHBFK5wpBv
Hv7AJIBupTSq3o2SCDDl9xtGTJntFUC9vmzyp8rqHaDq+0jL9roAifs7lrS31/kc
pD7IMwZuJg8yrzRmKDgDg6FP+e4twKoSMl7rsBh3R6Uxt1fdi5Toj4JcSdxAlVSc
iqw/KbOwYym7PAZUeAXyV6ZihGtKVT1645enA9rCkx3BWvRyTJiaETPCSvbNBN3G
NqmbhXeFXrsHeBbUXWnSbcm6D2jyMA==
-----END CERTIFICATE-----
SignaturefV4q5gfB1YN0APkHUrov/EMrhR186lJ1av7tJIRP9CHqyHlggaJ+plVholqsmauv4QylnZSpvWgtdv+A9F2EKZNyxGfZpRKqSIuj0mqrBckNnfLD/9lVQR00ZXZNapO8BZTtGDjfFgOMDq7U/GxO68entOXfUuPE4l+tVJp+ZtFlsBXj+1M5X/OW5OyXzg2NSrzAsDtMWdJGo4Bg+TdO/h3Rr+Ph9rd63Y9g1NxmqTToZ6xkL8bspJ0zuX5aRjyo4cR2xJAbGTl/Gd2+xuRlIZpzIFKEjUnqMYAjabbXPvPVgW3Y0Gs6zsn1+4mL56sHLiLcN+a3bbVy3saz5RYH9qfrTHRqPqcvUp+yF0OifJQ2JA2GzZW95f5Cr87O24ffRzYC4E+7Wxzn49tD7uyHCD0jJAbik/1uN4gELmue+QdfVoJbwJv160UDDEIBSqB7GYRJuPr5dOrTbOz80rhc564IORlJrsfifUgSo0JS37FA6L5jLws0ehM+t67nlFpwCageEiNPbe0E7B6LdDnxkztyNrvjiwl6pt1gRfNmPR8fFACn+v1B/6/rodw6QlNcdqCuseftY9duxdbrzq5MnEhn+PW3QjlOaTTIS6QsHk+zPxMxoknlsrMXkQl3SoBUaJcYCpRJjN8gulUDTl8kFihigbT7u7SVaDuKnDbhteY=
Signature digestsha512
Dependencies
Required Nextcloud versions >=32.0.0,<34.0.0
Minimum Integer bits32
PHP>=8.2.0