diff --git a/.env.example b/.env.example index ce9df51..e0cf2e1 100644 --- a/.env.example +++ b/.env.example @@ -1,10 +1,10 @@ # --- Container images --- -# Published to GHCR by .github/workflows/release.yml, multi-architecture +# Published to the Gitea registry by .gitea/workflows/release.yml, multi-architecture # (linux/amd64 and linux/arm64). The deploy host pulls these instead of # compiling: `docker compose pull && docker compose up -d`. Running # `docker compose build` locally still overrides them with a local build. # Pin IMAGE_TAG to a released version (e.g. 1.2.3) or a sha- tag to roll back. -IMAGE_NAMESPACE=ghcr.io/lucasrguerra/lambdamail +IMAGE_NAMESPACE=git.lucasrguerra.dev.br/lucasrguerra/lambdamail IMAGE_TAG=latest # --- Postgres --- diff --git a/.env.production.example b/.env.production.example index 4157295..6d3f0e3 100644 --- a/.env.production.example +++ b/.env.production.example @@ -10,9 +10,9 @@ # and must be URL-safe - see the note above them. # --- Container images ------------------------------------------------------- -# Published by .github/workflows/release.yml for linux/amd64 and linux/arm64. +# Published by .gitea/workflows/release.yml for linux/amd64 and linux/arm64. # Pin IMAGE_TAG to a released version or a sha- tag to roll back. -IMAGE_NAMESPACE=ghcr.io/lucasrguerra/lambdamail +IMAGE_NAMESPACE=git.lucasrguerra.dev.br/lucasrguerra/lambdamail IMAGE_TAG=latest # --- Identity --------------------------------------------------------------- diff --git a/.github/workflows/ci.yml b/.gitea/workflows/ci.yml similarity index 70% rename from .github/workflows/ci.yml rename to .gitea/workflows/ci.yml index a7a5438..053d5b3 100644 --- a/.github/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -15,7 +15,7 @@ on: workflow_call: concurrency: - group: ci-${{ github.ref }} + group: ci-${{ gitea.ref }} cancel-in-progress: true jobs: @@ -57,16 +57,30 @@ jobs: cache-dependency-path: services/protocols/go.sum - name: Run migrations run: | - docker run --rm --network host \ - -v "$(pwd)/../../migrations:/migrations" \ - migrate/migrate:v4.17.1 \ + # The job's workspace is a volume of its own, invisible to the Docker + # daemon the job talks to, so `-v "$PWD:..."` would mount an empty + # directory. Files are copied into the container instead. + cid=$(docker create --network host migrate/migrate:v4.17.1 \ -path=/migrations \ -database "postgres://lambdamail_test:lambdamail_test@localhost:5432/lambdamail_test?sslmode=disable" \ - up + up) + docker cp "$(pwd)/../../migrations/." "$cid:/migrations" + docker start -a "$cid" + status=$(docker inspect -f '{{.State.ExitCode}}' "$cid") + docker rm "$cid" >/dev/null + exit "$status" - run: go vet ./... - - run: go test ./... -v + # The end-to-end suites start an embedded Postgres, and initdb refuses to + # run as root, which is what a job container is. Run the tests as a + # throwaway unprivileged user (GitHub's hosted runners already are one). + - name: Testes env: TEST_DATABASE_URL: postgres://lambdamail_test:lambdamail_test@localhost:5432/lambdamail_test?sslmode=disable + run: | + id tester >/dev/null 2>&1 || useradd -m -u 1001 tester + chown -R tester:tester "$GITHUB_WORKSPACE" + runuser -u tester -- env "HOME=/home/tester" "PATH=$PATH" \ + "TEST_DATABASE_URL=$TEST_DATABASE_URL" go test ./... -v ts-auth: name: TypeScript (auth) @@ -97,12 +111,18 @@ jobs: # the database, so a mock would prove nothing. - name: Run migrations run: | - docker run --rm --network host \ - -v "$(pwd)/../../migrations:/migrations" \ - migrate/migrate:v4.17.1 \ + # The job's workspace is a volume of its own, invisible to the Docker + # daemon the job talks to, so `-v "$PWD:..."` would mount an empty + # directory. Files are copied into the container instead. + cid=$(docker create --network host migrate/migrate:v4.17.1 \ -path=/migrations \ -database "postgres://lambdamail_test:lambdamail_test@localhost:5432/lambdamail_test?sslmode=disable" \ - up + up) + docker cp "$(pwd)/../../migrations/." "$cid:/migrations" + docker start -a "$cid" + status=$(docker inspect -f '{{.State.ExitCode}}' "$cid") + docker rm "$cid" >/dev/null + exit "$status" - run: npm install - run: npm run lint - run: npm test @@ -148,14 +168,20 @@ jobs: # A mail server holds credentials for every mailbox it serves, so the # secret scanner matters as much as the vulnerability one here: a DKIM # key or a Cloudflare token committed by accident is a full compromise. + # + # Trivy runs from its official image rather than aquasecurity/trivy-action: + # that action clones the Trivy repository from the workflow's own server, + # which on Gitea is not GitHub. - name: Repositório - uses: aquasecurity/trivy-action@v0.36.0 - with: - scan-type: fs - scanners: vuln,secret,misconfig - severity: HIGH,CRITICAL - exit-code: '1' - skip-dirs: services/auth/node_modules,services/storage/node_modules,services/webmail/node_modules,services/webmail/.next + run: | + cid=$(docker create --network host -w /src aquasec/trivy:0.70.0 \ + fs --scanners vuln,secret,misconfig --severity HIGH,CRITICAL --exit-code 1 \ + --skip-dirs services/auth/node_modules,services/storage/node_modules,services/webmail/node_modules,services/webmail/.next .) + docker cp . "$cid:/src" + docker start -a "$cid" + status=$(docker inspect -f '{{.State.ExitCode}}' "$cid") + docker rm "$cid" >/dev/null + exit "$status" # MEDIUM is reported but does not fail the build. # @@ -168,13 +194,15 @@ jobs: # Reporting rather than gating, because failing on every MEDIUM makes the # scanner something people learn to skip. - name: Repositório (MEDIUM, informativo) - uses: aquasecurity/trivy-action@v0.36.0 - with: - scan-type: fs - scanners: vuln,secret - severity: MEDIUM - exit-code: '0' - skip-dirs: services/auth/node_modules,services/storage/node_modules,services/webmail/node_modules,services/webmail/.next + run: | + cid=$(docker create --network host -w /src aquasec/trivy:0.70.0 \ + fs --scanners vuln,secret --severity MEDIUM --exit-code 0 \ + --skip-dirs services/auth/node_modules,services/storage/node_modules,services/webmail/node_modules,services/webmail/.next .) + docker cp . "$cid:/src" + docker start -a "$cid" + status=$(docker inspect -f '{{.State.ExitCode}}' "$cid") + docker rm "$cid" >/dev/null + exit "$status" image: name: Imagem (${{ matrix.service }}) @@ -198,8 +226,6 @@ jobs: push: false load: true tags: lambdamail-${{ matrix.service }}:ci - cache-from: type=gha,scope=${{ matrix.service }} - cache-to: type=gha,mode=max,scope=${{ matrix.service }} # Scanned only for the images whose contents we author. migrations and # rspamd add .sql and .conf files to an upstream image and nothing else, @@ -209,11 +235,9 @@ jobs: # that their base images have to be watched. - name: Trivy na imagem if: matrix.service != 'migrations' && matrix.service != 'rspamd' - uses: aquasecurity/trivy-action@v0.36.0 - with: - image-ref: lambdamail-${{ matrix.service }}:ci - severity: HIGH,CRITICAL - exit-code: '1' + run: | + docker run --rm --network host -e DOCKER_HOST=tcp://127.0.0.1:2375 aquasec/trivy:0.70.0 \ + image --severity HIGH,CRITICAL --exit-code 1 lambdamail-${{ matrix.service }}:ci compose-up: name: Stack completa diff --git a/.github/workflows/release.yml b/.gitea/workflows/release.yml similarity index 65% rename from .github/workflows/release.yml rename to .gitea/workflows/release.yml index 2f04576..995e1cd 100644 --- a/.github/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -1,8 +1,9 @@ name: Release -# Publishes the four service images to GHCR after a merge into main, and again -# under semver tags when a v* tag is pushed. The deploy host only pulls, so -# nothing has to be built on the server. +# Publishes the service images to the Gitea container registry after a merge +# into main, and again under semver tags when a v* tag is pushed. The deploy +# host only pulls, so nothing has to be built on the server. Needs the user +# secret REGISTRY_TOKEN (a Gitea token with the write:package scope). on: push: branches: [main] @@ -14,15 +15,15 @@ concurrency: cancel-in-progress: false env: - REGISTRY: ghcr.io + REGISTRY: git.lucasrguerra.dev.br jobs: # Nothing is published unless the full suite passes first. ci: - uses: ./.github/workflows/ci.yml + uses: ./.gitea/workflows/ci.yml - # GHCR rejects an uppercase path, and this repository is "lucasrguerra/LambdaMail". - # Lowercasing github.repository here keeps the workflow fork-safe instead of + # Registry paths must be lowercase, and this repository is "lucasrguerra/LambdaMail". + # Lowercasing gitea.repository here keeps the workflow fork-safe instead of # hardcoding the owner. prepare: name: Namespace das imagens @@ -31,7 +32,10 @@ jobs: namespace: ${{ steps.namespace.outputs.value }} steps: - id: namespace - run: echo "value=${GITHUB_REPOSITORY,,}" >> "$GITHUB_OUTPUT" + # GITHUB_OUTPUT is the runner's own interface: Gitea sets it under that name. + run: | + repo='${{ gitea.repository }}' + echo "value=${repo,,}" >> "$GITHUB_OUTPUT" # Each architecture is built on a runner of its own kind. QEMU emulation # would also work, but it makes the Go and Next builds roughly an order of @@ -54,7 +58,7 @@ jobs: platform: [linux/amd64, linux/arm64] include: - platform: linux/amd64 - runner: ubuntu-latest + runner: linux-amd64 arch: amd64 - platform: linux/arm64 runner: ubuntu-24.04-arm @@ -62,14 +66,19 @@ jobs: steps: - uses: actions/checkout@v7 + # The only runner is arm64; linux/amd64 is built under QEMU emulation + # (label linux-amd64 points at the same runner), so it is slower. + - uses: docker/setup-qemu-action@v3 + if: matrix.arch == 'amd64' + - uses: docker/setup-buildx-action@v4 - - name: Autentica no GHCR + - name: Autentica no registro uses: docker/login-action@v4 with: registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + username: ${{ gitea.actor }} + password: ${{ secrets.REGISTRY_TOKEN }} - name: Metadados id: meta @@ -77,9 +86,10 @@ jobs: with: images: ${{ env.REGISTRY }}/${{ needs.prepare.outputs.namespace }}/${{ matrix.service }} - # Pushed by digest only: the tags are attached later, once both - # architectures exist and can be joined into a single manifest list. - - name: Build e push por digest + # Each architecture is pushed under its own tag (no digest artifacts: they + # are not portable to Gitea). The final tags are attached later, once both + # exist and can be joined into a single manifest list. + - name: Build e push por arquitetura id: build uses: docker/build-push-action@v7 with: @@ -87,26 +97,10 @@ jobs: file: services/${{ matrix.service }}/Dockerfile platforms: ${{ matrix.platform }} labels: ${{ steps.meta.outputs.labels }} - outputs: type=image,name=${{ env.REGISTRY }}/${{ needs.prepare.outputs.namespace }}/${{ matrix.service }},push-by-digest=true,name-canonical=true,push=true - cache-from: type=gha,scope=${{ matrix.service }}-${{ matrix.arch }} - cache-to: type=gha,mode=max,scope=${{ matrix.service }}-${{ matrix.arch }} - - - name: Exporta o digest - run: | - mkdir -p /tmp/digests - # The output already carries the `sha256:` prefix; the file name must - # not, since the merge step prepends it again. - digest='${{ steps.build.outputs.digest }}' - touch "/tmp/digests/${digest#sha256:}" - - - name: Guarda o digest - uses: actions/upload-artifact@v7 - with: - # Slashes are not allowed in artifact names, hence the arch alias. - name: digest-${{ matrix.service }}-${{ matrix.arch }} - path: /tmp/digests/* - retention-days: 1 - if-no-files-found: error + push: true + tags: ${{ env.REGISTRY }}/${{ needs.prepare.outputs.namespace }}/${{ matrix.service }}:build-${{ gitea.sha }}-${{ matrix.arch }} + cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ needs.prepare.outputs.namespace }}/${{ matrix.service }}:buildcache-${{ matrix.arch }} + cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ needs.prepare.outputs.namespace }}/${{ matrix.service }}:buildcache-${{ matrix.arch }},mode=max publish: name: Publica ${{ matrix.service }} @@ -124,19 +118,12 @@ jobs: - uses: docker/setup-buildx-action@v4 - - name: Autentica no GHCR + - name: Autentica no registro uses: docker/login-action@v4 with: registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Recupera os digests - uses: actions/download-artifact@v7 - with: - pattern: digest-${{ matrix.service }}-* - merge-multiple: true - path: /tmp/digests + username: ${{ gitea.actor }} + password: ${{ secrets.REGISTRY_TOKEN }} # `latest` is what compose pulls. The semver tags only materialise on a # v* tag push and make it possible to pin or roll back to an exact @@ -156,11 +143,11 @@ jobs: # Joins both architectures under one manifest list, so `docker pull` # resolves to the right one automatically. - name: Cria o manifesto multi-arquitetura - working-directory: /tmp/digests run: | + image='${{ env.REGISTRY }}/${{ needs.prepare.outputs.namespace }}/${{ matrix.service }}' docker buildx imagetools create \ $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< '${{ steps.meta.outputs.json }}') \ - $(printf '${{ env.REGISTRY }}/${{ needs.prepare.outputs.namespace }}/${{ matrix.service }}@sha256:%s ' *) + "$image:build-${{ gitea.sha }}-amd64" "$image:build-${{ gitea.sha }}-arm64" - name: Confere o resultado run: | diff --git a/docker-compose.yaml b/docker-compose.yaml index 2a0e2a8..a450802 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -60,7 +60,7 @@ services: # probe - a health check on a container that is meant to stop would report # unhealthy exactly when it has done its job. migrate: - image: ${IMAGE_NAMESPACE:-ghcr.io/lucasrguerra/lambdamail}/migrations:${IMAGE_TAG:-latest} + image: ${IMAGE_NAMESPACE:-git.lucasrguerra.dev.br/lucasrguerra/lambdamail}/migrations:${IMAGE_TAG:-latest} # "latest" is a moving tag and Docker considers a tag it already holds # locally to be satisfied, so recreating this container silently reused # the cached image and the newly published one was never fetched: the @@ -80,7 +80,7 @@ services: # ------------------------------------------------------------ RSPAMD rspamd: - image: ${IMAGE_NAMESPACE:-ghcr.io/lucasrguerra/lambdamail}/rspamd:${IMAGE_TAG:-latest} + image: ${IMAGE_NAMESPACE:-git.lucasrguerra.dev.br/lucasrguerra/lambdamail}/rspamd:${IMAGE_TAG:-latest} # "latest" is a moving tag and Docker considers a tag it already holds # locally to be satisfied, so recreating this container silently reused # the cached image and the newly published one was never fetched: the @@ -140,7 +140,7 @@ services: # -------------------------------------------------------------- AUTH auth: - image: ${IMAGE_NAMESPACE:-ghcr.io/lucasrguerra/lambdamail}/auth:${IMAGE_TAG:-latest} + image: ${IMAGE_NAMESPACE:-git.lucasrguerra.dev.br/lucasrguerra/lambdamail}/auth:${IMAGE_TAG:-latest} # "latest" is a moving tag and Docker considers a tag it already holds # locally to be satisfied, so recreating this container silently reused # the cached image and the newly published one was never fetched: the @@ -178,7 +178,7 @@ services: # ----------------------------------------------------------- STORAGE storage: - image: ${IMAGE_NAMESPACE:-ghcr.io/lucasrguerra/lambdamail}/storage:${IMAGE_TAG:-latest} + image: ${IMAGE_NAMESPACE:-git.lucasrguerra.dev.br/lucasrguerra/lambdamail}/storage:${IMAGE_TAG:-latest} # "latest" is a moving tag and Docker considers a tag it already holds # locally to be satisfied, so recreating this container silently reused # the cached image and the newly published one was never fetched: the @@ -214,7 +214,7 @@ services: # --------------------------------------------------------- PROTOCOLS protocols: - image: ${IMAGE_NAMESPACE:-ghcr.io/lucasrguerra/lambdamail}/protocols:${IMAGE_TAG:-latest} + image: ${IMAGE_NAMESPACE:-git.lucasrguerra.dev.br/lucasrguerra/lambdamail}/protocols:${IMAGE_TAG:-latest} # "latest" is a moving tag and Docker considers a tag it already holds # locally to be satisfied, so recreating this container silently reused # the cached image and the newly published one was never fetched: the @@ -297,7 +297,7 @@ services: # -------------------------------------------------------------- WEB web: - image: ${IMAGE_NAMESPACE:-ghcr.io/lucasrguerra/lambdamail}/webmail:${IMAGE_TAG:-latest} + image: ${IMAGE_NAMESPACE:-git.lucasrguerra.dev.br/lucasrguerra/lambdamail}/webmail:${IMAGE_TAG:-latest} # "latest" is a moving tag and Docker considers a tag it already holds # locally to be satisfied, so recreating this container silently reused # the cached image and the newly published one was never fetched: the diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md index c43357f..7b4d411 100644 --- a/docs/DEPLOYMENT.md +++ b/docs/DEPLOYMENT.md @@ -176,7 +176,7 @@ have propagated and the IP has some sending history. ## Upgrading -Images are published to GHCR for `linux/amd64` and `linux/arm64` on every merge +Images are published to the Gitea container registry for `linux/amd64` and `linux/arm64` on every merge to `main`. ```bash @@ -198,7 +198,7 @@ every release, which is what forces the pull. IMAGE_TAG=sha- The tags are published by `release.yml`; `docker buildx imagetools inspect -ghcr.io//lambdamail/webmail:latest` shows what `latest` currently points +git.lucasrguerra.dev.br//lambdamail/webmail:latest` shows what `latest` currently points at. **Pinning has a second edge: bump it on every release.** A pinned tag is an diff --git a/services/auth/vitest.config.ts b/services/auth/vitest.config.ts index 2c76e30..2075bce 100644 --- a/services/auth/vitest.config.ts +++ b/services/auth/vitest.config.ts @@ -2,6 +2,10 @@ import { defineConfig } from "vitest/config"; export default defineConfig({ test: { + // Real Argon2id hashes cost 1-3s each on a shared CI runner, and several + // tests chain a dozen of them. The production cost parameters stay as they + // are; the default 5s budget is what does not fit. + testTimeout: 30_000, // session.ts refuses to load without a real signing secret, and ESM hoists // imports - so the value has to exist before any test file is evaluated, // which an assignment inside a test file cannot guarantee. diff --git a/services/protocols/go.mod b/services/protocols/go.mod index cce3375..8da4aad 100644 --- a/services/protocols/go.mod +++ b/services/protocols/go.mod @@ -21,7 +21,7 @@ require ( require ( github.com/cenkalti/backoff/v5 v5.0.3 // indirect - github.com/go-jose/go-jose/v4 v4.1.4 // indirect + github.com/go-jose/go-jose/v4 v4.1.6 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect diff --git a/services/protocols/go.sum b/services/protocols/go.sum index 20d04b2..0b30d33 100644 --- a/services/protocols/go.sum +++ b/services/protocols/go.sum @@ -23,8 +23,8 @@ github.com/fergusstrange/embedded-postgres v1.30.0 h1:ewv1e6bBlqOIYtgGgRcEnNDpfG github.com/fergusstrange/embedded-postgres v1.30.0/go.mod h1:w0YvnCgf19o6tskInrOOACtnqfVlOvluz3hlNLY7tRk= github.com/go-acme/lego/v4 v4.35.2 h1:uVQg+KC/yj9R2g7Q9W5wDqhvQvxV5SMu5eqFVoN5xZU= github.com/go-acme/lego/v4 v4.35.2/go.mod h1:pX2jN5n8OphMGY1IaMjYm5DAEzguBaKRt8AvJAgJXpc= -github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= -github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= +github.com/go-jose/go-jose/v4 v4.1.6 h1:sNRkftxFJxwsILiQukqp5z83QBSmntVwmgRY7AqBDO4= +github.com/go-jose/go-jose/v4 v4.1.6/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= diff --git a/services/webmail/package-lock.json b/services/webmail/package-lock.json index 53f0856..472a32f 100644 --- a/services/webmail/package-lock.json +++ b/services/webmail/package-lock.json @@ -14,7 +14,7 @@ "framer-motion": "^11.18.2", "imagetracerjs": "1.2.6", "lucide-react": "^0.474.0", - "next": "15.5.27", + "next": "15.5.28", "qrcode-generator": "^2.0.4", "react": "^18.3.1", "react-dom": "^18.3.1", @@ -1334,15 +1334,15 @@ } }, "node_modules/@next/env": { - "version": "15.5.27", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.27.tgz", - "integrity": "sha512-WC5hvVqiuFOcRyz6gKPeJkiVvSMf3scNeAV49CdWtVqxmUlzh8UKR6YHt9yiNkh8LngtzqSlVz07/Ma3ZAzchA==", + "version": "15.5.28", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.28.tgz", + "integrity": "sha512-xxW5EBI8fMPuVTPBW7LL980IRbuDXlbkUAwp9DDhtb4Lnich3nJ13uYpvrX4VE74hWPf6AvHHAMmGCidcHjbfg==", "license": "MIT" }, "node_modules/@next/swc-darwin-arm64": { - "version": "15.5.27", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.27.tgz", - "integrity": "sha512-fBA9QurmK4+uj4wNhmRTuO5zMVRaBHCvp6H93zTG/5i6Yi6TewbvbesXB8YQNj8T99Cwrow87hHiFV6wL/hyMA==", + "version": "15.5.28", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.28.tgz", + "integrity": "sha512-dPoQYXcfSIqx5o+TOXVXO7kONK5qbtNRDeiTfII0bT3puGIT6VF5e0QwmxNZfEZ5Zety5f3m9P/p4xqwfiLlPg==", "cpu": [ "arm64" ], @@ -1356,9 +1356,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "15.5.27", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.27.tgz", - "integrity": "sha512-FGZwJwry8qZNHxD/nfwrCwCHHrqx6epqItkkxbYcBQEQ2uw5S43bY83fQB5zbAsZE7TELMjoYkbhsQ4oKM7wwg==", + "version": "15.5.28", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.28.tgz", + "integrity": "sha512-RgCJ7buBivTH+6sddqaVm+/v8kwMHlFkobvdt3DfETutws5HrxnToMIWSN9X3MZ3aAi7BbKrGZZWUDQLEycXqw==", "cpu": [ "x64" ], @@ -1372,9 +1372,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "15.5.27", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.27.tgz", - "integrity": "sha512-GQulAaJYNF1RYuatlsw9/uzbKz4if2V7Ic9nVO+P0ljYPm4yBRTFIl6g5YkKTw40lMLbpy9edLoH44g3jSHMYA==", + "version": "15.5.28", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.28.tgz", + "integrity": "sha512-OHXQe13olE59aKe++zHavGcJPh5SLHXi6Anret3BBeq1+qhSuOJDNAli/EDDfxs6UTqA4Qddo4uyYry2slyjiQ==", "cpu": [ "arm64" ], @@ -1391,9 +1391,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "15.5.27", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.27.tgz", - "integrity": "sha512-URFFsUmu8Pi0/1qdnUI7tx7keZw1Mt5zHfrIX1RfDG9Nih8DYxK54WZsDJUX2ZTlii1jgotL7qcbwKnSAES6xQ==", + "version": "15.5.28", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.28.tgz", + "integrity": "sha512-nTB7bB6vfn4ezCJNYP43ukt2o8L3+WxKF/sTcTxepdXsJh3SM9RhlU7wrZYbH7L4HO5M87dqDTwm8587vAkCiw==", "cpu": [ "arm64" ], @@ -1410,9 +1410,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "15.5.27", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.27.tgz", - "integrity": "sha512-aJp74z7uvU5jQhyH7lyk+4qSRcTdKbKT9NQE3jiO9kWYkoHZjKi0zzHDbCoZ+v2sJDEiJ/z58R0UlWMGWNF3HA==", + "version": "15.5.28", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.28.tgz", + "integrity": "sha512-WXCfVI32rW3xCusoUX1RpZKtyChWU2Zwe27JUDmM3KrXwcDNc9vV4zEq0GKFAURnuQ/Ouo/XqPvB0yh445XZCg==", "cpu": [ "x64" ], @@ -1429,9 +1429,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "15.5.27", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.27.tgz", - "integrity": "sha512-ILl2bQ8MbpvyMpY8AXljb3BXs0MJSC8HXZ6QV5AWpVS7ZELqNPtrHvhUk+SNarvjvICXX8bCS287TCi+gUFVYg==", + "version": "15.5.28", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.28.tgz", + "integrity": "sha512-Miq+NDb/HWsXuxseYxMM6fuEOQXgTziarkKIRpVKCn8W69cEfhQaQr+90pO+u4q2CbJR2wzXmUuCFyZaJs/Nng==", "cpu": [ "x64" ], @@ -1448,9 +1448,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "15.5.27", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.27.tgz", - "integrity": "sha512-1MB9Rh5y8TOPN2x7naNTJNkCZQav9c70AI7EBYXxsEewwOffC4DjjwBwKf20NBvcA+u+5jDv7nVmHxunlP2d7Q==", + "version": "15.5.28", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.28.tgz", + "integrity": "sha512-5LR79lemgDlgxvG7MQJ+zHCkVcrUoQuO7CiIvq3I58vNW4goSOE2b+19Z6FujRWMouvni4gvudYFuFuNxolGWA==", "cpu": [ "arm64" ], @@ -1464,9 +1464,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "15.5.27", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.27.tgz", - "integrity": "sha512-XtYgpGOswgnyBWXzOEG6q9RhvnSw0CEZ0MbWqCsl5PISgt9EzvJvNW5mU5n1PsphX/lnamzxjgQXH2GUJL8nqg==", + "version": "15.5.28", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.28.tgz", + "integrity": "sha512-GNipvXUYROSTf4PXEyH95FrWImIB5zdaK6uEOg0RP1/X2drnvoMwiBkJ0VWdzX7w3iiBm3y5g2TxkKDGVTOQcg==", "cpu": [ "x64" ], @@ -3016,12 +3016,12 @@ } }, "node_modules/next": { - "version": "15.5.27", - "resolved": "https://registry.npmjs.org/next/-/next-15.5.27.tgz", - "integrity": "sha512-F82CrlPZ8GRxBH9RIIoR3qU1t5RT3dv1K8moe8SjlDEquiFipvEI13R1Om90TaUOEwShkWCMlg8+gvTNzfMhvg==", + "version": "15.5.28", + "resolved": "https://registry.npmjs.org/next/-/next-15.5.28.tgz", + "integrity": "sha512-JjhLBBY1PNnuwPtcZ7t8yxVeJVYvD2Jyp633J+gRCNbzSt7N0E+xqCf6uQiff3+3qmUkwcF/ksfSsK1xsZ76Tw==", "license": "MIT", "dependencies": { - "@next/env": "15.5.27", + "@next/env": "15.5.28", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", @@ -3034,15 +3034,15 @@ "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "15.5.27", - "@next/swc-darwin-x64": "15.5.27", - "@next/swc-linux-arm64-gnu": "15.5.27", - "@next/swc-linux-arm64-musl": "15.5.27", - "@next/swc-linux-x64-gnu": "15.5.27", - "@next/swc-linux-x64-musl": "15.5.27", - "@next/swc-win32-arm64-msvc": "15.5.27", - "@next/swc-win32-x64-msvc": "15.5.27", - "sharp": "^0.34.3 || ^0.35.4" + "@next/swc-darwin-arm64": "15.5.28", + "@next/swc-darwin-x64": "15.5.28", + "@next/swc-linux-arm64-gnu": "15.5.28", + "@next/swc-linux-arm64-musl": "15.5.28", + "@next/swc-linux-x64-gnu": "15.5.28", + "@next/swc-linux-x64-musl": "15.5.28", + "@next/swc-win32-arm64-msvc": "15.5.28", + "@next/swc-win32-x64-msvc": "15.5.28", + "sharp": "^0.34.3 || ^0.35.5" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", diff --git a/services/webmail/package.json b/services/webmail/package.json index ab4be0a..668f513 100644 --- a/services/webmail/package.json +++ b/services/webmail/package.json @@ -16,7 +16,7 @@ "framer-motion": "^11.18.2", "imagetracerjs": "1.2.6", "lucide-react": "^0.474.0", - "next": "15.5.27", + "next": "15.5.28", "qrcode-generator": "^2.0.4", "react": "^18.3.1", "react-dom": "^18.3.1",