Compare commits

..
51 Commits
Author SHA1 Message Date
github-actions[bot] e1e0006a35 Bump versions for v13.07 2026-11-12 06:34:24 +00:00
Lauri Ojansivu 6f23e187ab Prepare v13.07 release 2026-11-12 07:15:19 +02:00
Lauri Ojansivu ab8c3452a8 CHANGELOG: Admin Panel Problems Clear button and event retention.
Thanks to Raymond-Voogt and xet7 !
2026-11-11 22:30:06 +02:00
Lauri Ojansivu fefabbf113 Admin Panel Problems: a Clear button, and resolved problems age out.
The problem streams were append-only and Acknowledge only reset the "new"
count, so a problem fixed long ago stayed in the table and buried the live
ones. Clear, beside Acknowledge, calls the admin-only clearEventLog, which
deletes the checked streams' events up to now and stamps the
acknowledgement; anything that happens after the click shows as new again,
and an unknown stream clears nothing. A daily sweep, claimed once per
installation, deletes events older than EVENTLOG_RETENTION_DAYS (default 90,
0 keeps them forever); a recurring problem's folded row keeps a recent date,
so it stays. The setting is listed on every platform, and clear-problems is
translated to every language.

Thanks to Raymond-Voogt and xet7 !

Fixes #6893,
2026-11-11 22:29:01 +02:00
Lauri Ojansivu 50ecd8944f CHANGELOG: ListLockAttachBleed, spent time as a duration, REST token deletion and the missing indexes.
Thanks to Furkan Derse, brlin-tw, AhmedLukman, Raymond-Voogt and xet7 !
2026-11-11 21:05:44 +02:00
Lauri Ojansivu 7bb3e13ba9 ListLockAttachBleed: a list's write refusal covers the attachment API.
A board admin can refuse a role write access in one list (#4527,
roleExceptions). The attachment API's upload, delete, copy and move, over
REST and DDP, asked only for board write access and mayWriteCardAttachment,
which allows every card to a member who is not assigned-only, so a normal
member the list refused still added and removed files on that list's cards.

Every attachment write that names a card now also asks mayWriteInCardList
with that card, and a move asks both the card it takes the file from and the
card it puts it on. The card's own board decides. As for the REST card
routes, only a list's refusal counts. A refusal is recorded in Admin Panel ->
Problems as ListLockAttachBleed (authz.list-locked-attachment, medium).

tests/listLockAttachments.test.cjs runs the guard on the reported case and
the negative cases, and fails on any mayWriteCardAttachment call in the tree
without the list check beside it; list-lock-attachments.e2e.js replays the
writes against a running server.

Thanks to Furkan Derse and xet7 !
2026-11-11 20:58:01 +02:00
Lauri Ojansivu 8dc77a89d8 Indexes for the LDAP id, cards' assignees and members, and History by entity and hash.
On a large installation the database-problems page filled with collection
scans of queries WeKan makes constantly but never indexed: a user looked
up by services.ldap.id at every LDAP login and sync pass (13,000+ users,
~430 ms per login), cards by assignees or members across every board for
My Cards and the filters (1.1M cards, 1-3.7 s, dozens of times a minute),
and changeHistory by entity and by integrity hash (120,000+ rows, and
growing). Each now has an index, created at startup with ensureIndex like
every other one: services.ldap.id sparse, assignees and members both so
their $or uses an index on each branch, and changeHistory's
{ entityType, entityId, createdAt } and { integrityHash }.

Thanks to Raymond-Voogt and xet7 !

Fixes #6892.
2026-11-11 20:29:31 +02:00
Lauri Ojansivu 9f5ab97a3c Spent time: the formatter imported as cardTime.js's other dependencies are.
A require() line stayed in the script tests/acceptedFixesLogic.test.cjs
evaluates, which strips imports, and failed it.

Thanks to brlin-tw and xet7 !
2026-11-11 20:29:31 +02:00
Lauri Ojansivu 3e8e8039ff Spent time is shown as a duration, not decimal hours.
A card's Spent time is stored in decimal hours, and a Pomodoro or Flowtime
session adds its duration to it, so a short session left a badge such as
0.034722222222222224. The badge shows days, hours, minutes and seconds now,
the leading zero units left out (12h34m56s, 2m5s), and the tooltip that
names hours rounds them to two decimals. The stored value and the edit
popup keep their hours. models/lib/spentTimeFormat.js, with a unit test
and a UI test.

Thanks to brlin-tw and xet7 !

Fixes #6890.
2026-11-11 20:20:55 +02:00
Lauri Ojansivu 4bdbded5d9 Merge remote-tracking branch 'origin/main' 2026-11-11 20:13:29 +02:00
Lauri Ojansivu dce58125c9 Merge pull request #6891 from AhmedLukman/codex/fix-rest-token-revocation
Await REST token deletion before reporting success
2026-11-11 19:54:56 +02:00
Ahmed Lukman fd59a8ff70 Await REST token deletion before reporting success
Wait for Accounts.destroyToken to finish so deletion completes before a success response and rejected database writes reach the existing error handler.

Add regression coverage for delayed and failed deletion, authorization, existing token input behavior, session isolation and browser logout.
2026-11-11 14:43:56 +03:00
Lauri Ojansivu 14a2fa9f43 CHANGELOG: releases/sec's GitHub security alert download script.
Thanks to xet7 !
2026-11-11 04:26:44 +02:00
Lauri Ojansivu 801f8956fe releases/sec: download a GitHub organization's Security and quality alerts with gh.
releases/sec/download-github-security.sh ORGANIZATION saves, for every
repository of the organization (or the ones named with --repo), its
Dependabot, code scanning, secret scanning and security advisory alerts
to .tools/log/sec/<organization>/<repository>/<YYYY-MM-DD_HH-MM-SS>/,
a directory per kind: alerts.json, a file per alert, an open code
scanning alert's instances, and SUMMARY.md with every open alert and its
link. It runs the GitHub CLI outside the editor's sandbox, where gh and
its login are, so the alerts can then be read and fixed from the files
inside it. A kind GitHub does not answer - not enabled, or not visible
to the account - gets status.txt with the reason and the run goes on;
archived repositories and forks are skipped unless asked for; the secret
a secret scanning alert found is redacted unless --include-secret-values
is given. A name that is not a GitHub name is refused before it becomes
a path or an API address. .tools/ keeps the downloads out of git.

tests/securityDownloadScript.test.cjs runs it against a stand-in gh: the
layout, both pages of a paginated answer, the summary, a disabled kind,
the redaction everywhere in the download and, as negatives, bad names,
no gh and gh signed out writing nothing. buildScriptParity knows why
build.sh has no menu entry for it.

Thanks to xet7 !
2026-11-11 04:25:18 +02:00
Lauri Ojansivu 4335614dcb CHANGELOG: CodeQL alerts #602 and #603 in the tests, and fast-xml-parser 5.12.0 for Dependabot alert #188.
Thanks to GitHub CodeQL, dependabot and xet7 !
2026-11-11 03:44:57 +02:00
Lauri Ojansivu a76a19058a Updated fast-xml-parser to 5.12.0, Dependabot alert #188.
fast-xml-parser <= 5.11.2, with its stopNodes option, rescanned the rest
of the input from every "<" of a stop node's body when no ">" followed,
so n such fragments cost O(n^2) CPU before it gave up (CWE-407). The
Azure and Google Cloud storage clients bring it in; each allows 5.x, so
the lock moves to 5.12.0 - which stops at the first failed scan - with
is-unsafe 2.0.3 and strnum 2.5.1, and no override.

tests/dependencySecurityUpdates.test.cjs pins that no tracked lockfile
resolves a version below 5.12.0, with a negative that the finder flags
5.11.2 at any depth, and runs the alert's input: 40,000 unterminated
fragments in a stop node are refused within two seconds. On 5.11.2 that
input grows quadratically (20,000 fragments took 1.2 s here, so 40,000
take about 5 s); on 5.12.0 it takes about a millisecond. A dependency
inside a storage client is not an attempt anybody makes, so there is
nothing to record in Admin Panel -> Problems.

Thanks to dependabot and xet7 !
2026-11-11 03:44:13 +02:00
Lauri Ojansivu 2b65b713a0 Tests: no path handed to a shell at all, CodeQL alerts #602 and #603.
The fix for #601 passed the paths to `bash -c` as arguments ("$1",
"$2") instead of pasting them into the script. That is safe in itself,
but it still hands a temporary or checkout path to a shell, and CodeQL
flagged js/shell-command-injection-from-environment again on the two
umask tests in tests/releaseDownloads.test.cjs. Those tests no longer
use a shell: fetch.sh runs as bash's program with its arguments, the
umask is set on the test's own process around the call and put back,
and `chmod +x` is fs.chmodSync. tests/macosSandbox.test.cjs, fixed the
same way for #601, now runs ls and touch as programs of sandbox-exec,
each path an argument.

The guard (tests/testShellPathsFromEnv.test.cjs) now also refuses any
value given to a shell's -c script as an argument - spawned or as a
wrapper's program - and the one other test that did so,
tests/dbConformanceWiring.test.cjs, passes its value in the environment.
Run against the files as they were, it names all three; its pattern
takes a backslash only as an escape, so a long file cannot make it
backtrack.

The findings were in tests, not in WeKan, so there is no attempt to
show in Admin Panel -> Problems.

Thanks to GitHub CodeQL and xet7 !
2026-11-11 03:44:13 +02:00
github-actions[bot] 77239ee100 Bump versions for v13.06 2026-11-10 22:50:32 +00:00
Lauri Ojansivu 3913fbd507 Prepare v13.06 release 2026-11-11 00:49:29 +02:00
Lauri Ojansivu c45359a759 CHANGELOG: CodeQL alert #601 and its siblings in the tests; the oldest October release archived to stay under GitHub's limit.
Thanks to GitHub CodeQL and xet7 !
2026-11-11 00:38:03 +02:00
Lauri Ojansivu d482856e03 Tests: no path is quoted into a bash -c script, CodeQL alert #601 and its siblings.
CodeQL flagged js/shell-command-injection-from-environment (CWE-78/88) in
tests/npmRetry.test.cjs: its bash -c script set
node_bin=${JSON.stringify(prog)} and ran bash ${JSON.stringify(script)},
pasting a path under the temporary directory and one under the checkout
into the script text. JSON's quotes are not the shell's: a path with $(,
a backtick or $ would change the command. The paths now go in through
the environment ("$NODE_BIN", "$NPM_RETRY_SCRIPT"), so the script is a
constant - and NODE_BIN is not node_bin, so the test still shows the
unbound variable it exists to show.

The guard written for alerts #549 and #550 (tests/testShellPathsFromEnv
.test.cjs) only knew `source "${path}"`. It now refuses any value quoted
into a -c script - "${...}" or ${JSON.stringify(...)} - across the tests,
while a script built from the test's own snippets stays allowed; with
the fixes taken away it names every offender. It found the same fault in
two more places, fixed as arguments ("$1", "$2"):
tests/releaseDownloads.test.cjs, which quoted fetch.sh and a temporary
file into its umask tests, and tests/macosSandbox.test.cjs, which quoted
the home and temporary paths into its sandbox probe.

The finding was in tests, not in WeKan, so there is no attempt to show
in Admin Panel -> Problems.

Thanks to GitHub CodeQL and xet7 !
2026-11-11 00:37:39 +02:00
Lauri Ojansivu 72ee10a3ed CHANGELOG: the merged REST overtime and card member fixes, their follow-ups, and cleared card dates.
Thanks to AhmedLukman and xet7 !
2026-11-11 00:08:21 +02:00
Lauri Ojansivu 32590ee7ab Card members and assignees: adding one whose account is gone no longer throws.
#6889 guarded the removal halves of the cardMembers and cardAssignees
hooks, which read user.username after a lookup that finds nobody for a
deleted account. The joining halves had the same read: the REST route
checks the user before adding, but a client $addToSet, a copied or
imported card, or a rule can still add such an id, and the hook threw.
Both now record the join with the id and no username, as a removal does.

tests/cardMemberRemoval.test.cjs runs the real hooks: adding a member
and an assignee whose account is gone records the join without
throwing; and, tree-wide, no `const x = user.field;` follows a
ReactiveCache.getUser() lookup without a guard.

Thanks to AhmedLukman and xet7 !
2026-11-11 00:07:53 +02:00
Lauri Ojansivu 569756b66c REST card overtime: an isOverTime stored before #6888 becomes isOvertime.
#6888 makes the REST card PUT write its isOverTime parameter to the
schema's isOvertime field. Every overtime set through the API before it
- since b895e61237 - was stored under isOverTime, which the UI and every
reader ignore: those cards still show no overtime.

A schema upgrade step, card-overtime-field, carries that over on the
next start: isOverTime becomes isOvertime where the card has none, the
value the UI already shows wins where it has both, and the stray field
is removed. Two updateMany batches and an $unset, version-gated and
idempotent like the steps beside it.

tests/schemaUpgradeSteps.test.cjs pins the fold, the precedence and a
second pass finding nothing; as negatives, no work on cards without the
field, and - tree-wide - no server code writing isOverTime into a card.

