From d32103618f7e297a8b8a09957f46107c7f81136d Mon Sep 17 00:00:00 2001 From: Juergen Kunz Date: Thu, 4 Dec 2025 17:45:40 +0000 Subject: [PATCH] update --- package.json | 16 +- pnpm-lock.yaml | 717 ++++++++------- .../ORG-002-member-management.md | 124 ++- ts/reception/classes.organization.ts | 2 +- ts/reception/classes.reception.ts | 2 + ts/reception/classes.receptionmailer.ts | 29 + ts/reception/classes.rolemanager.ts | 50 +- ts/reception/classes.userinvitation.ts | 136 +++ ts/reception/classes.userinvitationmanager.ts | 556 ++++++++++++ ts_web/elements/account/content.ts | 10 + ts_web/elements/account/navigation.ts | 4 +- ts_web/elements/account/views/adminview.ts | 15 +- ts_web/elements/account/views/appsview.ts | 9 +- ts_web/elements/account/views/baseview.ts | 11 +- ts_web/elements/account/views/index.ts | 1 + ts_web/elements/account/views/orgview.ts | 5 +- ts_web/elements/account/views/usersview.ts | 836 ++++++++++++++++++ ts_web/elements/idp-loginprompt.ts | 6 +- ts_web/elements/idp-registerprompt.ts | 8 +- ts_web/index.ts | 2 +- ts_web/states/idp.state.ts | 2 +- 21 files changed, 2174 insertions(+), 367 deletions(-) create mode 100644 ts/reception/classes.userinvitation.ts create mode 100644 ts/reception/classes.userinvitationmanager.ts create mode 100644 ts_web/elements/account/views/usersview.ts diff --git a/package.json b/package.json index c4d1c0f..c77814c 100644 --- a/package.json +++ b/package.json @@ -16,12 +16,12 @@ "author": "Task Venture Capital GmbH", "license": "MIT", "dependencies": { - "@api.global/typedrequest": "^3.1.10", + "@api.global/typedrequest": "^3.1.11", "@api.global/typedrequest-interfaces": "^3.0.19", - "@api.global/typedserver": "^3.0.80", - "@api.global/typedsocket": "^3.0.1", + "@api.global/typedserver": "^7.7.0", + "@api.global/typedsocket": "^4.1.0", "@consent.software/catalog": "^2.0.1", - "@design.estate/dees-catalog": "^2.0.2", + "@design.estate/dees-catalog": "^2.0.3", "@design.estate/dees-domtools": "^2.3.6", "@design.estate/dees-element": "^2.1.3", "@push.rocks/lik": "^6.2.2", @@ -40,19 +40,19 @@ "@push.rocks/smarttime": "^4.1.1", "@push.rocks/smartunique": "^3.0.9", "@push.rocks/smarturl": "^3.1.0", - "@push.rocks/taskbuffer": "^3.4.0", + "@push.rocks/taskbuffer": "^3.5.0", "@push.rocks/webjwt": "^1.0.9", "@push.rocks/websetup": "^3.0.15", "@push.rocks/webstore": "^2.0.20", "@serve.zone/platformclient": "^1.1.2", "@tsclass/tsclass": "^9.3.0", - "@uptime.link/webwidget": "^1.2.4" + "@uptime.link/webwidget": "^1.2.5" }, "devDependencies": { "@git.zone/tsbuild": "^3.1.2", - "@git.zone/tsbundle": "^2.6.2", + "@git.zone/tsbundle": "^2.6.3", "@git.zone/tsrun": "^2.0.0", - "@git.zone/tswatch": "^2.2.2", + "@git.zone/tswatch": "^2.2.3", "@push.rocks/projectinfo": "^5.0.1", "@types/node": "^24.10.1" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2f41db8..f58e172 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,23 +9,23 @@ importers: .: dependencies: '@api.global/typedrequest': - specifier: ^3.1.10 - version: 3.1.10 + specifier: ^3.1.11 + version: 3.1.11 '@api.global/typedrequest-interfaces': specifier: ^3.0.19 version: 3.0.19 '@api.global/typedserver': - specifier: ^3.0.80 - version: 3.0.80 + specifier: ^7.7.0 + version: 7.7.0 '@api.global/typedsocket': - specifier: ^3.0.1 - version: 3.0.1 + specifier: ^4.1.0 + version: 4.1.0(@push.rocks/smartserve@1.1.2) '@consent.software/catalog': specifier: ^2.0.1 version: 2.0.1 '@design.estate/dees-catalog': - specifier: ^2.0.2 - version: 2.0.2(@tiptap/pm@2.27.1) + specifier: ^2.0.3 + version: 2.0.3(@tiptap/pm@2.27.1) '@design.estate/dees-domtools': specifier: ^2.3.6 version: 2.3.6 @@ -81,8 +81,8 @@ importers: specifier: ^3.1.0 version: 3.1.0 '@push.rocks/taskbuffer': - specifier: ^3.4.0 - version: 3.4.0 + specifier: ^3.5.0 + version: 3.5.0 '@push.rocks/webjwt': specifier: ^1.0.9 version: 1.0.9 @@ -94,26 +94,26 @@ importers: version: 2.0.20 '@serve.zone/platformclient': specifier: ^1.1.2 - version: 1.1.2 + version: 1.1.2(@push.rocks/smartserve@1.1.2) '@tsclass/tsclass': specifier: ^9.3.0 version: 9.3.0 '@uptime.link/webwidget': - specifier: ^1.2.4 - version: 1.2.4(@tiptap/pm@2.27.1) + specifier: ^1.2.5 + version: 1.2.5(@tiptap/pm@2.27.1) devDependencies: '@git.zone/tsbuild': specifier: ^3.1.2 version: 3.1.2 '@git.zone/tsbundle': - specifier: ^2.6.2 - version: 2.6.2 + specifier: ^2.6.3 + version: 2.6.3 '@git.zone/tsrun': specifier: ^2.0.0 version: 2.0.0 '@git.zone/tswatch': - specifier: ^2.2.2 - version: 2.2.2 + specifier: ^2.2.3 + version: 2.2.3(@push.rocks/smartserve@1.1.2) '@push.rocks/projectinfo': specifier: ^5.0.1 version: 5.0.2 @@ -129,14 +129,27 @@ packages: '@api.global/typedrequest-interfaces@3.0.19': resolution: {integrity: sha512-uuHUXJeOy/inWSDrwD0Cwax2rovpxYllDhM2RWh+6mVpQuNmZ3uw6IVg6dA2G1rOe24Ebs+Y9SzEogo+jYN7vw==} - '@api.global/typedrequest@3.1.10': - resolution: {integrity: sha512-EiCp44XVcMjBvEs4oM1nMUaeY4ySU0Pzt3+mDwVG5DNP6EV87Nwancbr2jKScvaFNel9eeDgGtgEnFBKjOnApA==} + '@api.global/typedrequest@3.1.11': + resolution: {integrity: sha512-j8EO3na0WMw8pFkAfEaEui2a4TaAL1G/dv1CYl8LEPXckSKkl1BCAS1kFOW2xuI9pwZkmSqlo3xpQ3KmkmHaGQ==} '@api.global/typedserver@3.0.80': resolution: {integrity: sha512-dcp0oXsjBL+XdFg1wUUP08uJQid5bQ0Yv3V3Y3lnI2QCbat0FU+Tsb0TZRnZ4+P150Vj/ITBqJUgDzFsF34grA==} - '@api.global/typedsocket@3.0.1': - resolution: {integrity: sha512-xojiAVNXtHoxkpBo8U2HHJG8FrVXXuLvDNndSHXwx4C9VslUwDn5zSCI+PdBl8iAg+ZuBmKjqkpZZ9sL6DC5yQ==} + '@api.global/typedserver@7.7.0': + resolution: {integrity: sha512-32GKI3M3HVFQw30T9SszyjAciXjQsLDbm7KUmBsllJoamUZsE9tb6Fdgk2uc3TQziUiFOpq3tYllhj72oNLy3A==} + + '@api.global/typedsocket@3.1.1': + resolution: {integrity: sha512-Wkz3NlhmfdZMKqXXI2c2dMtGGmSmhdOegZiziL+9b2mqPYdc7Gd8AZRdEOKvbSoIvc9G22/5BEadIWHrfq66TA==} + peerDependencies: + '@push.rocks/smartserve': '>=1.0.0' + peerDependenciesMeta: + '@push.rocks/smartserve': + optional: true + + '@api.global/typedsocket@4.1.0': + resolution: {integrity: sha512-ttmoU5BNHmLAkAF/o+Ta8F5O4F7CUmkFo6LK7NKHQvuYJvodPMYWdhJ6yCINTF4pfCgljkMDUqoVKobm6ea4mQ==} + peerDependencies: + '@push.rocks/smartserve': '>=1.1.0' '@aws-crypto/crc32@5.2.0': resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} @@ -304,8 +317,8 @@ packages: '@borewit/text-codec@0.1.1': resolution: {integrity: sha512-5L/uBxmjaCIX5h8Z+uu+kA9BQLkc/Wl06UGR5ajNRxu+/XjonB5i8JpgFMrPj3LXTCPA0pv8yxUvbUi+QthGGA==} - '@cloudflare/workers-types@4.20251128.0': - resolution: {integrity: sha512-gQxQvxLRsFb+mDlaBKGoJwEHWt+ox9telZZEuRMbNUAD6v78XYqZepTI4yPDdKhkRTlqYcDqDhIdAI3HrsGk7w==} + '@cloudflare/workers-types@4.20251202.0': + resolution: {integrity: sha512-Q7m1Ivu2fbKalOPm00KLpu6GfRaq4TlrPknqugvZgp/gDH96OYKINO4x7jvCIBvCz/aK9vVoOj8tlbSQBervVA==} '@configvault.io/interfaces@1.0.17': resolution: {integrity: sha512-bEcCUR2VBDJsTin8HQh8Uw/mlYl2v8A3jMIaQ+MTB9Hrqd6CZL2dL7iJdWyFl/3EIX+LDxWFR+Oq7liIq7w+1Q==} @@ -319,8 +332,8 @@ packages: '@consent.software/webclient@1.1.0': resolution: {integrity: sha512-VX7e8ygZwgU8WEzn22fdvvEytLYl4kfp/u40GusaBU4iFtjrCY2hxDy9Z1FTKicpGcRxf3t13lM0Jaugq7Jj/w==} - '@design.estate/dees-catalog@2.0.2': - resolution: {integrity: sha512-+4sAj+GS5Tw56G9bEgN+86wLARzgRgPnEOTtTtvV8DItK1Qehgqw0++GFiEHjg76ARNU7Of1iu/Ly7yIUrnyEg==} + '@design.estate/dees-catalog@2.0.3': + resolution: {integrity: sha512-+LoCZd2sHlp+8WRTJkDqBg9Ui1tlLcg+K3mYGkqVn+P2JLUCWUM8+LsYxgWEpgGGA8C6n1I7d+y2a63RjXwZ+Q==} '@design.estate/dees-comms@1.0.27': resolution: {integrity: sha512-GvzTUwkV442LD60T08iqSoqvhA02Mou5lFvvqBPc4yBUiU7cZISqBx+76xvMgMIEI9Dx9JfTl4/2nW8MoVAanw==} @@ -349,8 +362,8 @@ packages: cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.27.0': - resolution: {integrity: sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==} + '@esbuild/aix-ppc64@0.27.1': + resolution: {integrity: sha512-HHB50pdsBX6k47S4u5g/CaLjqS3qwaOVE5ILsq64jyzgMhLuCuZ8rGzM9yhsAjfjkbgUPMzZEPa7DAp7yz6vuA==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] @@ -361,8 +374,8 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.27.0': - resolution: {integrity: sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==} + '@esbuild/android-arm64@0.27.1': + resolution: {integrity: sha512-45fuKmAJpxnQWixOGCrS+ro4Uvb4Re9+UTieUY2f8AEc+t7d4AaZ6eUJ3Hva7dtrxAAWHtlEFsXFMAgNnGU9uQ==} engines: {node: '>=18'} cpu: [arm64] os: [android] @@ -373,8 +386,8 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-arm@0.27.0': - resolution: {integrity: sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==} + '@esbuild/android-arm@0.27.1': + resolution: {integrity: sha512-kFqa6/UcaTbGm/NncN9kzVOODjhZW8e+FRdSeypWe6j33gzclHtwlANs26JrupOntlcWmB0u8+8HZo8s7thHvg==} engines: {node: '>=18'} cpu: [arm] os: [android] @@ -385,8 +398,8 @@ packages: cpu: [x64] os: [android] - '@esbuild/android-x64@0.27.0': - resolution: {integrity: sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==} + '@esbuild/android-x64@0.27.1': + resolution: {integrity: sha512-LBEpOz0BsgMEeHgenf5aqmn/lLNTFXVfoWMUox8CtWWYK9X4jmQzWjoGoNb8lmAYml/tQ/Ysvm8q7szu7BoxRQ==} engines: {node: '>=18'} cpu: [x64] os: [android] @@ -397,8 +410,8 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.27.0': - resolution: {integrity: sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==} + '@esbuild/darwin-arm64@0.27.1': + resolution: {integrity: sha512-veg7fL8eMSCVKL7IW4pxb54QERtedFDfY/ASrumK/SbFsXnRazxY4YykN/THYqFnFwJ0aVjiUrVG2PwcdAEqQQ==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] @@ -409,8 +422,8 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.27.0': - resolution: {integrity: sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==} + '@esbuild/darwin-x64@0.27.1': + resolution: {integrity: sha512-+3ELd+nTzhfWb07Vol7EZ+5PTbJ/u74nC6iv4/lwIU99Ip5uuY6QoIf0Hn4m2HoV0qcnRivN3KSqc+FyCHjoVQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] @@ -421,8 +434,8 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.27.0': - resolution: {integrity: sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==} + '@esbuild/freebsd-arm64@0.27.1': + resolution: {integrity: sha512-/8Rfgns4XD9XOSXlzUDepG8PX+AVWHliYlUkFI3K3GB6tqbdjYqdhcb4BKRd7C0BhZSoaCxhv8kTcBrcZWP+xg==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] @@ -433,8 +446,8 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.27.0': - resolution: {integrity: sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==} + '@esbuild/freebsd-x64@0.27.1': + resolution: {integrity: sha512-GITpD8dK9C+r+5yRT/UKVT36h/DQLOHdwGVwwoHidlnA168oD3uxA878XloXebK4Ul3gDBBIvEdL7go9gCUFzQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] @@ -445,8 +458,8 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.27.0': - resolution: {integrity: sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==} + '@esbuild/linux-arm64@0.27.1': + resolution: {integrity: sha512-W9//kCrh/6in9rWIBdKaMtuTTzNj6jSeG/haWBADqLLa9P8O5YSRDzgD5y9QBok4AYlzS6ARHifAb75V6G670Q==} engines: {node: '>=18'} cpu: [arm64] os: [linux] @@ -457,8 +470,8 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.27.0': - resolution: {integrity: sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==} + '@esbuild/linux-arm@0.27.1': + resolution: {integrity: sha512-ieMID0JRZY/ZeCrsFQ3Y3NlHNCqIhTprJfDgSB3/lv5jJZ8FX3hqPyXWhe+gvS5ARMBJ242PM+VNz/ctNj//eA==} engines: {node: '>=18'} cpu: [arm] os: [linux] @@ -469,8 +482,8 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.27.0': - resolution: {integrity: sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==} + '@esbuild/linux-ia32@0.27.1': + resolution: {integrity: sha512-VIUV4z8GD8rtSVMfAj1aXFahsi/+tcoXXNYmXgzISL+KB381vbSTNdeZHHHIYqFyXcoEhu9n5cT+05tRv13rlw==} engines: {node: '>=18'} cpu: [ia32] os: [linux] @@ -481,8 +494,8 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.27.0': - resolution: {integrity: sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==} + '@esbuild/linux-loong64@0.27.1': + resolution: {integrity: sha512-l4rfiiJRN7sTNI//ff65zJ9z8U+k6zcCg0LALU5iEWzY+a1mVZ8iWC1k5EsNKThZ7XCQ6YWtsZ8EWYm7r1UEsg==} engines: {node: '>=18'} cpu: [loong64] os: [linux] @@ -493,8 +506,8 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.27.0': - resolution: {integrity: sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==} + '@esbuild/linux-mips64el@0.27.1': + resolution: {integrity: sha512-U0bEuAOLvO/DWFdygTHWY8C067FXz+UbzKgxYhXC0fDieFa0kDIra1FAhsAARRJbvEyso8aAqvPdNxzWuStBnA==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] @@ -505,8 +518,8 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.27.0': - resolution: {integrity: sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==} + '@esbuild/linux-ppc64@0.27.1': + resolution: {integrity: sha512-NzdQ/Xwu6vPSf/GkdmRNsOfIeSGnh7muundsWItmBsVpMoNPVpM61qNzAVY3pZ1glzzAxLR40UyYM23eaDDbYQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] @@ -517,8 +530,8 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.27.0': - resolution: {integrity: sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==} + '@esbuild/linux-riscv64@0.27.1': + resolution: {integrity: sha512-7zlw8p3IApcsN7mFw0O1Z1PyEk6PlKMu18roImfl3iQHTnr/yAfYv6s4hXPidbDoI2Q0pW+5xeoM4eTCC0UdrQ==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] @@ -529,8 +542,8 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.27.0': - resolution: {integrity: sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==} + '@esbuild/linux-s390x@0.27.1': + resolution: {integrity: sha512-cGj5wli+G+nkVQdZo3+7FDKC25Uh4ZVwOAK6A06Hsvgr8WqBBuOy/1s+PUEd/6Je+vjfm6stX0kmib5b/O2Ykw==} engines: {node: '>=18'} cpu: [s390x] os: [linux] @@ -541,8 +554,8 @@ packages: cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.27.0': - resolution: {integrity: sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==} + '@esbuild/linux-x64@0.27.1': + resolution: {integrity: sha512-z3H/HYI9MM0HTv3hQZ81f+AKb+yEoCRlUby1F80vbQ5XdzEMyY/9iNlAmhqiBKw4MJXwfgsh7ERGEOhrM1niMA==} engines: {node: '>=18'} cpu: [x64] os: [linux] @@ -553,8 +566,8 @@ packages: cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-arm64@0.27.0': - resolution: {integrity: sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==} + '@esbuild/netbsd-arm64@0.27.1': + resolution: {integrity: sha512-wzC24DxAvk8Em01YmVXyjl96Mr+ecTPyOuADAvjGg+fyBpGmxmcr2E5ttf7Im8D0sXZihpxzO1isus8MdjMCXQ==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] @@ -565,8 +578,8 @@ packages: cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.27.0': - resolution: {integrity: sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==} + '@esbuild/netbsd-x64@0.27.1': + resolution: {integrity: sha512-1YQ8ybGi2yIXswu6eNzJsrYIGFpnlzEWRl6iR5gMgmsrR0FcNoV1m9k9sc3PuP5rUBLshOZylc9nqSgymI+TYg==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] @@ -577,8 +590,8 @@ packages: cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-arm64@0.27.0': - resolution: {integrity: sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==} + '@esbuild/openbsd-arm64@0.27.1': + resolution: {integrity: sha512-5Z+DzLCrq5wmU7RDaMDe2DVXMRm2tTDvX2KU14JJVBN2CT/qov7XVix85QoJqHltpvAOZUAc3ndU56HSMWrv8g==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] @@ -589,8 +602,8 @@ packages: cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.27.0': - resolution: {integrity: sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==} + '@esbuild/openbsd-x64@0.27.1': + resolution: {integrity: sha512-Q73ENzIdPF5jap4wqLtsfh8YbYSZ8Q0wnxplOlZUOyZy7B4ZKW8DXGWgTCZmF8VWD7Tciwv5F4NsRf6vYlZtqg==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] @@ -601,8 +614,8 @@ packages: cpu: [arm64] os: [openharmony] - '@esbuild/openharmony-arm64@0.27.0': - resolution: {integrity: sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==} + '@esbuild/openharmony-arm64@0.27.1': + resolution: {integrity: sha512-ajbHrGM/XiK+sXM0JzEbJAen+0E+JMQZ2l4RR4VFwvV9JEERx+oxtgkpoKv1SevhjavK2z2ReHk32pjzktWbGg==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] @@ -613,8 +626,8 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.27.0': - resolution: {integrity: sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==} + '@esbuild/sunos-x64@0.27.1': + resolution: {integrity: sha512-IPUW+y4VIjuDVn+OMzHc5FV4GubIwPnsz6ubkvN8cuhEqH81NovB53IUlrlBkPMEPxvNnf79MGBoz8rZ2iW8HA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] @@ -625,8 +638,8 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.27.0': - resolution: {integrity: sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==} + '@esbuild/win32-arm64@0.27.1': + resolution: {integrity: sha512-RIVRWiljWA6CdVu8zkWcRmGP7iRRIIwvhDKem8UMBjPql2TXM5PkDVvvrzMtj1V+WFPB4K7zkIGM7VzRtFkjdg==} engines: {node: '>=18'} cpu: [arm64] os: [win32] @@ -637,8 +650,8 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.27.0': - resolution: {integrity: sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==} + '@esbuild/win32-ia32@0.27.1': + resolution: {integrity: sha512-2BR5M8CPbptC1AK5JbJT1fWrHLvejwZidKx3UMSF0ecHMa+smhi16drIrCEggkgviBwLYd5nwrFLSl5Kho96RQ==} engines: {node: '>=18'} cpu: [ia32] os: [win32] @@ -649,8 +662,8 @@ packages: cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.27.0': - resolution: {integrity: sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==} + '@esbuild/win32-x64@0.27.1': + resolution: {integrity: sha512-d5X6RMYv6taIymSk8JBP+nxv8DQAMY6A51GPgusqLdK9wBz5wWIXy1KjTck6HnjE9hqJzJRdk+1p/t5soSbCtw==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -679,8 +692,8 @@ packages: resolution: {integrity: sha512-K0u840Qo0WEhvcpAtktvdBX6KEXjelU32o820WzcK7dMA7dd2YV+mPOEYfbmWLcdtFJkrjkigQq5fpLhTN4oKQ==} hasBin: true - '@git.zone/tsbundle@2.6.2': - resolution: {integrity: sha512-wj32zHpvbDUdStEjJ9RCqffmafqlopWSROSRBQDgpJ8hnMAO3ftWkTWWfGdTGh2p2pALfPqgSFzwxCd4RJG8aQ==} + '@git.zone/tsbundle@2.6.3': + resolution: {integrity: sha512-YD1qMYA/4eOuF57V0ccR+xo6ww1+QOYFA2K5gBPFBDNh9VdfvWxxDhOUybja8lT9PVMoli8PHG5WA5tKJkdXIQ==} hasBin: true '@git.zone/tspublish@1.10.3': @@ -691,8 +704,8 @@ packages: resolution: {integrity: sha512-yA6zCjL+kn7xfZe6sL/m4K+zYqgkznG/pF6++i/E17iwzpG6dHmW+VZmYldHe86sW4DcLMvqM6CxM+KlgaEpKw==} hasBin: true - '@git.zone/tswatch@2.2.2': - resolution: {integrity: sha512-dscBvB1Pg8bIvMLHMPrOnkh0AHXE9v5zuSz9t9BBmWL1ecR94gPSmIYalObMvyMrtXW4L7mBne1kU8N7DY9Otw==} + '@git.zone/tswatch@2.2.3': + resolution: {integrity: sha512-BKyVYXWOjVL+eUcnwjfTKFhUsEBHpgpSv5rbuZYOhmVp9BcglWaEswuAstGEISkCioizUcHiZkpJVPXO99sLHQ==} hasBin: true '@happy-dom/global-registrator@15.11.7': @@ -723,23 +736,23 @@ packages: '@mixmark-io/domino@2.2.0': resolution: {integrity: sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==} - '@module-federation/error-codes@0.21.4': - resolution: {integrity: sha512-ClpL5MereWNXh+EgDjz7w4RrC1JlisQTvXDa1gLxpviHafzNDfdViVmuhi9xXVuj+EYo8KU70Y999KHhk9424Q==} + '@module-federation/error-codes@0.21.6': + resolution: {integrity: sha512-MLJUCQ05KnoVl8xd6xs9a5g2/8U+eWmVxg7xiBMeR0+7OjdWUbHwcwgVFatRIwSZvFgKHfWEiI7wsU1q1XbTRQ==} - '@module-federation/runtime-core@0.21.4': - resolution: {integrity: sha512-SGpmoOLGNxZofpTOk6Lxb2ewaoz5wMi93AFYuuJB04HTVcngEK+baNeUZ2D/xewrqNIJoMY6f5maUjVfIIBPUA==} + '@module-federation/runtime-core@0.21.6': + resolution: {integrity: sha512-5Hd1Y5qp5lU/aTiK66lidMlM/4ji2gr3EXAtJdreJzkY+bKcI5+21GRcliZ4RAkICmvdxQU5PHPL71XmNc7Lsw==} - '@module-federation/runtime-tools@0.21.4': - resolution: {integrity: sha512-RzFKaL0DIjSmkn76KZRfzfB6dD07cvID84950jlNQgdyoQFUGkqD80L6rIpVCJTY/R7LzR3aQjHnoqmq4JPo3w==} + '@module-federation/runtime-tools@0.21.6': + resolution: {integrity: sha512-fnP+ZOZTFeBGiTAnxve+axGmiYn2D60h86nUISXjXClK3LUY1krUfPgf6MaD4YDJ4i51OGXZWPekeMe16pkd8Q==} - '@module-federation/runtime@0.21.4': - resolution: {integrity: sha512-wgvGqryurVEvkicufJmTG0ZehynCeNLklv8kIk5BLIsWYSddZAE+xe4xov1kgH5fIJQAoQNkRauFFjVNlHoAkA==} + '@module-federation/runtime@0.21.6': + resolution: {integrity: sha512-+caXwaQqwTNh+CQqyb4mZmXq7iEemRDrTZQGD+zyeH454JAYnJ3s/3oDFizdH6245pk+NiqDyOOkHzzFQorKhQ==} - '@module-federation/sdk@0.21.4': - resolution: {integrity: sha512-tzvhOh/oAfX++6zCDDxuvioHY4Jurf8vcfoCbKFxusjmyKr32GPbwFDazUP+OPhYCc3dvaa9oWU6X/qpUBLfJw==} + '@module-federation/sdk@0.21.6': + resolution: {integrity: sha512-x6hARETb8iqHVhEsQBysuWpznNZViUh84qV2yE7AD+g7uIzHKiYdoWqj10posbo5XKf/147qgWDzKZoKoEP2dw==} - '@module-federation/webpack-bundler-runtime@0.21.4': - resolution: {integrity: sha512-dusmR3uPnQh9u9ChQo3M+GLOuGFthfvnh7WitF/a1eoeTfRmXqnMFsXtZCUK+f/uXf+64874Zj/bhAgbBcVHZA==} + '@module-federation/webpack-bundler-runtime@0.21.6': + resolution: {integrity: sha512-7zIp3LrcWbhGuFDTUMLJ2FJvcwjlddqhWGxi/MW3ur1a+HaO8v5tF2nl+vElKmbG1DFLU/52l3PElVcWf/YcsQ==} '@mongodb-js/saslprep@1.3.2': resolution: {integrity: sha512-QgA5AySqB27cGTXBFmnpifAi7HxoGUeezwo6p9dI03MuDB6Pp33zgclqVb6oVK3j6I9Vesg0+oojW2XxB59SGg==} @@ -811,6 +824,9 @@ packages: '@napi-rs/wasm-runtime@1.0.7': resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==} + '@napi-rs/wasm-runtime@1.1.0': + resolution: {integrity: sha512-Fq6DJW+Bb5jaWE69/qOE0D1TUN9+6uWhCeZpdnSBk14pjLcCWR7Q8n49PTSPHazM37JqrsdpEthXy2xn6jWWiA==} + '@oxc-project/types@0.99.0': resolution: {integrity: sha512-LLDEhXB7g1m5J+woRSgfKsFPS3LhR9xRhTeIoEBm5WrkwMxn6eZ0Ld0c0K5eHB57ChZX6I3uSmmLjZ8pcjlRcw==} @@ -905,6 +921,7 @@ packages: '@push.rocks/smartchok@1.2.0': resolution: {integrity: sha512-I5fR++k6nR1wiMQUwcTYzO0g8FwD6gN+3HwfIzpQlolrM91i6Q5TaoMlt3aysbvKCSNvkL3FlJLOfUHNGWoWkA==} + deprecated: This package has been renamed. Please use @push.rocks/smartwatch instead. '@push.rocks/smartcli@4.0.19': resolution: {integrity: sha512-s1jZSgDZWi/az26AY4TJ2HPuG1qZzGC5R9fKWaECLmwnSpk6y9JXL5dnJAUohcdu50kdXCWEcRmLfYxOt81vEA==} @@ -957,8 +974,8 @@ packages: '@push.rocks/smartfs@1.1.2': resolution: {integrity: sha512-zk2RaflQMKoQa7ct1l/+dTtgBsW6cZI151H1H6TLrqKncyHETYBJBKdFL/cJTJKXvvi9jYhb/j7c5kDLCYX+7Q==} - '@push.rocks/smartfs@1.1.3': - resolution: {integrity: sha512-yUGHv27D2wTRTTsSai6FPT4P4LypNoRxioS7//wHFLD1l5i6LS64SvGq54fgZCP72fXxYPzeLbVCqABweCmocg==} + '@push.rocks/smartfs@1.2.0': + resolution: {integrity: sha512-1R47jJZwX869z7DYgKeAZKTU1SbGnM7W/ZmgsI7AkQQhiascNqY3/gF4V5kIprmuf1WhpRbCbZyum8s7J1LDdg==} '@push.rocks/smartguard@3.1.0': resolution: {integrity: sha512-J23q84f1O+TwFGmd4lrO9XLHUh2DaLXo9PN/9VmTWYzTkQDv5JehmifXVI0esophXcCIfbdIu6hbt7/aHlDF4A==} @@ -1047,6 +1064,9 @@ packages: '@push.rocks/smartrx@3.0.10': resolution: {integrity: sha512-USjIYcsSfzn14cwOsxgq/bBmWDTTzy3ouWAnW5NdMyRRzEbmeNrvmy6TRqNeDlJ2PsYNTt1rr/zGUqvIy72ITg==} + '@push.rocks/smartserve@1.1.2': + resolution: {integrity: sha512-NkJNgdDt/rfsd9AMheCxtFd5X+ubzffvxOxjb0Aw1A5JR3xmiWeRifqEV1oN7mMTGL9jyQVvIME6Yrdxr244dA==} + '@push.rocks/smartshell@3.3.0': resolution: {integrity: sha512-m0w618H6YBs+vXGz1CgS4nPi5CUAnqRtckcS9/koGwfcIx1IpjqmiP47BoCTbdgcv0IPUxQVBG1IXTHPuZ8Z5g==} @@ -1096,8 +1116,8 @@ packages: '@push.rocks/smartyaml@3.0.4': resolution: {integrity: sha512-1JRt+hnoc2zHw3AW+vXKlCdSVwqOmY/01fu+2HBviS0UDjoZCa+/rp6E3GaQb5lEEafKi8ENbffAfjXXp3N2xQ==} - '@push.rocks/taskbuffer@3.4.0': - resolution: {integrity: sha512-Rvwr1CzYztB9PMboojRzVSq3xGp8288kvtvWx4Mg3rvps913znMja1UOjNn52ivOxu3dHUNYE3NDSP+j84cUWQ==} + '@push.rocks/taskbuffer@3.5.0': + resolution: {integrity: sha512-Y9WwIEIyp6oVFdj06j84tfrZIvjhbMb3DF52rYxlTeYLk3W7RPhSg1bGPCbtkXWeKdBrSe37V90BkOG7Qq8Pqg==} '@push.rocks/webjwt@1.0.9': resolution: {integrity: sha512-IhWAv0hxfXbLbmQHHOGr96Oe3H1kB0OTtDofM8N+9qhJeKxTHfF2pUrdpck6btAQQbaBY2D7xtHvumrIXU5HIg==} @@ -1238,60 +1258,60 @@ packages: '@rolldown/pluginutils@1.0.0-beta.52': resolution: {integrity: sha512-/L0htLJZbaZFL1g9OHOblTxbCYIGefErJjtYOwgl9ZqNx27P3L0SDfjhhHIss32gu5NWgnxuT2a2Hnnv6QGHKA==} - '@rspack/binding-darwin-arm64@1.6.5': - resolution: {integrity: sha512-DaAJTlaenqZIqFqIYcitn0SzjJ7WpC9234JpiSDZdRyXii9qJJiToVwxSPY/CmkrP0201+aC4pzN4tI9T0Ummw==} + '@rspack/binding-darwin-arm64@1.6.6': + resolution: {integrity: sha512-vGVDP0rlWa2w/gLba/sncVfkCah0HmhdmK5vGj/7sSX0iViwQneA2xjxDHyCNSQrvfq9GJmj4Kmdq/9tGh0KuA==} cpu: [arm64] os: [darwin] - '@rspack/binding-darwin-x64@1.6.5': - resolution: {integrity: sha512-fPVfp7W/GMbHayb5hbefiMI30JxlsqPexOItHGtufHmTCrNne1aHmApspyUZIUUxG36oDRHuGPnfh+IQbHR6+g==} + '@rspack/binding-darwin-x64@1.6.6': + resolution: {integrity: sha512-IcdEG2kOmbPPO70Zl7gDnowDjK7d7C1hWew2vU7dPltr2t1JalRIMnS051lhiur0ULkSxV3cW1zXqv0Oi8AnOg==} cpu: [x64] os: [darwin] - '@rspack/binding-linux-arm64-gnu@1.6.5': - resolution: {integrity: sha512-K68YDoV2e4s+nlrKZxgF0HehiiRwOAGgZFUwJNRMZ7MUrTGMNlPTJlM+bNdaCjDb6GFxBVFcNwIa1sU+0tF1zg==} + '@rspack/binding-linux-arm64-gnu@1.6.6': + resolution: {integrity: sha512-rIguCCtlTcwoFlwheDiUgdImk27spuCRn43zGJogARpM/ZYRFKIuSwFDGUtJT2g0TSLUAHUhWAUqC36NwvrbMQ==} cpu: [arm64] os: [linux] - '@rspack/binding-linux-arm64-musl@1.6.5': - resolution: {integrity: sha512-JPtxFBOq7RRmBIwpdGIStf8iyCILehDsjQtEB0Kkhtm7TsAkVGwtC41GLcNuPxcQBKqNDmD8cy3yLYhXadH2CQ==} + '@rspack/binding-linux-arm64-musl@1.6.6': + resolution: {integrity: sha512-x6X6Gr0fUw6qrJGxZt3Rb6oIX+jd9pdcyp0VbtofcLaqGVQbzustYsYnuLATPOys0q4J/4kWnmEhkjLJHwkhpQ==} cpu: [arm64] os: [linux] - '@rspack/binding-linux-x64-gnu@1.6.5': - resolution: {integrity: sha512-oh4ZNo2HtizZ/E6UK3BEONu20h8VVBw9GAXuWmo1u22cJSihzg+WfRNCMjRDil82LqSsyAgBwnU+dEjEYGKyAA==} + '@rspack/binding-linux-x64-gnu@1.6.6': + resolution: {integrity: sha512-gSlVdASszWHosQKn+nzYOInBijdQboUnmNMGgW9/PijVg3433IvQjzviUuJFno8CMGgrACV9yw+ZFDuK0J57VA==} cpu: [x64] os: [linux] - '@rspack/binding-linux-x64-musl@1.6.5': - resolution: {integrity: sha512-8Xebp5bvPJqjifpkFEAX5nUvoU2JvbMU3gwAkEovRRuvooCXnVT2tqkUBjkR3AhivAGgAxAr9hRzUUz/6QWt3Q==} + '@rspack/binding-linux-x64-musl@1.6.6': + resolution: {integrity: sha512-TZaqVkh7memsTK/hxkOBrbpdzbmBUMea1YnYt++7QjMgco1kWFvAQ+YhAWtIaOaEg8s6C07Lt0Zp8izM2Dja0g==} cpu: [x64] os: [linux] - '@rspack/binding-wasm32-wasi@1.6.5': - resolution: {integrity: sha512-oINZNqzTxM+9dSUOjAORodHXYoJYzXvpaHI2U6ecEmoWaBCs+x3V3Po8DhpNFBwotB+jGlcoVhEHjpg5uaO6pw==} + '@rspack/binding-wasm32-wasi@1.6.6': + resolution: {integrity: sha512-W4mWdlLnYrbUaktyHOGNfATblxMTbgF7CBfDw8PhbDtjd2l8e/TnaHgIDkwITHXAOMEF/QEKfo9FtusbcQJNKw==} cpu: [wasm32] - '@rspack/binding-win32-arm64-msvc@1.6.5': - resolution: {integrity: sha512-UUmep2ayuZxWPdrzkrzAFxVgYUWTB82pa9bkAGyeDO9SNkz8vTpdtbDaTvAzjFb8Pn+ErktDEDBKT57FLjxwxQ==} + '@rspack/binding-win32-arm64-msvc@1.6.6': + resolution: {integrity: sha512-cw5OgxqoDwjoZlk0L3vGEwcjPZsOVFYLwr2ssiC05rsTbhBwxj8coLpAJdvUvbf6C2TTmCB7iPe2sPq1KWD37g==} cpu: [arm64] os: [win32] - '@rspack/binding-win32-ia32-msvc@1.6.5': - resolution: {integrity: sha512-7nx+mMimpmCMstcW7nsyToXy5TK7N+YGPu2W/oioX7qv9ZCuJGTddjzLS84wN8DVrNIirg4mcxpBsmOQMZeHQA==} + '@rspack/binding-win32-ia32-msvc@1.6.6': + resolution: {integrity: sha512-M4ruR+VZ59iy+mPjy6FQPT27cOgeytf3wFBrt7e0suKeNLYGxrNyI9YhgpCTY++SMJsAMgRLGDHoI3ZgWulw1Q==} cpu: [ia32] os: [win32] - '@rspack/binding-win32-x64-msvc@1.6.5': - resolution: {integrity: sha512-pzO7rYFu6f6stgSccolZHiXGTTwKrIGHHNV1ALY1xPRmQEdbHcbMwadeaG99JL2lRLve9iNI+Z9Pr3oDVRN46g==} + '@rspack/binding-win32-x64-msvc@1.6.6': + resolution: {integrity: sha512-q5QTvdhPUh+CA93cQG5zWKRIHMIWPzw+ftFDEwBw52zYdvNAoLniqD8o5Mi8CT0pndhulXgR5aw0Sjd3eMah+A==} cpu: [x64] os: [win32] - '@rspack/binding@1.6.5': - resolution: {integrity: sha512-FzYsr5vdjaVQIlDTxZFlISOQGxl/4grpF2BeiNy60Fpw9eeADeXk55DVacbXPqpiz7Doj6cyhEyMszQOvihrqQ==} + '@rspack/binding@1.6.6': + resolution: {integrity: sha512-noiV+qhyBTVpvG2M4bnOwKk2Ynl6G47Wf7wpCjPCFr87qr3txNwTTnhkEJEU59yj+VvIhbRD2rf5+9TLoT0Wxg==} - '@rspack/core@1.6.5': - resolution: {integrity: sha512-AqaOMA6MTNhqMYYwrhvPA+2uS662SkAi8Rb7B/IFOzh/Z5ooyczL4lUX+qyhAO3ymn50iwM4jikQCf9XfBiaQA==} + '@rspack/core@1.6.6': + resolution: {integrity: sha512-2mR+2YBydlgZ7Q0Rpd6bCC3MBnV9TS0x857K0zIhbDj4BQOqaWVy1n7fx/B3MrS8TR0QCuzKfyDAjNz+XTyJVQ==} engines: {node: '>=18.12.0'} peerDependencies: '@swc/helpers': '>=0.5.1' @@ -1744,8 +1764,8 @@ packages: '@types/express-serve-static-core@5.1.0': resolution: {integrity: sha512-jnHMsrd0Mwa9Cf4IdOzbz543y4XJepXrbia2T4b6+spXC2We3t1y6K44D3mR8XMFSXMCf3/l7rCgddfx7UNVBA==} - '@types/express@5.0.5': - resolution: {integrity: sha512-LuIQOcb6UmnF7C1PCFmEU1u2hmiHL43fgFQX67sN3H4Z+0Yk0Neo++mFsBjhOAuLzvlQeqAAkeDOZrJs9rzumQ==} + '@types/express@5.0.6': + resolution: {integrity: sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==} '@types/from2@2.3.6': resolution: {integrity: sha512-pO5qFhZ85+M4znizw6ihwU2nW+EarU/TuWbYzSEt6YSCis+vET8WJMUlg6/b2HLBzzT9cfKhtEoIciazgv9UXQ==} @@ -1795,9 +1815,6 @@ packages: '@types/mime-types@2.1.4': resolution: {integrity: sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w==} - '@types/mime@1.3.5': - resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} - '@types/minimatch@5.1.2': resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} @@ -1825,14 +1842,11 @@ packages: '@types/semver@7.7.1': resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} - '@types/send@0.17.6': - resolution: {integrity: sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==} - '@types/send@1.2.1': resolution: {integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==} - '@types/serve-static@1.15.10': - resolution: {integrity: sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==} + '@types/serve-static@2.2.0': + resolution: {integrity: sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==} '@types/symbol-tree@3.2.5': resolution: {integrity: sha512-zXnnyENt1TYQcS21MkPaJCVjfcPq7p7yc5mo5JACuumXp6sly5jnlS0IokHd+xmmuCbx6V7JqkMBpswR+nZAcw==} @@ -1873,8 +1887,8 @@ packages: '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} - '@uptime.link/webwidget@1.2.4': - resolution: {integrity: sha512-DkwNmdIBdhBJvvlRZAeUueah9V9l1+l1Ksuqd7ISxrXblWCmwip6r8ZWdajgdZg1FMso8r7rNzLUWObs5kIOYA==} + '@uptime.link/webwidget@1.2.5': + resolution: {integrity: sha512-uyVQ87JG0gz7M2MjMWJaTnFbigBTNhcdKpqP9V3kkQyzxod3HV963vidrdWTgKbULtDyPTjtaoS5gSqn67BJhQ==} '@webcontainer/api@1.2.0': resolution: {integrity: sha512-tzoKBd4lLdhHy5GHFpUkl+ndoSba8JqmB7x0ZQFnWfjbcbQOvKQfxA8MEMUYhgqjWHnbrWdAfnBEHz5f5lYG5A==} @@ -2270,8 +2284,8 @@ packages: engines: {node: '>=18'} hasBin: true - esbuild@0.27.0: - resolution: {integrity: sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==} + esbuild@0.27.1: + resolution: {integrity: sha512-yY35KZckJJuVVPXpvjgxiCuVEJT67F6zDeVTv4rizyPrfGBUpZQsvmxnN+C371c2esD/hNMjj4tpBhuueLN7aA==} engines: {node: '>=18'} hasBin: true @@ -2309,8 +2323,8 @@ packages: resolution: {integrity: sha1-AbK0mK5v0uQRUrIrV6Phc3c69n4=} engines: {node: '>=0.2.2'} - express@5.1.0: - resolution: {integrity: sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==} + express@5.2.1: + resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} engines: {node: '>= 18'} extend@3.0.2: @@ -2359,9 +2373,9 @@ packages: resolution: {integrity: sha512-ifJXo8zUqbQ/bLbl9sFoqHNTNWbnPY1COImFfM6CCy7z+E+jC1eY9YfOKkx0fckIg+VljAy2/87T61fp0+eEkg==} engines: {node: '>=20'} - finalhandler@2.1.0: - resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==} - engines: {node: '>= 0.8'} + finalhandler@2.1.1: + resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==} + engines: {node: '>= 18.0.0'} find-cache-dir@3.3.2: resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} @@ -2765,8 +2779,8 @@ packages: resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==} engines: {node: 20 || >=22} - lucide@0.553.0: - resolution: {integrity: sha512-zdU8nM8mTqFUE6uBP+ncZRN+CTONxwhZbOL2dy+7gINRb1/6zCNQnv6nqpdSrEy5/gy/aJj6FxWHO8WdQgfN0g==} + lucide@0.555.0: + resolution: {integrity: sha512-R7BkO2/XRpMADcMIRn1UOZOvirxr2Z6s/R82k0EUK71ZXXrlRbvkVwTAIf+9DRApeyH+zNMIGfiUdmrOhoAygQ==} make-dir@3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} @@ -3272,8 +3286,8 @@ packages: prosemirror-state@1.4.4: resolution: {integrity: sha512-6jiYHH2CIGbCfnxdHbXZ12gySFY/fz/ulZE333G6bPqIZ4F+TXo9ifiR86nAHpWnfoNjOb3o5ESi7J8Uz1jXHw==} - prosemirror-tables@1.8.1: - resolution: {integrity: sha512-DAgDoUYHCcc6tOGpLVPSU1k84kCUWTWnfWX3UDy2Delv4ryH0KqTD6RBI6k4yi9j9I8gl3j8MkPpRD/vWPZbug==} + prosemirror-tables@1.8.3: + resolution: {integrity: sha512-wbqCR/RlRPRe41a4LFtmhKElzBEfBTdtAYWNIGHM6X2e24NN/MTNUKyXjjphfAfdQce37Kh/5yf765mLPYDe7Q==} prosemirror-trailing-node@3.0.0: resolution: {integrity: sha512-xiun5/3q0w5eRnGYfNlW1uU9W6x5MoFKWwq/0TIRgt09lv7Hcser2QYV8t4muXbEr+Fwo0geYn79Xs4GKywrRQ==} @@ -3285,8 +3299,8 @@ packages: prosemirror-transform@1.10.5: resolution: {integrity: sha512-RPDQCxIDhIBb1o36xxwsaeAvivO8VLJcgBtzmOwQ64bMtsVFh5SSuJ6dWSxO1UsHTiTXPCgQm3PDJt7p6IOLbw==} - prosemirror-view@1.41.3: - resolution: {integrity: sha512-SqMiYMUQNNBP9kfPhLO8WXEk/fon47vc52FQsUiJzTBuyjKgEcoAwMyF04eQ4WZ2ArMn7+ReypYL60aKngbACQ==} + prosemirror-view@1.41.4: + resolution: {integrity: sha512-WkKgnyjNncri03Gjaz3IFWvCAE94XoiEgvtr0/r2Xw7R8/IjK3sKLSiDoCHWcsXSAinVaKlGRZDvMCsF1kbzjA==} proto-list@1.2.4: resolution: {integrity: sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=} @@ -3764,6 +3778,18 @@ packages: utf-8-validate: optional: true + ws@8.18.3: + resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + xmlhttprequest-ssl@2.1.2: resolution: {integrity: sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==} engines: {node: '>=0.4.0'} @@ -3798,7 +3824,7 @@ snapshots: '@api.global/typedrequest-interfaces@3.0.19': {} - '@api.global/typedrequest@3.1.10': + '@api.global/typedrequest@3.1.11': dependencies: '@api.global/typedrequest-interfaces': 3.0.19 '@push.rocks/isounique': 1.0.5 @@ -3810,12 +3836,12 @@ snapshots: '@push.rocks/webrequest': 3.0.37 '@push.rocks/webstream': 1.0.10 - '@api.global/typedserver@3.0.80': + '@api.global/typedserver@3.0.80(@push.rocks/smartserve@1.1.2)': dependencies: - '@api.global/typedrequest': 3.1.10 + '@api.global/typedrequest': 3.1.11 '@api.global/typedrequest-interfaces': 3.0.19 - '@api.global/typedsocket': 3.0.1 - '@cloudflare/workers-types': 4.20251128.0 + '@api.global/typedsocket': 3.1.1(@push.rocks/smartserve@1.1.2) + '@cloudflare/workers-types': 4.20251202.0 '@design.estate/dees-comms': 1.0.27 '@push.rocks/lik': 6.2.2 '@push.rocks/smartchok': 1.2.0 @@ -3839,16 +3865,61 @@ snapshots: '@push.rocks/smartsitemap': 2.0.4 '@push.rocks/smartstream': 3.2.5 '@push.rocks/smarttime': 4.1.1 - '@push.rocks/taskbuffer': 3.4.0 + '@push.rocks/taskbuffer': 3.5.0 '@push.rocks/webrequest': 3.0.37 '@push.rocks/webstore': 2.0.20 '@tsclass/tsclass': 9.3.0 - '@types/express': 5.0.5 + '@types/express': 5.0.6 body-parser: 2.2.1 cors: 2.8.5 - express: 5.1.0 + express: 5.2.1 express-force-ssl: 0.3.2 lit: 3.3.1 + transitivePeerDependencies: + - '@nuxt/kit' + - '@push.rocks/smartserve' + - bufferutil + - react + - supports-color + - utf-8-validate + - vue + + '@api.global/typedserver@7.7.0': + dependencies: + '@api.global/typedrequest': 3.1.11 + '@api.global/typedrequest-interfaces': 3.0.19 + '@api.global/typedsocket': 4.1.0(@push.rocks/smartserve@1.1.2) + '@cloudflare/workers-types': 4.20251202.0 + '@design.estate/dees-comms': 1.0.27 + '@push.rocks/lik': 6.2.2 + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartenv': 6.0.0 + '@push.rocks/smartfeed': 1.4.0 + '@push.rocks/smartfile': 13.1.0 + '@push.rocks/smartfs': 1.2.0 + '@push.rocks/smartjson': 5.2.0 + '@push.rocks/smartlog': 3.1.10 + '@push.rocks/smartlog-destination-devtools': 1.0.12 + '@push.rocks/smartlog-interfaces': 3.0.2 + '@push.rocks/smartmanifest': 2.0.2 + '@push.rocks/smartmatch': 2.0.0 + '@push.rocks/smartmime': 2.0.4 + '@push.rocks/smartntml': 2.0.8 + '@push.rocks/smartopen': 2.0.0 + '@push.rocks/smartpath': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrequest': 5.0.1 + '@push.rocks/smartrx': 3.0.10 + '@push.rocks/smartserve': 1.1.2 + '@push.rocks/smartsitemap': 2.0.4 + '@push.rocks/smartstream': 3.2.5 + '@push.rocks/smarttime': 4.1.1 + '@push.rocks/smartwatch': 5.0.0 + '@push.rocks/taskbuffer': 3.5.0 + '@push.rocks/webrequest': 4.0.1 + '@push.rocks/webstore': 2.0.20 + '@tsclass/tsclass': 9.3.0 + lit: 3.3.1 transitivePeerDependencies: - '@nuxt/kit' - bufferutil @@ -3857,16 +3928,18 @@ snapshots: - utf-8-validate - vue - '@api.global/typedsocket@3.0.1': + '@api.global/typedsocket@3.1.1(@push.rocks/smartserve@1.1.2)': dependencies: - '@api.global/typedrequest': 3.1.10 + '@api.global/typedrequest': 3.1.11 '@api.global/typedrequest-interfaces': 3.0.19 '@push.rocks/isohash': 2.0.1 '@push.rocks/smartjson': 5.2.0 '@push.rocks/smartrx': 3.0.10 - '@push.rocks/smartsocket': 2.1.0 + '@push.rocks/smartsocket': 2.1.0(@push.rocks/smartserve@1.1.2) '@push.rocks/smartstring': 4.1.0 '@push.rocks/smarturl': 3.1.0 + optionalDependencies: + '@push.rocks/smartserve': 1.1.2 transitivePeerDependencies: - '@nuxt/kit' - bufferutil @@ -3875,6 +3948,19 @@ snapshots: - utf-8-validate - vue + '@api.global/typedsocket@4.1.0(@push.rocks/smartserve@1.1.2)': + dependencies: + '@api.global/typedrequest': 3.1.11 + '@api.global/typedrequest-interfaces': 3.0.19 + '@push.rocks/isohash': 2.0.1 + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartjson': 5.2.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrx': 3.0.10 + '@push.rocks/smartserve': 1.1.2 + '@push.rocks/smartstring': 4.1.0 + '@push.rocks/smarturl': 3.1.0 + '@aws-crypto/crc32@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 @@ -4358,7 +4444,7 @@ snapshots: '@borewit/text-codec@0.1.1': {} - '@cloudflare/workers-types@4.20251128.0': {} + '@cloudflare/workers-types@4.20251202.0': {} '@configvault.io/interfaces@1.0.17': dependencies: @@ -4382,12 +4468,12 @@ snapshots: '@consent.software/webclient@1.1.0': dependencies: - '@api.global/typedrequest': 3.1.10 + '@api.global/typedrequest': 3.1.11 '@consent.software/interfaces': 1.0.14 '@push.rocks/smarttime': 4.1.1 '@push.rocks/webstore': 2.0.20 - '@design.estate/dees-catalog@2.0.2(@tiptap/pm@2.27.1)': + '@design.estate/dees-catalog@2.0.3(@tiptap/pm@2.27.1)': dependencies: '@design.estate/dees-domtools': 2.3.6 '@design.estate/dees-element': 2.1.3 @@ -4411,7 +4497,7 @@ snapshots: highlight.js: 11.11.1 ibantools: 4.5.1 lit: 3.3.1 - lucide: 0.553.0 + lucide: 0.555.0 monaco-editor: 0.52.2 pdfjs-dist: 4.10.38 xterm: 5.3.0 @@ -4425,14 +4511,14 @@ snapshots: '@design.estate/dees-comms@1.0.27': dependencies: - '@api.global/typedrequest': 3.1.10 + '@api.global/typedrequest': 3.1.11 '@api.global/typedrequest-interfaces': 3.0.19 '@push.rocks/smartdelay': 3.0.5 broadcast-channel: 7.2.0 '@design.estate/dees-domtools@2.3.6': dependencies: - '@api.global/typedrequest': 3.1.10 + '@api.global/typedrequest': 3.1.11 '@design.estate/dees-comms': 1.0.27 '@push.rocks/lik': 6.2.2 '@push.rocks/smartdelay': 3.0.5 @@ -4499,157 +4585,157 @@ snapshots: '@esbuild/aix-ppc64@0.25.12': optional: true - '@esbuild/aix-ppc64@0.27.0': + '@esbuild/aix-ppc64@0.27.1': optional: true '@esbuild/android-arm64@0.25.12': optional: true - '@esbuild/android-arm64@0.27.0': + '@esbuild/android-arm64@0.27.1': optional: true '@esbuild/android-arm@0.25.12': optional: true - '@esbuild/android-arm@0.27.0': + '@esbuild/android-arm@0.27.1': optional: true '@esbuild/android-x64@0.25.12': optional: true - '@esbuild/android-x64@0.27.0': + '@esbuild/android-x64@0.27.1': optional: true '@esbuild/darwin-arm64@0.25.12': optional: true - '@esbuild/darwin-arm64@0.27.0': + '@esbuild/darwin-arm64@0.27.1': optional: true '@esbuild/darwin-x64@0.25.12': optional: true - '@esbuild/darwin-x64@0.27.0': + '@esbuild/darwin-x64@0.27.1': optional: true '@esbuild/freebsd-arm64@0.25.12': optional: true - '@esbuild/freebsd-arm64@0.27.0': + '@esbuild/freebsd-arm64@0.27.1': optional: true '@esbuild/freebsd-x64@0.25.12': optional: true - '@esbuild/freebsd-x64@0.27.0': + '@esbuild/freebsd-x64@0.27.1': optional: true '@esbuild/linux-arm64@0.25.12': optional: true - '@esbuild/linux-arm64@0.27.0': + '@esbuild/linux-arm64@0.27.1': optional: true '@esbuild/linux-arm@0.25.12': optional: true - '@esbuild/linux-arm@0.27.0': + '@esbuild/linux-arm@0.27.1': optional: true '@esbuild/linux-ia32@0.25.12': optional: true - '@esbuild/linux-ia32@0.27.0': + '@esbuild/linux-ia32@0.27.1': optional: true '@esbuild/linux-loong64@0.25.12': optional: true - '@esbuild/linux-loong64@0.27.0': + '@esbuild/linux-loong64@0.27.1': optional: true '@esbuild/linux-mips64el@0.25.12': optional: true - '@esbuild/linux-mips64el@0.27.0': + '@esbuild/linux-mips64el@0.27.1': optional: true '@esbuild/linux-ppc64@0.25.12': optional: true - '@esbuild/linux-ppc64@0.27.0': + '@esbuild/linux-ppc64@0.27.1': optional: true '@esbuild/linux-riscv64@0.25.12': optional: true - '@esbuild/linux-riscv64@0.27.0': + '@esbuild/linux-riscv64@0.27.1': optional: true '@esbuild/linux-s390x@0.25.12': optional: true - '@esbuild/linux-s390x@0.27.0': + '@esbuild/linux-s390x@0.27.1': optional: true '@esbuild/linux-x64@0.25.12': optional: true - '@esbuild/linux-x64@0.27.0': + '@esbuild/linux-x64@0.27.1': optional: true '@esbuild/netbsd-arm64@0.25.12': optional: true - '@esbuild/netbsd-arm64@0.27.0': + '@esbuild/netbsd-arm64@0.27.1': optional: true '@esbuild/netbsd-x64@0.25.12': optional: true - '@esbuild/netbsd-x64@0.27.0': + '@esbuild/netbsd-x64@0.27.1': optional: true '@esbuild/openbsd-arm64@0.25.12': optional: true - '@esbuild/openbsd-arm64@0.27.0': + '@esbuild/openbsd-arm64@0.27.1': optional: true '@esbuild/openbsd-x64@0.25.12': optional: true - '@esbuild/openbsd-x64@0.27.0': + '@esbuild/openbsd-x64@0.27.1': optional: true '@esbuild/openharmony-arm64@0.25.12': optional: true - '@esbuild/openharmony-arm64@0.27.0': + '@esbuild/openharmony-arm64@0.27.1': optional: true '@esbuild/sunos-x64@0.25.12': optional: true - '@esbuild/sunos-x64@0.27.0': + '@esbuild/sunos-x64@0.27.1': optional: true '@esbuild/win32-arm64@0.25.12': optional: true - '@esbuild/win32-arm64@0.27.0': + '@esbuild/win32-arm64@0.27.1': optional: true '@esbuild/win32-ia32@0.25.12': optional: true - '@esbuild/win32-ia32@0.27.0': + '@esbuild/win32-ia32@0.27.1': optional: true '@esbuild/win32-x64@0.25.12': optional: true - '@esbuild/win32-x64@0.27.0': + '@esbuild/win32-x64@0.27.1': optional: true '@fortawesome/fontawesome-common-types@7.1.0': {} @@ -4690,20 +4776,20 @@ snapshots: - supports-color - vue - '@git.zone/tsbundle@2.6.2': + '@git.zone/tsbundle@2.6.3': dependencies: '@push.rocks/early': 4.0.4 '@push.rocks/smartcli': 4.0.19 '@push.rocks/smartdelay': 3.0.5 - '@push.rocks/smartfs': 1.1.3 + '@push.rocks/smartfs': 1.2.0 '@push.rocks/smartlog': 3.1.10 '@push.rocks/smartlog-destination-local': 9.0.2 '@push.rocks/smartpath': 6.0.0 '@push.rocks/smartpromise': 4.2.3 '@push.rocks/smartspawn': 3.0.3 - '@rspack/core': 1.6.5 + '@rspack/core': 1.6.6 '@types/html-minifier': 4.0.6 - esbuild: 0.27.0 + esbuild: 0.27.1 html-minifier: 4.0.0 rolldown: 1.0.0-beta.52 typescript: 5.9.3 @@ -4737,23 +4823,24 @@ snapshots: '@push.rocks/smartshell': 3.3.0 tsx: 4.20.6 - '@git.zone/tswatch@2.2.2': + '@git.zone/tswatch@2.2.3(@push.rocks/smartserve@1.1.2)': dependencies: - '@api.global/typedserver': 3.0.80 - '@git.zone/tsbundle': 2.6.2 + '@api.global/typedserver': 3.0.80(@push.rocks/smartserve@1.1.2) + '@git.zone/tsbundle': 2.6.3 '@git.zone/tsrun': 2.0.0 '@push.rocks/early': 4.0.4 '@push.rocks/lik': 6.2.2 '@push.rocks/smartcli': 4.0.19 '@push.rocks/smartdelay': 3.0.5 - '@push.rocks/smartfs': 1.1.3 + '@push.rocks/smartfs': 1.2.0 '@push.rocks/smartlog': 3.1.10 '@push.rocks/smartlog-destination-local': 9.0.2 '@push.rocks/smartshell': 3.3.0 '@push.rocks/smartwatch': 5.0.0 - '@push.rocks/taskbuffer': 3.4.0 + '@push.rocks/taskbuffer': 3.5.0 transitivePeerDependencies: - '@nuxt/kit' + - '@push.rocks/smartserve' - '@swc/helpers' - bufferutil - react @@ -4790,30 +4877,30 @@ snapshots: '@mixmark-io/domino@2.2.0': {} - '@module-federation/error-codes@0.21.4': {} + '@module-federation/error-codes@0.21.6': {} - '@module-federation/runtime-core@0.21.4': + '@module-federation/runtime-core@0.21.6': dependencies: - '@module-federation/error-codes': 0.21.4 - '@module-federation/sdk': 0.21.4 + '@module-federation/error-codes': 0.21.6 + '@module-federation/sdk': 0.21.6 - '@module-federation/runtime-tools@0.21.4': + '@module-federation/runtime-tools@0.21.6': dependencies: - '@module-federation/runtime': 0.21.4 - '@module-federation/webpack-bundler-runtime': 0.21.4 + '@module-federation/runtime': 0.21.6 + '@module-federation/webpack-bundler-runtime': 0.21.6 - '@module-federation/runtime@0.21.4': + '@module-federation/runtime@0.21.6': dependencies: - '@module-federation/error-codes': 0.21.4 - '@module-federation/runtime-core': 0.21.4 - '@module-federation/sdk': 0.21.4 + '@module-federation/error-codes': 0.21.6 + '@module-federation/runtime-core': 0.21.6 + '@module-federation/sdk': 0.21.6 - '@module-federation/sdk@0.21.4': {} + '@module-federation/sdk@0.21.6': {} - '@module-federation/webpack-bundler-runtime@0.21.4': + '@module-federation/webpack-bundler-runtime@0.21.6': dependencies: - '@module-federation/runtime': 0.21.4 - '@module-federation/sdk': 0.21.4 + '@module-federation/runtime': 0.21.6 + '@module-federation/sdk': 0.21.6 '@mongodb-js/saslprep@1.3.2': dependencies: @@ -4870,6 +4957,13 @@ snapshots: '@tybys/wasm-util': 0.10.1 optional: true + '@napi-rs/wasm-runtime@1.1.0': + dependencies: + '@emnapi/core': 1.7.1 + '@emnapi/runtime': 1.7.1 + '@tybys/wasm-util': 0.10.1 + optional: true + '@oxc-project/types@0.99.0': {} '@peculiar/asn1-cms@2.6.0': @@ -5006,7 +5100,7 @@ snapshots: '@push.rocks/smartpromise': 4.2.3 '@push.rocks/smartstring': 4.1.0 '@push.rocks/smartunique': 3.0.9 - '@push.rocks/taskbuffer': 3.4.0 + '@push.rocks/taskbuffer': 3.5.0 '@tsclass/tsclass': 9.3.0 transitivePeerDependencies: - '@nuxt/kit' @@ -5053,7 +5147,7 @@ snapshots: '@push.rocks/qenv@6.1.3': dependencies: - '@api.global/typedrequest': 3.1.10 + '@api.global/typedrequest': 3.1.11 '@configvault.io/interfaces': 1.0.17 '@push.rocks/smartfile': 11.2.7 '@push.rocks/smartlog': 3.1.10 @@ -5148,7 +5242,7 @@ snapshots: '@push.rocks/smartstring': 4.1.0 '@push.rocks/smarttime': 4.1.1 '@push.rocks/smartunique': 3.0.9 - '@push.rocks/taskbuffer': 3.4.0 + '@push.rocks/taskbuffer': 3.5.0 '@tsclass/tsclass': 9.3.0 mongodb: 6.21.0 transitivePeerDependencies: @@ -5177,7 +5271,7 @@ snapshots: '@push.rocks/smartstring': 4.1.0 '@push.rocks/smarttime': 4.1.1 '@push.rocks/smartunique': 3.0.9 - '@push.rocks/taskbuffer': 3.4.0 + '@push.rocks/taskbuffer': 3.5.0 '@tsclass/tsclass': 9.3.0 mongodb: 7.0.0 transitivePeerDependencies: @@ -5300,7 +5394,7 @@ snapshots: dependencies: '@push.rocks/smartpath': 6.0.0 - '@push.rocks/smartfs@1.1.3': + '@push.rocks/smartfs@1.2.0': dependencies: '@push.rocks/smartpath': 6.0.0 @@ -5515,6 +5609,18 @@ snapshots: '@push.rocks/smartpromise': 4.2.3 rxjs: 7.8.2 + '@push.rocks/smartserve@1.1.2': + dependencies: + '@api.global/typedrequest': 3.1.11 + '@push.rocks/lik': 6.2.2 + '@push.rocks/smartenv': 6.0.0 + '@push.rocks/smartlog': 3.1.10 + '@push.rocks/smartpath': 6.0.0 + ws: 8.18.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + '@push.rocks/smartshell@3.3.0': dependencies: '@push.rocks/smartdelay': 3.0.5 @@ -5533,10 +5639,10 @@ snapshots: '@push.rocks/webrequest': 4.0.1 '@tsclass/tsclass': 9.3.0 - '@push.rocks/smartsocket@2.1.0': + '@push.rocks/smartsocket@2.1.0(@push.rocks/smartserve@1.1.2)': dependencies: '@api.global/typedrequest-interfaces': 3.0.19 - '@api.global/typedserver': 3.0.80 + '@api.global/typedserver': 3.0.80(@push.rocks/smartserve@1.1.2) '@push.rocks/isohash': 2.0.1 '@push.rocks/isounique': 1.0.5 '@push.rocks/lik': 6.2.2 @@ -5552,6 +5658,7 @@ snapshots: socket.io-client: 4.8.1 transitivePeerDependencies: - '@nuxt/kit' + - '@push.rocks/smartserve' - bufferutil - react - supports-color @@ -5641,7 +5748,7 @@ snapshots: dependencies: yaml: 2.8.2 - '@push.rocks/taskbuffer@3.4.0': + '@push.rocks/taskbuffer@3.5.0': dependencies: '@design.estate/dees-element': 2.1.3 '@push.rocks/lik': 6.2.2 @@ -5774,7 +5881,7 @@ snapshots: '@rolldown/binding-wasm32-wasi@1.0.0-beta.52': dependencies: - '@napi-rs/wasm-runtime': 1.0.7 + '@napi-rs/wasm-runtime': 1.1.0 optional: true '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.52': @@ -5788,55 +5895,55 @@ snapshots: '@rolldown/pluginutils@1.0.0-beta.52': {} - '@rspack/binding-darwin-arm64@1.6.5': + '@rspack/binding-darwin-arm64@1.6.6': optional: true - '@rspack/binding-darwin-x64@1.6.5': + '@rspack/binding-darwin-x64@1.6.6': optional: true - '@rspack/binding-linux-arm64-gnu@1.6.5': + '@rspack/binding-linux-arm64-gnu@1.6.6': optional: true - '@rspack/binding-linux-arm64-musl@1.6.5': + '@rspack/binding-linux-arm64-musl@1.6.6': optional: true - '@rspack/binding-linux-x64-gnu@1.6.5': + '@rspack/binding-linux-x64-gnu@1.6.6': optional: true - '@rspack/binding-linux-x64-musl@1.6.5': + '@rspack/binding-linux-x64-musl@1.6.6': optional: true - '@rspack/binding-wasm32-wasi@1.6.5': + '@rspack/binding-wasm32-wasi@1.6.6': dependencies: '@napi-rs/wasm-runtime': 1.0.7 optional: true - '@rspack/binding-win32-arm64-msvc@1.6.5': + '@rspack/binding-win32-arm64-msvc@1.6.6': optional: true - '@rspack/binding-win32-ia32-msvc@1.6.5': + '@rspack/binding-win32-ia32-msvc@1.6.6': optional: true - '@rspack/binding-win32-x64-msvc@1.6.5': + '@rspack/binding-win32-x64-msvc@1.6.6': optional: true - '@rspack/binding@1.6.5': + '@rspack/binding@1.6.6': optionalDependencies: - '@rspack/binding-darwin-arm64': 1.6.5 - '@rspack/binding-darwin-x64': 1.6.5 - '@rspack/binding-linux-arm64-gnu': 1.6.5 - '@rspack/binding-linux-arm64-musl': 1.6.5 - '@rspack/binding-linux-x64-gnu': 1.6.5 - '@rspack/binding-linux-x64-musl': 1.6.5 - '@rspack/binding-wasm32-wasi': 1.6.5 - '@rspack/binding-win32-arm64-msvc': 1.6.5 - '@rspack/binding-win32-ia32-msvc': 1.6.5 - '@rspack/binding-win32-x64-msvc': 1.6.5 + '@rspack/binding-darwin-arm64': 1.6.6 + '@rspack/binding-darwin-x64': 1.6.6 + '@rspack/binding-linux-arm64-gnu': 1.6.6 + '@rspack/binding-linux-arm64-musl': 1.6.6 + '@rspack/binding-linux-x64-gnu': 1.6.6 + '@rspack/binding-linux-x64-musl': 1.6.6 + '@rspack/binding-wasm32-wasi': 1.6.6 + '@rspack/binding-win32-arm64-msvc': 1.6.6 + '@rspack/binding-win32-ia32-msvc': 1.6.6 + '@rspack/binding-win32-x64-msvc': 1.6.6 - '@rspack/core@1.6.5': + '@rspack/core@1.6.6': dependencies: - '@module-federation/runtime-tools': 0.21.4 - '@rspack/binding': 1.6.5 + '@module-federation/runtime-tools': 0.21.6 + '@rspack/binding': 1.6.6 '@rspack/lite-tapable': 1.1.0 '@rspack/lite-tapable@1.1.0': {} @@ -5849,19 +5956,22 @@ snapshots: '@push.rocks/smartlog-interfaces': 3.0.2 '@tsclass/tsclass': 4.4.4 - '@serve.zone/platformclient@1.1.2': + '@serve.zone/platformclient@1.1.2(@push.rocks/smartserve@1.1.2)': dependencies: - '@api.global/typedrequest': 3.1.10 - '@api.global/typedserver': 3.0.80 - '@api.global/typedsocket': 3.0.1 + '@api.global/typedrequest': 3.1.11 + '@api.global/typedserver': 3.0.80(@push.rocks/smartserve@1.1.2) + '@api.global/typedsocket': 3.1.1(@push.rocks/smartserve@1.1.2) '@push.rocks/qenv': 6.1.3 '@push.rocks/smartlog': 3.1.10 '@push.rocks/smartntml': 2.0.8 '@serve.zone/interfaces': 1.1.2 transitivePeerDependencies: - '@nuxt/kit' + - '@push.rocks/smartserve' + - bufferutil - react - supports-color + - utf-8-validate - vue '@sindresorhus/is@5.6.0': {} @@ -6350,10 +6460,10 @@ snapshots: prosemirror-schema-basic: 1.2.4 prosemirror-schema-list: 1.5.1 prosemirror-state: 1.4.4 - prosemirror-tables: 1.8.1 - prosemirror-trailing-node: 3.0.0(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.3) + prosemirror-tables: 1.8.3 + prosemirror-trailing-node: 3.0.0(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.4) prosemirror-transform: 1.10.5 - prosemirror-view: 1.41.3 + prosemirror-view: 1.41.4 '@tiptap/starter-kit@2.27.1': dependencies: @@ -6444,11 +6554,11 @@ snapshots: '@types/range-parser': 1.2.7 '@types/send': 1.2.1 - '@types/express@5.0.5': + '@types/express@5.0.6': dependencies: '@types/body-parser': 1.19.6 '@types/express-serve-static-core': 5.1.0 - '@types/serve-static': 1.15.10 + '@types/serve-static': 2.2.0 '@types/from2@2.3.6': dependencies: @@ -6506,8 +6616,6 @@ snapshots: '@types/mime-types@2.1.4': {} - '@types/mime@1.3.5': {} - '@types/minimatch@5.1.2': {} '@types/ms@2.1.0': {} @@ -6530,20 +6638,14 @@ snapshots: '@types/semver@7.7.1': {} - '@types/send@0.17.6': - dependencies: - '@types/mime': 1.3.5 - '@types/node': 24.10.1 - '@types/send@1.2.1': dependencies: '@types/node': 24.10.1 - '@types/serve-static@1.15.10': + '@types/serve-static@2.2.0': dependencies: '@types/http-errors': 2.0.5 '@types/node': 24.10.1 - '@types/send': 0.17.6 '@types/symbol-tree@3.2.5': {} @@ -6581,9 +6683,9 @@ snapshots: '@ungap/structured-clone@1.3.0': {} - '@uptime.link/webwidget@1.2.4(@tiptap/pm@2.27.1)': + '@uptime.link/webwidget@1.2.5(@tiptap/pm@2.27.1)': dependencies: - '@design.estate/dees-catalog': 2.0.2(@tiptap/pm@2.27.1) + '@design.estate/dees-catalog': 2.0.3(@tiptap/pm@2.27.1) '@design.estate/dees-domtools': 2.3.6 '@design.estate/dees-element': 2.1.3 '@design.estate/dees-wcctools': 1.2.1 @@ -7002,34 +7104,34 @@ snapshots: '@esbuild/win32-ia32': 0.25.12 '@esbuild/win32-x64': 0.25.12 - esbuild@0.27.0: + esbuild@0.27.1: optionalDependencies: - '@esbuild/aix-ppc64': 0.27.0 - '@esbuild/android-arm': 0.27.0 - '@esbuild/android-arm64': 0.27.0 - '@esbuild/android-x64': 0.27.0 - '@esbuild/darwin-arm64': 0.27.0 - '@esbuild/darwin-x64': 0.27.0 - '@esbuild/freebsd-arm64': 0.27.0 - '@esbuild/freebsd-x64': 0.27.0 - '@esbuild/linux-arm': 0.27.0 - '@esbuild/linux-arm64': 0.27.0 - '@esbuild/linux-ia32': 0.27.0 - '@esbuild/linux-loong64': 0.27.0 - '@esbuild/linux-mips64el': 0.27.0 - '@esbuild/linux-ppc64': 0.27.0 - '@esbuild/linux-riscv64': 0.27.0 - '@esbuild/linux-s390x': 0.27.0 - '@esbuild/linux-x64': 0.27.0 - '@esbuild/netbsd-arm64': 0.27.0 - '@esbuild/netbsd-x64': 0.27.0 - '@esbuild/openbsd-arm64': 0.27.0 - '@esbuild/openbsd-x64': 0.27.0 - '@esbuild/openharmony-arm64': 0.27.0 - '@esbuild/sunos-x64': 0.27.0 - '@esbuild/win32-arm64': 0.27.0 - '@esbuild/win32-ia32': 0.27.0 - '@esbuild/win32-x64': 0.27.0 + '@esbuild/aix-ppc64': 0.27.1 + '@esbuild/android-arm': 0.27.1 + '@esbuild/android-arm64': 0.27.1 + '@esbuild/android-x64': 0.27.1 + '@esbuild/darwin-arm64': 0.27.1 + '@esbuild/darwin-x64': 0.27.1 + '@esbuild/freebsd-arm64': 0.27.1 + '@esbuild/freebsd-x64': 0.27.1 + '@esbuild/linux-arm': 0.27.1 + '@esbuild/linux-arm64': 0.27.1 + '@esbuild/linux-ia32': 0.27.1 + '@esbuild/linux-loong64': 0.27.1 + '@esbuild/linux-mips64el': 0.27.1 + '@esbuild/linux-ppc64': 0.27.1 + '@esbuild/linux-riscv64': 0.27.1 + '@esbuild/linux-s390x': 0.27.1 + '@esbuild/linux-x64': 0.27.1 + '@esbuild/netbsd-arm64': 0.27.1 + '@esbuild/netbsd-x64': 0.27.1 + '@esbuild/openbsd-arm64': 0.27.1 + '@esbuild/openbsd-x64': 0.27.1 + '@esbuild/openharmony-arm64': 0.27.1 + '@esbuild/sunos-x64': 0.27.1 + '@esbuild/win32-arm64': 0.27.1 + '@esbuild/win32-ia32': 0.27.1 + '@esbuild/win32-x64': 0.27.1 escape-html@1.0.3: {} @@ -7055,7 +7157,7 @@ snapshots: dependencies: lodash.assign: 3.2.0 - express@5.1.0: + express@5.2.1: dependencies: accepts: 2.0.0 body-parser: 2.2.1 @@ -7064,10 +7166,11 @@ snapshots: cookie: 0.7.2 cookie-signature: 1.2.2 debug: 4.4.3 + depd: 2.0.0 encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 - finalhandler: 2.1.0 + finalhandler: 2.1.1 fresh: 2.0.0 http-errors: 2.0.1 merge-descriptors: 2.0.0 @@ -7133,7 +7236,7 @@ snapshots: transitivePeerDependencies: - supports-color - finalhandler@2.1.0: + finalhandler@2.1.1: dependencies: debug: 4.4.3 encodeurl: 2.0.0 @@ -7585,7 +7688,7 @@ snapshots: lru-cache@11.2.2: {} - lucide@0.553.0: {} + lucide@0.555.0: {} make-dir@3.1.0: dependencies: @@ -8203,20 +8306,20 @@ snapshots: dependencies: prosemirror-state: 1.4.4 prosemirror-transform: 1.10.5 - prosemirror-view: 1.41.3 + prosemirror-view: 1.41.4 prosemirror-gapcursor@1.4.0: dependencies: prosemirror-keymap: 1.2.3 prosemirror-model: 1.25.4 prosemirror-state: 1.4.4 - prosemirror-view: 1.41.3 + prosemirror-view: 1.41.4 prosemirror-history@1.5.0: dependencies: prosemirror-state: 1.4.4 prosemirror-transform: 1.10.5 - prosemirror-view: 1.41.3 + prosemirror-view: 1.41.4 rope-sequence: 1.3.4 prosemirror-inputrules@1.5.1: @@ -8260,29 +8363,29 @@ snapshots: dependencies: prosemirror-model: 1.25.4 prosemirror-transform: 1.10.5 - prosemirror-view: 1.41.3 + prosemirror-view: 1.41.4 - prosemirror-tables@1.8.1: + prosemirror-tables@1.8.3: dependencies: prosemirror-keymap: 1.2.3 prosemirror-model: 1.25.4 prosemirror-state: 1.4.4 prosemirror-transform: 1.10.5 - prosemirror-view: 1.41.3 + prosemirror-view: 1.41.4 - prosemirror-trailing-node@3.0.0(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.3): + prosemirror-trailing-node@3.0.0(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.4): dependencies: '@remirror/core-constants': 3.0.0 escape-string-regexp: 4.0.0 prosemirror-model: 1.25.4 prosemirror-state: 1.4.4 - prosemirror-view: 1.41.3 + prosemirror-view: 1.41.4 prosemirror-transform@1.10.5: dependencies: prosemirror-model: 1.25.4 - prosemirror-view@1.41.3: + prosemirror-view@1.41.4: dependencies: prosemirror-model: 1.25.4 prosemirror-state: 1.4.4 @@ -8861,6 +8964,8 @@ snapshots: ws@8.17.1: {} + ws@8.18.3: {} + xmlhttprequest-ssl@2.1.2: {} xterm-addon-fit@0.8.0(xterm@5.3.0): diff --git a/stories/organization-owner/ORG-002-member-management.md b/stories/organization-owner/ORG-002-member-management.md index fd1e308..86062d9 100644 --- a/stories/organization-owner/ORG-002-member-management.md +++ b/stories/organization-owner/ORG-002-member-management.md @@ -2,27 +2,127 @@ **ID:** ORG-002 **Priority:** Critical -**Status:** Planned +**Status:** In Development ## User Story As an organization owner, I want to invite team members to my organization and manage their access so that my team can collaborate securely. ## Acceptance Criteria -- [ ] Owner can invite users via email address -- [ ] Invited user receives email with invitation link -- [ ] Invitation can be accepted by existing users or during registration -- [ ] Owner can view pending invitations and resend/cancel them -- [ ] Owner can see all current members with their roles -- [ ] Owner can remove members from organization +- [x] Owner can invite users via email address +- [x] Invited user receives email with invitation link +- [x] Invitation can be accepted by existing users or during registration +- [x] Owner can view pending invitations and resend/cancel them +- [x] Owner can see all current members with their roles +- [x] Owner can remove members from organization - [ ] Owner can transfer ownership to another member - [ ] Bulk invite via CSV upload +## Technical Implementation + +### UserInvitation System + +The invitation system uses a shared `UserInvitation` model that supports multiple organizations inviting the same email address. + +#### Invitation Lifecycle + +1. **Create**: Org admin invites email โ†’ `UserInvitation` created (or existing one is updated) +2. **Share**: Multiple orgs can link to the same invitation (by email) +3. **Convert**: When user registers with that email โ†’ invitation converts to real User +4. **Fold**: If existing user adds that email as secondary โ†’ invitation folds into existing user +5. **Expire**: Auto-delete after 90 days with cleanup of all org refs + +#### Data Model + +```typescript +// IUserInvitation +{ + id: string; + data: { + email: string; // Unique key for sharing + token: string; // Secure invitation link token + status: 'pending' | 'accepted' | 'expired' | 'cancelled'; + createdAt: number; + expiresAt: number; // 90 days from creation + organizationRefs: Array<{ // Multiple orgs can share + organizationId: string; + invitedByUserId: string; + invitedAt: number; + roles: string[]; // Roles to assign on acceptance + }>; + acceptedAt?: number; + convertedToUserId?: string; + }; +} +``` + +### Role System Enhancement + +Users can have multiple roles within an organization: + +```typescript +// IRole +{ + id: string; + data: { + userId: string; + organizationId: string; + roles: string[]; // e.g., ['owner', 'billing-admin', 'developer'] + }; +} +``` + +Standard roles: `owner`, `admin`, `editor`, `viewer`, `guest` +Custom roles are also supported. + +### API Endpoints + +| Method | Purpose | +|--------|---------| +| `createInvitation` | Invite email to org with roles | +| `getOrgInvitations` | List pending invitations | +| `getOrgMembers` | List members with roles | +| `cancelInvitation` | Cancel pending invitation | +| `resendInvitation` | Resend invitation email | +| `removeMember` | Remove user from org | +| `updateMemberRoles` | Change member's roles | +| `transferOwnership` | Transfer org ownership | +| `acceptInvitation` | Accept invitation | +| `getInvitationByToken` | Get invitation details for landing page | + +### Frontend Implementation + +The Users page (`/account/org/:orgName/users`) provides: + +- **Members tab**: List all members with roles, remove/edit actions +- **Pending tab**: List pending invitations with resend/cancel +- **Invite tab**: Form to invite by email with role selection + +### Files + +**Backend:** +- `ts_interfaces/data/loint-reception.userinvitation.ts` - Data interface +- `ts_interfaces/request/loint-reception.userinvitation.ts` - API contracts +- `ts/reception/classes.userinvitation.ts` - Model +- `ts/reception/classes.userinvitationmanager.ts` - Manager with handlers +- `ts/reception/classes.receptionmailer.ts` - Invitation email + +**Frontend:** +- `ts_web/elements/account/views/usersview.ts` - Users page component +- `ts_web/elements/account/content.ts` - Route registration +- `ts_web/elements/account/navigation.ts` - Nav link + ## Technical Notes - Organization and User models exist with association -- Need new Invitation model with token and expiry -- Use `ReceptionMailer` for invitation emails -- RoleManager can be leveraged for role assignment -- Consider invitation expiry (7 days default) +- UserInvitation model stores invitation data with 90-day expiry +- `ReceptionMailer.sendInvitationEmail()` handles email delivery +- RoleManager updated to support `roles: string[]` array +- Backward compatible with existing single-role data + +## Related Stories +- ORG-003: Assign Roles to Members (enhanced with multi-role support) ## Related TODOs -- New feature - core organizational functionality +- [ ] Integrate invitation acceptance into registration flow +- [ ] Add email verification flow for secondary emails (folding) +- [ ] Implement scheduled cleanup job for expired invitations +- [ ] Add CSV bulk invite feature diff --git a/ts/reception/classes.organization.ts b/ts/reception/classes.organization.ts index 5b1155b..efe8d3a 100644 --- a/ts/reception/classes.organization.ts +++ b/ts/reception/classes.organization.ts @@ -35,6 +35,6 @@ export class Organization extends plugins.smartdata.SmartDataDbDoc< public async checkIfUserIsAdmin(userArg: User) { const role = await this.manager.receptionRef.roleManager.getRoleForUserAndOrg(userArg, this); - return role.data.role === 'admin'; + return role.data.roles?.includes('admin') || role.data.roles?.includes('owner'); } } diff --git a/ts/reception/classes.reception.ts b/ts/reception/classes.reception.ts index 969f212..dd10d31 100644 --- a/ts/reception/classes.reception.ts +++ b/ts/reception/classes.reception.ts @@ -16,6 +16,7 @@ import { BillingPlanManager } from './classes.billingplanmanager.js'; import { AppManager } from './classes.appmanager.js'; import { AppConnectionManager } from './classes.appconnectionmanager.js'; import { ActivityLogManager } from './classes.activitylogmanager.js'; +import { UserInvitationManager } from './classes.userinvitationmanager.js'; export interface IReceptionOptions { /** @@ -47,6 +48,7 @@ export class Reception { public appManager = new AppManager(this); public appConnectionManager = new AppConnectionManager(this); public activityLogManager = new ActivityLogManager(this); + public userInvitationManager = new UserInvitationManager(this); housekeeping = new ReceptionHousekeeping(this); constructor(public options: IReceptionOptions) { diff --git a/ts/reception/classes.receptionmailer.ts b/ts/reception/classes.receptionmailer.ts index 71ed1c8..6210037 100644 --- a/ts/reception/classes.receptionmailer.ts +++ b/ts/reception/classes.receptionmailer.ts @@ -268,4 +268,33 @@ export class ReceptionMailer { `), }); } + + public sendInvitationEmail( + email: string, + organizationName: string, + invitationToken: string, + baseUrl: string + ) { + const invitationUrl = `${baseUrl}/invite?token=${encodeURI(invitationToken)}`; + + this.receptionRef.szPlatformClient.emailConnector.sendEmail({ + from: `idp.global@${this.receptionRef.options.baseUrl} `, + title: `You've been invited to join ${organizationName}`, + to: email, + body: this.createBodyString(` +

You're Invited!

+

You've been invited to join ${organizationName} on idp.global.

+

Click the button below to accept the invitation and join the organization.

+
+ Accept Invitation +
+

+ If you don't have an account yet, you'll be able to create one when you accept the invitation. +

+

+ This invitation will expire in 90 days. +

+ `), + }); + } } diff --git a/ts/reception/classes.rolemanager.ts b/ts/reception/classes.rolemanager.ts index 482f6ec..1fa56df 100644 --- a/ts/reception/classes.rolemanager.ts +++ b/ts/reception/classes.rolemanager.ts @@ -15,13 +15,24 @@ export class RoleManager { this.receptionRef = receptionRefArg; } + /** + * Create, change, or delete a role for a user in an organization. + * Supports both old single-role and new multi-role patterns. + */ public async modifyRoleForUserAtOrg(optionsArg: { action: 'create' | 'change' | 'delete'; userId: string; organizationId: string; - role: plugins.idpInterfaces.data.IRole['data']['role']; + /** @deprecated Use `roles` instead */ + role?: string; + /** Array of roles to assign */ + roles?: string[]; }) { let returnRole: Role; + + // Support both old single role and new roles array + const roles = optionsArg.roles || (optionsArg.role ? [optionsArg.role] : ['viewer']); + switch (optionsArg.action) { case 'create': returnRole = new this.CRole(); @@ -29,9 +40,35 @@ export class RoleManager { returnRole.data = { userId: optionsArg.userId, organizationId: optionsArg.organizationId, - role: optionsArg.role, + roles: roles, }; await returnRole.save(); + break; + + case 'change': + returnRole = await this.CRole.getInstance({ + data: { + userId: optionsArg.userId, + organizationId: optionsArg.organizationId, + }, + }); + if (returnRole) { + returnRole.data.roles = roles; + await returnRole.save(); + } + break; + + case 'delete': + returnRole = await this.CRole.getInstance({ + data: { + userId: optionsArg.userId, + organizationId: optionsArg.organizationId, + }, + }); + if (returnRole) { + await returnRole.delete(); + } + break; } return returnRole; } @@ -54,4 +91,13 @@ export class RoleManager { }); return roles; } + + public async getAllRolesForOrg(organizationId: string) { + const roles = await this.CRole.getInstances({ + data: { + organizationId: organizationId + } + }); + return roles; + } } diff --git a/ts/reception/classes.userinvitation.ts b/ts/reception/classes.userinvitation.ts new file mode 100644 index 0000000..0e91f02 --- /dev/null +++ b/ts/reception/classes.userinvitation.ts @@ -0,0 +1,136 @@ +import * as plugins from '../plugins.js'; + +/** + * UserInvitation represents an invitation to join one or more organizations. + * + * Key characteristics: + * - Unique by email (multiple orgs can share the same invitation) + * - Converts to real User on registration + * - Can fold into existing user if they add the email as secondary + * - Auto-expires after 90 days + */ +@plugins.smartdata.Manager() +export class UserInvitation extends plugins.smartdata.SmartDataDbDoc< + UserInvitation, + plugins.idpInterfaces.data.IUserInvitation +> { + // STATIC + public static readonly EXPIRY_DAYS = 90; + + public static generateToken(): string { + return plugins.smartunique.shortId() + '-' + plugins.smartunique.shortId(); + } + + public static async createNewInvitation( + email: string, + organizationId: string, + invitedByUserId: string, + roles: string[] + ): Promise { + const invitation = new UserInvitation(); + invitation.id = plugins.smartunique.shortId(); + const now = Date.now(); + const expiresAt = now + (UserInvitation.EXPIRY_DAYS * 24 * 60 * 60 * 1000); + + invitation.data = { + email: email.toLowerCase().trim(), + token: UserInvitation.generateToken(), + status: 'pending', + createdAt: now, + expiresAt: expiresAt, + organizationRefs: [{ + organizationId, + invitedByUserId, + invitedAt: now, + roles, + }], + }; + + await invitation.save(); + return invitation; + } + + // INSTANCE + @plugins.smartdata.unI() + id: string; + + @plugins.smartdata.svDb() + public data: plugins.idpInterfaces.data.IUserInvitation['data']; + + constructor() { + super(); + } + + /** + * Add another organization to this invitation + */ + public async addOrganization( + organizationId: string, + invitedByUserId: string, + roles: string[] + ): Promise { + // Check if org already exists + const existingRef = this.data.organizationRefs.find( + ref => ref.organizationId === organizationId + ); + + if (existingRef) { + // Update roles for existing org ref + existingRef.roles = roles; + existingRef.invitedAt = Date.now(); + existingRef.invitedByUserId = invitedByUserId; + } else { + // Add new org ref + this.data.organizationRefs.push({ + organizationId, + invitedByUserId, + invitedAt: Date.now(), + roles, + }); + } + + await this.save(); + } + + /** + * Remove an organization from this invitation + */ + public async removeOrganization(organizationId: string): Promise { + this.data.organizationRefs = this.data.organizationRefs.filter( + ref => ref.organizationId !== organizationId + ); + + // If no more org refs, cancel the invitation + if (this.data.organizationRefs.length === 0) { + this.data.status = 'cancelled'; + } + + await this.save(); + } + + /** + * Check if invitation is expired + */ + public isExpired(): boolean { + return Date.now() > this.data.expiresAt || this.data.status === 'expired'; + } + + /** + * Mark invitation as accepted and record the user ID + */ + public async accept(userId: string): Promise { + this.data.status = 'accepted'; + this.data.acceptedAt = Date.now(); + this.data.convertedToUserId = userId; + await this.save(); + } + + /** + * Regenerate token and extend expiry (for resend) + */ + public async regenerateToken(): Promise { + this.data.token = UserInvitation.generateToken(); + this.data.expiresAt = Date.now() + (UserInvitation.EXPIRY_DAYS * 24 * 60 * 60 * 1000); + await this.save(); + } +} diff --git a/ts/reception/classes.userinvitationmanager.ts b/ts/reception/classes.userinvitationmanager.ts new file mode 100644 index 0000000..badf759 --- /dev/null +++ b/ts/reception/classes.userinvitationmanager.ts @@ -0,0 +1,556 @@ +import * as plugins from '../plugins.js'; +import { Reception } from './classes.reception.js'; +import { UserInvitation } from './classes.userinvitation.js'; +import { Organization } from './classes.organization.js'; +import { User } from './classes.user.js'; +import { Role } from './classes.role.js'; + +export class UserInvitationManager { + public receptionRef: Reception; + public get db() { + return this.receptionRef.db.smartdataDb; + } + public typedrouter = new plugins.typedrequest.TypedRouter(); + + public CUserInvitation = plugins.smartdata.setDefaultManagerForDoc(this, UserInvitation); + + constructor(receptionRefArg: Reception) { + this.receptionRef = receptionRefArg; + this.receptionRef.typedrouter.addTypedRouter(this.typedrouter); + + this.setupHandlers(); + } + + private setupHandlers() { + // Create invitation + this.typedrouter.addTypedHandler( + new plugins.typedrequest.TypedHandler( + 'createInvitation', + async (requestArg) => { + const user = await this.receptionRef.userManager.getUserByJwtValidation(requestArg.jwt); + await this.verifyUserIsAdminOfOrg(user.id, requestArg.organizationId); + + const email = requestArg.email.toLowerCase().trim(); + + // Check if user with this email already exists + const existingUser = await this.receptionRef.userManager.CUser.getInstance({ + data: { email }, + }); + if (existingUser) { + // User already exists - just add them to the org directly + const existingRole = await this.receptionRef.roleManager.CRole.getInstance({ + data: { + userId: existingUser.id, + organizationId: requestArg.organizationId, + }, + }); + if (existingRole) { + return { + success: false, + isNew: false, + message: 'User is already a member of this organization.', + }; + } + // Add user to org with the specified roles + await this.receptionRef.roleManager.modifyRoleForUserAtOrg({ + action: 'create', + userId: existingUser.id, + organizationId: requestArg.organizationId, + roles: requestArg.roles, + }); + return { + success: true, + isNew: false, + message: 'Existing user has been added to the organization.', + }; + } + + // Check if invitation already exists for this email + let invitation = await this.CUserInvitation.getInstance({ + data: { email }, + }); + + let isNew = false; + if (invitation) { + // Add org to existing invitation + await invitation.addOrganization(requestArg.organizationId, user.id, requestArg.roles); + } else { + // Create new invitation + invitation = await UserInvitation.createNewInvitation( + email, + requestArg.organizationId, + user.id, + requestArg.roles + ); + isNew = true; + } + + // Send invitation email + await this.sendInvitationEmail(invitation, requestArg.organizationId); + + return { + success: true, + invitation: await invitation.createSavableObject(), + isNew, + }; + } + ) + ); + + // Get org invitations + this.typedrouter.addTypedHandler( + new plugins.typedrequest.TypedHandler( + 'getOrgInvitations', + async (requestArg) => { + const user = await this.receptionRef.userManager.getUserByJwtValidation(requestArg.jwt); + await this.verifyUserIsAdminOfOrg(user.id, requestArg.organizationId); + + const allInvitations = await this.CUserInvitation.getInstances({}); + const orgInvitations = allInvitations.filter(inv => + inv.data.status === 'pending' && + !inv.isExpired() && + inv.data.organizationRefs.some(ref => ref.organizationId === requestArg.organizationId) + ); + + return { + invitations: await Promise.all(orgInvitations.map(inv => inv.createSavableObject())), + }; + } + ) + ); + + // Get org members + this.typedrouter.addTypedHandler( + new plugins.typedrequest.TypedHandler( + 'getOrgMembers', + async (requestArg) => { + const user = await this.receptionRef.userManager.getUserByJwtValidation(requestArg.jwt); + await this.verifyUserIsMemberOfOrg(user.id, requestArg.organizationId); + + const roles = await this.receptionRef.roleManager.CRole.getInstances({ + data: { organizationId: requestArg.organizationId }, + }); + + const members: Array<{ + user: plugins.idpInterfaces.data.IUser; + role: plugins.idpInterfaces.data.IRole; + }> = []; + + for (const role of roles) { + const memberUser = await this.receptionRef.userManager.CUser.getInstance({ + id: role.data.userId, + }); + if (memberUser) { + members.push({ + user: await memberUser.createSavableObject(), + role: await role.createSavableObject(), + }); + } + } + + return { members }; + } + ) + ); + + // Cancel invitation + this.typedrouter.addTypedHandler( + new plugins.typedrequest.TypedHandler( + 'cancelInvitation', + async (requestArg) => { + const user = await this.receptionRef.userManager.getUserByJwtValidation(requestArg.jwt); + await this.verifyUserIsAdminOfOrg(user.id, requestArg.organizationId); + + const invitation = await this.CUserInvitation.getInstance({ id: requestArg.invitationId }); + if (!invitation) { + return { success: false, message: 'Invitation not found.' }; + } + + await invitation.removeOrganization(requestArg.organizationId); + + return { success: true }; + } + ) + ); + + // Resend invitation + this.typedrouter.addTypedHandler( + new plugins.typedrequest.TypedHandler( + 'resendInvitation', + async (requestArg) => { + const user = await this.receptionRef.userManager.getUserByJwtValidation(requestArg.jwt); + await this.verifyUserIsAdminOfOrg(user.id, requestArg.organizationId); + + const invitation = await this.CUserInvitation.getInstance({ id: requestArg.invitationId }); + if (!invitation) { + return { success: false, message: 'Invitation not found.' }; + } + + await invitation.regenerateToken(); + await this.sendInvitationEmail(invitation, requestArg.organizationId); + + return { success: true, message: 'Invitation resent.' }; + } + ) + ); + + // Remove member + this.typedrouter.addTypedHandler( + new plugins.typedrequest.TypedHandler( + 'removeMember', + async (requestArg) => { + const user = await this.receptionRef.userManager.getUserByJwtValidation(requestArg.jwt); + await this.verifyUserIsAdminOfOrg(user.id, requestArg.organizationId); + + // Cannot remove yourself if you're the only owner + const role = await this.receptionRef.roleManager.CRole.getInstance({ + data: { + userId: requestArg.userId, + organizationId: requestArg.organizationId, + }, + }); + + if (!role) { + return { success: false, message: 'Member not found.' }; + } + + // Check if trying to remove an owner + if (role.data.roles.includes('owner')) { + // Count owners + const allRoles = await this.receptionRef.roleManager.CRole.getInstances({ + data: { organizationId: requestArg.organizationId }, + }); + const ownerCount = allRoles.filter(r => r.data.roles.includes('owner')).length; + if (ownerCount <= 1) { + return { + success: false, + message: 'Cannot remove the last owner. Transfer ownership first.', + }; + } + } + + await role.delete(); + + // Remove org from user's connectedOrgs + const memberUser = await this.receptionRef.userManager.CUser.getInstance({ + id: requestArg.userId, + }); + if (memberUser && memberUser.data.connectedOrgs) { + memberUser.data.connectedOrgs = memberUser.data.connectedOrgs.filter( + orgId => orgId !== requestArg.organizationId + ); + await memberUser.save(); + } + + return { success: true }; + } + ) + ); + + // Update member roles + this.typedrouter.addTypedHandler( + new plugins.typedrequest.TypedHandler( + 'updateMemberRoles', + async (requestArg) => { + const user = await this.receptionRef.userManager.getUserByJwtValidation(requestArg.jwt); + await this.verifyUserIsAdminOfOrg(user.id, requestArg.organizationId); + + const role = await this.receptionRef.roleManager.CRole.getInstance({ + data: { + userId: requestArg.userId, + organizationId: requestArg.organizationId, + }, + }); + + if (!role) { + return { success: false, message: 'Member not found.' }; + } + + // If removing owner role, check we're not removing the last owner + if (role.data.roles.includes('owner') && !requestArg.roles.includes('owner')) { + const allRoles = await this.receptionRef.roleManager.CRole.getInstances({ + data: { organizationId: requestArg.organizationId }, + }); + const ownerCount = allRoles.filter(r => r.data.roles.includes('owner')).length; + if (ownerCount <= 1) { + return { + success: false, + message: 'Cannot remove owner role from the last owner.', + }; + } + } + + role.data.roles = requestArg.roles; + await role.save(); + + return { success: true, role: await role.createSavableObject() }; + } + ) + ); + + // Transfer ownership + this.typedrouter.addTypedHandler( + new plugins.typedrequest.TypedHandler( + 'transferOwnership', + async (requestArg) => { + const user = await this.receptionRef.userManager.getUserByJwtValidation(requestArg.jwt); + + // Verify current user is an owner + const currentUserRole = await this.receptionRef.roleManager.CRole.getInstance({ + data: { + userId: user.id, + organizationId: requestArg.organizationId, + }, + }); + if (!currentUserRole || !currentUserRole.data.roles.includes('owner')) { + throw new plugins.typedrequest.TypedResponseError( + 'Only owners can transfer ownership.' + ); + } + + // Get new owner's role + const newOwnerRole = await this.receptionRef.roleManager.CRole.getInstance({ + data: { + userId: requestArg.newOwnerId, + organizationId: requestArg.organizationId, + }, + }); + if (!newOwnerRole) { + return { success: false, message: 'New owner must be a member of the organization.' }; + } + + // Add owner role to new owner + if (!newOwnerRole.data.roles.includes('owner')) { + newOwnerRole.data.roles.push('owner'); + await newOwnerRole.save(); + } + + // Remove owner role from current user (but keep other roles) + currentUserRole.data.roles = currentUserRole.data.roles.filter(r => r !== 'owner'); + if (currentUserRole.data.roles.length === 0) { + currentUserRole.data.roles = ['admin']; // Demote to admin + } + await currentUserRole.save(); + + return { success: true }; + } + ) + ); + + // Get invitation by token + this.typedrouter.addTypedHandler( + new plugins.typedrequest.TypedHandler( + 'getInvitationByToken', + async (requestArg) => { + const invitation = await this.CUserInvitation.getInstance({ + data: { token: requestArg.token }, + }); + + if (!invitation) { + return { isExpired: true, requiresRegistration: false }; + } + + if (invitation.isExpired()) { + return { isExpired: true, requiresRegistration: false }; + } + + // Get organization names + const organizations: Array<{ id: string; name: string }> = []; + for (const ref of invitation.data.organizationRefs) { + const org = await this.receptionRef.organizationmanager.COrganization.getInstance({ + id: ref.organizationId, + }); + if (org) { + organizations.push({ id: org.id, name: org.data.name }); + } + } + + // Check if user with this email exists + const existingUser = await this.receptionRef.userManager.CUser.getInstance({ + data: { email: invitation.data.email }, + }); + + return { + invitation: await invitation.createSavableObject(), + organizations, + isExpired: false, + requiresRegistration: !existingUser, + }; + } + ) + ); + + // Accept invitation + this.typedrouter.addTypedHandler( + new plugins.typedrequest.TypedHandler( + 'acceptInvitation', + async (requestArg) => { + const invitation = await this.CUserInvitation.getInstance({ + data: { token: requestArg.token }, + }); + + if (!invitation) { + return { success: false, message: 'Invalid invitation token.' }; + } + + if (invitation.isExpired()) { + return { success: false, message: 'This invitation has expired.' }; + } + + const user = await this.receptionRef.userManager.CUser.getInstance({ + id: requestArg.userId, + }); + if (!user) { + return { success: false, message: 'User not found.' }; + } + + // Create roles for each organization + const organizations: plugins.idpInterfaces.data.IOrganization[] = []; + const roles: plugins.idpInterfaces.data.IRole[] = []; + + for (const ref of invitation.data.organizationRefs) { + // Check if role already exists + let role = await this.receptionRef.roleManager.CRole.getInstance({ + data: { + userId: user.id, + organizationId: ref.organizationId, + }, + }); + + if (!role) { + role = await this.receptionRef.roleManager.modifyRoleForUserAtOrg({ + action: 'create', + userId: user.id, + organizationId: ref.organizationId, + roles: ref.roles, + }); + } + + roles.push(await role.createSavableObject()); + + const org = await this.receptionRef.organizationmanager.COrganization.getInstance({ + id: ref.organizationId, + }); + if (org) { + // Add role to org's roleIds if not already there + if (!org.data.roleIds.includes(role.id)) { + org.data.roleIds.push(role.id); + await org.save(); + } + organizations.push(await org.createSavableObject()); + } + + // Update user's connectedOrgs + if (!user.data.connectedOrgs) { + user.data.connectedOrgs = []; + } + if (!user.data.connectedOrgs.includes(ref.organizationId)) { + user.data.connectedOrgs.push(ref.organizationId); + } + } + + await user.save(); + await invitation.accept(user.id); + + return { success: true, organizations, roles }; + } + ) + ); + } + + /** + * Find invitation by email + */ + public async getInvitationByEmail(email: string): Promise { + return this.CUserInvitation.getInstance({ + data: { email: email.toLowerCase().trim() }, + }); + } + + /** + * Get pending invitations for an email (for registration flow) + */ + public async getPendingInvitationsForEmail(email: string): Promise { + const invitation = await this.getInvitationByEmail(email); + if (invitation && invitation.data.status === 'pending' && !invitation.isExpired()) { + return invitation; + } + return null; + } + + /** + * Clean up expired invitations + */ + public async cleanupExpiredInvitations(): Promise { + const allInvitations = await this.CUserInvitation.getInstances({ + data: { status: 'pending' }, + }); + + let cleanedCount = 0; + for (const invitation of allInvitations) { + if (invitation.isExpired()) { + invitation.data.status = 'expired'; + await invitation.save(); + cleanedCount++; + } + } + + return cleanedCount; + } + + /** + * Send invitation email + */ + private async sendInvitationEmail( + invitation: UserInvitation, + organizationId: string + ): Promise { + const org = await this.receptionRef.organizationmanager.COrganization.getInstance({ + id: organizationId, + }); + const orgName = org?.data.name || 'an organization'; + + await this.receptionRef.receptionMailer.sendInvitationEmail( + invitation.data.email, + orgName, + invitation.data.token, + this.receptionRef.options.baseUrl + ); + } + + /** + * Verify user is admin/owner of organization + */ + private async verifyUserIsAdminOfOrg(userId: string, organizationId: string): Promise { + const role = await this.receptionRef.roleManager.CRole.getInstance({ + data: { userId, organizationId }, + }); + + if (!role) { + throw new plugins.typedrequest.TypedResponseError('Not a member of this organization.'); + } + + const hasAdminRole = role.data.roles.some(r => + ['owner', 'admin'].includes(r) + ); + + if (!hasAdminRole) { + throw new plugins.typedrequest.TypedResponseError( + 'You do not have permission to perform this action.' + ); + } + } + + /** + * Verify user is member of organization + */ + private async verifyUserIsMemberOfOrg(userId: string, organizationId: string): Promise { + const role = await this.receptionRef.roleManager.CRole.getInstance({ + data: { userId, organizationId }, + }); + + if (!role) { + throw new plugins.typedrequest.TypedResponseError('Not a member of this organization.'); + } + } +} diff --git a/ts_web/elements/account/content.ts b/ts_web/elements/account/content.ts index d83d29b..ce1ba3d 100644 --- a/ts_web/elements/account/content.ts +++ b/ts_web/elements/account/content.ts @@ -180,6 +180,16 @@ export class IdpAccountContent extends DeesElement { await this.domtools.convenience.smartdelay.delayFor(300); }); + this.subrouter.on('/org/:orgName/users', async () => { + viewcontainer.classList.add('changing'); + await this.domtools.convenience.smartdelay.delayFor(300); + console.log('We are viewing the users page'); + await cleanupViews(); + viewcontainer.append(new views.UsersView()); + viewcontainer.classList.remove('changing'); + await this.domtools.convenience.smartdelay.delayFor(300); + }); + this.subrouter.on('/admin', async () => { viewcontainer.classList.add('changing'); await this.domtools.convenience.smartdelay.delayFor(300); diff --git a/ts_web/elements/account/navigation.ts b/ts_web/elements/account/navigation.ts index 825afc4..8d3088c 100644 --- a/ts_web/elements/account/navigation.ts +++ b/ts_web/elements/account/navigation.ts @@ -279,8 +279,8 @@ export class LeleAccountNavigation extends DeesElement { Apps