Skip to main content

Pulse - Releases

← App details

Nextcloud 35

Pulse 0.19.1
Release Details
UpdatedOct. 3, 2026, 1:58 a.m.
Changelog

Changed

  • The App Store description is easier to read: a short introduction, then polls, quizzes, presenting and notes under their own headings, with the features as lists. It now also mentions the self-paced quiz and that rooms nobody has used for 30 days are deleted automatically.
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEADCCAugCAhRCMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYxMDAyMTY1NjQ4WhcNMzcwMTA3MTY1NjQ4WjAQMQ4wDAYD
VQQDDAVwdWxzZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJ5l1XaC
d/PVhLzw8c/PihtpkhXOwqxeCqUa6TjWt5cfnT1o48S/2gTOb72VV+4FygVem9nw
augLTcdjyLVGq9KcA1rxZSYEChXWU7J3DkciwgsHW9MSvvXkpVPdUvIs9nRkko03
fJH2pjYKplppz7r4l2ysaMU3EcvBCapYEQhhdoX/PE+u03xpSz3b+pxx4zI8PgcT
t6qZrWoyJrjven7hZsNpJPruROGFU6DqIaMf8/6PYEozmGtyKgyMI7OkNrfSqyyi
5q5KJ6eli9HTouZcLJ2o0fGTSzNWbuBkeTb0BcZ/z7DriQ+FZq+XQbXoRPNNw5rS
S+E3qJGUjZMrFiMEbBIkhhM0IktzrI1jV7qJEOpGkDjGO4FgGQq6LkCxelxrmzIe
i5PG6raUs1rYfdp5rMOIwwuwK/w0jvJJlw5k0uMU6L4ZmISxd4WQC7a9VVEa6xq1
vM5iUsAyU2vFgTlymJjlibnv+JOIb5B3cxL3w3GBf3nvbD085gWq78LqoQP6XptZ
bFr13eUJnxtsQJVnISk0tlZZN1bFzMTcWuIcEjizKi0SjyL3INM3p/yDRK/T2dND
bLJSAnXWFljjjVff+SA50BeyNW63Cq/XO3Sh9QVca2OuI72wgFHy0q2iOk2PDrQF
kX4e7wygmj77Qv0g1GX9L7BYQaq/FjhmVbEXAgMBAAEwDQYJKoZIhvcNAQELBQAD
ggEBABlaqxeemLw+NHFW1NiBcjTwK2DMm+9Ib3xemp3Ig8MSFFl0xVLgFKEq6U6j
zAz6pkQ1b2Vb3OhWe/Ea6MTtK2pou56RBNXNtX+rIMlp/zHAYrc42Pr/rUwWiRER
+plP+80WJt4BAZ/VJvBvMaFgPaIhYAcnsyeCUtZXrSR/o5T0J+1ndfSiROmrTijf
TO7JGnD48aWYjs7DZG04Fl+YgUDnE5qXC0gyTQH3Y3Y4Vp6ukpMX4uOqDgQaeJmI
+8PJEROynqa5gIwQbjEvBWoPWX2dOonlHpUtGYqyD+56wqWuk64r7vmsbw5aUHlI
udu2qH/h5dinttwIChQfxGcwgyU=
-----END CERTIFICATE-----
SignaturegaIzYS6SxmZWUgQOM2e0b47fZgLCkTT7rmEnr8r8uWzoMri3tcrFnHQiY2LIr2ff
NDGyaWl1Tyv3MsUiLZjujjUWpDrhI1UAAjxYZVY5mH4VcHfNTJOW9BnNgzii0jwk
tUAAZuuFuzBiOOJ9CMfrUFx8dhDVjS8snX/7AYsCt7VEueTSZPODsDnSW77tH9WR
KYUCqGa+1dYJ5NH3P+AICat4ay4+O6O9HrgO3F9mb01mt4RAnmSTv+wWfgEb4T1C
vHS06ysgOo2Ha0PsBeOSX+FglTSwpqBiyuYISNbOJ0g2ahF+TOGaHFCKIK7NTEFt
PrNd0bDoVy469BSp4gH977GbNNlYVIxQ4dUbGCc63JbieAAEUfuyCEk9nnWgtaeq
us41a+r2Nr4Xsf+KwiT7zefWkt3NqrUxhthvcWyJR4gqEQMD0Ig5key0+Ks6gKV/
6XLNKyadA2ld4iqG9hOUH7bv6pDXYJQe34I7BQmnt5Wpq8LxNME032Qi8xIJn5+P
j+ekmfkNgecP4Vfjxv8Y06hMuWD7OO5h8HYR+jZ3eiejII/JEa3gZ3siaguZ9zBP
lznJnqcQjTjUtOBJad5WtERUrVPT3QbgH+nEgVsMAc7jgIf4grrem/th3OOzRpM1
kk07BVoKnEdCBYEb6qjcrkZ8bMeR47fv9Xe9dWDYxj0=
Signature digestsha512
Dependencies
Required Nextcloud versions >=34.0.0,<36.0.0
Minimum Integer bits32
Pulse 0.19.0
Release Details
UpdatedOct. 3, 2026, 12:35 a.m.
Changelog

Security