Thanks to AhmedLukman and xet7 !
2026-11-11 00:07:26 +02:00
Lauri Ojansivu 50334816ca Card dates: clearing one no longer goes through the timing hook as a set.
The Cards.before.update timing hook read modifier.$set[field] for any
update whose first field was a date, but unsetDue/unsetStart/unsetEnd/
unsetReceived send only a $unset. Without a $set the hook threw a
TypeError; with one beside the $unset (a stamped modifiedAt) it wrote an
a-dueAt with timeValue: undefined, which counted as a due date change
(#6081), matched the "date set or changed" rule triggers (#2474), and
showed in the activity feed as an empty date.

server/lib/timingChangeActivity.js now decides it: a date set records
timeValue, a date cleared records timeOldValue alone - the same record a
rule's removeDate writes, and the one models/lib/boardTimeline.js rewinds
- and clearing a date the card does not have records nothing. The rules
skip a cleared date before matching triggers, as server/triggersDef.js
already said they should, and the feed shows only the date it had.

tests/cardTimingActivity.test.cjs runs the real hook: a set, a $unset
alone and a $unset beside a $set (both used to fail), and clearing
nothing; and, tree-wide, no modifier.$set[...] read that assumes the $set
is there. The two guards that pinned the old inline list and its
modifier.$set[action] read now pin the helper instead.

Thanks to xet7 !
2026-11-11 00:06:31 +02:00
Lauri Ojansivu 9821478329 Merge pull request #6889 from AhmedLukman/codex/card-member-removal
Fix removal of card members and assignees with missing user accounts
2026-11-10 23:49:48 +02:00
Lauri Ojansivu ad5c35e9f3 Merge pull request #6888 from AhmedLukman/codex/rest-card-overtime
Fix REST card overtime persistence
2026-11-10 23:49:23 +02:00
Ahmed Lukman 416c69dfe2 Revert "Use optional chaining for removed assignment users"
This reverts commit 0acc9955d0.

Thanks to AhmedLukman and xet7 !
2026-11-10 16:59:39 +03:00
Ahmed Lukman 0acc9955d0 Use optional chaining for removed assignment users
Read the optional username safely when removing a card member or assignee whose account is missing.

Thanks to AhmedLukman and xet7 !
2026-11-10 16:52:39 +03:00
Ahmed Lukman 5e9d1cb630 Fix removal of missing card members and assignees
Allow card assignment removal when the target user no longer exists. Keep normal membership activity and no-op behavior intact, with unit and REST/browser regression coverage.

Thanks to AhmedLukman and xet7 !
2026-11-10 16:27:40 +03:00
github-actions[bot] 4f6832845d Bump versions for v13.05 2026-11-10 09:55:03 +00:00
Lauri Ojansivu 1ca199b607 Prepare v13.05 release 2026-11-10 11:54:10 +02:00
Lauri Ojansivu 63c6f42495 CHANGELOG: updated to Meteor 3.6.
Thanks to xet7 !
2026-11-10 09:20:28 +02:00
Lauri Ojansivu 0fbef8936f Updated to Meteor 3.6.
From 3.6-rc.1. `meteor update --release METEOR@3.6` refused it: WeKan's
forks of six Meteor packages in packages/ (allow-deny, ddp-server,
dynamic-import, facebook-oauth, google-oauth, shell-server) declared
3.6-rc.1's versions with a _1 wrap number, and a local package
overrides the release's, so ~3.6.0 could not be met. Meteor 3.6 changed
those six packages only in their version line (compared on GitHub,
release/METEOR@3.6-rc.1...release/METEOR@3.6), so each fork now
declares 3.6's version with its _1 wrap number; .meteor/packages drops
the rc pins, and .meteor/versions, @meteorjs/rspack 3.0.0 and the
lockfile are what meteor update wrote. webapp is 2.4.0.

The Dockerfile's METEOR_RELEASE is METEOR@3.6. The Bun build's patch
applies unchanged to Meteor 3.6, which still has no Bun ESM loader of
its own: it is meteor-3.6.patch, checked against 3.6's commit
e730097c. tests/meteor353SecurityFixes.test.cjs is moved to 3.6 by
decision, after that check. WeKan builds with Meteor 3.6, and the node
suites pass (2162 run, 0 failed).

Thanks to xet7 !
2026-11-10 09:20:28 +02:00
Lauri Ojansivu 0905de097b CHANGELOG: the Super Productivity fix's link names its commit after the rebase.
Thanks to xet7 !
2026-11-10 08:48:52 +02:00
Lauri Ojansivu 679ea9e63a CHANGELOG: the Android bundles build again.
Thanks to xet7 !
2026-11-10 08:48:37 +02:00
Lauri Ojansivu d08f658dea Android bundles build again: npm-retry.sh is given Android's node and npm, not a shell function.
v13.04's four Android bundle jobs all died with "environment: node:
unbound variable". v13.04 sent the Android npm installs through
releases/npm-retry.sh as `npm-retry.sh npm install`, and npm there is
build-bundle.sh's function npm() { "$node" "$npm_cli" ...; }.
npm-retry.sh is a new bash with set -u: export -f carried the function
into it, but not $node or $npm_cli, so the function failed before npm
ran - and the retry wrapper rightly called it not a network error.

The two installs now give npm-retry.sh the program itself, "$node"
"$npm_cli" install, still retried on a network error as before.
tests/npmRetry.test.cjs fails when any releases/ script gives
npm-retry.sh one of its own shell functions (it fails on the old two
lines), and reproduces the failure: an exported function without its
variable fails in npm-retry.sh, the program it runs works.

Thanks to xet7 !
2026-11-10 08:48:31 +02:00
Lauri Ojansivu dcd9fec925 CHANGELOG: the Super Productivity export no longer fails on a card whose list is archived.
Opens the Upcoming section. The fix is covered by a positive and a
negative check in tests/superProductivityFormat.test.cjs, which fails
on the old formatter; it is a pure formatter behind the REST export,
so no browser test was added, and WeKan's own server was not run here.

Thanks to xet7 !
2026-11-10 08:18:49 +02:00
Lauri Ojansivu 8b4fe0e737 Super Productivity export no longer fails on a card whose list is archived.
A card whose list is archived is collected with listTitle '', and the
Super Productivity formatter tagged such a card with tagFor(''), which
is undefined - the export then threw "Cannot read properties of
undefined (reading 'taskIds')" and the whole board's export failed.
The list with no title is now "Untitled", its tag and its panel alike,
so the panel shows its cards and every task's tags exist. The test
fails with that error on the old formatter.

Found while checking Weddy's Super Productivity export against
WeKan's formatter.

Thanks to xet7 !
2026-11-10 08:18:49 +02:00
github-actions[bot] bc698806b2 Bump versions for v13.04 2026-11-09 18:28:55 +00:00
Lauri Ojansivu 0556f01030 Prepare v13.04 release 2026-11-09 20:24:26 +02:00
Lauri Ojansivu b379a02631 CHANGELOG: the Sandstorm and Android bundles retry their npm install through a GitHub outage.
Thanks to xet7 !
2026-11-09 20:02:11 +02:00
Lauri Ojansivu c3f12b5659 Sandstorm and Android bundles retry their npm install through a GitHub outage.
v13.03's build-sandstorm died in releases/sandstorm-slim-spk.sh with
"npm error 504 Gateway Time-out - GET https://github.com/meteor/
node-source-map-support/tarball/81bce1f9..." - the same github.com outage
releases/npm-retry.sh was written for in v10.86. That install, and the
Android bundle's programs/server and sharp installs, ran npm bare, because
tests/npmRetry.test.cjs read only release-all.yml and never the scripts it
runs. All three now go through npm-retry.sh: a transient 5xx or socket
error is retried with backoff, a real npm error still fails at once.

tests/npmRetry.test.cjs now follows every releases/ script a workflow runs,
and the scripts those run, and fails on a bare npm install or ci in any of
them; it fails on the old lines. tests/androidBundles.test.cjs pins the same
installs in the same order, now through the retry.

Thanks to xet7 !
2026-11-09 20:01:57 +02:00
Lauri Ojansivu ea53de4985 CHANGELOG: ListLockBleed; the security regression inventory guards it.
The Upcoming release fixes the CRITICAL SECURITY ISSUE of ListLockBleed
(GHSA-4734-8vrg-8j3w): a list that refuses a role write access refuses that
role's checklist and checklist-item REST writes too.
tests/securityRegressionCoverage.test.cjs names its guards
(tests/listPermissions.test.cjs and
tests/playwright/specs/list-lock-checklists.e2e.js) and counts 147.

Thanks to tsurutanmen and xet7 !
2026-11-09 19:44:17 +02:00
Lauri Ojansivu 214b20e7ad ListLockBleed: a list's write refusal holds for the checklist REST routes too.
GHSA-4734-8vrg-8j3w. A board admin can refuse a role write access in one
list (#4527, list.roleExceptions). The card and comment REST routes and the
DDP checklist writes applied that refusal; the six checklist and
checklist-item REST routes asked only the board, so a member the list
refused still created, renamed, ticked and deleted its cards' checklists
and items with an API token.

They now call assertListNotRefused with the card's list, as the card routes
do, and answer 403. The refusal is recorded in Admin Panel -> Problems as
ListLockBleed (authz.list-locked, medium: recorded, never disables the
account): no screen offers such a write, so it is the lock being stepped
round. The card routes' refusals are recorded through the same gate.

tests/listPermissions.test.cjs scans every REST write route of the tree that
names a card and fails on one that does not ask the list - not only the
per-list card routes it checked before - naming the three that follow their
own rule (a comment's edit and deletion, dependency lines, a bot run's
report), and checks the refusal is recorded. It fails on the old routes.
tests/playwright/specs/list-lock-checklists.e2e.js refuses all six writes in
a locked list with 403, leaves the checklist and item untouched, records the
attempt, and still lets the same member write in an open list and the board
admin in the locked one.

Thanks to tsurutanmen and xet7 !
2026-11-09 19:41:49 +02:00
github-actions[bot] 0f89ad07b8 Bump versions for v13.03 2026-11-09 07:49:50 +00:00
Lauri Ojansivu 3fb9e4d1be Prepare v13.03 release 2026-11-09 09:47:39 +02:00
Lauri Ojansivu 5ca5b00a98 CHANGELOG: amd64 snaps wait out an archive outage; UnassignedArchiveBleed inventory.
Thanks to xet7 !
2026-11-09 09:08:09 +02:00
Lauri Ojansivu 6cc84a07cd Security regression inventory: UnassignedArchiveBleed is guarded.
The Hall of Fame published UnassignedArchiveBleed (GHSA-6xqf-jh8x-4wxc), so
tests/securityRegressionCoverage.test.cjs failed: the companion list had a
name the inventory did not. It is in GUARDED now, with the two suites that
pin the fix, and those suites name it.

Thanks to tsurutanmen and xet7 !
2026-11-09 09:07:51 +02:00
Lauri Ojansivu a7ace18af8 Snap: wait out an Ubuntu archive outage instead of failing the amd64 snaps.
v13.02's snap-native amd64 and both amd64 snap-variants failed within eight
minutes of each other with "Failed to refresh package list: failed to run
apt update" while snapcraft installed build-packages, and the arm64 snaps,
served by ports.ubuntu.com, built. releases/snap-refresh-managed-apt.py
recovered only a stale .deb 404 and refused this, so the one guarded retry
never ran.

It now also recognises a failed apt update in the managed project instance,
retries apt-get update there with a 30/60/120/240 s backoff until the archive
answers, and only then lets the Snapcraft retry run; an outage that outlasts
the backoff stays fatal. It prints apt's own E:/W:/Err: lines from the
Snapcraft log first, so a failing job says why apt failed. Anything else is
still refused.

Thanks to xet7 !
2026-11-09 09:07:51 +02:00
Ahmed Lukman f74ef4c40d Fix REST card overtime persistence
Keep accepting the isOverTime request parameter and write its validated value to the isOvertime schema field used by card readers and the UI.

Correct the handler regression and cover JSON/form edits, persistence, API reads, reactive display, reloads and rejected requests.
2026-11-06 19:04:30 +03:00
351 changed files with 3923 additions and 728 deletions

No files matched your search

+1 -1
View File
@@ -103,7 +103,7 @@ jobs:
app/.tools/meteor-bun/dev_bundle
app/.tools/meteor-bun/.babel-cache
app/.tools/meteor-bun/packages/*/.npm
key: bun-meteor-${{ runner.os }}-${{ hashFiles('app/.meteor/release', 'app/.meteor/versions', 'build-tools/releases/bun/meteor-3.6-rc.1.patch') }}
key: bun-meteor-${{ runner.os }}-${{ hashFiles('app/.meteor/release', 'app/.meteor/versions', 'build-tools/releases/bun/meteor-3.6.patch') }}
- name: Build the release's ESM application once
working-directory: app
env:
+2 -2
View File
@@ -4714,7 +4714,7 @@ jobs:
with:
snapcraft-args: pack
- name: Refresh stale managed APT indexes after a package 404
- name: Refresh managed APT after a package 404 or a failed apt update
if: steps.build-first.outcome == 'failure'
run: sudo -u "$(id -un)" -E python3 "$GITHUB_WORKSPACE/releases/snap-refresh-managed-apt.py"
@@ -5610,7 +5610,7 @@ jobs:
snapcraft-args: pack
path: variant
- name: Refresh stale managed APT indexes after a package 404
- name: Refresh managed APT after a package 404 or a failed apt update
if: steps.build-first.outcome == 'failure'
run: sudo -u "$(id -un)" -E python3 "$GITHUB_WORKSPACE/wekan/releases/snap-refresh-managed-apt.py"
+27 -27
View File
@@ -6,12 +6,12 @@
meteor-base@1.5.2
# Build system
ecmascript@0.19.2-rc360.1
standard-minifier-js@3.3.0-rc360.1
rspack@1.4.0-rc360.1
ecmascript@0.19.2
standard-minifier-js@3.3.0
rspack@1.4.0
# Declared explicitly because server/modernBrowsers.js imports it, to say that
# Yandex Browser is modern and must not be served the legacy bundle (#6557).
modern-browsers@0.2.4-rc360.1
modern-browsers@0.2.4
blaze@3.0.2
@@ -19,11 +19,11 @@ blaze@3.0.2
aldeed:collection2
aldeed:schema-index@4.0.0-beta.5
reywood:publish-composite
mongo@2.5.2-rc360.1
mongo@2.6.0
# Account system
accounts-password@3.3.2-rc360.1
accounts-2fa@3.1.1-rc360.1
accounts-password@3.3.2
accounts-2fa@3.1.1
accounts-express@1.0.0
communitypackages:core
communitypackages:unstyled
@@ -39,19 +39,19 @@ wekan-oidc
wekan-accounts-oidc
# Utilities
check@1.5.1-rc360.1
random@1.2.3-rc360.1
reactive-dict@1.3.3-rc360.1
session@1.2.4-rc360.1
tracker@1.3.5-rc360.1
check@1.5.1
random@1.2.3
reactive-dict@1.3.3
session@1.2.4
tracker@1.3.5
audit-argument-checks@1.0.8
# UI components
ostrio:i18n
reactive-var@1.0.13
shell-server@0.7.2-rc360.1
email@3.2.1-rc360.1
dynamic-import@0.8.1-rc360.1
shell-server@0.7.2
email@3.2.1
dynamic-import@0.8.1
wekan-markdown
quave:synced-cron
ostrio:cookies
@@ -59,21 +59,21 @@ ostrio:files
# lmieulet:meteor-coverage
meteortesting:mocha@3.0.0
matb33:collection-hooks
service-configuration@1.3.6-rc360.1
service-configuration@1.3.6
minifier-css@2.0.2
ejson@1.4.1-rc360.1
logging@1.3.7-rc360.1
ejson@1.4.1
logging@1.3.7
wekan-fullcalendar
wekan-fontawesome
accounts-google@1.4.2-rc360.1
accounts-github@1.5.2-rc360.1
accounts-facebook@1.3.5-rc360.1
accounts-twitter@1.5.3-rc360.1
accounts-meteor-developer@1.5.2-rc360.1
accounts-weibo@1.4.2-rc360.1
accounts-meetup@1.5.2-rc360.1
accounts-passwordless@3.1.2-rc360.1
instrumentation@0.0.1-rc360.1
accounts-google@1.4.2
accounts-github@1.5.2
accounts-facebook@1.3.5
accounts-twitter@1.5.3
accounts-meteor-developer@1.5.2
accounts-weibo@1.4.2
accounts-meetup@1.5.2
accounts-passwordless@3.1.2
instrumentation@0.0.1
# Prevent Meteor build/run tools from sending application package statistics.
package-stats-opt-out@1.0.8
+1 -1
View File
@@ -1 +1 @@
METEOR@3.6-rc.1
METEOR@3.6
+74 -74
View File
@@ -1,130 +1,130 @@
accounts-2fa@3.1.1-rc360.1
accounts-base@3.4.0-rc360.1
accounts-2fa@3.1.1
accounts-base@3.4.0
accounts-express@1.0.0
accounts-facebook@1.3.5-rc360.1
accounts-github@1.5.2-rc360.1
accounts-google@1.4.2-rc360.1
accounts-meetup@1.5.2-rc360.1
accounts-meteor-developer@1.5.2-rc360.1
accounts-oauth@1.4.8-rc360.1
accounts-password@3.3.2-rc360.1
accounts-passwordless@3.1.2-rc360.1
accounts-twitter@1.5.3-rc360.1
accounts-weibo@1.4.2-rc360.1
accounts-facebook@1.3.5
accounts-github@1.5.2
accounts-google@1.4.2
accounts-meetup@1.5.2
accounts-meteor-developer@1.5.2
accounts-oauth@1.4.8
accounts-password@3.3.2
accounts-passwordless@3.1.2
accounts-twitter@1.5.3
accounts-weibo@1.4.2
aldeed:collection2@4.2.2
aldeed:schema-index@4.0.0
aldeed:simple-schema@1.13.1
allow-deny@2.1.2-rc360.1_1
allow-deny@2.1.2_1
audit-argument-checks@1.0.8
autoupdate@2.0.2-rc360.1
babel-compiler@7.15.2-rc360.1
autoupdate@2.0.2
babel-compiler@7.15.2
babel-runtime@1.5.2
base64@1.0.15-rc360.1
binary-heap@1.0.14-rc360.1
base64@1.0.15
binary-heap@1.0.14
blaze@3.0.3
blaze-tools@2.0.1
boilerplate-generator@2.2.0-rc360.1
boilerplate-generator@2.2.0
caching-compiler@2.0.1
caching-html-compiler@2.0.1
callback-hook@1.8.1-rc360.1
check@1.5.1-rc360.1
callback-hook@1.8.1
check@1.5.1
communitypackages:core@2.0.3
communitypackages:flow-routing@2.1.0
communitypackages:unstyled@2.0.1
core-runtime@1.0.0
ddp@1.4.3-rc360.1
ddp-client@3.4.2-rc360.1
ddp-common@1.4.6-rc360.1
ddp-rate-limiter@1.3.1-rc360.1
ddp-server@3.6.0-rc360.1_1
diff-sequence@1.2.1-rc360.1
dynamic-import@0.8.1-rc360.1_1
ecmascript@0.19.2-rc360.1
ddp@1.4.3
ddp-client@3.4.2
ddp-common@1.4.6
ddp-rate-limiter@1.3.1
ddp-server@3.6.0_1
diff-sequence@1.2.1
dynamic-import@0.8.1_1
ecmascript@0.19.2
ecmascript-runtime@0.8.3
ecmascript-runtime-client@0.13.0
ecmascript-runtime-server@0.11.1
ejson@1.4.1-rc360.1
email@3.2.1-rc360.1
ejson@1.4.1
email@3.2.1
es5-shim@4.8.1
facebook-oauth@1.12.1-rc360.1_1
facts-base@1.0.3-rc360.1
fetch@0.2.1-rc360.1
geojson-utils@1.0.13-rc360.1
github-oauth@1.4.3-rc360.1
google-oauth@1.5.1-rc360.1_1
facebook-oauth@1.12.1_1
facts-base@1.0.3
fetch@0.2.1
geojson-utils@1.0.13
github-oauth@1.4.3
google-oauth@1.5.1_1
hot-code-push@1.0.5
html-tools@2.0.1
htmljs@2.0.2
id-map@1.2.1-rc360.1
instrumentation@0.0.1-rc360.1
inter-process-messaging@0.1.4-rc360.1
id-map@1.2.1
instrumentation@0.0.1
inter-process-messaging@0.1.4
jquery@3.0.2
lai:collection-extensions@1.0.0
localstorage@1.2.1
logging@1.3.7-rc360.1
logging@1.3.7
matb33:collection-hooks@2.1.0
meetup-oauth@1.1.4-rc360.1
meteor@2.3.2-rc360.1
meetup-oauth@1.1.4
meteor@2.3.2
meteor-base@1.5.2
meteor-developer-oauth@1.3.4-rc360.1
meteor-developer-oauth@1.3.4
meteortesting:browser-tests@1.8.0
meteortesting:mocha@3.4.0
meteortesting:mocha-core@8.2.0
minifier-css@2.0.2
minifier-js@3.3.2-rc360.1
minimongo@2.2.1-rc360.1
modern-browsers@0.2.4-rc360.1
minifier-js@3.3.2
minimongo@2.2.1
modern-browsers@0.2.4
modules@0.20.3
modules-runtime@0.13.2
mongo@2.5.2-rc360.1
mongo@2.6.0
mongo-decimal@0.2.0
mongo-dev-server@1.1.1
mongo-id@1.0.10-rc360.1
npm-mongo@6.18.1-rc360.1
oauth@3.0.5-rc360.1
oauth1@1.5.4-rc360.1
mongo-id@1.0.10
npm-mongo@6.18.1
oauth@3.0.5
oauth1@1.5.4
oauth2@1.3.3
observe-sequence@2.0.1
ordered-dict@1.2.1-rc360.1
ordered-dict@1.2.1
ostrio:cookies@2.9.2
ostrio:cstorage@4.0.1
ostrio:files@3.0.1
ostrio:flow-router-extra@3.15.3
ostrio:i18n@3.2.1
package-stats-opt-out@1.0.8
promise@1.0.1-rc360.1
promise@1.0.1
quave:synced-cron@2.4.0
raix:eventemitter@1.0.0
random@1.2.3-rc360.1
rate-limit@1.2.1-rc360.1
random@1.2.3
rate-limit@1.2.1
react-fast-refresh@0.3.0
reactive-dict@1.3.3-rc360.1
reactive-dict@1.3.3
reactive-var@1.0.13
reload@1.3.3-rc360.1
retry@1.1.2-rc360.1
reload@1.3.3
retry@1.1.2
reywood:publish-composite@1.9.0
routepolicy@1.1.3-rc360.1
rspack@1.4.0-rc360.1
service-configuration@1.3.6-rc360.1
session@1.2.4-rc360.1
sha@1.0.11-rc360.1
shell-server@0.7.2-rc360.1_1
socket-stream-client@0.7.2-rc360.1
routepolicy@1.1.3
rspack@1.4.0
service-configuration@1.3.6
session@1.2.4
sha@1.0.11
shell-server@0.7.2_1
socket-stream-client@0.7.2
spacebars@2.0.1
spacebars-compiler@2.0.1
standard-minifier-js@3.3.0-rc360.1
standard-minifier-js@3.3.0
templating@1.4.5
templating-compiler@2.0.1
templating-runtime@2.0.2
templating-tools@2.0.1
tools-core@1.4.0-rc360.1
tracker@1.3.5-rc360.1
twitter-oauth@1.3.5-rc360.1
typescript@5.11.2-rc360.1
url@1.3.7-rc360.1
webapp@2.3.1-rc360.1
webapp-hashing@1.1.3-rc360.1
weibo-oauth@1.3.4-rc360.1
tools-core@1.4.0
tracker@1.3.5
twitter-oauth@1.3.5
typescript@5.11.2
url@1.3.7
webapp@2.4.0
webapp-hashing@1.1.3
weibo-oauth@1.3.4
wekan-accounts-cas@0.2.0
wekan-accounts-lockout@1.1.0
wekan-accounts-oidc@1.0.10
+396 -432
View File
@@ -124,6 +124,402 @@ its reason.
</details>
# v13.07 2026-11-12 WeKan ® release
**In short:** **ListLockAttachBleed** is fixed: when a list refuses a role
write access, that refusal now also holds for the attachment API's upload,
delete, copy and move. **CodeQL** alerts #602 and #603 in the tests are fixed,
**fast-xml-parser** is updated to 5.12.0, spent time reads as a **duration**,
the **indexes** that LDAP, card member and History queries need are added, and
Admin Panel → Problems can **Clear** resolved problems, which also age out.
This release fixes the following CRITICAL SECURITY ISSUE of [ListLockAttachBleed](https://wekan.fi/hall-of-fame/listlockattachbleed/):
<details>
<summary><a href="https://github.com/wekan/wekan/commit/7bb3e13ba9">A list that refuses a role write access refuses its attachment API writes too</a>. Thanks to Furkan Derse and xet7.</summary>
[ListLockAttachBleed](https://wekan.fi/hall-of-fame/listlockattachbleed/),
reported by email, its GitHub security advisory awaited. A board admin can
refuse a role write access in one list (#4527). The card screen, the card and
checklist routes ([ListLockBleed](https://wekan.fi/hall-of-fame/listlockbleed/))
and the interface's own attachment upload and delete applied that refusal, but
the attachment API's upload, delete, copy and move, over REST and DDP, asked
only for board write access and the assigned-only rule. A normal member the
list refused could therefore still add and remove files on its cards. Every
attachment write that names a card now asks that card's list as well, a move
both the card it takes the file from and the one it puts it on, and the
refusal shows in Admin Panel / Problems. `tests/listLockAttachments.test.cjs`
runs the guard on the reported case and fails on any attachment write in the
tree without the list check beside it, and
`tests/playwright/specs/list-lock-attachments.e2e.js` replays the writes
against a running server.
</details>
and fixes the following SECURITY ISSUES found by GitHub CodeQL code scanning:
<details>
<summary><a href="https://github.com/wekan/wekan/commit/2b65b713a0f7b537efbe7c25bb2a8b454e88d1ad">Alerts #602 and #603: no test hands a path to a shell at all</a>. Thanks to GitHub CodeQL and xet7.</summary>
The fix for #601 passed the paths to `bash -c` as arguments rather than
pasting them into the script, but that still hands a temporary path to a
shell, and CodeQL flagged the two umask tests in
`tests/releaseDownloads.test.cjs` again. They no longer use a shell: `fetch.sh`
runs as bash's program with its arguments, the umask is set on the test's
process and put back, and `chmod +x` is `fs.chmodSync`. The macOS sandbox test
runs its probes as programs the same way. The guard now refuses any value
given to a shell's `-c` script as an argument, and found one more test doing
it. The findings were in tests, not in WeKan, so there is no attempt to show in
Admin Panel → Problems.
</details>
and adds the following new features:
**The Admin Panel** - Problems, and getting rid of the ones that are handled.
<details>
<summary><a href="https://github.com/wekan/wekan/commit/fefabbf113">Problems has a Clear button, and resolved problems age out on their own</a>. Thanks to Raymond-Voogt and xet7.</summary>
The problem streams were append-only, and Acknowledge only reset the "new"
count, so a problem fixed long ago stayed in the table and buried the ones
that are live now. Clear, beside Acknowledge, calls the admin-only
`clearEventLog`, which deletes the checked streams' events up to now and
stamps the acknowledgement. Anything that happens after the click shows as a
new problem again, and an unknown stream in the list clears nothing. A daily
sweep, claimed once per installation, deletes events older than
`EVENTLOG_RETENTION_DAYS` (default 90, `0` keeps them forever); a recurring
problem's folded row keeps a recent date, so it stays. The setting is listed
on every platform and in the Helm chart, and the button is translated to
every language. `tests/eventLogClearAndRetention.test.cjs` runs Clear and the
sweep on an in-memory log, including a non-admin and an unknown stream, and
`tests/playwright/specs/problems-clear.e2e.js` clears one stream in the UI.
</details>
and updates the following dependencies:
- [**fast-xml-parser 5.11.2 → 5.12.0**](https://github.com/wekan/wekan/commit/a76a19058ac896651ccd30311c36d48ee7f47b86) — Dependabot
alert #188: with `stopNodes`, an unterminated stop node made it rescan the
rest of the input from every `<`, O(n²) CPU; 5.12.0 stops at the first
failed scan. Brought in by the Azure and Google Cloud storage clients. The
test runs the alert's input and pins that no lockfile resolves an older
version. Thanks to dependabot.
and fixes the following bugs:
**Cards** - how spent time is shown.
<details>
<summary><a href="https://github.com/wekan/wekan/commit/3e8e8039ff">Spent time is shown as a duration, not decimal hours</a>. Thanks to brlin-tw and xet7.</summary>
A card's spent time showed as decimal hours, such as 12.58 for 12 hours and
35 minutes, which reads as twelve hours and fifty-eight minutes. The badge now
shows `12h35m`, drops the units that are zero and shows `0s` for none, and its
tooltip keeps the rounded hours. The formatter is
`models/lib/spentTimeFormat.js`; `tests/spentTimeFormat.test.cjs` pins it and
`tests/playwright/specs/spent-time-format.e2e.js` checks the badge. A
follow-up imports it the way `cardTime.js` imports its other helpers.
</details>
**The REST API** - logging out a token.
<details>
<summary><a href="https://github.com/wekan/wekan/commit/fd59a8ff70">POST /api/deletetoken waits for the token to be deleted before answering</a>. Thanks to AhmedLukman and xet7.</summary>
`Accounts.destroyToken` was not awaited, so the route answered success before
the token was gone, and a failed database write never reached its error
handler. It is awaited now. `tests/restTokenRevocation.test.cjs` covers a slow
and a failed deletion, authorization and session isolation, and
`tests/playwright/specs/rest-token-revocation.e2e.js` logs a browser out with
it.
</details>
**Database indexes** - the queries that scanned whole collections.
<details>
<summary><a href="https://github.com/wekan/wekan/commit/8dc77a89d8">Indexes for the LDAP id, cards' assignees and members, and History by entity and hash</a>. Thanks to Raymond-Voogt and xet7.</summary>
An LDAP login looked the user up by `services.ldap.id`, a member's cards were
found by `assignees` and `members`, and the card history by entity and by
integrity hash, all without an index, so each scanned its whole collection on
a large installation. They have indexes now, the LDAP one sparse.
`tests/cardQueryIndexes.test.cjs` and `tests/ldapAndHistoryIndexes.test.cjs`
pin them.
</details>
and adds the following developer tool:
<details>
<summary><a href="https://github.com/wekan/wekan/commit/801f8956fe813a5da0264abf660c18363d2d3bc2">releases/sec downloads a GitHub organization's Security and quality alerts with gh</a>. Thanks to xet7.</summary>
`releases/sec/download-github-security.sh wekan` saves every repository's
Dependabot, code scanning, secret scanning and security advisory alerts to
`.tools/log/sec/<organization>/<repository>/<YYYY-MM-DD_HH-MM-SS>/`, a
directory per kind with a file per alert and a `SUMMARY.md` of the open ones.
It runs the GitHub CLI outside the editor's sandbox, where `gh` and its login
are, so the alerts can be read and fixed from the files inside it. A kind
GitHub does not answer is recorded with its reason, a secret scanning alert's
secret is redacted unless asked for, and a name that is not a GitHub name is
refused before it becomes a path. The test runs it against a stand-in `gh`;
see `releases/sec/README.md`.
</details>
Thanks to above GitHub users for their contributions and translators for their translations.
# v13.06 2026-11-11 WeKan ® release
**In short:** **CodeQL** alert #601 in a test is fixed, with two more tests
that had the same fault. A card's **overtime** set through the REST API is
saved where WeKan reads it, and cards that lost it before are repaired at
startup. Card **members and assignees** whose account was deleted can be removed
and added without an error, and clearing a card **date** no longer passes as a
date set to the rules, the due date count and the activity feed.
This release fixes the following SECURITY ISSUES found by GitHub CodeQL code scanning:
<details>
<summary><a href="https://github.com/wekan/wekan/commit/d482856e03129d13c6e171a1503db60d81ab5166">Alert #601: no path is quoted into a bash -c script in the tests</a>. Thanks to GitHub CodeQL and xet7.</summary>
CodeQL flagged a shell command built from environment values (CWE-78, CWE-88)
in `tests/npmRetry.test.cjs`, whose `bash -c` script pasted a temporary path
and a checkout path into its text with `JSON.stringify` - JSON's quotes are not
the shell's, so a path with `$(`, a backtick or `$` would change the command.
The paths now go in through the environment. The guard written for alerts #549
and #550 only knew `source "${path}"`; it now refuses any value quoted into a
`-c` script across the tests, and found the same fault in
`tests/releaseDownloads.test.cjs` and `tests/macosSandbox.test.cjs`, fixed as
arguments. The finding was in tests, not in WeKan, so there is no attempt to
show in Admin Panel → Problems.
</details>
and fixes the following bugs:
**Card overtime** - what the REST API stores, and what it stored before.
<details>
<summary><a href="https://github.com/wekan/wekan/commit/f74ef4c40d85f9f6b91b8f4ecfc7372f67d32100">A REST card update saves isOverTime as the isOvertime WeKan reads</a>. Thanks to AhmedLukman.</summary>
A PUT with `{"isOverTime": true}` answered 200 and changed nothing anyone saw:
the handler wrote `isOverTime`, while the schema and the UI use `isOvertime`.
The request keeps its spelling and the validated value is stored in
`isOvertime`. Browser tests cover JSON and form updates, the stored value, a
REST read, the open card, a reload, and refused requests, and the unit test
pins the stored field name.
</details>
<details>
<summary><a href="https://github.com/wekan/wekan/commit/569756b66c0fc3e3c41aba93fa8311994c6fa754">An isOverTime stored before that fix becomes isOvertime at startup</a>. Thanks to AhmedLukman and xet7.</summary>
Every overtime set through the API since `b895e61237` was stored under the
field nothing reads. The `card-overtime-field` schema upgrade step folds it
into `isOvertime` where the card has none, keeps the value the UI already shows
where it has both, and removes the stray field - version-gated and idempotent
like the steps beside it. Tests pin the fold, the precedence and a second pass
finding nothing; as negatives, no work on cards without the field, and no
server code writing `isOverTime` into a card.
</details>
**Card members and assignees** - people whose account is gone.
<details>
<summary><a href="https://github.com/wekan/wekan/commit/5e9d1cb6305a4a36f9cb890c7f5babb66ab4f43c">A member or assignee whose account is gone can be removed</a>. Thanks to AhmedLukman.</summary>
Removing a card member or assignee whose user account no longer exists read
`user.username` of nobody and answered HTTP 500, so the stale id could never
be removed. Both removal hooks now look the name up safely and still record
the removed id. Unit tests run the real hooks, and browser tests cover stale,
missing, repeated and normal removals with their authentication and scope
checks.
</details>
<details>
<summary><a href="https://github.com/wekan/wekan/commit/32590ee7ab89b41ca6f764a58ec0f43d56d48ab8">Adding a member or assignee whose account is gone no longer throws either</a>. Thanks to AhmedLukman and xet7.</summary>
The joining halves of the same two hooks had the same read. The REST route
checks the user before adding, but a client update, a copied or imported card,
or a rule can still add such an id. Both now record the join with the id and
no username. Tests run the real hooks, and a tree-wide test finds no
`const x = user.field;` straight after a user lookup without a guard.
</details>
**Card dates** - what clearing a date records.
<details>
<summary><a href="https://github.com/wekan/wekan/commit/50334816caf227237124b007c53a467c8f6919f5">Clearing a card date no longer passes through the timing hook as a date set</a>. Thanks to xet7.</summary>
The hook that records `a-dueAt` and the other date activities read
`modifier.$set[field]` for every date update, but clearing a date sends only a
`$unset`: without a `$set` the hook threw, and with one beside it an `a-dueAt`
without a value was written - counted as a due date change (#6081), matched by
the "date set or changed" rule triggers (#2474) and shown as an empty date in
the activity feed. Now a date set records its value, a date cleared records
only the date it had - as a rule's removeDate does, and as the board timeline
rewinds - and clearing a date the card does not have records nothing. The rules
skip a cleared date, and the feed shows only the date it had. Tests run the real
hook with a set, a `$unset` alone and a `$unset` beside a `$set`, and a
tree-wide test finds no `modifier.$set[...]` read that assumes the `$set` is
there.
</details>
Thanks to above GitHub users for their contributions and translators for their translations.
# v13.05 2026-11-10 WeKan ® release
**In short:** WeKan is updated to **Meteor 3.6**. The **Android** bundles
build again, after v13.04's npm retry broke their install, and the **Super
Productivity** export no longer fails for a board with a card whose list is
archived.
This release updates the following dependencies:
<details>
<summary><a href="https://github.com/wekan/wekan/commit/0fbef8936fa2524d21048669e4c41be15e4e3f38">Updated to Meteor 3.6</a>. Thanks to xet7.</summary>
From 3.6-rc.1. `meteor update` refused it, because WeKan's forks of six Meteor
packages in `packages/` declared 3.6-rc.1's versions, and a local package
overrides the release's. Meteor 3.6 changed those six only in their version
line, so each fork now declares 3.6's version with its `_1` wrap number. The
Dockerfile builds with Meteor 3.6, and the Bun build's patch applies unchanged
to it as `meteor-3.6.patch`. WeKan builds with Meteor 3.6, and the node suites
pass.
</details>
and fixes the following bugs:
**Release builds** - what the release workflow builds.
<details>
<summary><a href="https://github.com/wekan/wekan/commit/d08f658deae3b8369b75f1c54371ad8c1cf9367d">The Android bundles build again: npm-retry.sh is given Android's node and npm</a>. Thanks to xet7.</summary>
v13.04's four Android bundle jobs all failed with "environment: node: unbound
variable". v13.04 sent the Android npm installs through
`releases/npm-retry.sh` by the name of `build-bundle.sh`'s own `npm` shell
function. `npm-retry.sh` is a new bash with `set -u`: the exported function
reached it, but the `$node` and `$npm_cli` it reads did not, so it failed before
npm ran. The two installs now give `npm-retry.sh` the program itself, still
retried on a network error. `tests/npmRetry.test.cjs` fails when any
`releases/` script gives `npm-retry.sh` one of its own shell functions, and
reproduces the failure.
</details>
**Exports** - a board in another tool's format.
<details>
<summary><a href="https://github.com/wekan/wekan/commit/8b4fe0e7376194c498219a0b496340a94020098a">The Super Productivity export no longer fails on a card whose list is archived</a>. Thanks to xet7.</summary>
A card whose list is archived is collected with an empty list title. The
Super Productivity formatter tagged that card with a tag that did not exist, so
the export threw "Cannot read properties of undefined (reading 'taskIds')" and
the whole board's export failed. That list is now "Untitled", for its tag and
its panel alike, so the panel shows its cards and every tag a task names
exists. `tests/superProductivityFormat.test.cjs` fails with that error on the
old formatter. It was found while checking Weddy's Super Productivity export
against WeKan's formatter.
</details>
Thanks to above GitHub users for their contributions and translators for their translations.
# v13.04 2026-11-09 WeKan ® release
**In short:** **ListLockBleed** is fixed: when a list refuses a role write
access, that refusal now also holds for the checklist and checklist-item REST
routes. The **Sandstorm** and **Android** bundles retry their npm install when
github.com is briefly unavailable.
This release fixes the following CRITICAL SECURITY ISSUE of [ListLockBleed](https://wekan.fi/hall-of-fame/listlockbleed/):
<details>
<summary><a href="https://github.com/wekan/wekan/commit/214b20e7ad">A list that refuses a role write access refuses its checklist REST writes too</a>. Thanks to tsurutanmen and xet7.</summary>
[ListLockBleed](https://wekan.fi/hall-of-fame/listlockbleed/),
[GHSA-4734-8vrg-8j3w](https://github.com/wekan/wekan/security/advisories/GHSA-4734-8vrg-8j3w).
A board admin can refuse a role write access in one list (#4527). The card
and comment REST routes and the DDP checklist writes applied that refusal,
but the six checklist and checklist-item REST routes asked only the board. A
member the list refused could therefore still create, rename, tick and delete
the checklists of its cards with an API token. Those routes now ask the
card's list and answer 403, and the refusal shows in Admin Panel / Problems.
`tests/listPermissions.test.cjs` fails for any REST write route of the tree
that names a card without asking its list. And
`tests/playwright/specs/list-lock-checklists.e2e.js` replays the six writes
against a running server.
</details>
and fixes the following bugs:
**Release builds** - what the release workflow does when a download fails.
<details>
<summary><a href="https://github.com/wekan/wekan/commit/c3f12b5659">The Sandstorm and Android bundles retry their npm install through a GitHub outage</a>. Thanks to xet7.</summary>
v13.03's Sandstorm .spk failed with "npm error 504 Gateway Time-out" for
github.com's `meteor/node-source-map-support` tarball: the same kind of
outage `releases/npm-retry.sh` has retried since v10.86. That install in
`releases/sandstorm-slim-spk.sh`, and the Android bundle's server and sharp
installs, ran npm without it, because `tests/npmRetry.test.cjs` read only
`release-all.yml`. All three go through the retry now. The test follows
every `releases/` script a workflow runs and fails on a bare npm install in
any of them.
</details>
Thanks to above GitHub users for their contributions and translators for their translations.
# v13.03 2026-11-09 WeKan ® release
**In short:** The amd64 **snaps** no longer fail the release when the Ubuntu
archive is briefly unreachable: the build waits for it and retries once.
This release fixes the following bugs:
**Release builds** - what the release workflow does when a build fails.
<details>
<summary><a href="https://github.com/wekan/wekan/commit/a7ace18af8">The amd64 snaps wait out an Ubuntu archive outage instead of failing</a>. Thanks to xet7.</summary>
v13.02's native amd64 snap and both amd64 snap variants failed within eight
minutes of each other with "Failed to refresh package list: failed to run apt
update" while Snapcraft installed build-packages; the arm64 snaps, served by
`ports.ubuntu.com`, built. `releases/snap-refresh-managed-apt.py` recovered
only a stale `.deb` 404, so the one guarded retry never ran. It now also
recognises a failed apt update in the managed build instance, retries
`apt-get update` there with a 30/60/120/240 s backoff, and lets the Snapcraft
retry run only once the archive answers; a longer outage stays fatal. It
prints apt's own error lines first, so a failing job says why apt failed.
`tests/snap-managed-apt.py` pins the recovery, its bound, and that unrelated
failures are still refused.
</details>
and has the following developer-tooling fix:
<details>
<summary><a href="https://github.com/wekan/wekan/commit/6cc84a07cd">The security regression inventory counts UnassignedArchiveBleed as guarded</a>. Thanks to tsurutanmen and xet7.</summary>
`tests/securityRegressionCoverage.test.cjs` failed once the Hall of Fame
published UnassignedArchiveBleed, because its inventory did not have the name.
It is guarded now by `tests/assignedCardMethods.test.cjs` and
`tests/playwright/specs/assigned-card-methods.e2e.js`, which name it.
</details>
Thanks to above GitHub users for their contributions and translators for their translations.
# v13.02 2026-11-09 WeKan ® release
**In short:** **UnassignedArchiveBleed** is fixed: a member with the
@@ -8210,435 +8606,3 @@ workflow that is code is imported disabled. Pinned by
</details>
Thanks to above GitHub users for their contributions and translators for their translations.
# v12.41 2026-10-14 WeKan ® release
**In short:** **custom board roles**, **per-list permissions** and boards
**every signed-in user may edit**; board **keys** (`DEV-7`) and **shared
labels**; WeKan serves **HTTPS** itself; **Bun single files** and **musl
bundles and AppImages** for Alpine; on **Sandstorm**, webhooks and list sync
leave through the Powerbox and the REST API takes a grain API key. Seventeen
locale files that held **another
language**, and six full of machine-fill prefixes, are rewritten in their
own, and fourteen **GitHub CodeQL** alerts are fixed.
This release fixes the following SECURITY ISSUES found by GitHub CodeQL code scanning:
<details>
<summary><a href="https://github.com/wekan/wekan/commit/2352f1f44f">HTML tags are removed until none are left, and no input is spliced into a pattern</a>. Thanks to GitHub CodeQL and xet7.</summary>
- **#570, #571:** an HTML-only email became card text with one pass of each
removal, so a script element spliced together by removing an inner one
survived, and its contents reached the card. Both removals now run until
nothing changes.
- **#574:** the single file's settings writer put the setting name into a
regular expression. A setting must be an environment variable name and is
compared literally, and a value must be one line. The kept-versions reader
now reads file names literally too.
- **#572, #573, #575-#580:** tests escaped only some characters, or matched
example hostnames with unescaped dots; they compare literally or escape
fully now.
`tests/tagStrippingFixedPoint.test.cjs` now also catches the `<[^>]+>`
spelling it missed, which also found the search-index text of Office
documents: never rendered, so recorded as such. `tests/emailToCard.test.cjs`
fails on the old code. Nothing here is an attempt the server refuses at run
time, so no Admin Panel / Problems key is added.
</details>
<details>
<summary><a href="https://github.com/wekan/wekan/commit/167ccf9e2d">An email's HTML becomes text in one pass, with no pattern to take apart</a>. Thanks to GitHub CodeQL and xet7.</summary>
CodeQL alerts #581 and #582 were raised on the fix above: email to card
still removed `<script>` elements and tags with regular expressions, looped
to a fixed point through a helper that CodeQL does not follow. `htmlToText`
in `models/lib/emailToCard.js` now walks the characters once. A tag is
dropped whole, a script, style or head element goes with what is in it (also
unclosed), an unfinished tag is not kept as text, and a `<` that does not
start a tag stays text - except right before another `<`, where it would
read as a tag once the next one is gone. `tests/emailToCard.test.cjs` covers
those cases, and `tests/tagStrippingFixedPoint.test.cjs` no longer accepts a
fixed-point helper and now also catches a whole element removed by pattern,
in every file. Nearly every HTML email has a `<style>`, so a removed element
is ordinary use, not an attempt: no Admin Panel / Problems key is added.
</details>
<details>
<summary><a href="https://github.com/wekan/wekan/commit/73fcfb8545">No HTTP response sends the request back, tests included</a>. Thanks to GitHub CodeQL and xet7.</summary>
CodeQL alert #583: the HTTPS test's server answered with the request's own
URL in the body, the shape of reflected cross-site scripting. It now names
the page by comparison. `tests/noReflectedRequest.test.cjs` keeps the shape
out of every file. Test code only, so no Admin Panel / Problems key is added.
</details>
and adds the following new features:
**Board roles** - who may do what on a board, and where a membership comes from.
<details>
<summary><a href="https://github.com/wekan/wekan/commit/50bb989eb8">Custom board roles, built in the Admin Panel from what a member may do</a>. Thanks to xet7.</summary>
In Admin Panel / People / Roles a site admin builds named roles from five
capabilities: sees all cards, comments, edits, moves cards, invites. A board
admin then gives one to a member in the same popup as the built-in roles.
Board admin stays a built-in role. Every check asks the capability table,
which answers from the custom role. The member's built-in flags carry the
strongest built-in role that grants nothing more, so code reading a flag
never grants more, and a deleted role leaves exactly that. This holds for
every combination, which `tests/customBoardRoles.test.cjs` checks.
Invitations, REST reads, imports and member mapping follow it. The comment
form, reactions and chat now ask the comment capability, so a No comments
member is no longer offered reactions the server refuses. The new strings are
translated in all 234 languages, and the Roles Status table gains a Move cards
column. See [Board roles](docs/Features/Members/Roles.md#custom-roles).
</details>
<details>
<summary><a href="https://github.com/wekan/wekan/commit/50bb989eb8">A membership that came through a team or organization leaves with it</a>. Thanks to mfnalex and xet7.</summary>
Joining a team already added its boards; leaving it now takes away the
memberships it gave, and only those. Each records where it came from
(`grantedBy`), so a direct membership is never touched and a board admin is
kept. A board admin's own add or removal is final. This covers user edits,
LDAP, OIDC, the board sidebar, and organizations that propagate their
members. `tests/groupBoardMembership.test.cjs` covers the decisions, and a
runtime test joins, leaves and rejoins a team against a real database.
</details>
**Outgoing requests** - webhooks and downloads.
<details>
<summary><a href="https://github.com/wekan/wekan/commit/78957e14cb">Outgoing webhooks go through an HTTP proxy, with the SSRF checks kept</a>. Thanks to gbarre and xet7.</summary>
`HTTP_PROXY`, `HTTPS_PROXY` and `NO_PROXY` work for every outgoing request
(on the snap: `http-proxy`, `https-proxy`, `no-proxy`). The destination is
still resolved and checked first, and the proxy is given that checked
address, never the name: an `http://` request goes in absolute form, an
`https://` one through a `CONNECT` tunnel, with TLS still checked against the
real name. A destination the guard refuses never reaches the proxy.
`tests/outboundProxy.test.cjs` runs a real proxy on loopback. See
[Proxy](docs/Features/Webhooks/Proxy.md).
</details>
**Who may edit where** - boards open to every signed-in user, and lists with
rules of their own.
<details>
<summary><a href="https://github.com/wekan/wekan/commit/7595727917">A board can let every signed-in user edit it, when the Admin Panel allows it</a>. Thanks to Meeques and xet7.</summary>
Admin Panel / Settings / Visibility gains "Allow boards that every signed-in
user may edit", off by default. With it on, a board admin of a public board
or one open to every signed-in user can turn it on for that board in the
visibility popup. A signed-in non-member may then comment, edit and move
cards like a Normal member - never change the board - and their first edit
makes them a Normal member, so every change stays attributed. A member keeps
their own role, a member a board admin removed stays removed, and rules,
webhooks, inbound email and list sync never act with a non-member's rights.
Board-wide settings such as list width and sticky headers stay members-only.
`tests/instanceEditing.test.cjs` and a runtime test cover it. See
[Visibility](docs/Features/Admin-Panel/Settings/Visibility.md).
</details>
<details>
<summary><a href="https://github.com/wekan/wekan/commit/7595727917">Lists can allow or refuse editing and commenting per role</a>. Thanks to Meeques and xet7.</summary>
The list menu gains List permissions, for board admins: for each role -
built-in, custom, and on an open board everyone signed in - Edit and Comment
are as on the board, allowed, or not allowed in this list. The issue's
example works: a read-only board with one list where everybody may add cards
and comment. A board admin is never restricted, and a removed member stays
removed. The server applies it to every card, checklist, attachment and
comment write and to moves into the list, and the REST API honours a list's
refusal on every per-list card route. Only the board admin method writes the
setting; a direct write is refused and shown in Admin Panel / Problems.
`tests/listPermissions.test.cjs` and a runtime test cover it. See
[List permissions](docs/Features/Board/List-Permissions.md).
</details>
**Boards and cards** - keys, card numbers and labels shared between boards.
<details>
<summary><a href="https://github.com/wekan/wekan/commit/7595727917">Every board has a key, and card numbers show as KEY-7</a>. Thanks to justinr1234 and xet7.</summary>
A key is 2-10 capital letters and digits, unique in the instance, suggested
from the board's title (Development Team: DT) and set for every existing
board at startup. A board admin can change it in the rename popup. Cards show
`DEV-7` instead of `#7`, and searching for `DEV-7` finds that card. The
per-board numbers themselves are unchanged, so nothing is renumbered.
`tests/boardKey.test.cjs` and a runtime test cover it. See
[Board key](docs/Features/Board/Boards/Board-Key.md).
</details>
<details>
<summary><a href="https://github.com/wekan/wekan/commit/7595727917">Shared labels for every board, an organization's boards or a team's</a>. Thanks to tiFabGrinch, ejlkemper and xet7.</summary>
Admin Panel / Labels keeps labels shared by every board, or by the boards of
one organization or team. A board offers them in its labels popup beside its
own, and using one copies it to the board linked to the shared label, so
renaming it or changing its colour in the Admin Panel changes it everywhere
it is used. Deleting a shared label leaves it on those boards as their own.
Only labels a member's own organizations and teams share are sent to them.
`tests/sharedLabels.test.cjs` and a runtime test cover it. See
[Shared labels](docs/Features/Board/Shared-Labels.md).
</details>
**Servers** - running WeKan without a proxy in front of it.
<details>
<summary><a href="https://github.com/wekan/wekan/commit/1bf7a62cab">WeKan serves HTTPS itself, when a certificate is configured</a>. Thanks to 68040 and xet7.</summary>
With `HTTPS_PORT`, `HTTPS_CERT_FILE` and `HTTPS_KEY_FILE` set (a path or
the PEM itself), WeKan also listens for HTTPS, on the same app, and
`HTTPS_REDIRECT=true` sends plain-HTTP requests there. Without them nothing
changes, and a proxy such as Caddy stays the recommendation for production.
The snap has `https-port`, `https-cert-file`, `https-key-file` and
`https-redirect`. `tests/httpsServer.test.cjs` makes a real TLS connection.
See [HTTPS without a proxy](docs/Platforms/Webserver/HTTPS-without-proxy.md).
</details>
**Platforms** - more ways to run WeKan.
<details>
<summary><a href="https://github.com/wekan/wekan/commit/b1e58094f4">Bun single files: one executable per Bun platform, musl included</a>. Thanks to xet7.</summary>
Each Bun bundle also comes as one executable:
`wekan-<version>-bun-<target>-single-file` for Linux x64 and arm64 (glibc
and musl, so Alpine too), macOS and Windows. It is the published bundle ZIP,
unchanged, inside that bundle's own Bun, built on the platform itself, so the
runtime is the one the bundle was tested with. The first start unpacks the
bundle once into a cache directory, without a second Bun, and every start
runs it with the executable itself as Bun. Like the Bun bundle it needs
`MONGO_URL` and `ROOT_URL`. Its ZIP reader refuses any entry or link that
would land outside the cache directory. Before it is published each file is
checked: it names itself, refuses to start without a database, unpacks once
and loads every native addon of the bundle. `tests/bunSingleFile.test.cjs`
covers the reader and its refusals. See
[Single file](docs/Platforms/Single-File.md#bun-single-files).
</details>
<details>
<summary><a href="https://github.com/wekan/wekan/commit/a1d2994c1c">musl bundles and AppImages for Alpine and the other musl systems</a>. Thanks to xet7.</summary>
Every release also has `wekan-<version>-linux-x64-musl.zip` and
`-linux-arm64-musl.zip`, with FerretDB, and the AppImages
`WeKan-<version>-x86_64-musl` and `-aarch64-musl`. Each is the release's
Linux bundle rebuilt inside Alpine on a runner of its CPU: the musl Node.js of
the same version, checked against its SHA256, and every native addon
compiled against musl. Before it is published, each addon's architecture is
checked, sharp must load, and the bundle must start and answer HTTP 200; the
AppImages are started inside Alpine too. `tests/muslBundles.test.cjs`
covers the build and the workflows. See [Alpine](docs/Platforms/FOSS/OS/Alpine.md).
</details>
**Sandstorm** - reaching out of a grain, and into it.
<details>
<summary><a href="https://github.com/wekan/wekan/commit/2cc0b59a51">Outgoing webhooks leave a grain through the Powerbox</a>. Thanks to xet7.</summary>
A grain has no network but the bridge proxy, so a webhook was never sent.
Each saved webhook now offers "Allow this grain to reach this address", which
opens the Powerbox for exactly that address; once approved, the webhook goes
through the bridge with that grant. The grant belongs to the destination, not
to a person, and is approved as the address's parent path so the bridge
delivers to the exact address. Off Sandstorm nothing changes: every sender
still goes through the SSRF guard. `tests/sandstormWebhookEgress.test.cjs`
runs it against a fake bridge proxy. See
[Powerbox](docs/Platforms/FOSS/Container/Sandstorm/Powerbox-External-APIs.md#outgoing-webhooks).
</details>
<details>
<summary><a href="https://github.com/wekan/wekan/commit/2cc0b59a51">The REST API works with a Sandstorm API key</a>. Thanks to xet7.</summary>
A Sandstorm API key keeps the Authorization header for itself, so WeKan saw
no user. In a grain the bridge says who is calling, and WeKan now acts as
that user - only in a grain, only for an account that exists and is enabled,
and a key without the participate permission reads only. Off Sandstorm the
`X-Sandstorm-*` headers are never believed.
`tests/sandstormApiIdentity.test.cjs`
covers both sides.
</details>
<details>
<summary><a href="https://github.com/wekan/wekan/commit/d53b4da799">List sync from GitHub, GitLab, Gitea and Forgejo works in a grain</a>. Thanks to xet7.</summary>
A board member who may write saves a list's sync source and allows the grain
to reach that tracker's API in the Powerbox; the periodic sync then goes
through the bridge with that grant, which belongs to the tracker, so no one
needs to be signed in. GitLab's token is sent as `private_token`, because the
bridge drops `PRIVATE-TOKEN`, so private GitLab projects sync too; GitHub,
Gitea and Forgejo sync public repositories, whose token headers cannot pass
the bridge. Jira signs in only with an `Authorization` header, which the
bridge replaces, so it is refused in a grain with that reason. Off Sandstorm
nothing changes. `tests/sandstormSyncEgress.test.cjs` runs it against a fake
bridge proxy. See [Powerbox](docs/Platforms/FOSS/Container/Sandstorm/Powerbox-External-APIs.md#list-sync).
</details>
and closes the following already-done feature request:
- [Each member chooses how often email notifications come: never, periodically or instantly](https://github.com/wekan/wekan/commit/3f88fb39a5).
Thanks to saurabharch and xet7.
and fixes the following bugs:
**Lists and swimlanes** - what goes with a list, and where it is shown.
<details>
<summary><a href="https://github.com/wekan/wekan/commit/0a3797dbf6">Archiving a list archives its cards, and restoring it brings them back</a>. Thanks to Raymond-Voogt and xet7.</summary>
Only template lists archived their cards, so archiving any other list left
its cards visible in the Lists, Table and Calendar views. The server now
archives the cards of every list with it, whichever way it is archived - the
list menu, the Archive sidebar, the REST API - and restoring the list
restores exactly those cards, the rule #2292 gave swimlanes. A card that was
archived on its own stays archived. Cards archived with the list get the
list's own archive time, so a browser clock that differs from the server's
cannot keep them from coming back. `tests/archiveListCards.test.cjs` and a
runtime test cover it.
</details>
<details>
<summary><a href="https://github.com/wekan/wekan/commit/ebf2a019a6">Lists missing their swimlane counts only lists that lost it, and Restore never hides cards</a>. Thanks to Raymond-Voogt and xet7.</summary>
Admin Panel / Problems counted every board-wide list whose history recorded
the swimlane it was created in, so lists made since the automatic
un-binding stopped (#6515, in v10.31) were counted too, and Restore would
have bound them there, hiding the cards they hold in other swimlanes. Now a
list created after v10.31 is never offered, and a list with any card in
another swimlane is never restored. A list that really lost its binding is
still restored. `tests/listSwimlaneRestore.test.cjs` and a runtime test
cover both rules.
</details>
**Board roles** - helpers that read a role.
- [Five role helpers that answered the same for everybody: Import never offered, rule controls for every member, the last admin not protected, OIDC default-board roles](https://github.com/wekan/wekan/commit/548834c4ee).
Thanks to xet7.
and fixes the following build bug:
- [The OpenBSD bundles are built on OpenBSD 7.8, where Node.js 26 now builds](https://github.com/wekan/wekan/commit/209e3b0c47).
Thanks to xet7.
and updates the following documentation:
- [Outgoing webhooks to Node-RED, and why an internal address is refused](https://github.com/wekan/wekan/commit/a0de507143).
Thanks to yeurplc and xet7.
- [Uberspace 7: install, the update script, and email on one environment line](https://github.com/wekan/wekan/commit/a0de507143).
Thanks to jeyca and xet7.
and updates the following translations:
**Languages that held another language** - each locale file now says what its
tag says.
<details>
<summary><a href="https://github.com/wekan/wekan/commit/f3c92273ae">Hong Kong Chinese in Traditional characters, and Flemish in Dutch</a>. Thanks to xet7.</summary>
Hong Kong Chinese had 90 values in Simplified Chinese; they are now
Traditional. Flemish held 158 values in about a dozen other languages, Venda
and Vietnamese among them, and they are now Flemish, with its 225 values
still in English filled too.
</details>
<details>
<summary><a href="https://github.com/wekan/wekan/commit/ba6d0014f7">Locale files that held another language are rewritten in their own</a>. Thanks to xet7.</summary>
Romanian held Italian, French and Spanish; Aromanian, Ladin, Romansh and
Venetian held Italian; Galician held Portuguese, Acehnese Malay, Venda Zulu,
Slovak Czech and Polish, Upper Sorbian Czech, Volapük Esperanto and Bislama
Tok Pisin, and Uzbek in Arabic script was half Latin script. Each is now in
its own language. Machine-fill prefixes and notes ("Faka-Tonga:", "Kay
willaymi:", "Wolayttatto:", "WeKan:" and others) are gone from Tongan,
Quechua, Wolaytta, Upper Sorbian, Aragonese, Friulian and Luganda. Chinese
no longer calls a board a wooden plank, and List actions no longer reads as
"list the actions" in seven languages. Values already reviewed - pinned by a
test, corrected by an audit, or quoted by another string - are kept.
`tests/wrongLanguageLocales.test.cjs` keeps the old languages and prefixes
out and checks every placeholder against English. Native speakers are asked
to review these languages.
</details>
**Igbo** - notification, integration, workflow and recovery settings.
<details>
<summary><a href="https://github.com/wekan/wekan/commit/238354f6a54a234c9db1cf88a9436d15087c6ba0">Translate Igbo notification delivery and integration settings</a>. Thanks to xet7.</summary>
Translate 42 notification and integration strings, preserving grouping,
schedules, quiet hours, inherited webhook settings, identity omission and
literal link-rule syntax. Direct technical wording needs fluent review.
Both translation and guarded-correction suites pass with 30,943 corrections.
All 21 human-preference checks pass; 38,430 existing Chinese values are
unchanged.
One notification browser case passes syntax and discovery; execution is pending.
All-language translation and semantic verification remain unfinished.
</details>
<details>
<summary><a href="https://github.com/wekan/wekan/commit/daac3ead0dceb451bdb69970cc5b19678d17ce6d">Translate Igbo workflow and permission controls</a>. Thanks to xet7.</summary>
Translate 19 workflow, directory-sync and permission messages, preserving
Wrike status behavior, environment identifiers and subtask completion choices.
Technical prose is lower confidence and needs fluent review.
Both translation and guarded-correction suites pass with 30,962 corrections.
All 21 human-preference checks pass; 38,430 existing Chinese values are
unchanged.
Three browser cases pass syntax and discovery; execution remains pending.
Igbo has 69 detected placeholders left. All-language semantic review is
unfinished.
</details>
<details>
<summary><a href="https://github.com/wekan/wekan/commit/5c5391fb98d3619308aa2ba3328f47db870e5655">Translate Igbo stopped list sync recovery messages</a>. Thanks to xet7.</summary>
Translate 18 recovery messages, preserving applied changes, discarded pending
writes, replay restrictions and the oldest-50 display limit. Recovery prose
needs fluent review.
Both translation and guarded-correction suites pass with 30,980 corrections.
All 21 human-preference checks pass; 38,430 existing Chinese values are
unchanged.
One browser case passes syntax and discovery; execution remains pending.
All-language translation and semantic verification remain unfinished.
</details>
<details>
<summary><a href="https://github.com/wekan/wekan/commit/8c25ce78b94d65d3a7fd4540bdb065443a6c6dbd">Translate Igbo interrupted import recovery messages</a>. Thanks to xet7.</summary>
Translate 21 messages, preserving permanent deletion, retained partial boards,
source-file limitations, untouched foreign boards and recovery limits.
Direct recovery prose needs fluent review.
Both translation and guarded-correction suites pass with 31,001 corrections.
All 21 human-preference checks pass; existing Chinese values are unchanged
(38,430 checked). One browser case passes syntax and discovery; execution is
pending. All-language translation and semantic verification remain unfinished.
</details>
Thanks to above GitHub users for their contributions and translators for their translations.
+32 -35
View File
@@ -5,52 +5,49 @@ each one changed and the project status are in
Written by `node releases/changelog-short.mjs` from CHANGELOG-big.md:
make changes there.
# v13.02 2026-11-09 WeKan ® release
# v13.07 2026-11-12 WeKan ® release
**UnassignedArchiveBleed** is fixed: a member with the
**Normal, assigned only** role archives and converts only the cards assigned
to them, through every card method.
**ListLockAttachBleed** is fixed: when a list refuses a role
write access, that refusal now also holds for the attachment API's upload,
delete, copy and move. **CodeQL** alerts #602 and #603 in the tests are fixed,
**fast-xml-parser** is updated to 5.12.0, spent time reads as a **duration**,
the **indexes** that LDAP, card member and History queries need are added, and
Admin Panel → Problems can **Clear** resolved problems, which also age out.
[All changes in v13.02](CHANGELOG-big.md#v1302-2026-11-09-wekan--release)
[All changes in v13.07](CHANGELOG-big.md#v1307-2026-11-12-wekan--release)
# v13.01 2026-11-08 WeKan ® release
# v13.06 2026-11-11 WeKan ® release
Translations: the strings still in English are written in **33
more languages**, **Sardinian** is Sardinian instead of Italian and **Moroccan
Arabic** is Darija instead of Persian. Dependabot's updates of **mailparser**,
**isomorphic-git**, **pdfjs-dist** and the S3 libraries are checked and kept,
with the S3 client brought to the version the upload library needs.
**CodeQL** alert #601 in a test is fixed, with two more tests
that had the same fault. A card's **overtime** set through the REST API is
saved where WeKan reads it, and cards that lost it before are repaired at
startup. Card **members and assignees** whose account was deleted can be removed
and added without an error, and clearing a card **date** no longer passes as a
date set to the rules, the due date count and the activity feed.
[All changes in v13.01](CHANGELOG-big.md#v1301-2026-11-08-wekan--release)
[All changes in v13.06](CHANGELOG-big.md#v1306-2026-11-11-wekan--release)
# v13.00 2026-11-07 WeKan ® release
# v13.05 2026-11-10 WeKan ® release
**CreateBleed** is fixed: "Only admins can create boards" now
holds on every path that creates a board - the browser console, the REST API,
imports, copies, clones and cards - not only on the Add Board form. The **REST
API documentation** spells the name **WeKan**, so the API pages published on
wekan.fi pass its brand-spelling check again.
WeKan is updated to **Meteor 3.6**. The **Android** bundles
build again, after v13.04's npm retry broke their install, and the **Super
Productivity** export no longer fails for a board with a card whose list is
archived.
[All changes in v13.00](CHANGELOG-big.md#v1300-2026-11-07-wekan--release)
[All changes in v13.05](CHANGELOG-big.md#v1305-2026-11-10-wekan--release)
# v12.99 2026-11-06 WeKan ® release
# v13.04 2026-11-09 WeKan ® release
The **mac-arm64** release bundle builds again: its job asked for
GitHub's retired **macos-14** runner and was cancelled in the v12.98 release
run. The **weba** instructions now live in the weba repository itself.
**ListLockBleed** is fixed: when a list refuses a role write
access, that refusal now also holds for the checklist and checklist-item REST
routes. The **Sandstorm** and **Android** bundles retry their npm install when
github.com is briefly unavailable.
[All changes in v12.99](CHANGELOG-big.md#v1299-2026-11-06-wekan--release)
[All changes in v13.04](CHANGELOG-big.md#v1304-2026-11-09-wekan--release)
# v12.98 2026-11-06 WeKan ® release
# v13.03 2026-11-09 WeKan ® release
**GroupLinkBleed** is fixed: a board admin can no longer skip the
board methods by writing the board directly, to attach an organization or team
they do not belong to or to add a member past the invitation checks.
**Public board CSV and TSV exports** honour the selected columns, and the REST
**card archive, restore and custom-field** endpoints answer an unmatched card
with a JSON 404 instead of 500, and a REST **card update** can set sort 0, turn
overtime off and clear a description. The **notifications drawer** gets its
attachments again, and the developer instructions cover the **weba** Gambas
companion repository.
The amd64 **snaps** no longer fail the release when the Ubuntu
archive is briefly unreachable: the build waits for it and retries once.
[All changes in v12.98](CHANGELOG-big.md#v1298-2026-11-06-wekan--release)
[All changes in v13.03](CHANGELOG-big.md#v1303-2026-11-09-wekan--release)
+4 -3
View File
@@ -38,7 +38,7 @@ FROM --platform=$BUILDPLATFORM debian:trixie AS bundle
ARG TARGETARCH
ARG TARGETVARIANT
ARG VERSION=13.02
ARG VERSION=13.07
ARG DEBIAN_FRONTEND=noninteractive
COPY --chmod=755 releases/check-telemetry.py /tmp/check-telemetry.py
@@ -148,8 +148,8 @@ ARG DEBIAN_FRONTEND=noninteractive
ENV \
DEBUG=false \
DDP_TRANSPORT=sockjs \
NODE_VERSION=v26.13.0 \
METEOR_RELEASE=METEOR@3.6-rc.1 \
NODE_VERSION=v26.13.1 \
METEOR_RELEASE=METEOR@3.6 \
USE_EDGE=false \
NPM_VERSION=12.2.2 \
SRC_PATH=./ \
@@ -318,6 +318,7 @@ ENV \
WEKAN_DISK_WATCH_PATHS="" \
WEKAN_RAM_MONITOR="" \
WEKAN_IMPORT_RUN_STALE_MS="" \
EVENTLOG_RETENTION_DAYS="" \
CORS="" \
CORS_ALLOW_HEADERS="" \
CORS_EXPOSE_HEADERS="" \
+1 -1
View File
@@ -1,5 +1,5 @@
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
appVersion: "v13.02.0"
appVersion: "v13.07.0"
files:
userUploads:
- README.md
+4 -1
View File
@@ -195,7 +195,10 @@ template(name="activity")
if(currentData.timeKey)
| {{_ activity.activityType }}
= ' '
i(title=currentData.timeValue).activity-meta {{ displayDate currentData.timeValue 'LLL' }}
//- A date cleared has no new value (server/lib/timingChangeActivity.js):
only the one it had, below, rather than an empty date.
if currentData.timeValue
i(title=currentData.timeValue).activity-meta {{ displayDate currentData.timeValue 'LLL' }}
if (currentData.timeOldValue)
= ' '
| {{{activityMessage "previous_as" }}}
+5 -3
View File
@@ -2,6 +2,8 @@ import { TAPi18n } from '/imports/i18n';
import Cards from '/models/cards';
import { getCurrentCardIdFromContext } from '/client/lib/currentCard';
import { backIfOwnPopup } from '/client/lib/popupBack';
// #6890: the badge shows a duration, the tooltip hours to two decimals.
import { formatSpentTime, roundedSpentHours } from '/models/lib/spentTimeFormat';
function getCardId() {
return getCurrentCardIdFromContext();
@@ -63,17 +65,17 @@ Template.cardSpentTime.helpers({
if (card.getIsOvertime && card.getIsOvertime()) {
return `${TAPi18n.__(
'overtime',
)} ${card.getSpentTime()} ${TAPi18n.__('hours')}`;
)} ${roundedSpentHours(card.getSpentTime())} ${TAPi18n.__('hours')}`;
} else if (card.getSpentTime) {
return `${TAPi18n.__(
'card-spent',
)} ${card.getSpentTime()} ${TAPi18n.__('hours')}`;
)} ${roundedSpentHours(card.getSpentTime())} ${TAPi18n.__('hours')}`;
}
return '';
},
showTime() {
const card = Cards.findOne(this._id) || this;
return card.getSpentTime ? card.getSpentTime() : '';
return card.getSpentTime ? formatSpentTime(card.getSpentTime()) : '';
},
getIsOvertime() {
const card = Cards.findOne(this._id) || this;
@@ -100,5 +100,6 @@ template(name="problemsSummary")
span.admin-problem-count {{area.count}} {{_ 'new-problems'}}
.admin-problem-actions
button.js-ack-checked.primary {{_ 'acknowledge'}}
button.js-clear-checked {{_ 'clear-problems'}}
else
p {{_ 'no-new-problems'}}
@@ -232,4 +232,14 @@ Template.problemsSummary.events({
if (!streams.length) return;
Meteor.call('acknowledgeEventLog', streams, () => templateInstance.reload());
},
// Clear (#6893) removes the checked streams' events up to now, so a resolved
// problem stops showing, where Acknowledge only resets the count.
'click .js-clear-checked'(event, templateInstance) {
const streams = Array.from(templateInstance.findAll('.js-problem-check:checked'))
.map(el => el.getAttribute('data-stream'))
.filter(Boolean);
if (!streams.length) return;
Meteor.call('clearEventLog', streams, () => templateInstance.reload());
},
});
+4
View File
@@ -986,6 +986,10 @@ services:
# progress counts as interrupted and can be resumed or discarded (at least
# 60000).
#- WEKAN_IMPORT_RUN_STALE_MS=600000
# EVENTLOG_RETENTION_DAYS : Days after which an Admin Panel / Problems event
# is deleted by the daily sweep, so resolved problems age out; a recurring
# problem keeps a recent date and stays. Default 90, 0 = keep forever.
#- EVENTLOG_RETENTION_DAYS=90
#---------------------------------------------------------------
# ATTACHMENT RETENTION (models/lib/attachmentRetention.js). Off unless set.
# ATTACHMENTS_RETENTION_DAYS : once a night, delete card attachments older
+4
View File
@@ -988,6 +988,10 @@ services:
# progress counts as interrupted and can be resumed or discarded (at least
# 60000).
#- WEKAN_IMPORT_RUN_STALE_MS=600000
# EVENTLOG_RETENTION_DAYS : Days after which an Admin Panel / Problems event
# is deleted by the daily sweep, so resolved problems age out; a recurring
# problem keeps a recent date and stays. Default 90, 0 = keep forever.
#- EVENTLOG_RETENTION_DAYS=90
#---------------------------------------------------------------
# ATTACHMENT RETENTION (models/lib/attachmentRetention.js). Off unless set.
# ATTACHMENTS_RETENTION_DAYS : once a night, delete card attachments older
@@ -975,6 +975,10 @@ services:
# progress counts as interrupted and can be resumed or discarded (at least
# 60000).
#- WEKAN_IMPORT_RUN_STALE_MS=600000
# EVENTLOG_RETENTION_DAYS : Days after which an Admin Panel / Problems event
# is deleted by the daily sweep, so resolved problems age out; a recurring
# problem keeps a recent date and stays. Default 90, 0 = keep forever.
#- EVENTLOG_RETENTION_DAYS=90
#---------------------------------------------------------------
# ATTACHMENT RETENTION (models/lib/attachmentRetention.js). Off unless set.
# ATTACHMENTS_RETENTION_DAYS : once a night, delete card attachments older
+4
View File
@@ -992,6 +992,10 @@ services:
# progress counts as interrupted and can be resumed or discarded (at least
# 60000).
#- WEKAN_IMPORT_RUN_STALE_MS=600000
# EVENTLOG_RETENTION_DAYS : Days after which an Admin Panel / Problems event
# is deleted by the daily sweep, so resolved problems age out; a recurring
# problem keeps a recent date and stays. Default 90, 0 = keep forever.
#- EVENTLOG_RETENTION_DAYS=90
#---------------------------------------------------------------
# ATTACHMENT RETENTION (models/lib/attachmentRetention.js). Off unless set.
# ATTACHMENTS_RETENTION_DAYS : once a night, delete card attachments older
@@ -898,6 +898,10 @@ services:
# progress counts as interrupted and can be resumed or discarded (at least
# 60000).
#- WEKAN_IMPORT_RUN_STALE_MS=600000
# EVENTLOG_RETENTION_DAYS : Days after which an Admin Panel / Problems event
# is deleted by the daily sweep, so resolved problems age out; a recurring
# problem keeps a recent date and stays. Default 90, 0 = keep forever.
#- EVENTLOG_RETENTION_DAYS=90
#---------------------------------------------------------------
# ATTACHMENT RETENTION (models/lib/attachmentRetention.js). Off unless set.
# ATTACHMENTS_RETENTION_DAYS : once a night, delete card attachments older
+4
View File
@@ -1129,6 +1129,10 @@ services:
# progress counts as interrupted and can be resumed or discarded (at least
# 60000).
#- WEKAN_IMPORT_RUN_STALE_MS=600000
# EVENTLOG_RETENTION_DAYS : Days after which an Admin Panel / Problems event
# is deleted by the daily sweep, so resolved problems age out; a recurring
# problem keeps a recent date and stays. Default 90, 0 = keep forever.
#- EVENTLOG_RETENTION_DAYS=90
#---------------------------------------------------------------
# ATTACHMENT RETENTION (models/lib/attachmentRetention.js). Off unless set.
# ATTACHMENTS_RETENTION_DAYS : once a night, delete card attachments older
+4
View File
@@ -973,6 +973,10 @@ services:
# progress counts as interrupted and can be resumed or discarded (at least
# 60000).
#- WEKAN_IMPORT_RUN_STALE_MS=600000
# EVENTLOG_RETENTION_DAYS : Days after which an Admin Panel / Problems event
# is deleted by the daily sweep, so resolved problems age out; a recurring
# problem keeps a recent date and stays. Default 90, 0 = keep forever.
#- EVENTLOG_RETENTION_DAYS=90
#---------------------------------------------------------------
# ATTACHMENT RETENTION (models/lib/attachmentRetention.js). Off unless set.
# ATTACHMENTS_RETENTION_DAYS : once a night, delete card attachments older
@@ -10,7 +10,7 @@ This is without container (without Docker or Snap).
Right click and download files 1-4:
1. [wekan-13.02-win64.zip](https://github.com/wekan/wekan/releases/download/v13.02/wekan-13.02-win64.zip) or newest available at https://github.com/wekan/wekan/releases/
1. [wekan-13.07-win64.zip](https://github.com/wekan/wekan/releases/download/v13.07/wekan-13.07-win64.zip) or newest available at https://github.com/wekan/wekan/releases/
2. [node.exe](https://nodejs.org/dist/latest-v26.x/win-x64/node.exe)
@@ -22,7 +22,7 @@ Right click and download files 1-4:
6. Double click `mongodb-windows-x86_64-7.0.34-signed.msi` . In installer, uncheck downloading MongoDB compass.
7. Unzip `wekan-13.02-win64.zip` , inside it is directory `bundle`, to it copy other files:
7. Unzip `wekan-13.07-win64.zip` , inside it is directory `bundle`, to it copy other files:
```
bundle (directory)
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Peukara pangkalan data",
"new-problems": "peukara barô",
"acknowledge": "Teurimong",
"clear-problems": "Peugléh",
"rulesReportTitle": "Laporan Atôran",
"boardsReportTitle": "Laporan Papan",
"cardsReportTitle": "Laporan Kad",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Databasisprobleme",
"new-problems": "nuwe probleme",
"acknowledge": "Erken",
"clear-problems": "Maak skoon",
"rulesReportTitle": "Reëlsverslag",
"boardsReportTitle": "Raadsverslag",
"cardsReportTitle": "Kaarte Verslag",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Databasisprobleme",
"new-problems": "nuwe probleme",
"acknowledge": "Erken",
"clear-problems": "Maak skoon",
"rulesReportTitle": "Reëlsverslag",
"boardsReportTitle": "Raadsverslag",
"cardsReportTitle": "Kaarte Verslag",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Nsɛm akorabea mu haw",
"new-problems": "Fa ade foforo ka ho",
"acknowledge": "Gye tom",
"clear-problems": "Pepa",
"rulesReportTitle": "Mmara ho amanneɛbɔ",
"boardsReportTitle": "Bɔɔd ho amanneɛbɔ",
"cardsReportTitle": "Kaad ho amanneɛbɔ",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "የውሂብ ጎታ ችግሮች",
"new-problems": "አዲስ ችግሮች",
"acknowledge": "እውቅና ስጥ",
"clear-problems": "አጽዳ",
"rulesReportTitle": "የደንቦች ሪፖርት",
"boardsReportTitle": "የሰሌዳዎች ሪፖርት",
"cardsReportTitle": "የካርዶች ሪፖርት",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Problemas d’a base de datos",
"new-problems": "problemas nuevos",
"acknowledge": "Confirmar",
"clear-problems": "Limpiar",
"rulesReportTitle": "Informe sobre as Reglas",
"boardsReportTitle": "Informe sobre os Tableros",
"cardsReportTitle": "Informe sobre as Tarchetas",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "مشاكل قاعدة البيانات",
"new-problems": "مشاكل جديدة",
"acknowledge": "إقرار",
"clear-problems": "مسح",
"rulesReportTitle": "تقرير القواعد",
"boardsReportTitle": "تقرير اللوحات",
"cardsReportTitle": "تقرير البطاقات",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "مشاكل قاعدة البيانات",
"new-problems": "مشاكل جديدة",
"acknowledge": "إقرار",
"clear-problems": "مسح",
"rulesReportTitle": "تقرير القواعد",
"boardsReportTitle": "تقرير اللوحات",
"cardsReportTitle": "تقرير البطاقات",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "مشاكل قاعدة البيانات",
"new-problems": "مشاكل جديدة",
"acknowledge": "إقرار",
"clear-problems": "مسح",
"rulesReportTitle": "تقرير القواعد",
"boardsReportTitle": "تقرير اللوحات",
"cardsReportTitle": "تقرير البطاقات",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "مشاكل قاعدة البيانات",
"new-problems": "مشاكل جداد",
"acknowledge": "تأكيد",
"clear-problems": "مسح",
"rulesReportTitle": "تقرير القواعد",
"boardsReportTitle": "تقرير اللوحات",
"cardsReportTitle": "تقرير البطاقات",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "ডাটাবেছৰ সমস্যাসমূহ",
"new-problems": "নতুন সমস্যাসমূহ",
"acknowledge": "স্বীকাৰ কৰক",
"clear-problems": "পৰিষ্কাৰ কৰক",
"rulesReportTitle": "নিয়মৰ প্ৰতিবেদন",
"boardsReportTitle": "বৰ্ডৰ প্ৰতিবেদন",
"cardsReportTitle": "কাৰ্ডৰ প্ৰতিবেদন",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Problemes de la base de datos",
"new-problems": "problemes nuevos",
"acknowledge": "Reconocer",
"clear-problems": "Llimpiar",
"rulesReportTitle": "Informe sobre las Reglas",
"boardsReportTitle": "Informe de los tableros",
"cardsReportTitle": "Informe de les tarxetes",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Aymar aruna: Database problems",
"new-problems": "machaqa problems",
"acknowledge": "Aymar aruna: Acknowledge",
"clear-problems": "Q'umachaña",
"rulesReportTitle": "Rules yatiyawi",
"boardsReportTitle": "pirqanaka yatiyawi",
"cardsReportTitle": "tarjetanaka yatiyawi",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Verilənlər bazası problemləri",
"new-problems": "yeni problem",
"acknowledge": "Təsdiqlə",
"clear-problems": "Təmizlə",
"rulesReportTitle": "Qaydalar Hesabatı",
"boardsReportTitle": "İdarə Heyətinin Hesabatı",
"cardsReportTitle": "Kartlar Hesabatı",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Verilənlər bazası problemləri",
"new-problems": "yeni problem",
"acknowledge": "Təsdiqlə",
"clear-problems": "Təmizlə",
"rulesReportTitle": "Qaydalar Hesabatı",
"boardsReportTitle": "İdarə Heyətinin Hesabatı",
"cardsReportTitle": "Kartlar Hesabatı",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Verilənlər bazası problemləri",
"new-problems": "yeni problem",
"acknowledge": "Təsdiqlə",
"clear-problems": "Təmizlə",
"rulesReportTitle": "Qaydalar Hesabatı",
"boardsReportTitle": "İdarə Heyətinin Hesabatı",
"cardsReportTitle": "Kartlar Hesabatı",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Мәғлүмәттәр базаһы мәсьәләләре",
"new-problems": "яңы мәсьәләләр",
"acknowledge": "Таныу",
"clear-problems": "Таҙартырға",
"rulesReportTitle": "Ҡағиҙәләр хисабы",
"boardsReportTitle": "Таҡталар хисабы",
"cardsReportTitle": "Карточкалар хисабы",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Праблемы базы даных",
"new-problems": "новых праблем",
"acknowledge": "Пацвердзіць",
"clear-problems": "Ачысціць",
"rulesReportTitle": "Справаздача па правілах",
"boardsReportTitle": "Справаздача па дошках",
"cardsReportTitle": "Справаздача па картках",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Проблеми с базата данни",
"new-problems": "нови проблема",
"acknowledge": "Потвърждаване",
"clear-problems": "Изчистване",
"rulesReportTitle": "Отчет за правилата",
"boardsReportTitle": "Отчет за таблата",
"cardsReportTitle": "Отчет за картите",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "डेटाबेस समस्या",
"new-problems": "नया समस्या",
"acknowledge": "जानकारी स्वीकार करीं",
"clear-problems": "साफ करीं",
"rulesReportTitle": "नियम रपट",
"boardsReportTitle": "बोर्ड रपट",
"cardsReportTitle": "कार्ड रपट",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Ol problem blong databes",
"new-problems": "niu problem",
"acknowledge": "Talem se yu kasem",
"clear-problems": "Klinim",
"rulesReportTitle": "Ripot blong ol rul",
"boardsReportTitle": "Ripot blong Ol bod",
"cardsReportTitle": "Ripot blong Ol kad",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Datakurun gɛlɛyaw",
"new-problems": "gɛlɛya kuraw",
"acknowledge": "A sɔrɔ",
"clear-problems": "Saniya",
"rulesReportTitle": "Sariyaw lapɔrɔ",
"boardsReportTitle": "Tabaliw lapɔrɔ",
"cardsReportTitle": "Karataw lapɔrɔ",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "ডেটাবেসের সমস্যা",
"new-problems": "নতুন সমস্যা",
"acknowledge": "স্বীকার করুন",
"clear-problems": "মুছুন",
"rulesReportTitle": "নিয়মের প্রতিবেদন",
"boardsReportTitle": "বোর্ডের প্রতিবেদন",
"cardsReportTitle": "কার্ডের প্রতিবেদন",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "གཞི་གྲངས་མཛོད་ཀྱི་གནད་དོན།",
"new-problems": "གནད་དོན་གསར་པ།",
"acknowledge": "ངོས་ལེན།",
"clear-problems": "གཙང་སེལ།",
"rulesReportTitle": "སྒྲིག་སྲོལ་སྙན་ཞུ།",
"boardsReportTitle": "ལས་སྟེགས་སྙན་ཞུ།",
"cardsReportTitle": "བྱང་བུའི་སྙན་ཞུ།",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Kudennoù an diaz roadennoù",
"new-problems": "kudenn nevez",
"acknowledge": "Anzav",
"clear-problems": "Skarzhañ",
"rulesReportTitle": "Raport a benn ar merde",
"boardsReportTitle": "Raport a benn taolennnoù",
"cardsReportTitle": "Raport a benn kartennnoù",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Problemi baze podataka",
"new-problems": "novih problema",
"acknowledge": "Potvrdi",
"clear-problems": "Očisti",
"rulesReportTitle": "Izvještaj o pravilima",
"boardsReportTitle": "Izvještaj o tablama",
"cardsReportTitle": "Izvještaj o karticama",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Үгэгдэлэй сангай асуудалнууд",
"new-problems": "шэнэ асуудалнууд",
"acknowledge": "Мэдэрхэ",
"clear-problems": "Арилгаха",
"rulesReportTitle": "Дүримүүдэй тайлан",
"boardsReportTitle": "Самбарнуудай тайлан",
"cardsReportTitle": "Картануудай тайлан",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Problemes de la base de dades",
"new-problems": "problemes nous",
"acknowledge": "Reconeix",
"clear-problems": "Neteja",
"rulesReportTitle": "Informe de normes",
"boardsReportTitle": "Informe de les Juntes",
"cardsReportTitle": "Informe de fitxes",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Problemes de la base de dades",
"new-problems": "problemes nous",
"acknowledge": "Reconeix",
"clear-problems": "Neteja",
"rulesReportTitle": "Informe de normes",
"boardsReportTitle": "Informe de les Juntes",
"cardsReportTitle": "Informe de fitxes",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Problemes de la base de dades",
"new-problems": "problemes nous",
"acknowledge": "Reconeix",
"clear-problems": "Neteja",
"rulesReportTitle": "Informe de normes",
"boardsReportTitle": "Informe de les Juntes",
"cardsReportTitle": "Informe de fitxes",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "ᎧᏃᎮᏓ ᏗᎦᏓᎭ",
"new-problems": "ᎢᏤ ᏗᎦᏓᎭ",
"acknowledge": "ᎠᏓᏂᎸᏤᏗ",
"clear-problems": "ᎯᏅᎦᎸ",
"rulesReportTitle": "ᏗᎧᎿᏩᏛᏍᏗ ᎧᏃᎮᏓ",
"boardsReportTitle": "ᏗᎦᏍᎩᎸ ᎧᏃᎮᏓ",
"cardsReportTitle": "ᏗᎪᏪᎵ ᏗᏍᏗ ᎧᏃᎮᏓ",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "کێشەکانی بنکەدراوە",
"new-problems": "کێشە نوێکان",
"acknowledge": "پەسەند بکە",
"clear-problems": "پاککردنەوە",
"rulesReportTitle": "ڕاپۆرتی یاساکان",
"boardsReportTitle": "ڕاپۆرتی تەختەکان",
"cardsReportTitle": "ڕاپۆرتی کارتەکان",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "数据库问题",
"new-problems": "个新问题",
"acknowledge": "确认",
"clear-problems": "清除",
"rulesReportTitle": "规则报告",
"boardsReportTitle": "看板报告",
"cardsReportTitle": "卡片报告",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Prublemi di a basa di dati",
"new-problems": "prublemi novi",
"acknowledge": "Cunfirmà",
"clear-problems": "Sguassà",
"rulesReportTitle": "Raportu di e regule",
"boardsReportTitle": "Raportu di e tavule",
"cardsReportTitle": "Raportu di e carte",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Problémy databáze",
"new-problems": "nových problémů",
"acknowledge": "Potvrdit",
"clear-problems": "Vymazat",
"rulesReportTitle": "Report pravidel",
"boardsReportTitle": "Report tabel",
"cardsReportTitle": "Report karet",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Problémy databáze",
"new-problems": "nových problémů",
"acknowledge": "Potvrdit",
"clear-problems": "Vymazat",
"rulesReportTitle": "Report pravidel",
"boardsReportTitle": "Report tabel",
"cardsReportTitle": "Report karet",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Problemë bazë dónëch",
"new-problems": "nowych problemòw",
"acknowledge": "Pòcwierdzë",
"clear-problems": "Wëczëszczë",
"rulesReportTitle": "Rapòrt reglów",
"boardsReportTitle": "Raport tôblëcòw",
"cardsReportTitle": "Raport kôrtòw",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Палӑрту базин проблемӗсем",
"new-problems": "ҫӗнӗ проблемӑсем",
"acknowledge": "Йышӑнас",
"clear-problems": "Тасатас",
"rulesReportTitle": "Правилӑсен отчӗчӗ",
"boardsReportTitle": "Хӑмасен отчӗчӗ",
"cardsReportTitle": "Карточкӑсен отчӗчӗ",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Problemau cronfa ddata",
"new-problems": "problemau newydd",
"acknowledge": "Cydnabod",
"clear-problems": "Clirio",
"rulesReportTitle": "Adroddiad Rheolau",
"boardsReportTitle": "Adroddiad y Byrddau",
"cardsReportTitle": "Adroddiad Cardiau",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Problemau cronfa ddata",
"new-problems": "problemau newydd",
"acknowledge": "Cydnabod",
"clear-problems": "Clirio",
"rulesReportTitle": "Adroddiad Rheolau",
"boardsReportTitle": "Adroddiad y Byrddau",
"cardsReportTitle": "Adroddiad Cardiau",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Databaseproblemer",
"new-problems": "nye problemer",
"acknowledge": "Bekræft",
"clear-problems": "Nulstil",
"rulesReportTitle": "Regelrapport",
"boardsReportTitle": "Tavlerapport",
"cardsReportTitle": "Kortrapport",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Datenbankprobleme",
"new-problems": "neue Probleme",
"acknowledge": "Bestätigen",
"clear-problems": "Zurücksetzen",
"rulesReportTitle": "Regeln-Bericht",
"boardsReportTitle": "Board-Bericht",
"cardsReportTitle": "Karten-Bericht",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Datenbankprobleme",
"new-problems": "neue Probleme",
"acknowledge": "Bestätigen",
"clear-problems": "Zurücksetzen",
"rulesReportTitle": "Regeln-Bericht",
"boardsReportTitle": "Board-Bericht",
"cardsReportTitle": "Karten-Bericht",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Datenbankprobleme",
"new-problems": "neue Probleme",
"acknowledge": "Bestätigen",
"clear-problems": "Zurücksetzen",
"rulesReportTitle": "Regeln-Bericht",
"boardsReportTitle": "Boardbericht",
"cardsReportTitle": "Kartenbericht",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Datenbankprobleme",
"new-problems": "neue Probleme",
"acknowledge": "Bestätigen",
"clear-problems": "Zurücksetzen",
"rulesReportTitle": "Regeln-Bericht",
"boardsReportTitle": "Boardbericht",
"cardsReportTitle": "Kartenbericht",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "གཞི་གྲངས་མཛོད་གནད་དོན།",
"new-problems": "གནད་དོན་གསར་པ།",
"acknowledge": "ངོས་ལེན།",
"clear-problems": "བསལ།",
"rulesReportTitle": "སྒྲིག་ལམ་སྙན་ཞུ།",
"boardsReportTitle": "བྱང་གཞིའི་སྙན་ཞུ།",
"cardsReportTitle": "ཤོག་བྱང་སྙན་ཞུ།",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Nyatakakadzraɖoƒe ƒe kuxiwo",
"new-problems": "kuxi yeyewo",
"acknowledge": "Lɔ̃ ɖe edzi",
"clear-problems": "Tutui ɖa",
"rulesReportTitle": "Sewo ƒe nyatakakagbalẽ",
"boardsReportTitle": "Kpekpeɖeŋuwo ƒe nyatakakagbalẽ",
"cardsReportTitle": "Kaɖiwo ƒe nyatakakagbalẽ",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Προβλήματα βάσης δεδομένων",
"new-problems": "νέα προβλήματα",
"acknowledge": "Επιβεβαίωση",
"clear-problems": "Εκκαθάριση",
"rulesReportTitle": "Αναφορά κανόνων",
"boardsReportTitle": "Αναφορά πινάκων",
"cardsReportTitle": "Αναφορά καρτών",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Προβλήματα βάσης δεδομένων",
"new-problems": "νέα προβλήματα",
"acknowledge": "Επιβεβαίωση",
"clear-problems": "Εκκαθάριση",
"rulesReportTitle": "Αναφορά κανόνων",
"boardsReportTitle": "Αναφορά πινάκων",
"cardsReportTitle": "Αναφορά καρτών",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Database problems",
"new-problems": "new problems",
"acknowledge": "Acknowledge",
"clear-problems": "Clear",
"rulesReportTitle": "Rules Report",
"boardsReportTitle": "Boards Report",
"cardsReportTitle": "Cards Report",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Database problems",
"new-problems": "new problems",
"acknowledge": "Acknowledge",
"clear-problems": "Clear",
"rulesReportTitle": "Rules Report",
"boardsReportTitle": "Boards Report",
"cardsReportTitle": "Cards Report",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Database problems",
"new-problems": "new problems",
"acknowledge": "Acknowledge",
"clear-problems": "Clear",
"rulesReportTitle": "Rules Report",
"boardsReportTitle": "Boards Report",
"cardsReportTitle": "Cards Report",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Database problems",
"new-problems": "new problems",
"acknowledge": "Acknowledge",
"clear-problems": "Clear",
"rulesReportTitle": "Rules Report",
"boardsReportTitle": "Boards Report",
"cardsReportTitle": "Cards Report",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Database problems",
"new-problems": "new problems",
"acknowledge": "Acknowledge",
"clear-problems": "Clear",
"rulesReportTitle": "Rules Report",
"boardsReportTitle": "Boards Report",
"cardsReportTitle": "Cards Report",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Database problems",
"new-problems": "new problems",
"acknowledge": "Acknowledge",
"clear-problems": "Clear",
"rulesReportTitle": "Rules Report",
"boardsReportTitle": "Boards Report",
"cardsReportTitle": "Cards Report",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Database problems",
"new-problems": "new problems",
"acknowledge": "Acknowledge",
"clear-problems": "Clear",
"rulesReportTitle": "Rules Report",
"boardsReportTitle": "Boards Report",
"cardsReportTitle": "Cards Report",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Database problems",
"new-problems": "new problems",
"acknowledge": "Acknowledge",
"clear-problems": "Clear",
"rulesReportTitle": "Rules Report",
"boardsReportTitle": "Boards Report",
"cardsReportTitle": "Cards Report",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Database problems",
"new-problems": "new problems",
"acknowledge": "Acknowledge",
"clear-problems": "Clear",
"rulesReportTitle": "Rules Report",
"boardsReportTitle": "Boards Report",
"cardsReportTitle": "Cards Report",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Database problems",
"new-problems": "new problems",
"acknowledge": "Acknowledge",
"clear-problems": "Clear",
"rulesReportTitle": "Rules Report",
"boardsReportTitle": "Boards Report",
"cardsReportTitle": "Cards Report",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Database problems",
"new-problems": "new problems",
"acknowledge": "Acknowledge",
"clear-problems": "Clear",
"rulesReportTitle": "Rules Report",
"boardsReportTitle": "Boards Report",
"cardsReportTitle": "Cards Report",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Database problems",
"new-problems": "new problems",
"acknowledge": "Acknowledge",
"clear-problems": "Clear",
"rulesReportTitle": "Rules Report",
"boardsReportTitle": "Boards Report",
"cardsReportTitle": "Cards Report",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Datumbazaj problemoj",
"new-problems": "novaj problemoj",
"acknowledge": "Konfirmi",
"clear-problems": "Viŝi",
"rulesReportTitle": "Raporto pri reguloj",
"boardsReportTitle": "Raporto pri tabuloj",
"cardsReportTitle": "Raporto pri kartoj",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Problemas de la base de datos",
"new-problems": "problemas nuevos",
"acknowledge": "Confirmar",
"clear-problems": "Borrar",
"rulesReportTitle": "Informe sobre las Reglas",
"boardsReportTitle": "Informe sobre los Tableros",
"cardsReportTitle": "Informe sobre las Tarjetas",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Problemas de la base de datos",
"new-problems": "problemas nuevos",
"acknowledge": "Confirmar",
"clear-problems": "Borrar",
"rulesReportTitle": "Informe sobre las Reglas",
"boardsReportTitle": "Informe sobre los Tableros",
"cardsReportTitle": "Informe sobre las Tarjetas",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Problemas de la base de datos",
"new-problems": "problemas nuevos",
"acknowledge": "Confirmar",
"clear-problems": "Borrar",
"rulesReportTitle": "Informe sobre las Reglas",
"boardsReportTitle": "Informe sobre los Tableros",
"cardsReportTitle": "Informe sobre las Tarjetas",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Problemas de la base de datos",
"new-problems": "problemas nuevos",
"acknowledge": "Confirmar",
"clear-problems": "Borrar",
"rulesReportTitle": "Informe sobre las Reglas",
"boardsReportTitle": "Informe sobre los Tableros",
"cardsReportTitle": "Informe sobre las Tarjetas",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Problemas de la base de datos",
"new-problems": "problemas nuevos",
"acknowledge": "Confirmar",
"clear-problems": "Borrar",
"rulesReportTitle": "Informe sobre las Reglas",
"boardsReportTitle": "Informe sobre los Tableros",
"cardsReportTitle": "Informe sobre las Tarjetas",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Problemas de la base de datos",
"new-problems": "problemas nuevos",
"acknowledge": "Confirmar",
"clear-problems": "Borrar",
"rulesReportTitle": "Informe sobre las Reglas",
"boardsReportTitle": "Informe sobre los Tableros",
"cardsReportTitle": "Informe sobre las Tarjetas",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Problemas de la base de datos",
"new-problems": "problemas nuevos",
"acknowledge": "Confirmar",
"clear-problems": "Borrar",
"rulesReportTitle": "Informe sobre las Reglas",
"boardsReportTitle": "Informe sobre los Tableros",
"cardsReportTitle": "Informe sobre las Tarjetas",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Problemas de la base de datos",
"new-problems": "problemas nuevos",
"acknowledge": "Confirmar",
"clear-problems": "Borrar",
"rulesReportTitle": "Informe sobre las Reglas",
"boardsReportTitle": "Informe sobre los Tableros",
"cardsReportTitle": "Informe sobre las Tarjetas",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Problemas de la base de datos",
"new-problems": "problemas nuevos",
"acknowledge": "Confirmar",
"clear-problems": "Borrar",
"rulesReportTitle": "Informe sobre las Reglas",
"boardsReportTitle": "Informe sobre los Tableros",
"cardsReportTitle": "Informe sobre las Tarjetas",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Andmebaasi probleemid",
"new-problems": "uut probleemi",
"acknowledge": "Kinnita",
"clear-problems": "Tühjenda",
"rulesReportTitle": "Reeglite aruanne",
"boardsReportTitle": "Juhatuse aruanne",
"cardsReportTitle": "Kaartide aruanne",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Datu-basearen arazoak",
"new-problems": "arazo berri",
"acknowledge": "Berretsi",
"clear-problems": "Garbitu",
"rulesReportTitle": "Arauen txostena",
"boardsReportTitle": "Arbelen txostena",
"cardsReportTitle": "Txartelen txostena",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "مشکلات پایگاه داده",
"new-problems": "مشکل جدید",
"acknowledge": "تأیید",
"clear-problems": "پاک کردن",
"rulesReportTitle": "گزارش قوانین",
"boardsReportTitle": "گزارش بردها",
"cardsReportTitle": "گزارش کارت‌ها",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "مشکلات پایگاه داده",
"new-problems": "مشکل جدید",
"acknowledge": "تأیید",
"clear-problems": "پاک کردن",
"rulesReportTitle": "گزارش قوانین",
"boardsReportTitle": "گزارش بردها",
"cardsReportTitle": "گزارش کارت‌ها",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Caɗeele ruttorde keɓe",
"new-problems": "caɗeele kese",
"acknowledge": "Jaɓ",
"clear-problems": "Laɓɓin",
"rulesReportTitle": "Jaŋtol kuule",
"boardsReportTitle": "Jaŋtol alluuje",
"cardsReportTitle": "Jaŋtol karte",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Tietokantaongelmat",
"new-problems": "uutta ongelmaa",
"acknowledge": "Kuittaa",
"clear-problems": "Tyhjennä",
"rulesReportTitle": "Säännöt raportti",
"boardsReportTitle": "Taulut raportti",
"cardsReportTitle": "Kortit raportti",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Leqa ni kato ni itukutuku",
"new-problems": "leqa vou",
"acknowledge": "Vakadinadinataka",
"clear-problems": "Vakasavasavataka",
"rulesReportTitle": "iTukutuku ni Lawa",
"boardsReportTitle": "iTukutuku ni Vola",
"cardsReportTitle": "iTukutuku ni Kadi",
+1
View File
@@ -2380,6 +2380,7 @@
"databaseReportTitle": "Dátugrunnstrupulleikar",
"new-problems": "nýggir trupulleikar",
"acknowledge": "Vátta",
"clear-problems": "Rudda",
"rulesReportTitle": "Reglufrágreiðing",
"boardsReportTitle": "Talvufrágreiðing",
"cardsReportTitle": "Kortfrágreiðing",
Loaded 100 of 351 files, more files were not shown because too many files have changed in this diff. Show more