Wekan
Open source kanban board application built with Meteor
Alternative to: trello
About
Versions (100)
v9.69
2026-06-23v9.69 2026-06-23 WeKan ® release
This release fixes the following bugs:
- Can’t edit a card’s members in the UI after removing them via the REST API,
#3697: clearing a card’s
members(orassignees) over REST left the field uneditable in the UI. The card PUT handler guarded withif (req.body.members)— falsy for the two natural clear payloads (nulland"") — so “remove the last member” was a silent no-op, and its string branch was written to storenullrather than[]; a card withmembers: nullthen breaks UI code that treats it as an array. The handler now uses an!== undefinedguard plus a shared coercion helper so any clear payload (null/""/[]) stores a cleanString[](never null), a single id is wrapped into an array, and stray non-string entries are dropped;getMembers()/getAssignees()also coerce a legacynullto[]on read so existing corrupted documents edit cleanly. Pure logic inmodels/lib/restArrayParam.jswith a Meteor-free Node unit test (tests/restArrayParam.test.cjs,npm run test:unit:node, incl. a negative test reproducing the old null-writing logic), plus a REST regression intests/playwright/specs/17-rest-api.e2e.js. - Can’t create a card with no member via the REST API,
#2875: the card-create endpoints (
POST .../cardsandPOST .../cards/bulk) wrotereq.body.members/assigneesstraight to the insert with no normalization — the create-side twin of #3697 — so anull/""payload persisted asnull(breaking later UI editing). Both handlers now run the samecoerceRestArrayParamhelper: the field is omitted when not provided (so the schema default[]applies), any clear payload becomes[](never null), and a single id is wrapped into an array. REST regression intests/playwright/specs/17-rest-api.e2e.js. - Board created through the REST API shows in the API but not in the browser UI,
#5650:
POST /api/boardsset the board’s sole member’suserIdfromreq.body.ownerwith no fallback, so a request that omitsownercreated a board whose only member haduserId: undefined. The board-list publication matchesmembers.$elemMatch: { userId, isActive: true }, which can never match an undefined id — so the board was returned by the REST API but invisible in the browser.ownernow falls back to the authenticated caller (req.body.owner || req.userId), mirroring the Meteor create method. REST + DB regression intests/playwright/specs/17-rest-api.e2e.js. - Copying a card to another board left its comments on the wrong board,
#5166:
CardComments.copy()cloned a comment but only changed itscardId, so a card copied to another board produced comments that kept the source board’sboardId. Comment permission checks key off the comment’sboardId, so edit/delete on a copied comment was validated against the wrong board, and any board-scoped query saw it on the old board.copy()now also sets the destinationboardId(the authoruserIdis intentionally preserved). Cross-board copy regression intests/playwright/specs/17-rest-api.e2e.js. Note: the related “wrong author shown” symptom is a separate display issue — when a copied comment’s author is not a member of the destination board, their user document isn’t published there, so the UI can’t resolve the name; adding those users to the board resolves it. A broader fix (publishing comment authors’ minimal profile on boards where their comments appear) is left as a follow-up. - Exception “Removed nonexistent document” when deleting a card detail,
#3252 (partial): deleting a comment or checklist/checklist-item could
throw
Removed nonexistent documenton the client. The delete handlers calledCollection.remove(_id)directly, but under heavy archive/delete churn the target doc can already have been evicted from the client’s Minimongo cache, and removing a missing_idthrows. The comment / checklist / checklist-item delete handlers now check the doc still exists in the local cache before removing it (client/components/activities/comments.js,client/components/cards/checklists.js). The server-sidebefore.removehooks were already hardened to guard + log instead of throwing. (No automated regression for the thrown exception — the eviction race is not deterministically reproducible; the guard itself is a self-evident findOne-then-remove.) The high CPU on bulk delete the issue also reports is reduced by the cascade change below; the remaining cost is on the archive path (a bulk update, not a delete) and is a separate follow-up. - Performance: deleting a card no longer fans out per-child activity churn (#3252,
#5322).
cardRemoverremoved a card’s checklist items, checklists and comments with the hookedremoveAsync, so collection-hooks fired each child’sbefore.removeonce per document — every one doing agetCardand inserting an activity (e.g. aremovedChecklistItemper item), which then triggered the notification + publication observers. Deleting (or bulk-deleting) a card with many children produced an activity-insert storm and pegged the CPU.cardRemovernow removes those children with.direct(skipping the per-child hooks — they only logged activities that are unviewable once the card is gone) and clears all of the card’s activities in a single bulk op, which also removes the activities that a delete previously left orphaned. ThedeleteCardactivity is still logged afterward (so the outgoing webhook fires), and attachments still go through the normal remove so their files are deleted. Cascade + activity-cleanup regression (also a negative test) intests/playwright/specs/17-rest-api.e2e.js.
and this issue is verified resolved in current code (could not reproduce / no error observed here; re-test on the reporter’s data requested):
- #2292 (archiving a swimlane appeared to delete all its cards):
Swimlane.archive()(models/swimlanes.js) only setsarchived: trueon the swimlane — it does not touch or delete the cards, andrestore()brings the swimlane and its cards back. While a swimlane is archived its cards are merely hidden from the board view (board queries filter toarchived: falseswimlanes), not lost — the v2.27-era cascade described in the report no longer happens. (A dedicated way to view an archived swimlane’s cards before restoring would be a separate UX improvement.)