Compare commits

..
5 Commits
Author SHA1 Message Date
github-actions[bot] 9ce35869a7 Bump versions for v12.96 2026-11-05 19:41:40 +00:00
Lauri Ojansivu 2017d07e37 Prepare v12.96 release 2026-11-05 21:40:23 +02:00
Lauri Ojansivu 9ea5c81932 CHANGELOG: repoint commit links after history moved.
A rebase rewrote the commits these entries link to, so the links named commits
that no longer exist and would have 404ed on GitHub. Repointed by
releases/fix-changelog-hashes.sh, which only touches a link no ref in this clone
can reach.

Thanks to xet7 !
2026-11-05 21:39:54 +02:00
Lauri Ojansivu 45ccdd9c3c CHANGELOG: the bundle starts again, and v12.95 records that its bundle did not.
Thanks to xet7 !
2026-11-05 21:39:02 +02:00
Lauri Ojansivu 5a21b074d4 The bundle starts again: nodemailer 10 in meteor/email gets back the lib/ paths it was built against.
releases/bump-bundle-npm-deps.mjs raises the nodemailer inside Meteor's email
package from 8.0.3 to 10.3.1 (dad03959d9), and nodemailer 10 moved lib/ to
dist/cjs/. packages/email.js, compiled against 8.0.3, links
lib/nodemailer.js and lib/well-known/index.js and Npm.requires
lib/mail-composer by path, so v12.95's build-amd64 failed its smoke boot:
"Cannot find module .../meteor/email/node_modules/nodemailer/lib/nodemailer.js".

releases/bundle-npm-security-bumps.json now shims nodemailer the way it
already shims uuid 11: lib/nodemailer.js and every lib/<name> directory the
exports map lists are written back, each forwarding to dist/cjs, and
lib/package.json marks lib/ as CommonJS because nodemailer is "type":
"module". A fresh local bundle taken through build-amd64's install, bump,
trim and prune steps now passes releases/bundle-smoke-boot.sh.

tests/bundleNpmSecurityBumps.test.cjs applies the shim to node_modules'
nodemailer 10, requires the recorded paths, checks that every exported
lib/<name> has a forward to the same module, and fails without the CommonJS
marker.

Thanks to xet7 !
2026-11-05 21:39:02 +02:00
13 changed files with 138 additions and 26 deletions

No files matched your search

