TrueCharts Bot 1c6d7fd9dd feat(wekan): update image docker.io/wekanteam/wekan v9.34 → v9.35 (#48816)
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [docker.io/wekanteam/wekan](https://redirect.github.com/wekan/wekan) |
minor | `894f63f` → `7f926f0` |

---

> [!WARNING]
> Some dependencies could not be looked up. Check the [Dependency
Dashboard](../issues/18710) for more information.

Add the preset `:preserveSemverRanges` to your config if you don't want
to pin your dependencies.

---

### Release Notes

<details>
<summary>wekan/wekan (docker.io/wekanteam/wekan)</summary>

###
[`v9.35`](https://redirect.github.com/wekan/wekan/blob/HEAD/CHANGELOG.md#v935-2026-06-06-WeKan--release)

[Compare
Source](https://redirect.github.com/wekan/wekan/compare/v9.34...v9.35)

TLDR:

- Admin Panel/Attachments/Move Files works:
CollectionFS/Meteor-Files/S3/Azure Blob/Google Cloud Storage.
- To have attachments and avatars visible, move them from CollectionFS
to any other Storage
- To upgrade, mongodump/mongorestore (older with
[LD\_LIBRARY\_PATH](https://redirect.github.com/wekan/wekan/blob/main/docs/Backup/Backup.md#backup-wekan-snap-to-directory-dump))
to MongoDB 7.x, and copy WRITABLE\_PATH files/attachments/avatars if
exists,
  at Snap /var/snap/wekan/common/files/, at Docker /data/files etc.

This release adds the following [CRITICAL SECURITY
FIXES](https://redirect.github.com/wekan/wekan/commit/357de728c03113b787065bac2c5832ad77f1a117):

- [Fix GHSA-qfqv-42qw-vvwh: `cloneBoard` Meteor method has no
authorization check — any user can clone (read) any private board by ID
(CWE-639,
CWE-862)](https://redirect.github.com/wekan/wekan/security/advisories/GHSA-qfqv-42qw-vvwh).
The `cloneBoard` Meteor method in `models/import.js` copied an entire
board —
including all cards, comments, attachments, member info and activities —
identified solely by a caller-supplied `sourceBoardId`, and performed no
authorization check: it never verified that the calling user was a
member of
(or otherwise permitted to read) the source board. Any authenticated
Wekan
user who knew a board's ID (board IDs appear in board URLs and remain
known to
removed members) could call `Meteor.call('cloneBoard',
'<targetBoardId>')`
over DDP and obtain a permanent, fully-readable copy of that board's
contents,
  even for private boards they had no access to. The method called
  `exporter.build()` directly, skipping the `canExport()` guard
(`models/exporter.js`) that the REST export route correctly enforces.
Fixed by
requiring `this.userId` and running the same `exporter.canExport(user)`
check
the export route uses before building/cloning the board, so cloning a
board
  now requires the same read authorization as exporting it.
  CVSS 6.5 (AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N).
  Thanks to dizconnectz for the coordinated disclosure, xet7 and Claude.

and, while fixing the above, the following similar authorization issues
found by code review were fixed (the
[CloneBleed](https://wekan.fi/hall-of-fame/clonebleed/) group):

- [Fix authorization guards that silently never ran in attachment, list,
checklist, migration and webhook server methods (CWE-862,
CWE-639)](https://redirect.github.com/wekan/wekan/blob/main/docs/hall-of-fame/clonebleed/).
A review for the same class of bug as `cloneBoard` found several
server-side
methods whose access checks were present in the source but never
actually
  enforced, plus a few methods missing a check entirely:
- `server/models/checklists.js` `moveChecklist`: the membership guard
called
`allowIsBoardMemberByCard(...)`, but that helper is `async` and was both
unimported and un-awaited, so `!allowIsBoardMemberByCard(...)` evaluated
`!Promise` (always `false`) and the check never ran — any logged-in user
could move a checklist between cards on boards they cannot access. Now
    imported and awaited, and login is required.
  - `server/models/lists.js` `updateListSort`: the guard read
`typeof allowIsBoardMember === 'function' && !allowIsBoardMember(...)`,
but
`allowIsBoardMember` was never imported, so the `typeof` was always
`false`
and the guard never ran — any caller could reorder/re-assign any board's
lists by ID. Replaced with a real `hasBoardWriteAccess` check, plus a
check
that the list actually belongs to the named board, and a login check.
  - `server/attachmentApi.js` and `server/routes/attachmentApi.js`: the
attachment Meteor methods and REST handlers called
`board.isBoardMember(...)`,
which is not a method on the board model, so the permission check never
behaved as intended. Replaced with the real `board.hasMember(...)`, and
the
upload path now also verifies the target card actually belongs to the
named
board (so `boardId` cannot be spoofed to a board the caller is a member
of).
- `server/models/users.js` `applyListWidth`: stored per-board list width
with
no authorization. Now requires the caller to be a member of the board
and
    requires the list to belong to that board.
- `server/models/boards.js` `getBackgroundImageURL`: returned any
board's
background image URL by ID. Now requires the board to be visible to the
    caller.
  - `server/migrations/fixMissingListsMigration.js` and
`server/migrations/migrateAttachments.js`: the migration status/execute
methods only checked that the caller was logged in. Reading status now
requires board visibility, executing a board-rewriting migration now
requires
board admin (or instance admin), and the attachment migration methods
now
    require board access (global status reads require instance admin).
- `server/notifications/outgoing.js`: the webhook delivery method
trusted the
caller-supplied `integration` object and only checked that *some*
integration
with that URL existed. It now verifies a matching integration exists on
its
own board and that the caller is a member of that board, closing a path
where
any authenticated user could drive webhooks (and, via the two-way
response
    path, overwrite comments) on boards they cannot access.
  - `server/models/userPositionHistory.js`: the
`userPositionHistory.createCheckpoint`, `.getRecent`, `.getCheckpoints`
and
`.restoreToCheckpoint` methods only checked that the caller was logged
in,
    even though the sibling `positionHistory.track*` methods
(`server/methods/positionHistory.js`) already require the board to be
visible
to the caller — the same PositionHistoryBleed class fixed in
v8.20/v8.21.
All four now require board visibility (via the shared `isVisibleBy`
guard)
    before reading or restoring position history scoped to a board.
    Thanks to xet7 and Claude.

and, while auditing that client-side permission checks are also enforced
server-side, the following gaps where the server did not re-verify a
UI-gated permission were fixed:

- [Fix client-side permission gates not re-verified server-side
(CWE-862,
CWE-269)](https://redirect.github.com/wekan/wekan/blob/main/docs/hall-of-fame/clonebleed/).
  The browser UI hides certain actions from read-only members and from
non-admins, but those are cosmetic — the server-side `allow` rules and
Meteor
methods must enforce the same role. An audit found four places that did
not:
  - `server/permissions/customFields.js`: the Custom Field `allow`
insert/update/remove rules used `allowIsAnyBoardMember` (mere
membership), so
read-only/comment-only/worker members could create/modify/delete Custom
Fields (board-wide schema) via direct DDP collection writes — the same
read-only-write class as GHSA-6733, which had only fixed the REST path.
Now
uses the new `allowIsAnyBoardMemberWithWriteAccess` write-access helper.
- `server/permissions/cardCommentReactions.js`: the reaction `allow`
rules used
`allowIsBoardMember`, letting read-only members add/remove comment
reactions.
Reacting is a form of commenting, so it now uses
`allowIsBoardMemberCommentOnly`
(Normal/Comment-only allowed, Read-only/No-comments denied), matching
    `CardComments.insert`.
- `server/models/boards.js` `archiveBoard`: only required board
membership, so
any member (including read-only) could archive a board (hiding it for
everyone) over DDP, although the UI gates archiving behind board admin.
Now
    requires board admin (or global admin), matching the `Boards.allow`
    update/remove rules.
- `server/models/settings.js` `sendSMTPTestEmail`: only required login,
so any
authenticated user could trigger the server to send an SMTP test (and
have
the server's SMTP error messages surfaced to them), although the UI
gates it
    behind global admin. Now requires global admin.
    Thanks to xet7 and Claude.

and, in the same access-control audit, the attachment write API was
tightened:

- **Security: attachment write operations in the REST/DDP API now
require board
write access, not just membership (CWE-862, CWE-639).** Both attachment
API
  implementations (`server/routes/attachmentApi.js` HTTP routes and
`server/attachmentApi.js` Meteor methods) gated upload / copy / move /
delete
on `board.hasMember()`, which is true for any active member regardless
of role.
This let read-only, comment-only, no-comments, worker and assigned-only
board
members add, copy, move and delete attachments through the API — actions
the UI
forbids for those roles. They now require board write access (global
site
  admins still allowed); read operations (download / list / info) keep
  membership-level access. Added security tests in
  `server/lib/tests/attachmentApi.tests.js`.
  Thanks to xet7 and Claude.

and adds the following new features:

- **[Admin Panel /
Attachments](https://redirect.github.com/wekan/wekan/commit/a86a087915aac9d204e157b1a698091c079e04e6):
  "Calculate file counts" on every storage backend,
shown right below the "Read" toggle.** Azure Blob Storage and Google
Cloud
Storage now have a "Calculate file counts" button (new
`getAzureStorageStats` /
`getGcsStorageStats` methods) that reports how many attachments and
avatars are
stored on that backend, matching what Filesystem, MongoDB GridFS and S3
already
offer. The count is read from the stored file metadata (fast, no cloud
API
calls). The S3 button was also moved up to sit directly under its "Read"
  checkbox, so all backends are consistent. Thanks to Claude.
- \*\*[Admin Panel / Attachments: the MongoDB GridFS page notes how to
make legacy files
visible](https://redirect.github.com/wekan/wekan/commit/dca9427bfb58532778bc705e4c8c8014ba4b01ae).
  \*\* A translatable line under the "MongoDB GridFS Storage" title
reminds admins: "To have attachments and avatars visible, move them from
  CollectionFS to any other Storage." Thanks to Claude.
- **Admin Panel / Attachments: the Google Cloud Storage page now
documents the
required bucket permission.** A note under the "GCS Storage" title
explains that
  the service account needs the **Storage Object Admin** role
(`roles/storage.objectAdmin`) on the bucket (Cloud Console → Cloud
Storage →
Buckets → your bucket → Permissions → Grant access → add the service
account →
role "Storage Object Admin"), and that the bucket must exist in the same
project — otherwise "Test connection" fails with `storage.objects.list
denied`.
  Thanks to xet7 and Claude.
- **Admin Panel / Attachments: a "Save" button next to the Enabled /
Read toggles
at the top of each cloud storage.** S3, Azure and Google Cloud Storage
now have
a Save button directly below the "\[ ] Enabled \[ ] Read" row, so those
toggles
can be saved without scrolling to the bottom of the (now quite long)
storage
page. It saves the same way as the existing bottom Save button — the
server
merges that provider's config and preserves secrets left blank — and the
bottom
Save button is kept. (Filesystem and GridFS have only a Read toggle,
which
already saves the instant it is toggled, so they need no button.) Thanks
to Claude.
- **Admin Panel / Attachments: bilingual, self-documenting cloud-storage
fields
(S3, Azure and Google Cloud Storage).** Each cloud-storage setting now
guides
the admin from top to bottom with both English and translated text, so
it is
easy to follow along while clicking through the provider's Cloud
Console:
- the field **label** uses the provider's own console wording in English
    (e.g. *Access key ID*, *Secret access key*, *Storage account key*,
*Service account key (JSON)*), with the translated label shown below it;
  - a literal **example** of what the value should look like
(e.g. `eu-west-1`, an example bucket name / endpoint / connection
string),
    which is intentionally not translated;
- a short **description** of the value, in English and then translated;
- the **Cloud Console menu path** showing exactly where to find or
create the
value (e.g. *AWS Console → IAM → Users → your user → Security
credentials →
Access keys → Create access key*; *Azure Portal → Storage accounts →
your
    account → Access keys → key1*; *Google Cloud Console → IAM & Admin →
Service accounts → … → Keys → Add key → Create new key → JSON*), again
in
    English and then translated.
The provider field names, examples and menu paths are kept in English so
they
match what the Cloud Console actually shows, while the descriptions and
menu
paths are also translatable; section titles, the
enable/read/force-path-style
checkboxes and the Test/Save buttons remain fully translated. Thanks to
Claude.
- **Admin Panel / Attachments / Move Attachment: "Repair file locations"
button
and a persistent "last move" message.** The new **Repair file
locations** button
  scans all attachments and avatars and finds any whose recorded storage
(`versions.<v>.storage` / `path` / `meta.gridFsFileId`) no longer
matches where
the binary actually is — left inconsistent by an interrupted or failed
move —
and fixes the database to point at the real location: it detects the
binary in
GridFS (by the `metadata.fileId` stamped on upload, recovering files
whose
  GridFS id reference was lost) or on the filesystem (using the storage
strategy's own thorough path resolution, so the repair agrees with what
a real
download/move would find even when `versions.<v>.path` is stale), then
corrects
`storage`, `path` and `meta.gridFsFileId` accordingly. Cloud-stored
files are
left untouched, and files found nowhere are reported as "Not found". The
scan is
streamed (memory-safe) and shows a per-scope searched / repaired /
not-found
  summary. Separately, after a move finishes the page now keeps showing
the last move operation — source → destination (scope) and the date/time
as
  `YYYY-MM-DD HH:MM:SS` — so it is clear what was last done.
  Thanks to xet7 and Claude.
- **SVG image uploads are now sanitized instead of rejected.** Uploaded
SVGs
(attachments and avatars) are cleaned in place in `onAfterUpload` via
the new
`models/lib/sanitizeSvg.js`, which removes JavaScript (`<script>`,
inline
`on*=` event handlers, `javascript:`/`vbscript:` URIs, `<foreignObject>`
/
`<iframe>` / `<object>` / `<embed>` and similar active content) and XML
loops
  (`<!DOCTYPE>` / `<!ENTITY>` entity-expansion / XXE constructs and
`<?xml-stylesheet?>`), so SVG images can be uploaded safely. Thanks to
Claude.
- **Unified attachment/avatar storage migration: move any → any.** Admin
Panel /
Attachments / Move Attachment can now move **Attachments, Avatars, or
both**,
from **any source to any destination** across Filesystem, Meteor-Files
GridFS,
Cloud (S3/Azure/GCS) and legacy CollectionFS GridFS. The default source
is
"All Read-enabled storages" (every backend whose Read flag is enabled
and whose
settings work), so everything can be consolidated into one destination
in a
single run. All metadata is preserved (board / swimlane / list / card /
user /
  uploaded date / name / type / size), attachment cover references
(`cards.coverId`) are remapped when an id changes, and the legacy source
is
  deleted only after the new copy is verified. Thanks to Claude.
- **Legacy CollectionFS GridFS is now a first-class storage backend**
(read,
migrate-from, and export-to) for both attachments and avatars, via the
new
`models/lib/collectionFsStore.js` (binary keyed by `copies.<coll>.key`
in the
`cfs_gridfs.<coll>` bucket, metadata in `cfs.<coll>.filerecord`). Thanks
to Claude.
- **The storage strategy layer is now collection-aware.**
`moveToStorage` and the
GridFS/Cloud strategies previously hard-coded the `Attachments`
collection, so
moving avatars to GridFS/cloud would have updated the wrong collection.
The
factory now carries its collection (`Attachments` or `Avatars`), so
**avatars
can be stored in Meteor-Files GridFS and cloud**, not only on the
filesystem.
  Attachment behavior is unchanged.
  Thanks to xet7 and Claude.

and adds the following updates:

- [Update Windows
MongoDB](https://redirect.github.com/wekan/wekan/commit/beedf2fefa614018ce7ed499465092e814a050d9).
  Thanks to xet7.
- [Update DDP transport and reactivity order for multi-tenant
deployment](https://redirect.github.com/wekan/wekan/pull/6365).
  Thanks to italojs.
- [Updated to Meteor
3.5-rc.1](https://redirect.github.com/wekan/wekan/commit/29b3f52e50ea2ee9bfbfb98d3842ce8a9b8e52e3).
  Thanks to Meteor developers.
- **Documented the attachment / file REST API in the OpenAPI docs** —
file
upload, download, info, listing a board's files, copy, move and delete
(the
`/api/attachment/*` endpoints registered via `WebApp.handlers.use()`,
which the
generator cannot auto-discover) are now documented in
`openapi/extra_paths.yml`
and injected into the generated docs, including their authentication and
  permission requirements.
  Thanks to xet7 and Claude.

and adds the following fixes:

- **[Admin Panel / Attachments: "Run MongoDB compact" now actually
compacts the
database](https://redirect.github.com/wekan/wekan/commit/dca9427bfb58532778bc705e4c8c8014ba4b01ae).**
  MongoDB refuses `compact` on an active replica-set primary unless
`force: true` is given, so every collection failed with "will not run
compact
on an active replica set primary … use force:true to force" — and
because the
  usual Meteor setup is a single-node replica set (only a primary, no
secondaries), nothing was compacted at all and no disk space was
reclaimed. The
primary is now compacted with `force: true` (secondaries are still
compacted
without it, so the primary stays available while they run), so the
GridFS
  collections are actually rewritten and freed space is returned to the
  filesystem. Thanks to Claude.
- **Admin Panel / Attachments: clearer cloud "Test connection" errors,
and cloud
config inputs are trimmed.** Testing an Azure/GCS/S3 connection used to
report a
single generic `Incomplete configuration or adapter not installed` even
when the
real problem was specific — e.g. Azure rejecting the config with
`Invalid URL`
(a stray space/newline in the account name, or a bad endpoint /
connection
string). `testCloudConnection` now reports the actual cause: adapter not
installed, required fields missing, the adapter's own configuration
error (such
as `Invalid URL`), or the real `listFiles` error (auth failure,
container not
found, …). It also pre-validates the config and gives an actionable
message
before the adapter turns it into a cryptic error — e.g. for Azure it
explains
that the **Storage account name** must be just the account name (3–24
lowercase
letters/numbers, e.g. `wekanstorage`, not a full `https://…` URL and
with no
spaces), or that the **Connection string** is malformed; and when Azure
still
returns `Invalid URL` the message appends which field to check. In
addition, all
  cloud-storage text fields are now trimmed when read from the form, so
leading/trailing whitespace from copy-paste no longer produces an
invalid URL.
  Thanks to xet7 and Claude.
- **[Fixed moving attachments to
S3](https://redirect.github.com/wekan/wekan/commit/a86a087915aac9d204e157b1a698091c079e04e6)
  (and other cloud storage) failing and crashing the server.**
  Uploading to S3 failed two ways, each of which crashed
the whole server because the rejection was unhandled and SyncedCron
treats
those as fatal. The `@tweedegolf/sab-adapter-amazon-s3` adapter uploaded
with a
`PutObjectCommand` whose `Body` was a live stream: (1) with no
`ContentLength`
the AWS SDK fell back to a chunked signed upload that needs a decoded
content
length, which was undefined for a stream of unknown size — `Invalid
value
"undefined" for header "x-amz-decoded-content-length"`; and (2) if the
socket
dropped mid-upload (`socket hang up`), the SDK's body-stream promise
rejected
unhandled. Fixed by uploading the file as a complete in-memory
**buffer**
(`addFileFromBuffer`) instead of a live stream: a buffer has a known
length (no
content-length error) and no socket-bound stream to re-reject. The cloud
upload
  promise now never rejects — any failure is captured and exposed via
`waitUntilStored()`, which `moveToStorage` checks inside a try/catch so
a failed
upload leaves the source file intact and is logged cleanly. (Files are
moved one
  at a time, so peak memory is one file.) Thanks to Claude.
- **Fixed `TypeError: Cannot read properties of undefined (reading
'on')` when
moving attachments between Meteor-Files/GridFS and Filesystem.** If a
file's
  source binary was missing at its recorded location (e.g. a file left
half-moved by an earlier interrupted run — storage says "gridfs" but the
GridFS id reference is gone, or a filesystem path that no longer
exists),
`getReadStream()`/`getWriteStream()` returned `undefined` and
`moveToStorage`
(and `copyFile`) called `.on()` on it, throwing. Both now detect a
missing
read/write stream, log a clear message (which file, version, from→to
storage,
and why), **skip that file and leave the source intact** so no data is
lost,
and continue with the rest. Use the new "Repair file locations" button
to fix
  the underlying inconsistent records. Thanks to Claude.
- **Fixed moving attachments/avatars from CollectionFS to Meteor-Files
crashing
the server, hanging the Admin Panel move at "File 1 / N", and leaving
broken
avatars.** Three problems in Admin Panel / Attachments / Move
Attachment:
- **Server crash on the first file** (`uncaughtException: TypeError:
Cannot read
    properties of undefined (reading '_id')` at
`AttachmentStoreStrategyGridFs.writeStreamFinished`). The current
mongodb
driver's GridFS `GridFSBucketWriteStream` `'finish'` event no longer
passes
the stored file document, so `finishedData._id` threw and killed the
process
(which is also why the move appeared stuck at "File 1 / 4" — the
background
job died mid-file and its persisted status was frozen). The GridFS
strategy
now reads the uploaded file id from the write stream itself
(`gridFSFile._id`
/ `id`), the `'finish'` handler is wrapped so it can never crash the
process,
and a startup reconciliation clears a stale "running" move status left
by a
    crashed run so the UI un-sticks and a new move can be started.
- **Broken avatar after migrating avatars.** The bulk move only
repointed card
cover references (`cards.coverId`); a user's `profile.avatarUrl` still
pointed
at the deleted legacy `/cfs/files/avatars/<oldId>` URL, so the avatar
rendered
broken. The move now repoints `profile.avatarUrl` to the migrated avatar
    (`remapReferences` handles avatars), and migrated files stamp
`meta.migratedFromId` so references can be repaired to the **exact** new
file.
The startup repair in `server/models/users.js` (previously a no-op: it
string-replaced the URL prefix while keeping the now-deleted id and
never
saved the document) now points each affected user's avatar at their
migrated
Meteor-Files avatar — matched precisely by `meta.migratedFromId`,
otherwise
strictly by `userId` (newest migrated avatar first), so a user can only
ever
    be given their own avatar, never another user's.
- **`ObjectID` deprecation warning** from
`models/lib/grid/createObjectId.js`
    (`MongoInternals.NpmModule.ObjectID` → `ObjectId`).
    Thanks to xet7 and Claude.
- [Fix Dropdown list cannot be created with
values](https://redirect.github.com/wekan/wekan/commit/e01f99eb52812df5e2754c193860002ec2716ecb).
- **Fixed Dropdown custom field options not being addable / saving as
empty.**
Creating a "Dropdown" custom field showed the "List Options" box, but
pressing
Enter (or typing and saving) never added any option, and on the card the
only
selectable value was `(none)`. The custom-fields sidebar component was
migrated
from `BlazeComponent` to a plain `Template`, but the template still
iterates the
options with `{{#each dropdownItems.get}}` — under BlazeComponent that
resolved
to the instance's `dropdownItems` ReactiveVar, whereas a plain Template
does not
expose instance variables to the template, so the list rendered nothing.
Because
the options were never rendered as inputs, `getDropdownItems()` then
overwrote
the ReactiveVar with the empty DOM on save and every entered value was
dropped.
Fixed by re-adding the missing `dropdownItems` helper (returning the
ReactiveVar),
matching the pattern the other migrated templates already use. Thanks to
Claude.
- **Fixed `Exception in global helper _` when opening the Create Custom
Field
popup (and any translation containing a literal `%`).** i18n is
configured with
a global sprintf post-processor (`postProcess: ["sprintf"]`), so every
translation is run through `i18next-sprintf-postprocessor`. The help
text
`custom-field-stringtemplate-format` (`"Format (use %{value} as
placeholder)"`)
contains a literal `%{value}` that sprintf cannot parse, so `vsprintf`
threw and
crashed the global Blaze `_` translation helper — breaking that popup
and any
string (in any language, including user translation overrides) that
contains a
stray `%`. `TAPi18n.__` now retries without the sprintf post-processor
when it
throws, returning the raw string (so `%{value}` is shown literally)
instead of
    crashing.
    Thanks to rouceto1, xet7 and Claude.
- [Fixed new checklists (and checklist items) on a newly added card not
being visible until
logout/login](https://redirect.github.com/wekan/wekan/commit/075e86b00e1f0dc0dea519acd37cece4d0a1fad3).
  The `board` publication batched checklists,
checklist items, comments and attachments into board-level cursors
filtered by
`cardId: { $in: cardIds }`, where `cardIds` was a one-time snapshot. In
`reywood:publish-composite` a child cursor only re-runs when its parent
(the
board) document changes, so the snapshot never refreshed when a card was
added
— a checklist on a card created after subscribing matched no published
card and
only appeared on the next subscribe (logout/login). This was a
regression from
the "Optimized board loading" change, which had replaced the original
reactive
per-card child cursors with these batched snapshots. Fixed by
**denormalizing a
`boardId` field onto `Checklists` and `ChecklistItems`** so they can be
published with a single board-level cursor filtered by `boardId` — one
cursor
per collection (keeping the load optimization) that still reacts to
checklists
on newly added cards, because a new checklist is created already
carrying the
board's id. `boardId` is set on insert (server `before.insert` hooks,
plus
explicitly in the Trello/WeKan board importers, which use
`direct.insert` and
bypass hooks), re-derived when a checklist/item or its card moves to
another
  card (`before.update` on `cardId`) or the card moves to another board
  (`Cards.after.update` cascade), and backfilled for existing data by an
idempotent startup migration. New `{ boardId: 1 }` indexes were added on
both
collections. Comments and attachments instead remain reactive as
per-card
children of the cards cursor. Assigned-only board members still only
receive
checklists for cards assigned to them (the board-level cursor falls back
to the
  assigned cards' ids for those roles).
  Thanks to ahlgrimma, xet7 and Claude.
- [Fixed SyncedCron
crash](https://redirect.github.com/wekan/wekan/commit/72767ad9a769fee2548f93bbd7174edd69995e97).
**Fixed deleting archived lists (or many cards) crashing the server with
`SyncedCron: Fatal error encountered (unhandledRejection): TypeError:
Cannot
  read properties of undefined (reading 'boardId')` at
`server/models/checklistItems.js`.** Deleting a list cascades into
removing its
cards, and each card's checklists, checklist items, comments and
attachments
(`cardRemover` in `models/cards.js`). `Cards.before.remove` called
`cardRemover`
**without `await`** (and was not `async`), so the card document was
deleted
  first and the cascade then ran with the parent card already gone; the
`ChecklistItems.before.remove` / `Checklists.before.remove` hooks
dereferenced
the now-undefined card (`card.boardId`) and threw, and because the
promise was
unhandled, SyncedCron caught the rejection and tore down all running
cron jobs.
Fixed by making `Cards.before.remove` `async` and awaiting `cardRemover`
(so
sub-items are removed while the card still exists), and the REST
card-delete
handler now runs `cardRemover` before removing the card. As defense in
depth,
  every card-activity hook and helper that looked up a card and used its
`boardId` / `listId` / `swimlaneId` now skips (with a warning) when the
parent
card — or, for checklist-completion activities, the parent checklist —
is
  missing, instead of throwing: `before.remove` on checklist items and
checklists, `Checklists.after.insert`, the `Cards.before.update` timing
  activity, and the shared `itemCreation` / `publishCheckActivity` /
`publishChekListCompleted` / `publishChekListUncompleted` /
`commentCreation`
  helpers (matching the guards already present in
  `server/models/cardComments.js`).
  Thanks to titver968, xet7 and Claude.
- **[Fixed upgrade
crash](https://redirect.github.com/wekan/wekan/commit/39f3c89b0a11c5671b77d3a0b95200ac7256a4f1)
  `An error occurred when creating an index for collection
"users": Topology is closed` / `MongoServerSelectionError: Server
selection
timed out after 30000 ms`.** When WeKan started before MongoDB was
reachable
and had an elected replica-set primary (common right after an upgrade,
while
MongoDB replays its WiredTiger journal, or when the app container starts
at the
same instant as the database), the first index creation threw and Node
exited.
  Now:
- **WeKan waits until MongoDB is ready** (reachable, with an elected
primary)
before it starts, in every launch path: `start-wekan.sh`,
`start-wekan.bat`,
    the Snap (`snap-src/bin/wekan-control`), and the app itself
(`server/00waitForMongo.js` / `server/lib/mongoStartup.js`, which blocks
the
first `Meteor.startup` so it also protects the plain Docker image). The
Docker
`docker-compose.yml` and `docker-compose-multitenancy.yml` now give
`wekandb`
    a `healthcheck` (primary elected) and the WeKan/tenant services
    `depends_on: condition: service_healthy`.
- **If MongoDB stays unreachable for too long** (default 120s,
configurable via
`WEKAN_DB_WAIT_TIMEOUT`), a clear English-only message is printed to the
Node.js console / `docker logs` / `snap logs` explaining that a database
upgrade with `mongodump` (old MongoDB) and `mongorestore --drop` (new
MongoDB) may be needed, and reminding that attachments and avatars live
on disk under `WRITABLE_PATH` (`files`, `attachments`, `avatars`; on
Snap
`/var/snap/wekan/common/files`, on Docker the `wekan-files` volume at
`/data`) and must be copied too. WeKan keeps retrying after printing it.
- **Index creation is now idempotent and crash-safe.** A new
`ensureIndex`
helper checks the existing indexes and only creates the ones that are
missing, and never throws — a single index problem is logged in English
instead of taking the whole server down. All startup index creation
across
    the model files was switched to it.
    Thanks to xet7 and Claude.
- [Fixed OpenAPI REST API documentation
generation](https://redirect.github.com/wekan/wekan/commit/c71a97cba20247ce227a288fa74ef23cb3c4c83e),
  which had been broken
since after WeKan v7.93 and only generated docs for the
`login`/`register`
endpoints (2 operations) instead of the full API. The Meteor 3 migration
moved
  the REST routes from `models/*.js` (`JsonRoutes.add(...)`) into
  `server/models/*.js` (`WebApp.handlers.get/post/put/delete(...)`) and
introduced optional chaining (`?.`) that the `esprima` Python parser
cannot
read, so `openapi/generate_openapi.py` silently skipped every route
file.
The generator now understands both routing styles, scans both `models/`
and
`server/models/`, downlevels modern JS syntax so files parse, handles
the
`type: Array` SimpleSchema idiom, and `releases/rebuild-docs.sh` works
directly
  with Python 3.12.x (PEP 668). The generated `public/api/wekan.yml` /
  `wekan.html` now cover the full API again (89 operations / 61 paths).
  Thanks to xet7 and Claude.
- **The attachment copy API now honours the admin "Admin Panel /
Attachments"
API transfer limits.** Copying an attachment creates a new attachment
but
skipped the `apiUploadBlocked` / `apiUploadMaxBytes` checks that upload
enforces; copy now respects them in both API implementations. Thanks to
Claude.
- [Fixed Admin Panel / Attachments / Move Attachment doing nothing /
crashing](https://redirect.github.com/wekan/wekan/commit/d30803276d6d06db44f65ee1fb583cc11aac8b7b).
  Several issues in the bulk move:
- The GridFS source matcher required `meta.gridFsFileId` to be *absent*,
but
Meteor-Files always sets it, so selecting "MongoDB Meteor-Files" matched
zero
files and "nothing happened". The matcher now recognizes real GridFS
files
(`versions.*.storage === 'gridfs'` or a `meta.gridFsFileId` reference),
and a
"nothing to move" message is shown when a source is empty instead of
silently
    doing nothing.
  - Moving files crashed the whole server with
`FilesCollection#findOne() not available in server` —
`ReactiveCache.getAttachment`
used a synchronous `findOne()`; it now uses `findOneAsync()`. The
background
job is also hardened so a single failing file is skipped instead of
crashing
    the server via an unhandled rejection.
- The attachment **copy** API now honours the admin API upload limits
(it
    previously skipped them).
- **Fixed the "MongoDB Meteor-Files" file-count statistic** in Admin
Panel /
Attachments, which counted *every* attachment metadata document (so
files on
the Filesystem were wrongly reported as being in GridFS). It now counts
only
attachments actually stored in GridFS, consistent with the move tool.
Also
renamed the mislabeled "Mongo-Files" column to "Meteor-Files". Thanks to
Claude.
- **Read legacy CollectionFS attachments and avatars in place** (without
  migrating). The backward-compatibility layer
(`models/lib/attachmentBackwardCompatibility.js`) was broken — it looked
up the
  GridFS binary by the filerecord `_id` and by filename instead of by
`ObjectId(copies.<coll>.key)`, so legacy files were never found. It is
fixed and
generalized for attachments and avatars. Legacy attachments now appear
in the
card attachment gallery (new `legacyBoardAttachments` publication) and
stream
  from the `cfs_gridfs.attachments` bucket, and legacy avatars
(`/cfs/files/avatars/<id>` URLs) are served from the
`cfs_gridfs.avatars`
  bucket instead of redirecting to a 404.
  Thanks to xet7 and Claude.
- [Ask to install npm dependencies before running
tests](https://redirect.github.com/wekan/wekan/commit/b77b62bfa2e7a63fdd2d2d071693d5aa485a34c5).
  Thanks to xet7 and Claude.

Thanks to above GitHub users for their contributions and translators for
their translations.

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Renovate
Bot](https://redirect.github.com/renovatebot/renovate).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMzAuMSIsInVwZGF0ZWRJblZlciI6IjQzLjEzMC4xIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbImFwcC93ZWthbiIsImF1dG9tZXJnZSIsInJlbm92YXRlL2NvbnRhaW5lciIsInR5cGUvbWlub3IiXX0=-->
2026-06-06 13:48:56 +02:00

title
title
TrueCharts

Community Helm Chart Catalog

docs Discord GitHub last commit


TrueCharts is a catalog of highly optimised Helm Charts. Made for the community, by the community!

All our charts are supposed to work together and be easy to setup using any helm-compatible deployment tool, above all, give the average user more than enough options to tune things to their liking.


Getting started using TrueCharts

docs


Support

Please check our FAQ, manual and Issue tracker There is a significant chance your issue has been reported before!

Still something not working as expected? Contact us! and we'll figure it out together!

Development

pre-commit renovate GitHub last commit


Our development process is fully distributed and agile, so every chart-maintainer is free to set their own roadmap and development speed and does not have to comply to a centralised roadmap. This ensures freedom and flexibility for everyone involved and makes sure you, the end user, always has the latest and greatest of every Chart installed.

Getting into creating Charts

For more information check the website: https://truecharts.org

Contact and Support

Discord


To contact the TrueCharts project:




Contributors

All Contributors

Thanks goes to these wonderful people (emoji key):


Kjeld Schouten-Lebbing
Kjeld Schouten-Lebbing

💻 🚇 📖 👀 💵
Justin Clift
Justin Clift

📖
whiskerz007
whiskerz007

💻
Stavros Kois
Stavros Kois

💻 📖 🐛 👀 💵
allen-4
allen-4

💻
Troy Prelog
Troy Prelog

💻 📖 💵
Dan Sheridan
Dan Sheridan

💻
Sebastien Dupont
Sebastien Dupont

📖 💵
Vegetto
Vegetto

👀
Ellie Nieuwdorp
Ellie Nieuwdorp

💻
Nate Walck
Nate Walck

💻
Lloyd
Lloyd

💻 💵
Dave Withnall
Dave Withnall

📖
ksimm1
ksimm1

📖 🐛 💵 🧑‍🏫
Aaron Johnson
Aaron Johnson

📖
Ralph
Ralph

💻
Joachim Baten
Joachim Baten

💻 🐛
Michael Yang
Michael Yang

💻
Ciaran Farley
Ciaran Farley

📖
Heavybullets8
Heavybullets8

📖 💻 🐛 📹 🧑‍🏫 💵
662
662

💻
alex171
alex171

📖
Techno Tim
Techno Tim

📖
Mingyao Liu
Mingyao Liu

💻 🐛
NightShaman
NightShaman

💻 📖 🐛 💵 🧑‍🏫
Andrew Smith
Andrew Smith

📖 ⚠️
Bob Klosinski
Bob Klosinski

💻
Sukarn
Sukarn

💻 📖
sebs
sebs

💻
Dyllan Tinoco
Dyllan Tinoco

💻
StevenMcElligott
StevenMcElligott

💻 💵 📖 🐛 🧑‍🏫
brothergomez
brothergomez

💻 🐛
sagit
sagit

💻 🐛 📹 📖 🧑‍🏫
Nevan Chow
Nevan Chow

💻
Daniel Carlsson
Daniel Carlsson

🐛
Devon Louie
Devon Louie

🐛
Alex-Orsholits
Alex-Orsholits

🐛
Tails32
Tails32

🐛
Menaxerius
Menaxerius

🐛
hidefog
hidefog

🐛
Darren Gibbard
Darren Gibbard

🐛
Barti
Barti

🐛
Sunii
Sunii

🐛
trbmchs
trbmchs

🐛
Light
Light

🐛
Boostflow
Boostflow

🐛
Trigardon
Trigardon

🐛
dbb12345
dbb12345

🐛 💻
karypid
karypid

🐛
Philipp
Philipp

🐛
John
John

🐛 📖
John Parton
John Parton

🐛
Marc
Marc

🐛
fdzaebel
fdzaebel

🐛
kloeckwerx
kloeckwerx

🐛
Bradley Bare
Bradley Bare

🐛
Alexander Thamm
Alexander Thamm

🐛
rexit1982
rexit1982

🐛
iaxx
iaxx

🐛
Xstar97
Xstar97

💻 🐛 🧑‍🏫
ornias
ornias

📹
Josh Asplund
Josh Asplund

💵
midnight33233
midnight33233

💵
kbftech
kbftech

💵
hogenf
hogenf

💵
Hawks
Hawks

💵
Jim Russell
Jim Russell

💵
TheGovnah
TheGovnah

💵
famewolf
famewolf

💵 🐛
Konrad Bujak
Konrad Bujak

📖
190n
190n

💻 📖
Alexej Kubarev
Alexej Kubarev

📖
r-vanooyen
r-vanooyen

📖
shadofall
shadofall

📖 🧑‍🏫
agreppin
agreppin

💻
Stavros Ntentos
Stavros Ntentos

💻 🤔
Vlad-Florin Ilie
Vlad-Florin Ilie

💻
huma2000
huma2000

🐛
hugalafutro
hugalafutro

🐛 💵
yehia Amer
yehia Amer

📖
Tyler Stransky
Tyler Stransky

🐛
juggie
juggie

🐛
Ben Tilford
Ben Tilford

🐛 💻
I-nebukad-I
I-nebukad-I

🐛 💻
Ethan Leisinger
Ethan Leisinger

💻 📖
Cullen Murphy
Cullen Murphy

💻 🐛
Jason Thatcher
Jason Thatcher

💻 🐛 📖
Stefan Schramek
Stefan Schramek

🐛
nokaka
nokaka

🐛
Gal Szkolnik
Gal Szkolnik

🐛
Evgeny Stepanovych
Evgeny Stepanovych

🐛
Waqar Ahmed
Waqar Ahmed

🐛
DrSKiZZ
DrSKiZZ

💵
Jan Puciłowski
Jan Puciłowski

💻 ⚠️
Shaun Coyne
Shaun Coyne

💵
Christoph
Christoph

💵
Brandon Rutledge
Brandon Rutledge

🐛
Michael Bestas
Michael Bestas

🐛
Jurģis Rudaks
Jurģis Rudaks

🐛
brunofatia
brunofatia

💵
TopicsLP
TopicsLP

📖
Michael Schnerring
Michael Schnerring

🐛 💻
Tamas Nagy
Tamas Nagy

🐛
OpenSpeedTest™️
OpenSpeedTest™️

💻
Richard James Acton
Richard James Acton

📖
lps-rocks
lps-rocks

🐛
Faust
Faust

🐛
uranderu
uranderu

🐛
Tom Cassady
Tom Cassady

🐛
Huftierchen
Huftierchen

🐛
ZasX
ZasX

📖 🧑‍🏫 💻
Kevin T.
Kevin T.

🐛
Steven Scott
Steven Scott

📖
Watteel Pascal
Watteel Pascal

💻
JamesOsborn-SE
JamesOsborn-SE

💻 📖
NeoToxic
NeoToxic

🧑‍🏫 🐛
jab416171
jab416171

📖
Anna
Anna

📖
ChaosBlades
ChaosBlades

🐛
Patric Stout
Patric Stout

💻
Ben Kochie
Ben Kochie

💻
Jeff Bachtel
Jeff Bachtel

📖
Ben Woods
Ben Woods

💻
Karl Shea
Karl Shea

🐛
Balakumaran MN
Balakumaran MN

📖
Jesperbelt
Jesperbelt

📖
cccs31
cccs31

🐛
Sam Smucny
Sam Smucny

💻
Keith Cirkel
Keith Cirkel

💻
mgale456
mgale456

💻
Alec Fenichel
Alec Fenichel

💻
John Dorman
John Dorman

💻
Dan
Dan

💻
u4ium
u4ium

📖
ErroneousBosch
ErroneousBosch

🐛
MaverickD650
MaverickD650

💻 🐛
Grogdor
Grogdor

📖
Ryan Gooler
Ryan Gooler

📖
Rob Herley
Rob Herley

📖
Christian Heimlich
Christian Heimlich

📖
l-moon-git
l-moon-git

💻
hughes5
hughes5

📖
sdimovv
sdimovv

💻
AllieQpzm
AllieQpzm

💻
Dominik
Dominik

🐛
renovate[bot]
renovate[bot]

🔧
allcontributors[bot]
allcontributors[bot]

🔧
dependabot[bot]
dependabot[bot]

🔧
TrueCharts Bot
TrueCharts Bot

🔧 🚇 💻
Mend Renovate
Mend Renovate

🔧
Simone
Simone

💻
Jean-François Roy
Jean-François Roy

💻
Whiskey24
Whiskey24

💻
inmanturbo
inmanturbo

📖
Alex
Alex

💻
Brian Semrad
Brian Semrad

💻
Christopher
Christopher

💻 📖
Csaba Engedi
Csaba Engedi

💻
Cyb3rzombie
Cyb3rzombie

💻
Eric Cavalcanti
Eric Cavalcanti

💻
Gavin Chappell
Gavin Chappell

💻 🐛
raynay-r
raynay-r

💻
Jip-Hop
Jip-Hop

📖
Jonas Wrede
Jonas Wrede

💻
SilentNyte
SilentNyte

📖
Stan
Stan

💻
Tiago Gaspar
Tiago Gaspar

💻
gismo2004
gismo2004

💻
jsegaert
jsegaert

📖
Miguel Angel Nubla
Miguel Angel Nubla

💻
xal3xhx
xal3xhx

💻
jeremybox
jeremybox

📖
Cameron Sabuda
Cameron Sabuda

📖
Jeroen Schepens
Jeroen Schepens

🐛
James Wright
James Wright

📖
Malpractis
Malpractis

🐛
CommanderStarhump
CommanderStarhump

🐛
Vianchiel
Vianchiel

🐛
Maximilian Ehlers
Maximilian Ehlers

🐛
nautilus7
nautilus7

🐛 💻
kqmaverick
kqmaverick

🐛
ccalby
ccalby

🐛
kofeyh
kofeyh

🐛
imjustleaving
imjustleaving

🐛
Cristian Torres
Cristian Torres

🐛
schopenhauer
schopenhauer

🐛
Zackptg5
Zackptg5

🐛
Brad Ackerman
Brad Ackerman

🐛
mcspiff313
mcspiff313

🐛
Fletcher Nichol
Fletcher Nichol

💻 🐛
Marco Faggian
Marco Faggian

💻
John P
John P

📖
kryojenik
kryojenik

💻
Malcolm
Malcolm

📖
depasseg
depasseg

📖
j1mbl3s
j1mbl3s

📖
VictorienXP
VictorienXP

💻
yelhouti
yelhouti

💻
Jaroslav Lichtblau
Jaroslav Lichtblau

📖
MaximilianS
MaximilianS

📖
Dion Larson
Dion Larson

💻 📖
Physics-Dude
Physics-Dude

📖
waflint
waflint

💻
Henry Wilkinson
Henry Wilkinson

💻 📖
cedstrom
cedstrom

💻
v3DJG6GL
v3DJG6GL

🐛 💻
polarstack
polarstack

💻
Keyvan
Keyvan

💻
MickaelFontes
MickaelFontes

💻
David CM
David CM

💻
Aamir Azad
Aamir Azad

📖
Jordan Woyak
Jordan Woyak

💻
Simon Hofman
Simon Hofman

💻
notyouraveragegamer
notyouraveragegamer

📖
Varac
Varac

💻
tuxsudo
tuxsudo

💻
TylerRudie
TylerRudie

📖
qnb59bny5x
qnb59bny5x

💻
Filip Bednárik
Filip Bednárik

🐛
Serhii Shcherbinin
Serhii Shcherbinin

💻
Quentin Raynaud
Quentin Raynaud

🐛
Felix Schäfer
Felix Schäfer

📖
Julien Nicolas de Verteuil
Julien Nicolas de Verteuil

💻
Gabriel Donadel Dall'Agnol
Gabriel Donadel Dall'Agnol

📖
Jon S. Stumpf
Jon S. Stumpf

📖
Tanguille
Tanguille

📖
Dennis
Dennis

🐛 📖
TheIceCreamTroll
TheIceCreamTroll

💻
Atanas Pamukchiev
Atanas Pamukchiev

💻
Boemeltrein
Boemeltrein

📖
Yiannis Marangos
Yiannis Marangos

💻
Michael Ruoss
Michael Ruoss

💻
Aron Kahrs
Aron Kahrs

💻
nemesis1982
nemesis1982

📖
Ed P
Ed P

💻
Frédéric Nadeau
Frédéric Nadeau

📖
frapbod
frapbod

💻
Max Bachhuber
Max Bachhuber

💻
zierbeek
zierbeek

💻
Ac1dburn
Ac1dburn

💻
Antoine Saget
Antoine Saget

📖
Ben Bodenmiller
Ben Bodenmiller

🐛
felixfon
felixfon

📖
adtwomey
adtwomey

📖
alfi0812
alfi0812

💻 📖 🐛 👀
Agassi
Agassi

💻
Artur
Artur

💻
Morgan Hunter
Morgan Hunter

💻
Aleksandr Oleinikov
Aleksandr Oleinikov

💻
Jamie
Jamie

💻
David Gries
David Gries

🐛 💻
Phreeman33
Phreeman33

💻 🐛
Jens Wolvers
Jens Wolvers

💻
Bart Willems
Bart Willems

💻
Caidy
Caidy

💻
Mr Khachaturov
Mr Khachaturov

💻
LordCrash101
LordCrash101

📖
elendil95
elendil95

💻
TheDodger
TheDodger

💻
Saad Awan
Saad Awan

💻
Felix von Arx
Felix von Arx

💻
yodatak
yodatak

💻
Marcel Henrich
Marcel Henrich

💻
Florent Viel
Florent Viel

💻
SniperAsh6
SniperAsh6

💻
Alexandre Acebedo
Alexandre Acebedo

💻
Douglas Chimento
Douglas Chimento

💻
Addison McDermid
Addison McDermid

💻
Jaël Gareau
Jaël Gareau

💻
Steve Sampson
Steve Sampson

📖
Albert Romkes
Albert Romkes

💻
Maja Bojarska
Maja Bojarska

💻
astro-stan
astro-stan

💻
Oliver Simons
Oliver Simons

💻
Brioche
Brioche

💻

This project follows the all-contributors specification. Contributions of any kind welcome!

Licence

License


Truecharts, is primarily based on the AGPL-v3 license, this ensures almost everyone can use and modify our charts. Licences can vary on a per-Chart basis. This can easily be seen by the presence of a "LICENSE" file in that folder.

An exception to this, has been made for every document inside folders labeled as docs or doc and their subfolders: those folders are not licensed under AGPL-v3 and are considered "all rights reserved". Said content can be modified and changes submitted per PR, in accordance to the github End User License Agreement.

SPDX-License-Identifier: AGPL-3.0


built-with-resentment contains-technical-debt

S
Description
Fork of trueforge-org/truecharts with some customizations
Readme 890 MiB
luanti-v1.0.0 Latest
2026-07-08 18:51:26 +00:00
Languages
Go Template 97.9%
Shell 2.1%