Found in a security review of the code by AI agents in September 2026 (see the README's AI disclosure), most important first. What is still open is described under "Security notes" and "Known limits" in the README.

  • Wrong room codes no longer lock a school or a venue out of Pulse. After ten wrong codes from one address within 30 minutes, Nextcloud's brute-force protection answered every participant and projector request from that address with "Too many requests" for 30 minutes — valid codes included, on every phone and the projector behind the same school or conference network; only an admin could lift it earlier. Typos in the join form were enough, so was a room deleted while a dozen phones still polled it, and so was any web page with an image pointing at a made-up code; the join form then said "That code does not exist." Now only unknown codes count, and only unknown codes are refused: an existing room always opens. Requests from an address that is already blocked are not counted, so phones still polling a deleted room no longer keep the block alive for as long as they are open.
  • Scripted ballot stuffing can no longer slow down the whole Nextcloud. A script that votes or joins without a cookie could add thousands of votes, players or presence entries per minute, and every one of them made each phone and the projector download the complete results again — at 60,000 votes 2.4 MB and half a second of server time per poll, on the web server all of Nextcloud shares. Now:

    • phones and the projector get capped results: the top 100 words or free-text groups, at most 500 compass points (a fair sample; the total and the centre stay exact) and the first ten rows of the leaderboard plus your own place and the people around you, each with the full count — the projector says how many more there are. A word cloud with 60,000 words now costs under 4 KB instead of 2.2 MB. The moderator's results, the summary and the CSV export stay complete;
    • "nothing has changed" is answered without reading any votes (a change marker in Nextcloud's memory cache);
    • new identities without a cookie are limited to 300 per address and room in ten minutes, and a phone counts as present from its second poll, when its cookie comes back; made-up cookies add at most 600 presence entries per address and room in ten minutes;
    • a moderated quiz takes at most 600 players (max_players_per_room in the app config changes that).

    Voting again under new identities stays possible; the README's security notes explain what remains.

  • A word-cloud vote carrying a huge list of words no longer ties up the server. A 16 MB request kept a PHP worker busy for more than eleven seconds, because every entry was cleaned up before the list was cut to the allowed number. A list longer than twice the allowed number of words (at least 20) is now refused with "Invalid words.", each word is cut to 200 characters first, and free-text answers and nicknames are shortened before they are checked.

  • One account can no longer fill the server's disk. Question images are stored in Nextcloud's app data, outside every user quota, and Pulse re-encodes them — a 1.4 MB image could become an 8.6 MB PNG — so three copies of a room with images wrote 821 MB in a second and a half. Rooms, questions and question texts had no limits either. Now each account has an image budget of 200 MB, at most 200 rooms, 100 questions per room and 1000 characters per question; creating and copying rooms, adding questions, uploading images and demo votes are limited per minute; answer options are cut to 200 characters, and a free-text question keeps at most 50 accepted answers. A copy is checked against the caps before anything is written and removed again if it still fails halfway (such a failure used to be an internal server error). Requests sent at the same moment count again after writing and take their own write back when the account ended up over a cap, so a burst of copies can no longer store more than the budget. All values can be changed per instance in the app config — keys and defaults in the README under "Limits". Creating or copying a room shows the server's reason when it fails.
  • Rooms of deleted accounts no longer pass to a new account with the same user ID. An account deleted while Pulse was disabled — as earlier versions were after an update to Nextcloud 35 — left its rooms behind, and whoever later got the same user ID, for example through a login provider, owned them with all answers, nicknames and exports. The daily job now deletes the rooms of every owner that no user backend knows any more and that left no login record behind; the second condition keeps the rooms of real people while their LDAP or OIDC backend is merely switched off. And participants' polling keeps a room alive only until 180 days after its owner last used it, so a phone left open no longer defeats the 30-day retention.
  • The voter cookie can no longer be planted from a sibling subdomain. Another service under the same domain could set a pulse_vt cookie with a token it knew; browsers sent it along to Pulse, and with it that service could read a participant's own answers, free text included, and vote or rename in their name — in every room, for a year. On https with Nextcloud at the root of its domain the cookie is now called __Host-pulse_vt, which browsers accept only from Nextcloud's own origin, and a request that sends a cookie name twice counts as having none — except a name such as _.Host-pulse_vt, which PHP itself drops and which therefore cannot cost anyone their cookie. An existing pulse_vt is taken over during the first 60 days after the update, so a homework that is running keeps its players; after that it is ignored. Under http or a sub-path the name stays pulse_vt.
  • Votes are accepted only from Pulse's own page. Joining, voting and "Next question" need no request token — participants have no Nextcloud session — so any web site a participant opened could post to them: a hidden form could replace the participant's cookie, leaving their quiz points under an orphaned name and restarting a self-paced quiz, and a sibling subdomain could vote or rename in their name. These requests now need the header the page's own script sends (X-Requested-With: XMLHttpRequest, or Sec-Fetch-Site: same-origin); anything else gets 403 and no cookie.
  • The development tree is no longer public when Pulse runs from a git checkout inside the web root. A shipped .htaccess makes Apache answer 404 for node_modules/ — whose demo pages include one that can be made to run script on Nextcloud's origin —, the screenshot harness, sources, tests, build files, .git/ and local _*.php scripts. The README no longer tells people to clone into apps/: it installs the release archive, or the runtime folders, built outside the web root.
  • Hosts of a moderated quiz can remove players and lock joining. Anyone with the code could put a name on the podium, and a player could rename themselves after answering — even after the final standings — into something abusive or into somebody else's name; the only remedy was resetting the whole room. Now the "Only for you" panel and the standings have a "Participants" list with "Remove from the quiz" (the player's answers go too; they can join again from zero points), the menus have "Lock joining" (the header then shows "Joining locked"), a name is frozen once its player has answered or a question has ended, and two phones that join at the same moment under the same name no longer both get it.
  • Lookalike names are refused. A fullwidth "Anna", a Greek "Αnna" or a Cyrillic "Аnna" was accepted next to "Anna", so somebody could pass as another player on the projector, in the progress view and in the CSV a teacher grades by. Names are now compared with lookalike letters folded, and with PHP's intl extension also against pairs such as "PauI" and "Paul"; characters that browsers draw as nothing are ignored, including the ones Unicode has reserved but not assigned yet, and another spelling of one's own name is checked like a new name. Now and then a genuine name close to a taken one is refused; adding a letter helps.
  • The moderator API no longer tells other accounts which room codes exist. Someone else's room answered "403 No access to this room." and an unknown code "404", without any rate limit, so any account could search for live rooms at hundreds of guesses per second. Both now answer "404 Room not found.".
  • A self-paced quiz can no longer be filled up by a script. Joining without ever starting took one of the 300 places, and the limit of 120 join requests per address and room let one person behind a school's NAT use up the whole class's budget. Now only players who have started count towards the 300; up to 600 can join, and at that ceiling people who joined more than ten minutes ago and never started make room while the quiz is open. What is limited per address is new names — 120 per room in ten minutes, as many as the old request limit let in — and not requests: a taken name, a retry or a player coming back costs nothing. The request limit stays as a mere flood guard of 2,400 per address and room in ten minutes, now in moderated quizzes too. An instance that runs larger events raises the ceiling and the count per address in the app config (max_players_per_room, max_new_players_per_address).
  • Images uploaded to the same question at the same moment no longer leave files behind that nothing deletes — not deleting the room, not the daily job, not deleting the account. The upload that loses now gets "The image was changed at the same time elsewhere. Please try again." and its file is removed, removing an image no longer undoes an upload that arrives at the same moment, and the daily job sweeps image files no question refers to (once they are an hour old). A room that cannot be deleted no longer stops the clean-up of all the others.
  • The PowerPoint add-in asks only for the lowest permission level, "Restricted", instead of "ReadWriteDocument": it just keeps the room code in the document settings. Script that got into the embedded page could otherwise have read or rewritten the whole presentation. Download the manifest again (office-addin/README.md).
  • The add-in shell frames a saved room code only if it is six letters and digits. A code of .. from a shared .pptx or a link framed Pulse's moderator page or the Nextcloud login inside the slide; anything that is not a room code now opens the code form.
  • Voter tokens, nicknames and answers no longer appear in exception traces in nextcloud.log: the parameters that carry them are marked #[\SensitiveParameter].
  • Release signing (build/package.sh, for developers) no longer puts the private key into the production container. It signs in a disposable container without network, created from a Nextcloud image and removed with the key right afterwards; CONTAINER=<name> is the explicit opt-in to sign inside a running container.
  • CI checks that the committed bundles in js/ are exactly what the sources build to (Node.js 22.18.0, npm ci), so a change hidden in minified code cannot pass review unnoticed, and the GitHub Actions it uses are pinned to commits.
  • The README and the App Store description no longer claim that the voter cookie "prevents" double voting: it discourages it, and whoever clears their cookies can vote again. The README's security notes now say what is protected and what is not — ballot stuffing, names on the podium, scouting a self-paced quiz (for anything graded: feedback "At the end"), the framing exemption of the projector view and the add-in shell, and office.js in the Nextcloud origin (test the add-in address in a private window). A new SECURITY.md says how to report a vulnerability.

Added

  • Every instance hands out its own PowerPoint add-in manifest, at /apps/pulse/addin/manifest.xml and from the deck's overflow menu. An Office manifest cannot hold variables — <AppDomain> and <SourceLocation> have to be absolute URLs — so a shipped file needed a hand edit in two places on every installation, and forgetting it pointed the add-in at somebody else's Nextcloud with no error message anywhere.
  • Setup check "Pulse: embedding in PowerPoint" under Administration → Overview. It fetches the embed page under every address the server can reach itself on and reports whether X-Frame-Options still blocks framing, listing blocked and working addresses separately — a proxy rule that covers the internal host but not the public one now shows up instead of quietly breaking the add-in on the road. The header cannot be dropped from inside the app on Apache, so the check points at the web server rather than pretending to fix it.
  • Self-paced quiz. A quiz room can now run at its own pace instead of following the presenter: tick "Self-paced" in the deck's menu, and everybody works through the questions alone on their own phone, with a clock for each question that starts only when they open it. Switching clears the players and answers collected so far and asks first if there are any; the questions stay. Instead of presenting, the presenter opens the quiz with "Open quiz …" and closes it later. Without a deadline it is a race: by default with a timer and a verdict after every question, and closing it releases the results. With a deadline one minute to 30 days ahead it is homework: by default without a timer and with the verdict only after the release, and the deadline closes the quiz with nobody around. Both defaults can be changed when opening; a practice run always gives the verdict at once and never shows a leaderboard. Moderated quizzes work as before, apart from the fixes listed below.
    • While the quiz is open, the presenter follows everyone on a progress page: how far each person got, their answers, points and last activity, the join code with its QR code, a preview of the projector, and one main button that names the next step — close the quiz, check free-text answers, release the results. Free-text answers are marked right or wrong there without the list of accepted answers on screen, and a slip can be undone under "Checked just now". A race can also be stopped without releasing the results, to check answers first. The end can be moved, a closed quiz reopened, joining locked and single players removed; participants and answers download as CSV. With the verdict at the end, points stay hidden on this page until the presenter shows them.
    • Phones go from name to start card to question to verdict. "Next question" appears once the answer is final — a few seconds, which cost no points — so the verdict is never skipped by accident. Questions without a timer can be skipped, the position and the deadline stay in view, and a phone that is reloaded carries on where it was.
    • The projector never shows a question. While the quiz is open it shows the race — how many people are on each question and how many have finished — with a large join code for the first two minutes and afterwards, when verdicts come after every question, the top eight of the leaderboard. A closed quiz shows only the count, a released one the final standings.
    • The question order is frozen when the quiz opens, and the deck stays locked until the room is reset. An answer counts once its correction window is over or it can no longer be changed, and phone, projector, progress page, leaderboard and CSV all count the same answers. Before the release, phones show no solution, distribution or leaderboard. Joining ends when the quiz closes; a room takes at most 300 players who have started and 600 who have joined, and at most 120 new names per address in ten minutes (see Security).
    • All of it works through the API as well: POST /api/1.0/rooms/{code}/pace switches the pace and opens, closes (with release: false without releasing the results, whatever the deadline), extends or releases the quiz, GET /api/1.0/rooms/{code}/progress follows everyone, POST /s/{code}/next moves a phone on, and the CSV export takes ?view=players and ?view=answers.
  • An AI disclosure. Pulse is vibe-coded: its code, tests, development tools, documentation and German translation were written by AI coding agents (Anthropic's Claude Code), and there has been no independent human code review and no security audit. The README now says so in a notice right under the title and in a section "How this app was built (AI disclosure)" with the models, the commit counts and what the tests can and cannot vouch for; the App Store description carries a short version in English and German.

Changed

  • Pulse now supports Nextcloud 35 as well as 34 (max-version 35). It was tested on Nextcloud 35.0.1 with SQLite, MariaDB, PostgreSQL and MySQL, and through a server update from 34.0.4 to 35.0.1 with existing rooms and votes (PostgreSQL). Earlier versions supported Nextcloud 34 at most, so a server update to 35 switched them off.
  • Documentation and code comments are in English now. The READMEs, the App Store guide and the comments in PHP, JavaScript, Vue, CSS, shell and configuration files used to be mostly German, and so were the messages of the release scripts, the CI step names and the package.json description. The German translation of the interface (l10n/) and the German store description stay German on purpose, and so does the test data that checks Unicode, case folding and the CSV export. Still German, for a later round: German inside the code itself — other test data, the JavaScript unit test, the messages of the test runner and of the translation and development scripts, the seed words of the demo mode, the comments inside the add-in manifest template and inside the browser scripts of the screenshot harness.
  • The README was brought up to date for a public audience: installation from the repository, a section on security notes, the adaptive polling intervals instead of a fixed 2.5 s, the databases Pulse was tested on, and the App Store status. It no longer says that info.xml advertises Nextcloud 29 and later.
  • The add-in manifest is no longer German-only: source locale en-US with a German override, like the rest of the app. Its <Version> now comes from info.xml, so PowerPoint recognises an updated add-in.
  • The Traefik snippet next to it carries nextcloud.example.com instead of one specific server.
  • "Show final standings" at the end of a quiz, and the automatic advance after the last question, now end the quiz for the whole room: projector and phones switch to the final standings together with the moderator. With reveal per question they used to appear on the moderator's screen only. If ending the quiz fails, the moderator stays on the question and sees an error instead of standings nobody else has.
  • Standings opened from the menu in the middle of a quiz are called "Leaderboard"; "Final standings" is reserved for the end. From there, Next and Back take the moderator back to presenting along with the room, and on the final standings Back is disabled. Opened with no question running, the standings offer "Back to the deck" instead of "Finish quiz".
  • A practice run with "Reveal at the end" can now reveal its last question: the main button reads "Reveal" (still without a leaderboard, as always in practice), then "Finish" sends the room back to the lobby. It used to go straight to the lobby, so nothing was ever revealed. A practice run revealed per question no longer drops the moderator back to the deck on its own after the last question.
  • Nicknames are unique within a room. A name already taken — also in different case, or with invisible characters or extra spaces — is refused with "This name is already taken. Please choose another one.", so the leaderboard no longer shows two identical rows. Players can keep their own name and change it until they start answering (lookalike letters and the rename freeze: see Security). Invisible characters are stripped from names, and a name made only of them is refused.
  • info.xml gives the licence as AGPL-3.0-or-later instead of agpl. The store schema still accepts the short form but lists it as deprecated, and for apps targeting Nextcloud 31 and later the store's guide asks for an SPDX identifier. package.json names the licence now as well.
  • The repository moved from hotochan123/hotochan123-nextcloud-pulse to hotochan123/nextcloud-pulse. info.xml (website, issue tracker, screenshots), the add-in manifest's support link, the setup check's link to the add-in guide and the documentation point to the new address; GitHub redirects the old one.
  • The store description and the README describe Pulse as a self-hosted alternative to services such as Kahoot!, Mentimeter or Slido and state that Pulse is not affiliated with their providers. Code comments no longer name other products, and the README credits the four icons taken from or adapted from Feather Icons and includes their MIT licence text.

Fixed

  • On SQLite, a class joining a quiz at the same moment no longer gets "Joining failed." on up to half of the phones. The room lock began there as a plain read, and a transaction that a parallel one had overtaken could not write any more ("database is locked") — the database's busy timeout does not wait in that case. The lock now takes the write lock first, so the joins queue up. The same lock guards correcting a free-text answer in a self-paced quiz and the host's actions on it (opening, closing, locking joining, removing a player, grading).
  • The join panel no longer reopens by itself while presenting. It used to open whenever nobody was connected yet, and that decision was taken again on every results poll — every 1.2 s in a quiz — so closing it with ×, a click beside it or Escape had no effect for longer than one tick. In a room nobody had joined yet it could not be closed at all. The panel is now only ever opened by the "Join" button; the room code stays visible in the header and on the projector either way.
  • The framing rules now also cover /index.php/apps/pulse/embed and /index.php/apps/pulse/screen/…. Without htaccess.IgnoreFrontController Nextcloud builds its URLs with /index.php in front, so a rule that only knew the short form never applied — the same page came back without the header under one address and with it under the other. Affects the shipped Traefik file and the Apache/nginx snippets in the add-in README.
  • The setup check asked the router for the embed path and got an empty string when the app routes were not loaded, then dutifully measured / instead — which carries X-Frame-Options quite rightly, so the check reported "blocked" for every instance. It now uses the fixed path, which also keeps the result identical between occ setupchecks and the admin overview.
  • Quiz answers no longer leak before the reveal:
    • The change marker phones and the projector poll with contained checksums of the answer key and of all votes, which could be tested against candidate answers. It is now a keyed hash that says nothing about the content.
    • Ranking and matching questions went out in their stored order, which is the solution — on the projector and through the API. Until the reveal they are now shuffled, the same way for everyone and independent of the solution.
    • "See all results" on the phone listed the whole deck, including questions not shown yet — in a quiz with their answer options. It now lists only questions that have been shown.
    • Public leaderboards counted questions that were not revealed yet, such as one the moderator skipped without revealing, so a jump in points told a player whether the answer was right. Hidden questions now stay out until the quiz is finished; the final standings count everything and match on phone, projector and moderator screen.
    • A "Reveal at the end" quiz run a second time without a reset still carried the first run's end, and "See all results" gave away every solution from the first question on. Showing a question now clears the old run's end.
    • An edited question that had already been revealed stayed revealed, so its new solution showed up in "See all results" at once. A question edited while it is not on screen now counts as not shown yet, unless a finished quiz ended on it.
  • An answer sent just as the moderator moved on is refused with "This question is closed." instead of being counted for the next question, where a number, a word or a scale value often fits just as well.
  • Open phones and the projector now pick up changes they used to miss: switching "Reveal at the end" after a reveal, editing a running poll question nobody had answered yet (every vote on it failed afterwards), renaming the room, and resetting it or toggling the practice run while everyone waits in the lobby (phones kept greeting players whose names had just been deleted). A question that is closed but not revealed yet shows as "Answers closed" on the projector instead of a result view without results.
  • The projector now fits the first quiz question to the screen. Its size was only recalculated when results arrived, and a quiz sends none before the reveal. An edited running question with a longer text is refitted as well.
  • Word clouds count each word once per person. "Coffee" and "COFFEE" from one person counted twice and used up two of the allowed words; invisible characters, non-breaking spaces, double spaces and emoji variants no longer make a second word either. The cloud shows the first spelling, in lower case as before, and votes given before this change are counted the same way.
  • Phones: in a poll, "Your answer" now appears for every question type once results are up — word clouds, rankings, matchings and spectrum or compass scales used to read "Did not answer this round." After a reload, multiple-choice, number and free-text questions show the answer given instead of an empty, locked field. A status update that overtook a vote no longer resets the selection and the correction window. When the running question is edited, phones drop the old selection, and once their answer has been cleared they get a fresh correction window.
  • Open phone and projector pages now reload themselves after an app update that changes how page and server talk to each other. A tab kept running the script it was opened with, even after the server behind it had moved on, until somebody reloaded it by hand. /state now carries a protocol number that goes up whenever server and page no longer fit together; a page that sees a different number than the one it was built with reloads once — at most once per tab and protocol, so a stubborn cache cannot turn it into a reload loop. Where the browser refuses session storage, as some do inside the PowerPoint add-in's frame, the page carries on without reloading rather than risk that loop. The number is also part of every state version, so an outdated page gets one full state instead of an endless run of "unchanged" replies. Pages opened before this version do not know the number yet and pick up the new scripts on their next reload, as before.
  • Word clouds and grouped free-text answers show the first spelling that came in. Votes were read without a defined order, and PostgreSQL returns rows in storage order, which differs from the order of arrival once new votes fill the space of deleted ones.
  • "Export CSV" on the summary page delivers the file again. The link carried no request token, so Nextcloud answered with "412 Precondition Failed" instead of the CSV.
  • German phones labelled the button that changes an answer "Wandel" instead of "Ändern": the English "Change" was also a word in the word-cloud demo, and that translation won. The demo word is now "Transformation" in English and still "Wandel" in German. The practice-run banner in the deck said "Übungslauf", while everything else in German says "Probelauf"; now it says "Probelauf" as well.
  • When resetting the room, switching "Reveal at the end" or the practice run, saving the question order or deleting a question fails, the error message now gives the server's reason instead of a general "Could not …".
  • Joining a quiz no longer throws the phone back to the name screen for a moment. A status update that had set off before the name was sent could arrive after the join and still report no name; it is now discarded.
  • Requests that send a value as a list or an object where text or a number is expected (for example action[]=close), a number the server cannot hold (1e999), text that is not valid UTF-8, or a participant cookie the server never issued no longer write "Array to string conversion" or similar warnings to the Nextcloud log, and no longer fail with an internal server error. Such values count as missing: the request gets the usual message with status 400, or the default applies. A deadline, a question pointer or a switch of the self-paced quiz that cannot be read is refused instead of being taken as "none".
  • The results export (CSV) of a quiz with a free-text question no longer fails with an internal server error. Free-text answers get one row per group of equal answers, as on the grading screen, and number guesses show the number instead of an empty answer column. Free-text answers and words from the audience that start like a spreadsheet formula get an apostrophe in front, as in the self-paced export, and quotation marks inside a cell are doubled the way spreadsheets expect.
  • Two votes sent at the same moment from the same phone in a poll — a double tap, or a retry after a network hiccup — no longer end in an internal server error. The later one counts, as when a vote is changed.
  • The daily clean-up no longer deletes decks their owner is still working on. A moderated room created more than 30 days ago that no audience had joined in those 30 days was deleted, even if the owner had edited it the day before: only participants kept such a room alive. Now whatever the owner does with a room counts as well, in every room mode — opening it, editing the deck or its settings, presenting, looking at the results or the progress — so a room goes only after 30 days in which neither the owner nor a participant used it. The owner's activity is recorded at most once an hour and changes nothing anyone sees. It is recorded from this version on: on an installation where the clean-up already ran, a room its owner has not opened since the update is still judged by its participants alone, as before.
  • Rooms of a deleted Nextcloud account no longer stay behind. They were left with nobody to manage them, still reachable under their public codes, and a room the audience kept using was never cleaned up at all. Deleting an account now deletes its rooms together with their questions, votes, players, progress and images, and their codes stop working.
  • New installations now register the clean-up job. It was only added by a migration step, and Nextcloud skips those steps when it installs an app for the first time, so rooms there were never deleted. The job is now declared in info.xml, which Nextcloud reads on every install and update. An installation that started out on an earlier version without the job gets it with this update. Its existing rooms count as used on the day of the update, so the job deletes none of them in the first 30 days — not even a deck its owner edited just before the update, which the job has no record of.
  • Deleting a room — with the delete button, by the daily clean-up or with its owner's account — no longer leaves its questions, votes, players or progress behind when the database fails halfway, for example on a deadlock with a vote arriving at the same moment. The rows now go in one transaction, which is retried after a deadlock; a deletion that still fails leaves the room complete instead of half deleted.
  • On MySQL, adding a word cloud, a number question or a free-text question no longer fails with an internal server error, and neither does duplicating a room that contains one. MySQL cannot keep the default value of a text column, so a new question has to write its empty option list itself, and these three types left it out. A duplicate that failed this way left an incomplete "(copy)" room behind, which can simply be deleted. MariaDB, PostgreSQL and SQLite were not affected. No migration is needed: existing MySQL installations work as soon as they run this version.
  • Release packaging (build/package.sh, for developers): signing works. It failed every time and then left the private key in the Nextcloud container's /tmp; it now signs in a disposable container that is removed, key included, on every exit (see Security). Archive entries are 755/644 and owned by 0:0 instead of world-writable, info.xml is checked against the store's current schema, and packing stops when info.xml, package.json and CHANGELOG.md disagree about the version (ALLOW_UNRELEASED=1 packs a test archive, as CI does). A pre-release such as 0.19.0-beta.1 needs its notes under [Unreleased], where the store looks for them.
  • Moving a question with the keyboard ("Move up" / "Move down" in its row menu) keeps the focus on that question. The focus landed on the neighbour it had just swapped places with, so pressing again moved the neighbour back instead.
  • The question editor stops labels at 40 characters, answer options at 200 and match pairs and accepted answers at 100 — the lengths the server keeps. Longer text used to be cut on saving without a word. The compass field for the heat-map threshold now also goes up to 9999 with its arrows, the value saving always accepted.
  • On the projector, the four corner labels of a compass question sat upside down: the two top labels were drawn at the bottom and the other way round, each next to answers it did not describe. They now sit in the corners the editor and the phone show them in.
  • Word clouds take words of up to 40 characters from the phone, as the server always kept them. The phone stopped at 24, which cut long compounds such as "Verantwortungsbewusstsein". On the projector a word too wide for the cloud is now shrunk until it fits instead of being clipped on both sides, and on phones and in the moderator view long words wrap inside their box.
  • On the phone, moving an item of a ranking question down with its arrow button keeps the keyboard focus on that item. The focus fell back to the top of the page, so a keyboard user had to find the list again after every step.
  • API: editing a question, uploading its image and reordering the deck answer 404 "Question not found." (or "This question does not belong to this room.") when the question no longer exists or belongs to another room, like every other question action, instead of 400. Grading a free-text answer stays at 400, which the run view relies on.
  • When a new order of the deck cannot be saved, the deck goes back to the order the server kept (as soon as Pulse reaches the server again), and the keyboard focus stays on the question that was moved. The unsaved order used to stay on screen next to the error message, and the next move that did save took it along. If a question had been deleted in another tab, every later move failed until the page was reloaded.
  • Self-paced quiz: the dialog for opening the quiz, reopening it or changing its end accepts a deadline just over a minute away, as its message says. A deadline 90 seconds ahead used to be refused with that very message, and the date picker could offer such a refused minute.
  • Long compass corner labels no longer run across the axis into the opposite corner. On the projector and in the phone and moderator results each label stays in its quadrant and wraps onto at most two lines, ending in "…" only when it is longer still (the moderator sees the full label on hover). Short labels look as before.
  • Self-paced quiz embedded in PowerPoint: after the first two minutes, when the leaderboard appears next to the race, the slide shows as many leaders as fit — at least three — instead of cutting off the last two rows in the middle. The embed frame is lower than a projector at 1280 × 720, and the race with eight leaders did not fit even at the smallest text size. The projector itself looks as before.
  • Self-paced quiz embedded in PowerPoint: when the race has more rows than the embed frame holds — more than six questions while some people have not started, or a long quiz in two columns or groups — the questions move into two columns or larger groups ("Questions 1–4") instead of losing their bottom rows, "Finished" among them. On the projector itself nothing changes. A last group of a single question now reads "Question 22" instead of "Questions 22–22".
  • On the phone, "See all results" and "See your answers" scroll again. The overall summary stopped at the bottom of the screen: with more than two or three questions the rest of the list, the leaderboard and the "Back" button below it could not be reached, because Nextcloud keeps its page frame at screen height and Pulse relied on the page scrolling.

Removed

  • office-addin/manifest.xml. It is generated now, and a second editable copy next to the generated one is exactly the trap this change removes.
  • Internal design notes — design briefs, handoffs and HTML mockups from the design rounds under docs/ — are no longer part of the public repository. They were working material of those rounds, not documentation of the app. Code comments still cite their section numbers, and those of the self-paced quiz specification, which was never in the repository; every file that does so says in a note that these documents are not public, and the README explains such references under "References in code comments".
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEADCCAugCAhRCMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYxMDAyMTY1NjQ4WhcNMzcwMTA3MTY1NjQ4WjAQMQ4wDAYD
VQQDDAVwdWxzZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJ5l1XaC
d/PVhLzw8c/PihtpkhXOwqxeCqUa6TjWt5cfnT1o48S/2gTOb72VV+4FygVem9nw
augLTcdjyLVGq9KcA1rxZSYEChXWU7J3DkciwgsHW9MSvvXkpVPdUvIs9nRkko03
fJH2pjYKplppz7r4l2ysaMU3EcvBCapYEQhhdoX/PE+u03xpSz3b+pxx4zI8PgcT
t6qZrWoyJrjven7hZsNpJPruROGFU6DqIaMf8/6PYEozmGtyKgyMI7OkNrfSqyyi
5q5KJ6eli9HTouZcLJ2o0fGTSzNWbuBkeTb0BcZ/z7DriQ+FZq+XQbXoRPNNw5rS
S+E3qJGUjZMrFiMEbBIkhhM0IktzrI1jV7qJEOpGkDjGO4FgGQq6LkCxelxrmzIe
i5PG6raUs1rYfdp5rMOIwwuwK/w0jvJJlw5k0uMU6L4ZmISxd4WQC7a9VVEa6xq1
vM5iUsAyU2vFgTlymJjlibnv+JOIb5B3cxL3w3GBf3nvbD085gWq78LqoQP6XptZ
bFr13eUJnxtsQJVnISk0tlZZN1bFzMTcWuIcEjizKi0SjyL3INM3p/yDRK/T2dND
bLJSAnXWFljjjVff+SA50BeyNW63Cq/XO3Sh9QVca2OuI72wgFHy0q2iOk2PDrQF
kX4e7wygmj77Qv0g1GX9L7BYQaq/FjhmVbEXAgMBAAEwDQYJKoZIhvcNAQELBQAD
ggEBABlaqxeemLw+NHFW1NiBcjTwK2DMm+9Ib3xemp3Ig8MSFFl0xVLgFKEq6U6j
zAz6pkQ1b2Vb3OhWe/Ea6MTtK2pou56RBNXNtX+rIMlp/zHAYrc42Pr/rUwWiRER
+plP+80WJt4BAZ/VJvBvMaFgPaIhYAcnsyeCUtZXrSR/o5T0J+1ndfSiROmrTijf
TO7JGnD48aWYjs7DZG04Fl+YgUDnE5qXC0gyTQH3Y3Y4Vp6ukpMX4uOqDgQaeJmI
+8PJEROynqa5gIwQbjEvBWoPWX2dOonlHpUtGYqyD+56wqWuk64r7vmsbw5aUHlI
udu2qH/h5dinttwIChQfxGcwgyU=
-----END CERTIFICATE-----
SignatureDvfhl1F1oCgY6hgKnhuwPFf9EmDtuocaCs8n+wUHyz7VIiNT69IpxRkuGcl7uy7ykiwHuDV98rFqysRODMR/QEC4WMAjqGUK/tHKcv8SJCiQruDhqNgd2D1WP3T/bXszvcr4UGpFLpHS9GzEFXtSrV6TeO8JYPvHOGw7sBi5n23v16vVqBAI+3s8DBHpmrfBPZCgKF59cW0XNNdK00BYN0VW+9CKQEJ1wa7buBJIeI1nRZLsM+sMeF49b/Fe1DB3KUM8tU/domRf0EvzBrMQ3iFF5/x0RLe0VdeLS/sOZ777vh6j0mPdXOddA2I2E7ZlQ35wWkGMrDYniBdRqrq06xtAOm7ppoACRYtb827ONxVDC4m23AbzcH4grmIA5Kuo2XTN/UOyCyiV69GBOQAKLBA4NMJcKP6bV4vMgYjfL/oI89t8voQklh+3ZW0LcxpBEUUZ7jWFXcv+3N6LX32QZxeZDkZkrqSfmuhv3tlj+CFMmK0i2xWAcR2LpbwOwAtT3ExtaPYs9oFIjj6byyU1YHe19+cJTMERRF2b591AKlKMxfmKD3IkI1vyOQjVEwjrjztC5UgqmvQCkesWHTnY3JnxrjzZTlyGId4V7KePJyykWIj5JsrsRS7e82TyWMmcFDxoVfdP59vzoIYo9xeP2u147oMVLGceQE3rFMtDKp0=
Signature digestsha512
Dependencies
Required Nextcloud versions >=34.0.0,<36.0.0
Minimum Integer bits32

Nextcloud 34

Pulse 0.19.1
Release Details
UpdatedOct. 3, 2026, 1:58 a.m.
Changelog

Changed

  • The App Store description is easier to read: a short introduction, then polls, quizzes, presenting and notes under their own headings, with the features as lists. It now also mentions the self-paced quiz and that rooms nobody has used for 30 days are deleted automatically.
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEADCCAugCAhRCMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYxMDAyMTY1NjQ4WhcNMzcwMTA3MTY1NjQ4WjAQMQ4wDAYD
VQQDDAVwdWxzZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJ5l1XaC
d/PVhLzw8c/PihtpkhXOwqxeCqUa6TjWt5cfnT1o48S/2gTOb72VV+4FygVem9nw
augLTcdjyLVGq9KcA1rxZSYEChXWU7J3DkciwgsHW9MSvvXkpVPdUvIs9nRkko03
fJH2pjYKplppz7r4l2ysaMU3EcvBCapYEQhhdoX/PE+u03xpSz3b+pxx4zI8PgcT
t6qZrWoyJrjven7hZsNpJPruROGFU6DqIaMf8/6PYEozmGtyKgyMI7OkNrfSqyyi
5q5KJ6eli9HTouZcLJ2o0fGTSzNWbuBkeTb0BcZ/z7DriQ+FZq+XQbXoRPNNw5rS
S+E3qJGUjZMrFiMEbBIkhhM0IktzrI1jV7qJEOpGkDjGO4FgGQq6LkCxelxrmzIe
i5PG6raUs1rYfdp5rMOIwwuwK/w0jvJJlw5k0uMU6L4ZmISxd4WQC7a9VVEa6xq1
vM5iUsAyU2vFgTlymJjlibnv+JOIb5B3cxL3w3GBf3nvbD085gWq78LqoQP6XptZ
bFr13eUJnxtsQJVnISk0tlZZN1bFzMTcWuIcEjizKi0SjyL3INM3p/yDRK/T2dND
bLJSAnXWFljjjVff+SA50BeyNW63Cq/XO3Sh9QVca2OuI72wgFHy0q2iOk2PDrQF
kX4e7wygmj77Qv0g1GX9L7BYQaq/FjhmVbEXAgMBAAEwDQYJKoZIhvcNAQELBQAD
ggEBABlaqxeemLw+NHFW1NiBcjTwK2DMm+9Ib3xemp3Ig8MSFFl0xVLgFKEq6U6j
zAz6pkQ1b2Vb3OhWe/Ea6MTtK2pou56RBNXNtX+rIMlp/zHAYrc42Pr/rUwWiRER
+plP+80WJt4BAZ/VJvBvMaFgPaIhYAcnsyeCUtZXrSR/o5T0J+1ndfSiROmrTijf
TO7JGnD48aWYjs7DZG04Fl+YgUDnE5qXC0gyTQH3Y3Y4Vp6ukpMX4uOqDgQaeJmI
+8PJEROynqa5gIwQbjEvBWoPWX2dOonlHpUtGYqyD+56wqWuk64r7vmsbw5aUHlI
udu2qH/h5dinttwIChQfxGcwgyU=
-----END CERTIFICATE-----
SignaturegaIzYS6SxmZWUgQOM2e0b47fZgLCkTT7rmEnr8r8uWzoMri3tcrFnHQiY2LIr2ff
NDGyaWl1Tyv3MsUiLZjujjUWpDrhI1UAAjxYZVY5mH4VcHfNTJOW9BnNgzii0jwk
tUAAZuuFuzBiOOJ9CMfrUFx8dhDVjS8snX/7AYsCt7VEueTSZPODsDnSW77tH9WR
KYUCqGa+1dYJ5NH3P+AICat4ay4+O6O9HrgO3F9mb01mt4RAnmSTv+wWfgEb4T1C
vHS06ysgOo2Ha0PsBeOSX+FglTSwpqBiyuYISNbOJ0g2ahF+TOGaHFCKIK7NTEFt
PrNd0bDoVy469BSp4gH977GbNNlYVIxQ4dUbGCc63JbieAAEUfuyCEk9nnWgtaeq
us41a+r2Nr4Xsf+KwiT7zefWkt3NqrUxhthvcWyJR4gqEQMD0Ig5key0+Ks6gKV/
6XLNKyadA2ld4iqG9hOUH7bv6pDXYJQe34I7BQmnt5Wpq8LxNME032Qi8xIJn5+P
j+ekmfkNgecP4Vfjxv8Y06hMuWD7OO5h8HYR+jZ3eiejII/JEa3gZ3siaguZ9zBP
lznJnqcQjTjUtOBJad5WtERUrVPT3QbgH+nEgVsMAc7jgIf4grrem/th3OOzRpM1
kk07BVoKnEdCBYEb6qjcrkZ8bMeR47fv9Xe9dWDYxj0=
Signature digestsha512
Dependencies
Required Nextcloud versions >=34.0.0,<36.0.0
Minimum Integer bits32
Pulse 0.19.0
Release Details
UpdatedOct. 3, 2026, 12:35 a.m.
Changelog

Security

Found in a security review of the code by AI agents in September 2026 (see the README's AI disclosure), most important first. What is still open is described under "Security notes" and "Known limits" in the README.

  • Wrong room codes no longer lock a school or a venue out of Pulse. After ten wrong codes from one address within 30 minutes, Nextcloud's brute-force protection answered every participant and projector request from that address with "Too many requests" for 30 minutes — valid codes included, on every phone and the projector behind the same school or conference network; only an admin could lift it earlier. Typos in the join form were enough, so was a room deleted while a dozen phones still polled it, and so was any web page with an image pointing at a made-up code; the join form then said "That code does not exist." Now only unknown codes count, and only unknown codes are refused: an existing room always opens. Requests from an address that is already blocked are not counted, so phones still polling a deleted room no longer keep the block alive for as long as they are open.
  • Scripted ballot stuffing can no longer slow down the whole Nextcloud. A script that votes or joins without a cookie could add thousands of votes, players or presence entries per minute, and every one of them made each phone and the projector download the complete results again — at 60,000 votes 2.4 MB and half a second of server time per poll, on the web server all of Nextcloud shares. Now:

    • phones and the projector get capped results: the top 100 words or free-text groups, at most 500 compass points (a fair sample; the total and the centre stay exact) and the first ten rows of the leaderboard plus your own place and the people around you, each with the full count — the projector says how many more there are. A word cloud with 60,000 words now costs under 4 KB instead of 2.2 MB. The moderator's results, the summary and the CSV export stay complete;
    • "nothing has changed" is answered without reading any votes (a change marker in Nextcloud's memory cache);
    • new identities without a cookie are limited to 300 per address and room in ten minutes, and a phone counts as present from its second poll, when its cookie comes back; made-up cookies add at most 600 presence entries per address and room in ten minutes;
    • a moderated quiz takes at most 600 players (max_players_per_room in the app config changes that).

    Voting again under new identities stays possible; the README's security notes explain what remains.

  • A word-cloud vote carrying a huge list of words no longer ties up the server. A 16 MB request kept a PHP worker busy for more than eleven seconds, because every entry was cleaned up before the list was cut to the allowed number. A list longer than twice the allowed number of words (at least 20) is now refused with "Invalid words.", each word is cut to 200 characters first, and free-text answers and nicknames are shortened before they are checked.

  • One account can no longer fill the server's disk. Question images are stored in Nextcloud's app data, outside every user quota, and Pulse re-encodes them — a 1.4 MB image could become an 8.6 MB PNG — so three copies of a room with images wrote 821 MB in a second and a half. Rooms, questions and question texts had no limits either. Now each account has an image budget of 200 MB, at most 200 rooms, 100 questions per room and 1000 characters per question; creating and copying rooms, adding questions, uploading images and demo votes are limited per minute; answer options are cut to 200 characters, and a free-text question keeps at most 50 accepted answers. A copy is checked against the caps before anything is written and removed again if it still fails halfway (such a failure used to be an internal server error). Requests sent at the same moment count again after writing and take their own write back when the account ended up over a cap, so a burst of copies can no longer store more than the budget. All values can be changed per instance in the app config — keys and defaults in the README under "Limits". Creating or copying a room shows the server's reason when it fails.
  • Rooms of deleted accounts no longer pass to a new account with the same user ID. An account deleted while Pulse was disabled — as earlier versions were after an update to Nextcloud 35 — left its rooms behind, and whoever later got the same user ID, for example through a login provider, owned them with all answers, nicknames and exports. The daily job now deletes the rooms of every owner that no user backend knows any more and that left no login record behind; the second condition keeps the rooms of real people while their LDAP or OIDC backend is merely switched off. And participants' polling keeps a room alive only until 180 days after its owner last used it, so a phone left open no longer defeats the 30-day retention.
  • The voter cookie can no longer be planted from a sibling subdomain. Another service under the same domain could set a pulse_vt cookie with a token it knew; browsers sent it along to Pulse, and with it that service could read a participant's own answers, free text included, and vote or rename in their name — in every room, for a year. On https with Nextcloud at the root of its domain the cookie is now called __Host-pulse_vt, which browsers accept only from Nextcloud's own origin, and a request that sends a cookie name twice counts as having none — except a name such as _.Host-pulse_vt, which PHP itself drops and which therefore cannot cost anyone their cookie. An existing pulse_vt is taken over during the first 60 days after the update, so a homework that is running keeps its players; after that it is ignored. Under http or a sub-path the name stays pulse_vt.
  • Votes are accepted only from Pulse's own page. Joining, voting and "Next question" need no request token — participants have no Nextcloud session — so any web site a participant opened could post to them: a hidden form could replace the participant's cookie, leaving their quiz points under an orphaned name and restarting a self-paced quiz, and a sibling subdomain could vote or rename in their name. These requests now need the header the page's own script sends (X-Requested-With: XMLHttpRequest, or Sec-Fetch-Site: same-origin); anything else gets 403 and no cookie.
  • The development tree is no longer public when Pulse runs from a git checkout inside the web root. A shipped .htaccess makes Apache answer 404 for node_modules/ — whose demo pages include one that can be made to run script on Nextcloud's origin —, the screenshot harness, sources, tests, build files, .git/ and local _*.php scripts. The README no longer tells people to clone into apps/: it installs the release archive, or the runtime folders, built outside the web root.
  • Hosts of a moderated quiz can remove players and lock joining. Anyone with the code could put a name on the podium, and a player could rename themselves after answering — even after the final standings — into something abusive or into somebody else's name; the only remedy was resetting the whole room. Now the "Only for you" panel and the standings have a "Participants" list with "Remove from the quiz" (the player's answers go too; they can join again from zero points), the menus have "Lock joining" (the header then shows "Joining locked"), a name is frozen once its player has answered or a question has ended, and two phones that join at the same moment under the same name no longer both get it.
  • Lookalike names are refused. A fullwidth "Anna", a Greek "Αnna" or a Cyrillic "Аnna" was accepted next to "Anna", so somebody could pass as another player on the projector, in the progress view and in the CSV a teacher grades by. Names are now compared with lookalike letters folded, and with PHP's intl extension also against pairs such as "PauI" and "Paul"; characters that browsers draw as nothing are ignored, including the ones Unicode has reserved but not assigned yet, and another spelling of one's own name is checked like a new name. Now and then a genuine name close to a taken one is refused; adding a letter helps.
  • The moderator API no longer tells other accounts which room codes exist. Someone else's room answered "403 No access to this room." and an unknown code "404", without any rate limit, so any account could search for live rooms at hundreds of guesses per second. Both now answer "404 Room not found.".
  • A self-paced quiz can no longer be filled up by a script. Joining without ever starting took one of the 300 places, and the limit of 120 join requests per address and room let one person behind a school's NAT use up the whole class's budget. Now only players who have started count towards the 300; up to 600 can join, and at that ceiling people who joined more than ten minutes ago and never started make room while the quiz is open. What is limited per address is new names — 120 per room in ten minutes, as many as the old request limit let in — and not requests: a taken name, a retry or a player coming back costs nothing. The request limit stays as a mere flood guard of 2,400 per address and room in ten minutes, now in moderated quizzes too. An instance that runs larger events raises the ceiling and the count per address in the app config (max_players_per_room, max_new_players_per_address).
  • Images uploaded to the same question at the same moment no longer leave files behind that nothing deletes — not deleting the room, not the daily job, not deleting the account. The upload that loses now gets "The image was changed at the same time elsewhere. Please try again." and its file is removed, removing an image no longer undoes an upload that arrives at the same moment, and the daily job sweeps image files no question refers to (once they are an hour old). A room that cannot be deleted no longer stops the clean-up of all the others.
  • The PowerPoint add-in asks only for the lowest permission level, "Restricted", instead of "ReadWriteDocument": it just keeps the room code in the document settings. Script that got into the embedded page could otherwise have read or rewritten the whole presentation. Download the manifest again (office-addin/README.md).
  • The add-in shell frames a saved room code only if it is six letters and digits. A code of .. from a shared .pptx or a link framed Pulse's moderator page or the Nextcloud login inside the slide; anything that is not a room code now opens the code form.
  • Voter tokens, nicknames and answers no longer appear in exception traces in nextcloud.log: the parameters that carry them are marked #[\SensitiveParameter].
  • Release signing (build/package.sh, for developers) no longer puts the private key into the production container. It signs in a disposable container without network, created from a Nextcloud image and removed with the key right afterwards; CONTAINER=<name> is the explicit opt-in to sign inside a running container.
  • CI checks that the committed bundles in js/ are exactly what the sources build to (Node.js 22.18.0, npm ci), so a change hidden in minified code cannot pass review unnoticed, and the GitHub Actions it uses are pinned to commits.
  • The README and the App Store description no longer claim that the voter cookie "prevents" double voting: it discourages it, and whoever clears their cookies can vote again. The README's security notes now say what is protected and what is not — ballot stuffing, names on the podium, scouting a self-paced quiz (for anything graded: feedback "At the end"), the framing exemption of the projector view and the add-in shell, and office.js in the Nextcloud origin (test the add-in address in a private window). A new SECURITY.md says how to report a vulnerability.

Added

  • Every instance hands out its own PowerPoint add-in manifest, at /apps/pulse/addin/manifest.xml and from the deck's overflow menu. An Office manifest cannot hold variables — <AppDomain> and <SourceLocation> have to be absolute URLs — so a shipped file needed a hand edit in two places on every installation, and forgetting it pointed the add-in at somebody else's Nextcloud with no error message anywhere.
  • Setup check "Pulse: embedding in PowerPoint" under Administration → Overview. It fetches the embed page under every address the server can reach itself on and reports whether X-Frame-Options still blocks framing, listing blocked and working addresses separately — a proxy rule that covers the internal host but not the public one now shows up instead of quietly breaking the add-in on the road. The header cannot be dropped from inside the app on Apache, so the check points at the web server rather than pretending to fix it.
  • Self-paced quiz. A quiz room can now run at its own pace instead of following the presenter: tick "Self-paced" in the deck's menu, and everybody works through the questions alone on their own phone, with a clock for each question that starts only when they open it. Switching clears the players and answers collected so far and asks first if there are any; the questions stay. Instead of presenting, the presenter opens the quiz with "Open quiz …" and closes it later. Without a deadline it is a race: by default with a timer and a verdict after every question, and closing it releases the results. With a deadline one minute to 30 days ahead it is homework: by default without a timer and with the verdict only after the release, and the deadline closes the quiz with nobody around. Both defaults can be changed when opening; a practice run always gives the verdict at once and never shows a leaderboard. Moderated quizzes work as before, apart from the fixes listed below.
    • While the quiz is open, the presenter follows everyone on a progress page: how far each person got, their answers, points and last activity, the join code with its QR code, a preview of the projector, and one main button that names the next step — close the quiz, check free-text answers, release the results. Free-text answers are marked right or wrong there without the list of accepted answers on screen, and a slip can be undone under "Checked just now". A race can also be stopped without releasing the results, to check answers first. The end can be moved, a closed quiz reopened, joining locked and single players removed; participants and answers download as CSV. With the verdict at the end, points stay hidden on this page until the presenter shows them.
    • Phones go from name to start card to question to verdict. "Next question" appears once the answer is final — a few seconds, which cost no points — so the verdict is never skipped by accident. Questions without a timer can be skipped, the position and the deadline stay in view, and a phone that is reloaded carries on where it was.
    • The projector never shows a question. While the quiz is open it shows the race — how many people are on each question and how many have finished — with a large join code for the first two minutes and afterwards, when verdicts come after every question, the top eight of the leaderboard. A closed quiz shows only the count, a released one the final standings.
    • The question order is frozen when the quiz opens, and the deck stays locked until the room is reset. An answer counts once its correction window is over or it can no longer be changed, and phone, projector, progress page, leaderboard and CSV all count the same answers. Before the release, phones show no solution, distribution or leaderboard. Joining ends when the quiz closes; a room takes at most 300 players who have started and 600 who have joined, and at most 120 new names per address in ten minutes (see Security).
    • All of it works through the API as well: POST /api/1.0/rooms/{code}/pace switches the pace and opens, closes (with release: false without releasing the results, whatever the deadline), extends or releases the quiz, GET /api/1.0/rooms/{code}/progress follows everyone, POST /s/{code}/next moves a phone on, and the CSV export takes ?view=players and ?view=answers.
  • An AI disclosure. Pulse is vibe-coded: its code, tests, development tools, documentation and German translation were written by AI coding agents (Anthropic's Claude Code), and there has been no independent human code review and no security audit. The README now says so in a notice right under the title and in a section "How this app was built (AI disclosure)" with the models, the commit counts and what the tests can and cannot vouch for; the App Store description carries a short version in English and German.

Changed

  • Pulse now supports Nextcloud 35 as well as 34 (max-version 35). It was tested on Nextcloud 35.0.1 with SQLite, MariaDB, PostgreSQL and MySQL, and through a server update from 34.0.4 to 35.0.1 with existing rooms and votes (PostgreSQL). Earlier versions supported Nextcloud 34 at most, so a server update to 35 switched them off.
  • Documentation and code comments are in English now. The READMEs, the App Store guide and the comments in PHP, JavaScript, Vue, CSS, shell and configuration files used to be mostly German, and so were the messages of the release scripts, the CI step names and the package.json description. The German translation of the interface (l10n/) and the German store description stay German on purpose, and so does the test data that checks Unicode, case folding and the CSV export. Still German, for a later round: German inside the code itself — other test data, the JavaScript unit test, the messages of the test runner and of the translation and development scripts, the seed words of the demo mode, the comments inside the add-in manifest template and inside the browser scripts of the screenshot harness.
  • The README was brought up to date for a public audience: installation from the repository, a section on security notes, the adaptive polling intervals instead of a fixed 2.5 s, the databases Pulse was tested on, and the App Store status. It no longer says that info.xml advertises Nextcloud 29 and later.
  • The add-in manifest is no longer German-only: source locale en-US with a German override, like the rest of the app. Its <Version> now comes from info.xml, so PowerPoint recognises an updated add-in.
  • The Traefik snippet next to it carries nextcloud.example.com instead of one specific server.
  • "Show final standings" at the end of a quiz, and the automatic advance after the last question, now end the quiz for the whole room: projector and phones switch to the final standings together with the moderator. With reveal per question they used to appear on the moderator's screen only. If ending the quiz fails, the moderator stays on the question and sees an error instead of standings nobody else has.
  • Standings opened from the menu in the middle of a quiz are called "Leaderboard"; "Final standings" is reserved for the end. From there, Next and Back take the moderator back to presenting along with the room, and on the final standings Back is disabled. Opened with no question running, the standings offer "Back to the deck" instead of "Finish quiz".
  • A practice run with "Reveal at the end" can now reveal its last question: the main button reads "Reveal" (still without a leaderboard, as always in practice), then "Finish" sends the room back to the lobby. It used to go straight to the lobby, so nothing was ever revealed. A practice run revealed per question no longer drops the moderator back to the deck on its own after the last question.
  • Nicknames are unique within a room. A name already taken — also in different case, or with invisible characters or extra spaces — is refused with "This name is already taken. Please choose another one.", so the leaderboard no longer shows two identical rows. Players can keep their own name and change it until they start answering (lookalike letters and the rename freeze: see Security). Invisible characters are stripped from names, and a name made only of them is refused.
  • info.xml gives the licence as AGPL-3.0-or-later instead of agpl. The store schema still accepts the short form but lists it as deprecated, and for apps targeting Nextcloud 31 and later the store's guide asks for an SPDX identifier. package.json names the licence now as well.
  • The repository moved from hotochan123/hotochan123-nextcloud-pulse to hotochan123/nextcloud-pulse. info.xml (website, issue tracker, screenshots), the add-in manifest's support link, the setup check's link to the add-in guide and the documentation point to the new address; GitHub redirects the old one.
  • The store description and the README describe Pulse as a self-hosted alternative to services such as Kahoot!, Mentimeter or Slido and state that Pulse is not affiliated with their providers. Code comments no longer name other products, and the README credits the four icons taken from or adapted from Feather Icons and includes their MIT licence text.

Fixed

  • On SQLite, a class joining a quiz at the same moment no longer gets "Joining failed." on up to half of the phones. The room lock began there as a plain read, and a transaction that a parallel one had overtaken could not write any more ("database is locked") — the database's busy timeout does not wait in that case. The lock now takes the write lock first, so the joins queue up. The same lock guards correcting a free-text answer in a self-paced quiz and the host's actions on it (opening, closing, locking joining, removing a player, grading).
  • The join panel no longer reopens by itself while presenting. It used to open whenever nobody was connected yet, and that decision was taken again on every results poll — every 1.2 s in a quiz — so closing it with ×, a click beside it or Escape had no effect for longer than one tick. In a room nobody had joined yet it could not be closed at all. The panel is now only ever opened by the "Join" button; the room code stays visible in the header and on the projector either way.
  • The framing rules now also cover /index.php/apps/pulse/embed and /index.php/apps/pulse/screen/…. Without htaccess.IgnoreFrontController Nextcloud builds its URLs with /index.php in front, so a rule that only knew the short form never applied — the same page came back without the header under one address and with it under the other. Affects the shipped Traefik file and the Apache/nginx snippets in the add-in README.
  • The setup check asked the router for the embed path and got an empty string when the app routes were not loaded, then dutifully measured / instead — which carries X-Frame-Options quite rightly, so the check reported "blocked" for every instance. It now uses the fixed path, which also keeps the result identical between occ setupchecks and the admin overview.
  • Quiz answers no longer leak before the reveal:
    • The change marker phones and the projector poll with contained checksums of the answer key and of all votes, which could be tested against candidate answers. It is now a keyed hash that says nothing about the content.
    • Ranking and matching questions went out in their stored order, which is the solution — on the projector and through the API. Until the reveal they are now shuffled, the same way for everyone and independent of the solution.
    • "See all results" on the phone listed the whole deck, including questions not shown yet — in a quiz with their answer options. It now lists only questions that have been shown.
    • Public leaderboards counted questions that were not revealed yet, such as one the moderator skipped without revealing, so a jump in points told a player whether the answer was right. Hidden questions now stay out until the quiz is finished; the final standings count everything and match on phone, projector and moderator screen.
    • A "Reveal at the end" quiz run a second time without a reset still carried the first run's end, and "See all results" gave away every solution from the first question on. Showing a question now clears the old run's end.
    • An edited question that had already been revealed stayed revealed, so its new solution showed up in "See all results" at once. A question edited while it is not on screen now counts as not shown yet, unless a finished quiz ended on it.
  • An answer sent just as the moderator moved on is refused with "This question is closed." instead of being counted for the next question, where a number, a word or a scale value often fits just as well.
  • Open phones and the projector now pick up changes they used to miss: switching "Reveal at the end" after a reveal, editing a running poll question nobody had answered yet (every vote on it failed afterwards), renaming the room, and resetting it or toggling the practice run while everyone waits in the lobby (phones kept greeting players whose names had just been deleted). A question that is closed but not revealed yet shows as "Answers closed" on the projector instead of a result view without results.
  • The projector now fits the first quiz question to the screen. Its size was only recalculated when results arrived, and a quiz sends none before the reveal. An edited running question with a longer text is refitted as well.
  • Word clouds count each word once per person. "Coffee" and "COFFEE" from one person counted twice and used up two of the allowed words; invisible characters, non-breaking spaces, double spaces and emoji variants no longer make a second word either. The cloud shows the first spelling, in lower case as before, and votes given before this change are counted the same way.
  • Phones: in a poll, "Your answer" now appears for every question type once results are up — word clouds, rankings, matchings and spectrum or compass scales used to read "Did not answer this round." After a reload, multiple-choice, number and free-text questions show the answer given instead of an empty, locked field. A status update that overtook a vote no longer resets the selection and the correction window. When the running question is edited, phones drop the old selection, and once their answer has been cleared they get a fresh correction window.
  • Open phone and projector pages now reload themselves after an app update that changes how page and server talk to each other. A tab kept running the script it was opened with, even after the server behind it had moved on, until somebody reloaded it by hand. /state now carries a protocol number that goes up whenever server and page no longer fit together; a page that sees a different number than the one it was built with reloads once — at most once per tab and protocol, so a stubborn cache cannot turn it into a reload loop. Where the browser refuses session storage, as some do inside the PowerPoint add-in's frame, the page carries on without reloading rather than risk that loop. The number is also part of every state version, so an outdated page gets one full state instead of an endless run of "unchanged" replies. Pages opened before this version do not know the number yet and pick up the new scripts on their next reload, as before.
  • Word clouds and grouped free-text answers show the first spelling that came in. Votes were read without a defined order, and PostgreSQL returns rows in storage order, which differs from the order of arrival once new votes fill the space of deleted ones.
  • "Export CSV" on the summary page delivers the file again. The link carried no request token, so Nextcloud answered with "412 Precondition Failed" instead of the CSV.
  • German phones labelled the button that changes an answer "Wandel" instead of "Ändern": the English "Change" was also a word in the word-cloud demo, and that translation won. The demo word is now "Transformation" in English and still "Wandel" in German. The practice-run banner in the deck said "Übungslauf", while everything else in German says "Probelauf"; now it says "Probelauf" as well.
  • When resetting the room, switching "Reveal at the end" or the practice run, saving the question order or deleting a question fails, the error message now gives the server's reason instead of a general "Could not …".
  • Joining a quiz no longer throws the phone back to the name screen for a moment. A status update that had set off before the name was sent could arrive after the join and still report no name; it is now discarded.
  • Requests that send a value as a list or an object where text or a number is expected (for example action[]=close), a number the server cannot hold (1e999), text that is not valid UTF-8, or a participant cookie the server never issued no longer write "Array to string conversion" or similar warnings to the Nextcloud log, and no longer fail with an internal server error. Such values count as missing: the request gets the usual message with status 400, or the default applies. A deadline, a question pointer or a switch of the self-paced quiz that cannot be read is refused instead of being taken as "none".
  • The results export (CSV) of a quiz with a free-text question no longer fails with an internal server error. Free-text answers get one row per group of equal answers, as on the grading screen, and number guesses show the number instead of an empty answer column. Free-text answers and words from the audience that start like a spreadsheet formula get an apostrophe in front, as in the self-paced export, and quotation marks inside a cell are doubled the way spreadsheets expect.
  • Two votes sent at the same moment from the same phone in a poll — a double tap, or a retry after a network hiccup — no longer end in an internal server error. The later one counts, as when a vote is changed.
  • The daily clean-up no longer deletes decks their owner is still working on. A moderated room created more than 30 days ago that no audience had joined in those 30 days was deleted, even if the owner had edited it the day before: only participants kept such a room alive. Now whatever the owner does with a room counts as well, in every room mode — opening it, editing the deck or its settings, presenting, looking at the results or the progress — so a room goes only after 30 days in which neither the owner nor a participant used it. The owner's activity is recorded at most once an hour and changes nothing anyone sees. It is recorded from this version on: on an installation where the clean-up already ran, a room its owner has not opened since the update is still judged by its participants alone, as before.
  • Rooms of a deleted Nextcloud account no longer stay behind. They were left with nobody to manage them, still reachable under their public codes, and a room the audience kept using was never cleaned up at all. Deleting an account now deletes its rooms together with their questions, votes, players, progress and images, and their codes stop working.
  • New installations now register the clean-up job. It was only added by a migration step, and Nextcloud skips those steps when it installs an app for the first time, so rooms there were never deleted. The job is now declared in info.xml, which Nextcloud reads on every install and update. An installation that started out on an earlier version without the job gets it with this update. Its existing rooms count as used on the day of the update, so the job deletes none of them in the first 30 days — not even a deck its owner edited just before the update, which the job has no record of.
  • Deleting a room — with the delete button, by the daily clean-up or with its owner's account — no longer leaves its questions, votes, players or progress behind when the database fails halfway, for example on a deadlock with a vote arriving at the same moment. The rows now go in one transaction, which is retried after a deadlock; a deletion that still fails leaves the room complete instead of half deleted.
  • On MySQL, adding a word cloud, a number question or a free-text question no longer fails with an internal server error, and neither does duplicating a room that contains one. MySQL cannot keep the default value of a text column, so a new question has to write its empty option list itself, and these three types left it out. A duplicate that failed this way left an incomplete "(copy)" room behind, which can simply be deleted. MariaDB, PostgreSQL and SQLite were not affected. No migration is needed: existing MySQL installations work as soon as they run this version.
  • Release packaging (build/package.sh, for developers): signing works. It failed every time and then left the private key in the Nextcloud container's /tmp; it now signs in a disposable container that is removed, key included, on every exit (see Security). Archive entries are 755/644 and owned by 0:0 instead of world-writable, info.xml is checked against the store's current schema, and packing stops when info.xml, package.json and CHANGELOG.md disagree about the version (ALLOW_UNRELEASED=1 packs a test archive, as CI does). A pre-release such as 0.19.0-beta.1 needs its notes under [Unreleased], where the store looks for them.
  • Moving a question with the keyboard ("Move up" / "Move down" in its row menu) keeps the focus on that question. The focus landed on the neighbour it had just swapped places with, so pressing again moved the neighbour back instead.
  • The question editor stops labels at 40 characters, answer options at 200 and match pairs and accepted answers at 100 — the lengths the server keeps. Longer text used to be cut on saving without a word. The compass field for the heat-map threshold now also goes up to 9999 with its arrows, the value saving always accepted.
  • On the projector, the four corner labels of a compass question sat upside down: the two top labels were drawn at the bottom and the other way round, each next to answers it did not describe. They now sit in the corners the editor and the phone show them in.
  • Word clouds take words of up to 40 characters from the phone, as the server always kept them. The phone stopped at 24, which cut long compounds such as "Verantwortungsbewusstsein". On the projector a word too wide for the cloud is now shrunk until it fits instead of being clipped on both sides, and on phones and in the moderator view long words wrap inside their box.
  • On the phone, moving an item of a ranking question down with its arrow button keeps the keyboard focus on that item. The focus fell back to the top of the page, so a keyboard user had to find the list again after every step.
  • API: editing a question, uploading its image and reordering the deck answer 404 "Question not found." (or "This question does not belong to this room.") when the question no longer exists or belongs to another room, like every other question action, instead of 400. Grading a free-text answer stays at 400, which the run view relies on.
  • When a new order of the deck cannot be saved, the deck goes back to the order the server kept (as soon as Pulse reaches the server again), and the keyboard focus stays on the question that was moved. The unsaved order used to stay on screen next to the error message, and the next move that did save took it along. If a question had been deleted in another tab, every later move failed until the page was reloaded.
  • Self-paced quiz: the dialog for opening the quiz, reopening it or changing its end accepts a deadline just over a minute away, as its message says. A deadline 90 seconds ahead used to be refused with that very message, and the date picker could offer such a refused minute.
  • Long compass corner labels no longer run across the axis into the opposite corner. On the projector and in the phone and moderator results each label stays in its quadrant and wraps onto at most two lines, ending in "…" only when it is longer still (the moderator sees the full label on hover). Short labels look as before.
  • Self-paced quiz embedded in PowerPoint: after the first two minutes, when the leaderboard appears next to the race, the slide shows as many leaders as fit — at least three — instead of cutting off the last two rows in the middle. The embed frame is lower than a projector at 1280 × 720, and the race with eight leaders did not fit even at the smallest text size. The projector itself looks as before.
  • Self-paced quiz embedded in PowerPoint: when the race has more rows than the embed frame holds — more than six questions while some people have not started, or a long quiz in two columns or groups — the questions move into two columns or larger groups ("Questions 1–4") instead of losing their bottom rows, "Finished" among them. On the projector itself nothing changes. A last group of a single question now reads "Question 22" instead of "Questions 22–22".
  • On the phone, "See all results" and "See your answers" scroll again. The overall summary stopped at the bottom of the screen: with more than two or three questions the rest of the list, the leaderboard and the "Back" button below it could not be reached, because Nextcloud keeps its page frame at screen height and Pulse relied on the page scrolling.

Removed

  • office-addin/manifest.xml. It is generated now, and a second editable copy next to the generated one is exactly the trap this change removes.
  • Internal design notes — design briefs, handoffs and HTML mockups from the design rounds under docs/ — are no longer part of the public repository. They were working material of those rounds, not documentation of the app. Code comments still cite their section numbers, and those of the self-paced quiz specification, which was never in the repository; every file that does so says in a note that these documents are not public, and the README explains such references under "References in code comments".
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEADCCAugCAhRCMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYxMDAyMTY1NjQ4WhcNMzcwMTA3MTY1NjQ4WjAQMQ4wDAYD
VQQDDAVwdWxzZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJ5l1XaC
d/PVhLzw8c/PihtpkhXOwqxeCqUa6TjWt5cfnT1o48S/2gTOb72VV+4FygVem9nw
augLTcdjyLVGq9KcA1rxZSYEChXWU7J3DkciwgsHW9MSvvXkpVPdUvIs9nRkko03
fJH2pjYKplppz7r4l2ysaMU3EcvBCapYEQhhdoX/PE+u03xpSz3b+pxx4zI8PgcT
t6qZrWoyJrjven7hZsNpJPruROGFU6DqIaMf8/6PYEozmGtyKgyMI7OkNrfSqyyi
5q5KJ6eli9HTouZcLJ2o0fGTSzNWbuBkeTb0BcZ/z7DriQ+FZq+XQbXoRPNNw5rS
S+E3qJGUjZMrFiMEbBIkhhM0IktzrI1jV7qJEOpGkDjGO4FgGQq6LkCxelxrmzIe
i5PG6raUs1rYfdp5rMOIwwuwK/w0jvJJlw5k0uMU6L4ZmISxd4WQC7a9VVEa6xq1
vM5iUsAyU2vFgTlymJjlibnv+JOIb5B3cxL3w3GBf3nvbD085gWq78LqoQP6XptZ
bFr13eUJnxtsQJVnISk0tlZZN1bFzMTcWuIcEjizKi0SjyL3INM3p/yDRK/T2dND
bLJSAnXWFljjjVff+SA50BeyNW63Cq/XO3Sh9QVca2OuI72wgFHy0q2iOk2PDrQF
kX4e7wygmj77Qv0g1GX9L7BYQaq/FjhmVbEXAgMBAAEwDQYJKoZIhvcNAQELBQAD
ggEBABlaqxeemLw+NHFW1NiBcjTwK2DMm+9Ib3xemp3Ig8MSFFl0xVLgFKEq6U6j
zAz6pkQ1b2Vb3OhWe/Ea6MTtK2pou56RBNXNtX+rIMlp/zHAYrc42Pr/rUwWiRER
+plP+80WJt4BAZ/VJvBvMaFgPaIhYAcnsyeCUtZXrSR/o5T0J+1ndfSiROmrTijf
TO7JGnD48aWYjs7DZG04Fl+YgUDnE5qXC0gyTQH3Y3Y4Vp6ukpMX4uOqDgQaeJmI
+8PJEROynqa5gIwQbjEvBWoPWX2dOonlHpUtGYqyD+56wqWuk64r7vmsbw5aUHlI
udu2qH/h5dinttwIChQfxGcwgyU=
-----END CERTIFICATE-----
SignatureDvfhl1F1oCgY6hgKnhuwPFf9EmDtuocaCs8n+wUHyz7VIiNT69IpxRkuGcl7uy7ykiwHuDV98rFqysRODMR/QEC4WMAjqGUK/tHKcv8SJCiQruDhqNgd2D1WP3T/bXszvcr4UGpFLpHS9GzEFXtSrV6TeO8JYPvHOGw7sBi5n23v16vVqBAI+3s8DBHpmrfBPZCgKF59cW0XNNdK00BYN0VW+9CKQEJ1wa7buBJIeI1nRZLsM+sMeF49b/Fe1DB3KUM8tU/domRf0EvzBrMQ3iFF5/x0RLe0VdeLS/sOZ777vh6j0mPdXOddA2I2E7ZlQ35wWkGMrDYniBdRqrq06xtAOm7ppoACRYtb827ONxVDC4m23AbzcH4grmIA5Kuo2XTN/UOyCyiV69GBOQAKLBA4NMJcKP6bV4vMgYjfL/oI89t8voQklh+3ZW0LcxpBEUUZ7jWFXcv+3N6LX32QZxeZDkZkrqSfmuhv3tlj+CFMmK0i2xWAcR2LpbwOwAtT3ExtaPYs9oFIjj6byyU1YHe19+cJTMERRF2b591AKlKMxfmKD3IkI1vyOQjVEwjrjztC5UgqmvQCkesWHTnY3JnxrjzZTlyGId4V7KePJyykWIj5JsrsRS7e82TyWMmcFDxoVfdP59vzoIYo9xeP2u147oMVLGceQE3rFMtDKp0=
Signature digestsha512
Dependencies
Required Nextcloud versions >=34.0.0,<36.0.0
Minimum Integer bits32