+35
View File
@@ -124,6 +124,34 @@ its reason.
</details>
# v12.96 2026-11-05 WeKan ® release
**In short:** The release **bundle starts again**: v12.95's build stopped on
boot because the **nodemailer** 10 raised inside Meteor's email package no
longer had the files that package was built against.
This release fixes the following bug:
<details>
<summary><a href="https://github.com/wekan/wekan/commit/5a21b074d4">The bundle starts again, with nodemailer 10 inside Meteor's email package</a>. Thanks to xet7.</summary>
v12.95 raised the nodemailer in `meteor/email` from 8.0.3 to 10.3.1, and
nodemailer 10 moved `lib/` to `dist/cjs/`. `packages/email.js`, compiled
against 8.0.3, links `lib/nodemailer.js` and `lib/well-known/index.js` and
`Npm.require`s `lib/mail-composer` by path, so build-amd64 failed its smoke
boot. `releases/bundle-npm-security-bumps.json` now shims nodemailer as it
already shims uuid 11: `lib/nodemailer.js` and every `lib/<name>` directory the
exports map lists are written back, forwarding to `dist/cjs`, with a
`lib/package.json` marking them CommonJS because nodemailer is `"type":
"module"`. A fresh local bundle taken through build-amd64's install, bump, trim
and prune steps passes `releases/bundle-smoke-boot.sh`.
`tests/bundleNpmSecurityBumps.test.cjs` requires the recorded paths through the
shim, checks every exported `lib/<name>`, and fails without the CommonJS marker.
</details>
Thanks to above GitHub users for their contributions and translators for their translations.
# v12.95 2026-11-05 WeKan ® release
**In short:** **Continuous backup** now runs on one server at a time, with a
@@ -313,6 +341,13 @@ predates them. The runtime image installs no compiler (`gcc-14-base` is Debian's
one-file package), so the multi-stage build the report asks for is already how
it is built. Run against a copy of the published image's bundle, the bumper
raised all of the above and every raised copy loaded.
**This release's bundle did not start.** "Every raised copy loaded" was checked
by loading each package, not by booting the bundle: nodemailer 10 moved `lib/`
to `dist/cjs/`, Meteor's `email` package still links the `lib/` paths of 8.0.3,
and build-amd64 failed its smoke boot with "Cannot find module
.../meteor/email/node_modules/nodemailer/lib/nodemailer.js". The fix is in the
next release.
`tests/bundleNpmSecurityBumps.test.cjs` pins the minimums, the per-major
rule and the shim, and runs the bumper with `--dry-run` on a bundle of
body-parser, uuid and nodemailer copies at, below and above their minimums.
+8 -8
View File
@@ -5,6 +5,14 @@ each one changed and the project status are in
Written by `node releases/changelog-short.mjs` from CHANGELOG-big.md:
make changes there.
# v12.96 2026-11-05 WeKan ® release
The release **bundle starts again**: v12.95's build stopped on
boot because the **nodemailer** 10 raised inside Meteor's email package no
longer had the files that package was built against.
[All changes in v12.96](CHANGELOG-big.md#v1296-2026-11-05-wekan--release)
# v12.95 2026-11-05 WeKan ® release
**Continuous backup** now runs on one server at a time, with a
@@ -41,11 +49,3 @@ A missing **REST checklist** answers a JSON 404 instead of an
empty 500.
[All changes in v12.92](CHANGELOG-big.md#v1292-2026-11-03-wekan--release)
# v12.91 2026-11-03 WeKan ® release
A **GitHub CodeQL** finding in a test is fixed, and the guard
against
replacing text with itself now also sees patterns with a `^` or `$` anchor.
[All changes in v12.91](CHANGELOG-big.md#v1291-2026-11-03-wekan--release)
+1 -1
View File
@@ -38,7 +38,7 @@ FROM --platform=$BUILDPLATFORM debian:trixie AS bundle
ARG TARGETARCH
ARG TARGETVARIANT
ARG VERSION=12.95
ARG VERSION=12.96
ARG DEBIAN_FRONTEND=noninteractive
COPY --chmod=755 releases/check-telemetry.py /tmp/check-telemetry.py
+1 -1
View File
@@ -1,5 +1,5 @@
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
appVersion: "v12.95.0"
appVersion: "v12.96.0"
files:
userUploads:
- README.md
@@ -10,7 +10,7 @@ This is without container (without Docker or Snap).
Right click and download files 1-4:
1. [wekan-12.95-win64.zip](https://github.com/wekan/wekan/releases/download/v12.95/wekan-12.95-win64.zip) or newest available at https://github.com/wekan/wekan/releases/
1. [wekan-12.96-win64.zip](https://github.com/wekan/wekan/releases/download/v12.96/wekan-12.96-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-12.95-win64.zip` , inside it is directory `bundle`, to it copy other files:
7. Unzip `wekan-12.96-win64.zip` , inside it is directory `bundle`, to it copy other files:
```
bundle (directory)
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "wekan",
"version": "v12.95.0",
"version": "v12.96.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "wekan",
"version": "v12.95.0",
"version": "v12.96.0",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "wekan",
"version": "v12.95.0",
"version": "v12.96.0",
"description": "Open-Source kanban",
"private": true,
"repository": {
+3 -3
View File
@@ -3,7 +3,7 @@
<head>
<meta charset="utf8" />
<title>WeKan REST API v12.95</title>
<title>WeKan REST API v12.96</title>
<!-- needed for adaptive design -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
@@ -484,11 +484,11 @@ data-styled.g658[id="sc-hHttOM"]{content:"dKSNwp,"}/*!sc*/
<body>
<div id="redoc"><div hidden=""><script>try{var m=localStorage.getItem("redoc.colorMode");if(m!=="light"&&m!=="dark")m=matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light";document.documentElement.classList.add(m)}catch(e){}</script></div><div style="--navbar-height:0px;--navbar-stack-height:0px" class="sc-kIbBWU fFQMWf"><div class="sc-cjUTkN dGsweu menu-content"><div class="sc-jqwVmx jjzLa-d"><div data-testid="search-trigger" class="sc-cToEys dffrbr"><div class="sc-cRcubC ddjiE"><svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" data-component-name="icons/SearchIcon/SearchIcon" class="sc-cHazmW gTzQi"><path d="M14.5 13.7931L10.724 10.017C11.6313 8.9277 12.0838 7.5305 11.9872 6.11608C11.8907 4.70165 11.2525 3.37891 10.2055 2.423C9.15857 1.4671 7.78336 0.951637 6.36602 0.983845C4.94867 1.01605 3.5983 1.59345 2.59582 2.59593C1.59335 3.5984 1.01595 4.94877 0.983738 6.36612C0.95153 7.78347 1.46699 9.15867 2.4229 10.2057C3.3788 11.2526 4.70155 11.8908 6.11597 11.9873C7.53039 12.0839 8.92759 11.6314 10.0169 10.7241L13.793 14.5001L14.5 13.7931ZM2.00001 6.50012C2.00001 5.6101 2.26393 4.74007 2.7584 4.00005C3.25286 3.26003 3.95567 2.68325 4.77794 2.34266C5.6002 2.00207 6.505 1.91295 7.37792 2.08658C8.25083 2.26022 9.05266 2.6888 9.68199 3.31814C10.3113 3.94747 10.7399 4.7493 10.9135 5.62221C11.0872 6.49513 10.9981 7.39993 10.6575 8.22219C10.3169 9.04446 9.7401 9.74726 9.00008 10.2417C8.26006 10.7362 7.39003 11.0001 6.50001 11.0001C5.30694 10.9988 4.16312 10.5243 3.31949 9.68064C2.47587 8.83701 2.00133 7.69319 2.00001 6.50012Z"></path></svg><span>Loading...</span></div></div></div><div class="sc-dNLPWG dtcefb"><ul data-component-name="Menu/Menu" class="sc-kBPbfe ctPApS"><div data-component-name="Menu/MenuItem" class="sc-gwVKcS fGSWQx menu-item-type-default" role="listitem"><a class="sc-iJONRL iBHKJo" href="/" data-discover="true"><li role="none" data-testid="menu-item-label" data-active="true" class="sc-epufQc fYmDZR"><div class="sc-boLXHU jshptd"><span class="sc-bcyEQV hrIrOF"><span data-text="Wekan REST API" class="sc-eStdmu iyAVQU">Wekan REST API</span></span></div></li></a></div><div data-component-name="Menu/MenuItem" class="sc-gwVKcS fGSWQx menu-item-type-default" role="listitem"><a class="sc-iJONRL iBHKJo" href="/section/production-security-concerns" data-discover="true"><li role="none" data-testid="menu-item-label" data-active="false" class="sc-epufQc itBMtf"><div class="sc-boLXHU jshptd"><span class="sc-bcyEQV hrIrOF"><span data-text="Production Security Concerns" class="sc-eStdmu liVEkC">Production Security Concerns</span></span></div></li></a></div><div data-component-name="Menu/MenuItem" class="sc-gwVKcS fGSWQx menu-item-type-group" role="listitem"><a class="sc-iJONRL iBHKJo" href="/login" data-discover="true"><li role="none" data-testid="menu-item-label" data-active="false" class="sc-epufQc hKPPiy"><div class="sc-jokKPH jtaKKl"><svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" color="--tree-content-color-default" data-component-name="icons/ChevronRightIcon/ChevronRightIcon" class="sc-iUlCMS kEEIsB"><path d="M11 8L6.00002 13L5.30002 12.3L9.60002 8L5.30002 3.7L6.00002 3L11 8Z"></path></svg></div><div class="sc-boLXHU jshptd"><span class="sc-bcyEQV hrIrOF"><span data-text="Login" class="sc-eStdmu liVEkC">Login</span></span></div></li></a><div style="display:none;height:0px;overflow:hidden" class="sc-hgJgCR dlNiXx"></div></div><div data-component-name="Menu/MenuItem" class="sc-gwVKcS fGSWQx menu-item-type-group" role="listitem"><a class="sc-iJONRL iBHKJo" href="/attachmentstoragesettings" data-discover="true"><li role="none" data-testid="menu-item-label" data-active="false" class="sc-epufQc hKPPiy"><div class="sc-jokKPH jtaKKl"><svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" color="--tree-content-color-default" data-component-name="icons/ChevronRightIcon/ChevronRightIcon" class="sc-iUlCMS kEEIsB"><path d="M11 8L6.00002 13L5.30002 12.3L9.60002 8L5.30002 3.7L6.00002 3L11 8Z"></path></svg></div><div class="sc-boLXHU jshptd"><span class="sc-bcyEQV hrIrOF"><span data-text="AttachmentStorageSettings" class="sc-eStdmu liVEkC">AttachmentStorageSettings</span></span></div></li></a><div style="display:none;height:0px;overflow:hidden" class="sc-hgJgCR dlNiXx"></div></div><div data-component-name="Menu/MenuItem" class="sc-gwVKcS fGSWQx menu-item-type-group" role="listitem"><a class="sc-iJONRL iBHKJo" href="/settings" data-discover="true"><li role="none" data-testid="menu-item-label" data-active="false" class="sc-epufQc hKPPiy"><div class="sc-jokKPH jtaKKl"><svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" color="--tree-content-color-default" data-component-name="icons/ChevronRightIcon/ChevronRightIcon" class="sc-iUlCMS kEEIsB"><path d="M11 8L6.00002 13L5.30002 12.3L9.60002 8L5.30002 3.7L6.00002 3L11 8Z"></path></svg></div><div class="sc-boLXHU jshptd"><span class="sc-bcyEQV hrIrOF"><span data-text="Settings" classLine truncated
<div id="redoc"><div hidden=""><script>try{var m=localStorage.getItem("redoc.colorMode");if(m!=="light"&&m!=="dark")m=matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light";document.documentElement.classList.add(m)}catch(e){}</script></div><div style="--navbar-height:0px;--navbar-stack-height:0px" class="sc-kIbBWU fFQMWf"><div class="sc-cjUTkN dGsweu menu-content"><div class="sc-jqwVmx jjzLa-d"><div data-testid="search-trigger" class="sc-cToEys dffrbr"><div class="sc-cRcubC ddjiE"><svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" data-component-name="icons/SearchIcon/SearchIcon" class="sc-cHazmW gTzQi"><path d="M14.5 13.7931L10.724 10.017C11.6313 8.9277 12.0838 7.5305 11.9872 6.11608C11.8907 4.70165 11.2525 3.37891 10.2055 2.423C9.15857 1.4671 7.78336 0.951637 6.36602 0.983845C4.94867 1.01605 3.5983 1.59345 2.59582 2.59593C1.59335 3.5984 1.01595 4.94877 0.983738 6.36612C0.95153 7.78347 1.46699 9.15867 2.4229 10.2057C3.3788 11.2526 4.70155 11.8908 6.11597 11.9873C7.53039 12.0839 8.92759 11.6314 10.0169 10.7241L13.793 14.5001L14.5 13.7931ZM2.00001 6.50012C2.00001 5.6101 2.26393 4.74007 2.7584 4.00005C3.25286 3.26003 3.95567 2.68325 4.77794 2.34266C5.6002 2.00207 6.505 1.91295 7.37792 2.08658C8.25083 2.26022 9.05266 2.6888 9.68199 3.31814C10.3113 3.94747 10.7399 4.7493 10.9135 5.62221C11.0872 6.49513 10.9981 7.39993 10.6575 8.22219C10.3169 9.04446 9.7401 9.74726 9.00008 10.2417C8.26006 10.7362 7.39003 11.0001 6.50001 11.0001C5.30694 10.9988 4.16312 10.5243 3.31949 9.68064C2.47587 8.83701 2.00133 7.69319 2.00001 6.50012Z"></path></svg><span>Loading...</span></div></div></div><div class="sc-dNLPWG dtcefb"><ul data-component-name="Menu/Menu" class="sc-kBPbfe ctPApS"><div data-component-name="Menu/MenuItem" class="sc-gwVKcS fGSWQx menu-item-type-default" role="listitem"><a class="sc-iJONRL iBHKJo" href="/" data-discover="true"><li role="none" data-testid="menu-item-label" data-active="true" class="sc-epufQc fYmDZR"><div class="sc-boLXHU jshptd"><span class="sc-bcyEQV hrIrOF"><span data-text="Wekan REST API" class="sc-eStdmu iyAVQU">Wekan REST API</span></span></div></li></a></div><div data-component-name="Menu/MenuItem" class="sc-gwVKcS fGSWQx menu-item-type-default" role="listitem"><a class="sc-iJONRL iBHKJo" href="/section/production-security-concerns" data-discover="true"><li role="none" data-testid="menu-item-label" data-active="false" class="sc-epufQc itBMtf"><div class="sc-boLXHU jshptd"><span class="sc-bcyEQV hrIrOF"><span data-text="Production Security Concerns" class="sc-eStdmu liVEkC">Production Security Concerns</span></span></div></li></a></div><div data-component-name="Menu/MenuItem" class="sc-gwVKcS fGSWQx menu-item-type-group" role="listitem"><a class="sc-iJONRL iBHKJo" href="/login" data-discover="true"><li role="none" data-testid="menu-item-label" data-active="false" class="sc-epufQc hKPPiy"><div class="sc-jokKPH jtaKKl"><svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" color="--tree-content-color-default" data-component-name="icons/ChevronRightIcon/ChevronRightIcon" class="sc-iUlCMS kEEIsB"><path d="M11 8L6.00002 13L5.30002 12.3L9.60002 8L5.30002 3.7L6.00002 3L11 8Z"></path></svg></div><div class="sc-boLXHU jshptd"><span class="sc-bcyEQV hrIrOF"><span data-text="Login" class="sc-eStdmu liVEkC">Login</span></span></div></li></a><div style="display:none;height:0px;overflow:hidden" class="sc-hgJgCR dlNiXx"></div></div><div data-component-name="Menu/MenuItem" class="sc-gwVKcS fGSWQx menu-item-type-group" role="listitem"><a class="sc-iJONRL iBHKJo" href="/attachmentstoragesettings" data-discover="true"><li role="none" data-testid="menu-item-label" data-active="false" class="sc-epufQc hKPPiy"><div class="sc-jokKPH jtaKKl"><svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" color="--tree-content-color-default" data-component-name="icons/ChevronRightIcon/ChevronRightIcon" class="sc-iUlCMS kEEIsB"><path d="M11 8L6.00002 13L5.30002 12.3L9.60002 8L5.30002 3.7L6.00002 3L11 8Z"></path></svg></div><div class="sc-boLXHU jshptd"><span class="sc-bcyEQV hrIrOF"><span data-text="AttachmentStorageSettings" class="sc-eStdmu liVEkC">AttachmentStorageSettings</span></span></div></li></a><div style="display:none;height:0px;overflow:hidden" class="sc-hgJgCR dlNiXx"></div></div><div data-component-name="Menu/MenuItem" class="sc-gwVKcS fGSWQx menu-item-type-group" role="listitem"><a class="sc-iJONRL iBHKJo" href="/settings" data-discover="true"><li role="none" data-testid="menu-item-label" data-active="false" class="sc-epufQc hKPPiy"><div class="sc-jokKPH jtaKKl"><svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" color="--tree-content-color-default" data-component-name="icons/ChevronRightIcon/ChevronRightIcon" class="sc-iUlCMS kEEIsB"><path d="M11 8L6.00002 13L5.30002 12.3L9.60002 8L5.30002 3.7L6.00002 3L11 8Z"></path></svg></div><div class="sc-boLXHU jshptd"><span class="sc-bcyEQV hrIrOF"><span data-text="Settings" classLine truncated
<script type="module">
import { hydrate } from "https://cdn.redocly.com/redoc/v3.0.1/bundles/redoc.standalone.js";
const __redoc_definition = {"openapi":"3.2.0","info":{"title":"Wekan REST API","version":"v12.95","description":"The REST API allows you to control and extend Wekan with ease.\n\nIf you are an end-user and not a dev or a tester, [create an issue](https://github.com/wekan/wekan/issues/new) to request new APIs.\n\n> All API calls in the documentation are made using `curl`. However, you are free to use Java / Python / PHP / Golang / Ruby / Swift / Objective-C / Rust / Scala / C# or any other programming languages.\n\n# Production Security Concerns\nWhen calling a production Wekan server, ensure it is running via HTTPS and has a valid SSL Certificate. The login method requires you to post your username and password in plaintext, which is why we highly suggest only calling the REST login api over HTTPS. Also, few things to note:\n\n* Only call via HTTPS\n* Implement a timed authorization token expiration strategy\n* Ensure the calling user only has permissions for what they are calling and no more\n"},"paths":{"/users/login":{"post":{"operationId":"login","summary":"Login with REST API","tags":["Login"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["username","password"],"properties":{"username":{"description":"Your username\n","type":"string"},"password":{"description":"Your password\n","type":"string","format":"password"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["username","password"],"properties":{"username":{"description":"Your username\n","type":"string"},"password":{"description":"Your password\n","type":"string","format":"password"}}}}},"description":"Login credentials","required":true},"responses":{"200":{"description":"Successful authentication","content":{"*/*":{"schema":{"type":"object","required":["id","token","tokenExpires"],"properties":{"id":{"type":"string","description":"User ID"},"token":{"type":"string","description":"Authentication token\n"},"tokenExpires":{"type":"string","format":"date-time","description":"Token expiration date\n"}}}}}},"400":{"description":"Error in authentication\n","content":{"*/*":{"schema":{"type":"object","properties":{"error":{"type":"string"},"reason":{"type":"string"}}}}}},"default":{"description":"Error in authentication\n"}}}},"/users/register":{"post":{"operationId":"register","summary":"Register with REST API","description":"Notes:\n - You will need to provide the token for any of the authenticated methods.\n","tags":["Login"],"requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"username":{"description":"Your username\n","type":"string"},"password":{"description":"Your password\n","type":"string","format":"password"},"email":{"description":"Your email\n","type":"string"}},"required":["username","password","email"]}}},"required":true},"responses":{"200":{"description":"Successful registration","content":{"*/*":{"schema":{"items":{"properties":{"id":{"type":"string"},"token":{"type":"string"},"tokenExpires":{"type":"string"}}}}}}},"400":{"description":"Error in registration\n","content":{"*/*":{"schema":{"items":{"properties":{"error":{"type":"number"},"reason":{"type":"string"}}}}}}},"default":{"description":"Error in registration\n"}}}},"/api/admin/attachment-settings":{"get":{"operationId":"get_attachment_settings","summary":"Get the attachment storage / upload-block settings (GlobalAdmin)","description":"Only the global admin can call this. Returns the Admin Panel >\n Attachments settings document, including `limitSettings.attachmentsUploadBlocked`\n and `limitSettings.avatarsUploadBlocked` plus the size limits. Cloud-storage\n secret keys (S3 secretAccessKey, Azure accountKey/connectionString, GCS\n credentials) are masked and never returned; a boolean `\u003cfield>Set` marker\n shows whether a value exists.\n","tags":["AttachmentStorageSettings","Settings"],"security":[{"UserSecurity":[]}],"responses":{"200":{"description":"200 response","content":{"application/json":{"schema":{"type":"Object"}}}}}},"put":{"operationId":"update_attachment_settings","summary":"Update the attachment storage / upload-block settings (GlobalAdmin)","description":"Only the global admin can call this. The request body is a\n partial settings object (for example\n `{\"limitSettings\": {\"avatarsUploadBlocked\": true}}`). It is applied through\n the same update path as the `updateAttachmentStorageSettings` Meteor method,\n so validation and `$set` semantics are identical: cloud-storage secrets left\n blank are preserved. The masked, updated settings document is returned.\n","tags":["AttachmentStorageSettings","Settings"],"security":[{"UserSecurity":[]}],"responses":{"200":{"description":"200 response","content":{"application/json":{"schema":{"type":"Object"}}}}}}},"/api/admin/domains":{"get":{"operationId":"get_admin_domains","summary":"List email domains with their user counts (GlobalAdmin)","description":"Only the global admin can call this. CountsLine truncated
const __redoc_definition = {"openapi":"3.2.0","info":{"title":"Wekan REST API","version":"v12.96","description":"The REST API allows you to control and extend Wekan with ease.\n\nIf you are an end-user and not a dev or a tester, [create an issue](https://github.com/wekan/wekan/issues/new) to request new APIs.\n\n> All API calls in the documentation are made using `curl`. However, you are free to use Java / Python / PHP / Golang / Ruby / Swift / Objective-C / Rust / Scala / C# or any other programming languages.\n\n# Production Security Concerns\nWhen calling a production Wekan server, ensure it is running via HTTPS and has a valid SSL Certificate. The login method requires you to post your username and password in plaintext, which is why we highly suggest only calling the REST login api over HTTPS. Also, few things to note:\n\n* Only call via HTTPS\n* Implement a timed authorization token expiration strategy\n* Ensure the calling user only has permissions for what they are calling and no more\n"},"paths":{"/users/login":{"post":{"operationId":"login","summary":"Login with REST API","tags":["Login"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["username","password"],"properties":{"username":{"description":"Your username\n","type":"string"},"password":{"description":"Your password\n","type":"string","format":"password"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["username","password"],"properties":{"username":{"description":"Your username\n","type":"string"},"password":{"description":"Your password\n","type":"string","format":"password"}}}}},"description":"Login credentials","required":true},"responses":{"200":{"description":"Successful authentication","content":{"*/*":{"schema":{"type":"object","required":["id","token","tokenExpires"],"properties":{"id":{"type":"string","description":"User ID"},"token":{"type":"string","description":"Authentication token\n"},"tokenExpires":{"type":"string","format":"date-time","description":"Token expiration date\n"}}}}}},"400":{"description":"Error in authentication\n","content":{"*/*":{"schema":{"type":"object","properties":{"error":{"type":"string"},"reason":{"type":"string"}}}}}},"default":{"description":"Error in authentication\n"}}}},"/users/register":{"post":{"operationId":"register","summary":"Register with REST API","description":"Notes:\n - You will need to provide the token for any of the authenticated methods.\n","tags":["Login"],"requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"username":{"description":"Your username\n","type":"string"},"password":{"description":"Your password\n","type":"string","format":"password"},"email":{"description":"Your email\n","type":"string"}},"required":["username","password","email"]}}},"required":true},"responses":{"200":{"description":"Successful registration","content":{"*/*":{"schema":{"items":{"properties":{"id":{"type":"string"},"token":{"type":"string"},"tokenExpires":{"type":"string"}}}}}}},"400":{"description":"Error in registration\n","content":{"*/*":{"schema":{"items":{"properties":{"error":{"type":"number"},"reason":{"type":"string"}}}}}}},"default":{"description":"Error in registration\n"}}}},"/api/admin/attachment-settings":{"get":{"operationId":"get_attachment_settings","summary":"Get the attachment storage / upload-block settings (GlobalAdmin)","description":"Only the global admin can call this. Returns the Admin Panel >\n Attachments settings document, including `limitSettings.attachmentsUploadBlocked`\n and `limitSettings.avatarsUploadBlocked` plus the size limits. Cloud-storage\n secret keys (S3 secretAccessKey, Azure accountKey/connectionString, GCS\n credentials) are masked and never returned; a boolean `\u003cfield>Set` marker\n shows whether a value exists.\n","tags":["AttachmentStorageSettings","Settings"],"security":[{"UserSecurity":[]}],"responses":{"200":{"description":"200 response","content":{"application/json":{"schema":{"type":"Object"}}}}}},"put":{"operationId":"update_attachment_settings","summary":"Update the attachment storage / upload-block settings (GlobalAdmin)","description":"Only the global admin can call this. The request body is a\n partial settings object (for example\n `{\"limitSettings\": {\"avatarsUploadBlocked\": true}}`). It is applied through\n the same update path as the `updateAttachmentStorageSettings` Meteor method,\n so validation and `$set` semantics are identical: cloud-storage secrets left\n blank are preserved. The masked, updated settings document is returned.\n","tags":["AttachmentStorageSettings","Settings"],"security":[{"UserSecurity":[]}],"responses":{"200":{"description":"200 response","content":{"application/json":{"schema":{"type":"Object"}}}}}}},"/api/admin/domains":{"get":{"operationId":"get_admin_domains","summary":"List email domains with their user counts (GlobalAdmin)","description":"Only the global admin can call this. CountsLine truncated
const __redoc_options = {"skipBundle":true,"disableTelemetry":false};
hydrate(__redoc_definition, __redoc_options, document.getElementById('redoc'));
+1 -1
View File
@@ -1,7 +1,7 @@
swagger: '2.0'
info:
title: Wekan REST API
version: v12.95
version: v12.96
description: |
The REST API allows you to control and extend Wekan with ease.
+30 -1
View File
@@ -20,7 +20,12 @@
"that moved its entry point cannot just be swapped in: uuid 11 moved it from",
"dist/index.js to dist/cjs/index.js and the server died on boot (\"Cannot find",
"module .../uuid/dist/index.js\"). \"shims\" writes the old entry file back,",
"re-exporting the new one.",
"re-exporting the new one. nodemailer 10 moved lib/ to dist/cjs/, while",
"meteor/email, built against 8.0.3, links lib/nodemailer.js and",
"lib/well-known/index.js and Npm.requires lib/mail-composer by path: v12.95's",
"bundle failed its smoke boot on the first. nodemailer is \"type\": \"module\",",
"so its shim marks lib/ as CommonJS and forwards lib/nodemailer.js and every",
"lib/<name> directory its exports map lists to dist/cjs.",
"",
"Applied by releases/bump-bundle-npm-deps.mjs, pinned by",
"tests/bundleNpmSecurityBumps.test.cjs. A package NOT listed here is a package",
@@ -63,6 +68,30 @@
]
},
"shims": {
"nodemailer": {
"lib/package.json": "{ \"type\": \"commonjs\" }\n",
"lib/nodemailer.js": "module.exports = require('../dist/cjs/nodemailer.js');\n",
"lib/addressparser/index.js": "module.exports = require('../../dist/cjs/addressparser/index.js');\n",
"lib/base64/index.js": "module.exports = require('../../dist/cjs/base64/index.js');\n",
"lib/dkim/index.js": "module.exports = require('../../dist/cjs/dkim/index.js');\n",
"lib/fetch/index.js": "module.exports = require('../../dist/cjs/fetch/index.js');\n",
"lib/json-transport/index.js": "module.exports = require('../../dist/cjs/json-transport/index.js');\n",
"lib/mail-composer/index.js": "module.exports = require('../../dist/cjs/mail-composer/index.js');\n",
"lib/mailer/index.js": "module.exports = require('../../dist/cjs/mailer/index.js');\n",
"lib/mime-funcs/index.js": "module.exports = require('../../dist/cjs/mime-funcs/index.js');\n",
"lib/mime-node/index.js": "module.exports = require('../../dist/cjs/mime-node/index.js');\n",
"lib/punycode/index.js": "module.exports = require('../../dist/cjs/punycode/index.js');\n",
"lib/qp/index.js": "module.exports = require('../../dist/cjs/qp/index.js');\n",
"lib/sendmail-transport/index.js": "module.exports = require('../../dist/cjs/sendmail-transport/index.js');\n",
"lib/ses-transport/index.js": "module.exports = require('../../dist/cjs/ses-transport/index.js');\n",
"lib/shared/index.js": "module.exports = require('../../dist/cjs/shared/index.js');\n",
"lib/smtp-connection/index.js": "module.exports = require('../../dist/cjs/smtp-connection/index.js');\n",
"lib/smtp-pool/index.js": "module.exports = require('../../dist/cjs/smtp-pool/index.js');\n",
"lib/smtp-transport/index.js": "module.exports = require('../../dist/cjs/smtp-transport/index.js');\n",
"lib/stream-transport/index.js": "module.exports = require('../../dist/cjs/stream-transport/index.js');\n",
"lib/well-known/index.js": "module.exports = require('../../dist/cjs/well-known/index.js');\n",
"lib/xoauth2/index.js": "module.exports = require('../../dist/cjs/xoauth2/index.js');\n"
},
"uuid": {
"dist/index.js": "export * from './esm/index.js';\n"
}
+2 -2
View File
@@ -22,10 +22,10 @@ const pkgdef :Spk.PackageDefinition = (
appTitle = (defaultText = "Wekan"),
# The name of the app as it is displayed to the user.
appVersion = 1295,
appVersion = 1296,
# Increment this for every release.
appMarketingVersion = (defaultText = "12.95~2026-11-05"),
appMarketingVersion = (defaultText = "12.96~2026-11-05"),
# Human-readable presentation of the app version.
minUpgradableAppVersion = 0,
+4 -4
View File
@@ -19,7 +19,7 @@
# base: core24 (not core26) · no build-base: devel · grade: stable
# ─────────────────────────────────────────────────────────────────────────────
name: wekan
version: '12.95'
version: '12.96'
base: core24
confinement: strict
grade: stable
@@ -703,18 +703,18 @@ parts:
armhf) WEKAN_ARCH="armhf" ;;
*) echo "Unsupported architecture: ${CRAFT_ARCH_BUILD_FOR}"; exit 1 ;;
esac
WEKAN_ZIP="wekan-12.95-${WEKAN_ARCH}.zip"
WEKAN_ZIP="wekan-12.96-${WEKAN_ARCH}.zip"
echo "Cleaning environment first"
rm -rf .build
mkdir .build
cd .build
#wget https://github.com/wekan/wekan/releases/download/v12.95/wekan-12.95-amd64.zip
#wget https://github.com/wekan/wekan/releases/download/v12.96/wekan-12.96-amd64.zip
# Retry: a release asset can 404 for a short while right after it is
# uploaded (CDN/propagation lag), and a plain wget treated that as
# fatal. --retry-on-http-error covers the 404/5xx window; a genuinely
# missing bundle still fails after the tries are spent.
wget --tries=20 --waitretry=20 --retry-on-http-error=404,403,500,502,503 \
"https://github.com/wekan/wekan/releases/download/v12.95/${WEKAN_ZIP}"
"https://github.com/wekan/wekan/releases/download/v12.96/${WEKAN_ZIP}"
unzip "${WEKAN_ZIP}"
python3 ../releases/check-telemetry.py --bundle bundle
rm "${WEKAN_ZIP}"
+48
View File
@@ -74,6 +74,54 @@ test('uuid is bumped to 11.1.1 and the entry point the bundle recorded is writte
}
});
test('nodemailer 10 gets back the lib/ files meteor/email was built against', () => {
// v12.95's bundle failed its smoke boot: nodemailer 10 moved lib/ to dist/cjs/,
// and packages/email.js links the paths it recorded for 8.0.3 - "Cannot find
// module .../meteor/email/node_modules/nodemailer/lib/nodemailer.js" - and
// Npm.requires nodemailer/lib/mail-composer, which Meteor resolves by path.
const shim = (manifest.shims || {}).nodemailer || {};
const os = require('os');
const src = path.join(repoRoot, 'node_modules/nodemailer');
const pkg = JSON.parse(fs.readFileSync(path.join(src, 'package.json'), 'utf8'));
assert.ok(Number(pkg.version.split('.')[0]) >= 10, `node_modules/nodemailer ${pkg.version} has the 10 layout`);
// every lib/<name> directory nodemailer 10 still exports has its old file back,
// so no path a nodemailer 8 caller could have recorded is left unresolvable
const dirs = Object.entries(pkg.exports)
.filter(([key, target]) => /^\.\/lib\/[a-z0-9-]+$/.test(key)
&& target && target.require === `./dist/cjs/${key.slice(6)}/index.js`)
.map(([key]) => `lib/${key.slice(6)}/index.js`);
assert.ok(dirs.includes('lib/mail-composer/index.js') && dirs.includes('lib/well-known/index.js'));
for (const rel of ['lib/package.json', 'lib/nodemailer.js', ...dirs]) {
assert.ok(rel in shim, `nodemailer shim for ${rel}`);
}
const tmp = fs.mkdtempSync(path.join(process.env.TMPDIR || os.tmpdir(), 'nodemailer-shim-'));
try {
const shimmed = path.join(tmp, 'with', 'nodemailer');
const bare = path.join(tmp, 'without', 'nodemailer');
for (const [dir, files] of [[shimmed, Object.keys(shim)], [bare, ['lib/nodemailer.js']]]) {
fs.cpSync(src, dir, { recursive: true });
for (const rel of files) {
fs.mkdirSync(path.dirname(path.join(dir, rel)), { recursive: true });
fs.writeFileSync(path.join(dir, rel), shim[rel]);
}
}
// the two paths the bundle recorded, required by file as Meteor's runtime does
assert.strictEqual(typeof require(path.join(shimmed, 'lib/nodemailer.js')).createTransport, 'function');
assert.strictEqual(typeof require(path.join(shimmed, 'lib/well-known/index.js')), 'function');
assert.strictEqual(typeof require(path.join(shimmed, 'lib/mail-composer')), 'function');
// and each forward is the module the exports map gives a require() caller
for (const rel of dirs) {
assert.strictEqual(require(path.join(shimmed, rel)),
require(path.join(shimmed, 'dist/cjs', rel.slice(4))), rel);
}
// negative: without lib/package.json the CommonJS shim is parsed as ESM
// (nodemailer is "type": "module") and does not load
assert.throws(() => require(path.join(bare, 'lib/nodemailer.js')));
} finally {
fs.rmSync(tmp, { recursive: true, force: true });
}
});
test('body-parser 1.x and 2.x are each raised inside their own major', () => {
assert.strictEqual(manifest.minimums['body-parser'], '1.20.9');
assert.strictEqual(manifest.minimums['body-parser@2'], '2.4.0');